Sem categoria

Icon Pro: Primeira Release, e página no Code Plex!!!

Olá pessoal,

É com grande alegria que venho divulgar com vocês a primeira Release do Icon Pro, e também a página no Code Plex.

A primeira Release tem novas funcionalidades em relação à versão beta. Segue o vídeo demo, e o link para a página de desenvolvimento.

Icon Pro – Home

Anúncios

WPF: Classe EditableBitmapImage (Implementando método SetPixel e GetPixel) – C#

Olá galera!!

Neste post, apresento à você uma implementação bem simples e funcional dos métodos SetPixel e GetPixel, para Wpf:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace HL.IconPro.Lib.Wpf
{
    public sealed class EditableBitmapImage
    {
        #region Constructors
        public EditableBitmapImage(BitmapSource Source)
        {
            Initialize(Source);
        }
        public EditableBitmapImage(int PixelWidth, int PixelHeight, double DpiX, double DpiY)
        {
            WriteableBitmap bp = new WriteableBitmap(PixelWidth, PixelHeight, DpiX, DpiY, PixelFormats.Bgra32, null);
            Initialize(bp);
        }
        #endregion

        #region Destructors
        ~EditableBitmapImage()
        {
            _Buffer = null;
            GC.Collect();
        }
        #endregion

        #region Fields
        private BitmapSource _OriginalSource;
        private WriteableBitmap _Source;
        private byte[] _Buffer;
        #endregion

        #region Properties
        public WriteableBitmap Source
        {
            get
            {
                _Source.Lock();
                Marshal.Copy(_Buffer, 0, _Source.BackBuffer, _Buffer.Length);
                _Source.AddDirtyRect(new System.Windows.Int32Rect(0, 0, _Source.PixelWidth, _Source.PixelHeight));
                _Source.Unlock();
                return _Source;
            }
            set
            {
                if (value == null) throw new NullReferenceException("Value can not be null");
                Initialize(value);
            }
        }
        public BitmapSource OriginalSource
        {
            get
            {
                return _OriginalSource;
            }
            set
            {
                if (value == null) throw new NullReferenceException("Value can not be null");
                Initialize(value);
            }
        }
        public byte[] Buffer
        {
            get
            {
                return _Buffer;
            }
            set
            {
                if (value == null) throw new NullReferenceException("Value can not be null");
                if (value.Rank > 1) throw new NullReferenceException("Invalid buffer: Can not be multidimensional");
                if (value.Length != _Buffer.Length) throw new NullReferenceException("Invalid buffer: Can not have a different length from the source");
                _Buffer = value;
            }
        }
        public int PixelWidth
        {
            get { return _OriginalSource.PixelWidth; }
        }
        public int PixelHeight
        {
            get { return _OriginalSource.PixelHeight; }
        }
        public double DpiX
        {
            get { return _OriginalSource.DpiX; }
        }
        public double DpiY
        {
            get { return _OriginalSource.DpiX; }
        }
        public double Width
        {
            get { return _OriginalSource.Width; }
        }
        public double Height
        {
            get { return _OriginalSource.Height; }
        }
        #endregion

        #region Procedures
        private void Initialize(BitmapSource Source)
        {
            _OriginalSource = Source;
            BitmapSource bgra = new FormatConvertedBitmap(Source, PixelFormats.Bgra32, null, 0);
            _Source = new WriteableBitmap(bgra);
            _Buffer = new byte[_Source.BackBufferStride * _Source.PixelHeight];
            Marshal.Copy(_Source.BackBuffer, _Buffer, 0, (_Source.BackBufferStride * _Source.PixelHeight));
        }
        public void SetPixel(int x, int y, Color Color)
        {
            if ((x > _Source.PixelWidth - 1) || (x < 0)) return;
            if ((y > _Source.PixelHeight - 1) || (y < 0)) return;
            if (Color == null) return;

            int loc = (x * 4) + (y * _Source.BackBufferStride);
            _Buffer[loc] = Color.B;
            _Buffer[loc + 1] = Color.G;
            _Buffer[loc + 2] = Color.R;
            _Buffer[loc + 3] = Color.A;
        }

        public Color GetPixel(int x, int y)
        {
            if ((x > _Source.PixelWidth - 1) || (x < 0)) return Color.FromArgb(0, 0, 0, 0);
            if ((y > _Source.PixelHeight - 1) || (y < 0)) return Color.FromArgb(0, 0, 0, 0);

            int loc = (x * 4) + (y * _Source.BackBufferStride);
            return Color.FromArgb(_Buffer[loc + 3], _Buffer[loc + 2], _Buffer[loc + 1], _Buffer[loc]);
        }
        #endregion

        #region Static

        #endregion

        #region Others
        public static implicit operator BitmapSource(EditableBitmapImage Source)
        {
            return Source.Source;
        }
        #endregion
    }
}

Essa classe é na verdade uma espécie de “interface” para a classe WriteableBitmap.
Com ela você pode fazer coisas do tipo:

EditableBitmapImage eb = new EditableBitmapImage(Source);
eb.SetPixel(23, 23, Color.FromArgb(245, 12, 45, 23));
BitmapSource bp = eb;

Como é possível notar no código, você precisa declara-la fornecendo uma imagem, um objeto do tipo BitmapImage ou BitmapFrame. Então você usa o objeto EditableBitmapImage para fazer as edições.

Devo ressaltar algo importante: Toda vez que você converte um EditableBitmapImage de volta para um BitmapSource, ele recria na memória um objeto do tipo WriteableBitmap. Então, por questões de desempenho, faças todas as edições na imagem de uma vez, e no final, quando você tiver certeza que não será feita mais nenhuma edição, faça a conversão para BitmapSource.

Divirta-se!!!

WPF & Win Forms: Capturar um controle para uma imagem – C#

Fala galera,

As vezes, okay, muito raramente, aliás, eu nem mesmo tenho ideia de qual seja a utilidade disso, precisamos capturar um controle de nosso aplicativo, e “salva-lo” para uma Imagem.

Isso é possível, no Win Forms e de forma bem fácil no WPF.
Criei uma classe para fazer a captura no Win Forms, e outra classe para fazer a captura no WPF. A diferença? Você vê a seguir:

WPF:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HerbertLausmann.Wpf
{
    class VisualToBitmap
    {
        public static System.Windows.Media.Imaging.BitmapSource Render(System.Windows.Media.Visual Visual, int Resolution = 96)
        {
            System.Windows.Media.Imaging.RenderTargetBitmap render;
            double width, height;
            int pixelWidth, pixelHeight;
            width = (double)Visual.GetValue(System.Windows.FrameworkElement.ActualWidthProperty);
            height = (double)Visual.GetValue(System.Windows.FrameworkElement.ActualHeightProperty);
            pixelWidth = Convert.ToInt32((width / 96) * Resolution);
            pixelHeight =  Convert.ToInt32((height / 96) * Resolution);
            render = new System.Windows.Media.Imaging.RenderTargetBitmap(
                pixelWidth, pixelHeight, Resolution, Resolution,
                System.Windows.Media.PixelFormats.Pbgra32);
            render.Render(Visual);
            return render;
        }
    }
}

Win Forms:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace HerbertLausmann.WinForms
{
    class HandleToBitmap
    {
        /// <summary>
        /// Gera um Bitmap diretamente do hWnd correspondente à Janela/Controle
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap RenderHwnd(IntPtr hWnd)
        {
            IntPtr hDC = USER32.GetDC(hWnd);
            USER32.RECT WndRect = new USER32.RECT();
            USER32.GetWindowRect(hWnd, out WndRect);

            IntPtr capHDC = GDI32.CreateCompatibleDC(hDC);
            IntPtr capBMP = GDI32.CreateCompatibleBitmap(hDC, WndRect.Width(false), WndRect.Height(false));

            if (capBMP == IntPtr.Zero)
            {
                USER32.ReleaseDC(hWnd, hDC);
                GDI32.DeleteDC(capHDC);
                return null;
            }

            IntPtr prvHDC = (IntPtr)GDI32.SelectObject(capHDC, capBMP);
            GDI32.BitBlt(capHDC, 0, 0, WndRect.Width(false), WndRect.Height(false), hDC, 0, 0, GDI32.SRCCOPY);
            GDI32.SelectObject(capHDC, prvHDC);

            System.Drawing.Bitmap bmp = System.Drawing.Bitmap.FromHbitmap(capBMP);

            USER32.ReleaseDC(hWnd, hDC);
            GDI32.DeleteDC(capHDC);
            GDI32.DeleteObject(capBMP);

            return bmp;
        }
        /// <summary>
        /// A grosso modo, essa função tira um Print Screen da tela e recorta a imagem para as proporções da janela/controle.
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap RenderFromDesktop(IntPtr hWnd)
        {
            IntPtr hDC = USER32.GetDC(USER32.GetDesktopWindow());
            USER32.RECT WndRect = new USER32.RECT();
            USER32.GetWindowRect(hWnd, out WndRect);

            IntPtr capHDC = GDI32.CreateCompatibleDC(hDC);
            IntPtr capBMP = GDI32.CreateCompatibleBitmap(hDC, WndRect.Width(), WndRect.Height());

            if (capBMP == IntPtr.Zero)
            {
                USER32.ReleaseDC(hWnd, hDC);
                GDI32.DeleteDC(capHDC);
                return null;
            }

            IntPtr prvHDC = (IntPtr)GDI32.SelectObject(capHDC, capBMP);
            GDI32.BitBlt(capHDC, 0, 0, WndRect.Width(), WndRect.Height(), hDC, WndRect.X(), WndRect.Y(), GDI32.SRCCOPY);
            GDI32.SelectObject(capHDC, prvHDC);

            System.Drawing.Bitmap bmp = System.Drawing.Bitmap.FromHbitmap(capBMP);

            USER32.ReleaseDC(USER32.GetDesktopWindow(), hDC);
            GDI32.DeleteDC(capHDC);
            GDI32.DeleteObject(capBMP);

            return bmp;
        }
        /// <summary>
        /// Gera um Bitmap correspondente à área cliente da Janela/Controle
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap RenderClientArea(IntPtr hWnd)
        {
            IntPtr hDC = USER32.GetDC(hWnd);
            USER32.RECT WndRect = new USER32.RECT();
            USER32.GetClientRect(hWnd, out WndRect);

            IntPtr capHDC = GDI32.CreateCompatibleDC(hDC);
            IntPtr capBMP = GDI32.CreateCompatibleBitmap(hDC, WndRect.Width(false), WndRect.Height(false));

            if (capBMP == IntPtr.Zero)// if no compatible bitmap
            {
                USER32.ReleaseDC(hWnd, hDC); //   release window context
                GDI32.DeleteDC(capHDC); //   delete capture context
                return null; //   return null bitmap
            }

            IntPtr prvHDC = (IntPtr)GDI32.SelectObject(capHDC, capBMP);
            GDI32.BitBlt(capHDC, 0, 0, WndRect.Width(false), WndRect.Height(false), hDC, WndRect.X(false), WndRect.Y(false), GDI32.SRCCOPY);
            GDI32.SelectObject(capHDC, prvHDC);

            System.Drawing.Bitmap bmp = System.Drawing.Bitmap.FromHbitmap(capBMP);

            USER32.ReleaseDC(hWnd, hDC);
            GDI32.DeleteDC(capHDC);
            GDI32.DeleteObject(capBMP);

            return bmp;
        }
        private class GDI32
        {
            public const int SRCCOPY = 13369376;

            [DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
            public static extern IntPtr DeleteDC(IntPtr hDc);

            [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
            public static extern IntPtr DeleteObject(IntPtr hDc);

            [DllImport("gdi32.dll", EntryPoint = "BitBlt")]
            public static extern bool BitBlt(IntPtr hdcDest, int xDest,
                int yDest, int wDest, int hDest, IntPtr hdcSource,
                int xSrc, int ySrc, int RasterOp);

            [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")]
            public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc,
                int nWidth, int nHeight);

            [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")]
            public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

            [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
            public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);

            [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
            public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
        }
        private class USER32
        {
            public const int SM_CXSCREEN = 0;
            public const int SM_CYSCREEN = 1;

            [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
            public static extern IntPtr GetDesktopWindow();

            [DllImport("user32.dll", EntryPoint = "GetDC")]
            public static extern IntPtr GetDC(IntPtr ptr);

            [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
            public static extern int GetSystemMetrics(int abc);

            [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
            public static extern IntPtr GetWindowDC(Int32 ptr);

            [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
            public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);

            [DllImport("user32.dll", EntryPoint = "GetWindowRect")]
            public static extern IntPtr GetWindowRect([In] IntPtr hWnd, out RECT lpRect);

            [DllImport("user32.dll", EntryPoint = "GetClientRect")]
            public static extern IntPtr GetClientRect([In] IntPtr hWnd, out RECT lpRect);

            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                int left;
                int top;
                int right;
                int bottom;

                public int X(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(left * getScalingFactor());
                    else
                        return left;
                }

                public int Y(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(top * getScalingFactor());
                    else
                        return top;
                }
                public int Width(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(Math.Abs(right - left) * getScalingFactor());
                    else
                        return (int)(Math.Abs(right - left));                    
                }

                public int Height(bool autoScale = true)
                {
                    if (autoScale)
                        return (int)Math.Round(Math.Abs(bottom - top) * getScalingFactor());
                    else
                        return (int)(Math.Abs(bottom - top));
                }
            }

            [DllImport("gdi32.dll")]
            static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

            public enum DeviceCap
            {
                VERTRES = 10,
                DESKTOPVERTRES = 117,
            }

            public static float getScalingFactor()
            {
                IntPtr desktop = GetDC(GetDesktopWindow());
                int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
                int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

                float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
                USER32.ReleaseDC(GetDesktopWindow(), desktop);
                return ScreenScalingFactor; // 1.25 = 125%
            }
        }
    }
}

Como você pode ver, a diferença é que o WPF oferece uma opção nativa, enquanto que no Win Forms temos que lidar com interoperabilidade na API do Windows.

Um pequeno exemplo de uso para o WPF:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF_Control_to_Image
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnRender_Click(object sender, RoutedEventArgs e)
        {
            BitmapSource bmp = VisualToBitmap.Render(MainBorder);
            Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
            dialog.Filter = "Imagem PNG(*.png)|*.png";
            if(dialog.ShowDialog() == true)
            {
                System.Windows.Media.Imaging.PngBitmapEncoder encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bmp));
                System.IO.FileStream fs = new System.IO.FileStream(dialog.FileName, System.IO.FileMode.Create);
                encoder.Save(fs);
                fs.Close();
            }
        }
    }
}

E um para o Win Forms:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HWND_To_Image
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnRender_Click(object sender, EventArgs e)
        {
            Bitmap bmp = HandleToBitmap.RenderClientArea(this.Handle);
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "Imagem PNG (*.png)|*.png";
            dialog.AddExtension = true;
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Png);
            }
        }

    }
}

E isso é tudo. Vou disponibilizar o download da Solution com os exemplos para Win Forms e WPF:

Control to Image.zip

Até a próxima, pessoal!!!

Baixa frequencia no MSDN e no Blog

Olá pessoal,

Já faz um certo tempinho desde o meu último post, e por isso vim aqui dizer que o blog não morreu! Tampouco eu.. kkk

Minha participação nos fóruns do MSDN também diminuiu muito e irei explicar o porquê.

Na minha região onde vivo (Extremo Sul da Bahia, Sta. Cruz Cabrália) há bem poucas oportunidades de emprego relacionado à TI, a economia da região é basicamente turismo.

Me surgiu uma possibilidade de emprego em um novo hotel da cidade, bem aqui perto de onde moro, e consegui ser admitido. Por isso não me sobra tempo livre para o blog e o fórum, a não ser nas folgas (como hoje, por exemplo).

Masss, eu não larguei fórum e muito menos o blog. Vou continuar postando, assim que eu tiver alguma coisa interessante em mente, postarei hehe…

That’s all folks!