Invert Image colors

Mar 7, 2014 at 7:25 PM
Hi,

I want to implement a function to can invert colors for readability on a small screen. I came across some code that works for me, but i don't know where to implement this the right way, so i can stil use page/zoom etc.

public Bitmap Transform(Bitmap source)
{
//create a blank bitmap the same size as original
Bitmap newBitmap = new Bitmap(source.Width, source.Height);

//get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap);

// create the negative color matrix
ColorMatrix colorMatrix = new ColorMatrix(new float[][]
{
    new float[] {-1, 0, 0, 0, 0},
    new float[] {0, -1, 0, 0, 0},
    new float[] {0, 0, -1, 0, 0},
    new float[] {0, 0, 0, 1, 0},
    new float[] {1, 1, 1, 0, 1}
}); 

// create some image attributes
ImageAttributes attributes = new ImageAttributes();

attributes.SetColorMatrix(colorMatrix);

g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height),
            0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes);

//dispose the Graphics object
g.Dispose();

return newBitmap;
}
Coordinator
Mar 9, 2014 at 8:43 AM
Hi,

I would implement this in the 'DisplayPage' event handler.

So, the complete source would look like this:
namespace Ghostscript.NET.Viewer
{
    public partial class FMain : Form
    {
        private GhostscriptViewer _viewer;
        private GhostscriptVersionInfo _gsVersion = GhostscriptVersionInfo.GetLastInstalledVersion(GhostscriptLicense.GPL | GhostscriptLicense.AFPL, GhostscriptLicense.GPL);

        public FMain()
        {
            InitializeComponent();

            this.Text = Program.NAME;

            pbPage.Width = 100;
            pbPage.Height = 100;

            _viewer = new GhostscriptViewer();

            _viewer.DisplaySize += new GhostscriptViewerViewEventHandler(_viewer_DisplaySize);
            _viewer.DisplayPage += new GhostscriptViewerViewEventHandler(_viewer_DisplayPage);
        }

        void _viewer_DisplaySize(object sender, GhostscriptViewerViewEventArgs e)
        {
            pbPage.Image = e.Image;
        }

        void _viewer_DisplayPage(object sender, GhostscriptViewerViewEventArgs e)
        {
            pbPage.Image = this.Transform(pbPage.Image as Bitmap);

            tbPageNumber.Text = _viewer.CurrentPageNumber.ToString();
            tbTotalPages.Text = " / " + _viewer.LastPageNumber.ToString();
        }

        private void FMain_Load(object sender, EventArgs e)
        {
            lblSystemInformation.Text = "Operating system: " + (Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit") + "   " +
                "Process: " + (Environment.Is64BitProcess ? "64-bit" : "32-bit");

            lblGsVersion.Text = "Rasterizer: " + _gsVersion.LicenseType.ToString() + " Ghostscript " + 
                _gsVersion.Version.ToString() + " (" + Path.GetFileName(_gsVersion.DllPath) + ")";
        }

        private void mnuFileOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "Open PDF file";
            ofd.Filter = "PDF, PS, EPS files|*.pdf;*.ps;*.eps";

            if (ofd.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                mnuFileClose_Click(this, null);

                _viewer.Open(ofd.FileName, _gsVersion, true);
                this.Text = System.IO.Path.GetFileName(ofd.FileName) + " - " + Program.NAME;
            }
        }

        private void mnuFileClose_Click(object sender, EventArgs e)
        {
            _viewer.Close();
            pbPage.Image = null;
            this.Text = Program.NAME;
            tbPageNumber.Text = string.Empty;
            tbTotalPages.Text = string.Empty;
        }

        private void mnuFileExit_Click(object sender, EventArgs e)
        {
            this.Close();
            Application.Exit();
        }

        private void tbPageFirst_Click(object sender, EventArgs e)
        {
            _viewer.ShowFirstPage();
        }

        private void tbPagePrevious_Click(object sender, EventArgs e)
        {
            _viewer.ShowPreviousPage();
        }

        private void tbPageNext_Click(object sender, EventArgs e)
        {
            _viewer.ShowNextPage();
        }

        private void tbPageLast_Click(object sender, EventArgs e)
        {
            _viewer.ShowLastPage();
        }

        private void tbPageNumber_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (tbPageNumber.Text.Length > 0)
                {
                    _viewer.ShowPage(int.Parse(tbPageNumber.Text));
                }
            }
            catch { }
        }

        private void mnuAbout_Click(object sender, EventArgs e)
        {
            MessageBox.Show(this, "Powered by Ghostscript.NET & Josip Habjan (habjan@gmail.com)", "About " + Program.NAME, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void mnuNext_Click(object sender, EventArgs e)
        {
            _viewer.ShowNextPage();
        }

        private void mnuPrev_Click(object sender, EventArgs e)
        {
            _viewer.ShowPreviousPage();
        }

        private void mnuFirst_Click(object sender, EventArgs e)
        {
            _viewer.ShowFirstPage();
        }

        private void mnuLast_Click(object sender, EventArgs e)
        {
            _viewer.ShowLastPage();
        }

        private void tpZoomIn_Click(object sender, EventArgs e)
        {
            _viewer.ZoomIn();
        }

        private void tpZoomOut_Click(object sender, EventArgs e)
        {
            _viewer.ZoomOut();
        }

        public Bitmap Transform(Bitmap source)
        {
            //create a blank bitmap the same size as original
            Bitmap newBitmap = new Bitmap(source.Width, source.Height);

            //get a graphics object from the new image
            Graphics g = Graphics.FromImage(newBitmap);

            // create the negative color matrix
            ColorMatrix colorMatrix = new ColorMatrix(new float[][]
            {
                new float[] {-1, 0, 0, 0, 0},
                new float[] {0, -1, 0, 0, 0},
                new float[] {0, 0, -1, 0, 0},
                new float[] {0, 0, 0, 1, 0},
                new float[] {1, 1, 1, 0, 1}
            });

            // create some image attributes
            ImageAttributes attributes = new ImageAttributes();

            attributes.SetColorMatrix(colorMatrix);

            g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height),
                        0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes);

            //dispose the Graphics object
            g.Dispose();

            return newBitmap;
        }
    }
}
Cheers,
Josip
Mar 9, 2014 at 5:56 PM
Hi Josip,

Thanks for helping me out. I was a little confused, but its working now. I noticed the DisplaySize event is called twice when loading a document, and DisplayUpdate can be called more than once, and in the source code you call pbPage.Invalidate(); and pbPage.Update() in both DisplayUpdate and DisplayPage handler. I only call pbPage.Invalidate(); in DisplayUpdate. (less flashing now)

I changed this:
pbPage.Image = this.Transform(pbPage.Image as Bitmap);
to this
pbPage.Image = this.Transform(e.Image as Bitmap);
because the image was converted back to original when going to the next page, and the page was not going to the next one.

and i keep track if image is converted or not.
this the result:
    void _viewer_DisplaySize(object sender, GhostscriptViewerViewEventArgs e)
    {
        pbPage.Image = e.Image;
        System.Diagnostics.Debug.Write("displaySize...." + "\n");
    }

    void _viewer_DisplayUpdate(object sender, GhostscriptViewerViewEventArgs e)
    {
        pbPage.Invalidate();
        System.Diagnostics.Debug.Write("displayUpdate...." + "\n");
    }

    void _viewer_DisplayPage(object sender, GhostscriptViewerViewEventArgs e)
    {
        if (_isInverted == true)
        {
            pbPage.Image = this.InvertBitmap(e.Image);
        }

        System.Diagnostics.Debug.Write("displayPage...." + "\n");
        tbPageNumber.Text = _viewer.CurrentPageNumber.ToString();
        tbTotalPages.Text = " / " + _viewer.LastPageNumber.ToString();
    }

    public Bitmap InvertBitmap(Image img)
    {
        Bitmap bm = new Bitmap(img.Width, img.Height);
        Graphics g = Graphics.FromImage(bm);
        ColorMatrix cm = new ColorMatrix(new float[][]
        {
            new float[] {-1, 0, 0, 0, 0},
            new float[] {0, -1, 0, 0, 0},
            new float[] {0, 0, -1, 0, 0},
            new float[] {0, 0, 0, 1, 0},
            new float[] {1, 1, 1, 0, 1}
        });
        ImageAttributes ia = new ImageAttributes();
        ia.SetColorMatrix(cm);
        g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);
        g.Dispose();

        return bm;
    }
Thanks again,
regards, Sil
Coordinator
Mar 12, 2014 at 9:48 AM
Hi,

I'm glad you manage to work this out.

Cheers,
Josip