using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using FreeImageAPI; using FreeImageAPI.Metadata; using FreeImageAPI.Plugins; namespace Sample11 { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } [STAThread] static void Main() { // Capture messages generated by FreeImage FreeImageEngine.Message += new OutputMessageFunction(FreeImageEngine_Message); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } static void FreeImageEngine_Message(FREE_IMAGE_FORMAT fif, string message) { // Display the message // FreeImage continues code executing when all // addes subscribers of 'Message' finished returned. MessageBox.Show(message, "FreeImage-Message", MessageBoxButtons.OK, MessageBoxIcon.Information); } // The FreeImageBitmap this sample will work with. FreeImageBitmap bitmap = null; // Replaces the current bitmap with the given one. private void ReplaceBitmap(FreeImageBitmap newBitmap) { // Checks whether the bitmap is usable if (newBitmap == null || newBitmap.IsDisposed) { MessageBox.Show( "Unexpected error.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } // Check whether the image type of the new bitmap is 'FIT_BITMAP'. // If not convert to 'FIT_BITMAP'. if (newBitmap.ImageType != FREE_IMAGE_TYPE.FIT_BITMAP) { if (!newBitmap.ConvertType(FREE_IMAGE_TYPE.FIT_BITMAP, true)) { MessageBox.Show( "Error converting bitmap to standard type.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } // Dispose the old bitmap only in case it exists and // the old instance is another than the new one. if ((bitmap != null) && !object.ReferenceEquals(bitmap, newBitmap)) { bitmap.Dispose(); } // Dispose the picturebox's bitmap in case it exists. if (pictureBox.Image != null) { pictureBox.Image.Dispose(); } // Set the new bitmap. pictureBox.Image = (Bitmap)(bitmap = newBitmap); // Update gui. UpdateBitmapInformations(); UpdateFrameSelection(); } // Get bitmap properties and display them in the gui. private void UpdateBitmapInformations() { if (Bitmap) { // Get width lWidth.Text = String.Format("Width: {0}", bitmap.Width); // Get Height lHeight.Text = String.Format("Height: {0}", bitmap.Height); // Get color depth lBpp.Text = String.Format("Bpp: {0}", bitmap.ColorDepth); // Get number of metadata ImageMetadata mData = bitmap.Metadata; mData.HideEmptyModels = true; int mCnt = 0; foreach (MetadataModel model in mData.List) { mCnt += model.Count; } lMetadataCount.Text = String.Format("Metadata: {0}", mCnt); // Get image comment lComment.Text = String.Format("Image-comment: {0}", bitmap.Comment != null ? bitmap.Comment : String.Empty); // Get the number of real colors in the image lColors.Text = String.Format("Colors: {0}", bitmap.UniqueColors); } else { // Reset all values lWidth.Text = String.Format("Width: {0}", 0); lHeight.Text = String.Format("Height: {0}", 0); lBpp.Text = String.Format("Bpp: {0}", 0); lMetadataCount.Text = String.Format("Metadata: {0}", 0); lComment.Text = String.Format("Image-comment: {0}", String.Empty); lColors.Text = String.Format("Colors: {0}", 0); } } // Update combobox for frame selection. private void UpdateFrameSelection() { cbSelectFrame.Items.Clear(); if (Bitmap) { // Get number of frames in the bitmap if (bitmap.FrameCount > 1) { // Add an entry for each frame to the combobox for (int i = 0; i < bitmap.FrameCount; i++) { cbSelectFrame.Items.Add(String.Format("Frame {0}", i + 1)); } } } } // Returns true in case the variable 'bitmap' // is set and not disposed. private bool Bitmap { get { return ((bitmap != null) && (!bitmap.IsDisposed)); } } private void bLoadImage_Click(object sender, EventArgs e) { if (ofd.ShowDialog() == DialogResult.OK) { try { // Load the file using autodetection FreeImageBitmap fib = new FreeImageBitmap(ofd.FileName); // Rescale the image so that it fits the picturebox // Get the plugin that was used to load the bitmap FreeImagePlugin plug = PluginRepository.Plugin(fib.ImageFormat); lImageFormat.Text = String.Format("Image-format: {0}", plug.Format); // Replace the existing bitmap with the new one ReplaceBitmap(fib); } catch { } } } private void bSaveImage_Click(object sender, EventArgs e) { if (pictureBox.Image != null) { try { if (sfd.ShowDialog() == DialogResult.OK) { // Save the bitmap using autodetection using (FreeImageBitmap temp = new FreeImageBitmap(pictureBox.Image)) { temp.Save(sfd.FileName); } } } catch { } } } private void bRotate_Click(object sender, EventArgs e) { if (Bitmap) { // Create a temporary rescaled bitmap using (FreeImageBitmap temp = bitmap.GetScaledInstance( pictureBox.DisplayRectangle.Width, pictureBox.DisplayRectangle.Height, FREE_IMAGE_FILTER.FILTER_CATMULLROM)) { if (temp != null) { // Rotate the bitmap temp.Rotate((double)vRotate.Value); if (pictureBox.Image != null) { pictureBox.Image.Dispose(); } // Display the result pictureBox.Image = (Bitmap)temp; } } } } private void bGreyscale_Click(object sender, EventArgs e) { if (Bitmap) { // Convert the bitmap to 8bpp and greyscale ReplaceBitmap(bitmap.GetColorConvertedInstance( FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP | FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE)); } } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { ComboBox cb = sender as ComboBox; if ((cb != null) && (cb.Items.Count > 0)) { if (Bitmap) { try { // Switch the selected frame bitmap.SelectActiveFrame(cb.SelectedIndex); ReplaceBitmap(bitmap); } catch (ArgumentOutOfRangeException) { MessageBox.Show("Error changing frame.", "Error"); } } } } private void bAdjustGamma_Click(object sender, EventArgs e) { if (Bitmap) { // Adjust the gamma value bitmap.AdjustGamma((double)vGamma.Value); ReplaceBitmap(bitmap); } } private void bRedChannelOnly_Click(object sender, EventArgs e) { // Mask out green and blue SetColorChannels(0xFF, 0x00, 0x00); } private void bGreenChannel_Click(object sender, EventArgs e) { // Mask out red and blue SetColorChannels(0x00, 0xFF, 0x00); } private void bBlueChannel_Click(object sender, EventArgs e) { // Mask out red and green SetColorChannels(0x00, 0x00, 0xFF); } private void bAllChannels_Click(object sender, EventArgs e) { if (Bitmap) { // Restore the bitmap using the original ReplaceBitmap(bitmap); } } private void SetColorChannels(int redmask, int greenmask, int bluemask) { if (Bitmap) { // Create a temporary clone. using (FreeImageBitmap bitmap = (FreeImageBitmap)this.bitmap.Clone()) { if (bitmap != null) { // Check whether the bitmap has a palette if (bitmap.HasPalette) { // Use the Palette class to handle the bitmap's // palette. A palette always consist of RGBQUADs. Palette palette = bitmap.Palette; // Apply the new values for all three color components. for (int i = 0; i < palette.Length; i++) { RGBQUAD rgbq = palette[i]; rgbq.rgbRed = (byte)(rgbq.rgbRed & redmask); rgbq.rgbGreen = (byte)(rgbq.rgbGreen & greenmask); rgbq.rgbBlue = (byte)(rgbq.rgbBlue & bluemask); palette[i] = rgbq; } } // In case the bitmap has no palette it must have a color depth // of 16, 24 or 32. Each color depth needs a different wrapping // structure for the bitmaps data. These structures can be accessed // by using the foreach clause. else if (bitmap.ColorDepth == 16) { // Iterate over each scanline // For 16bpp use either Scanline or Scanline if (bitmap.IsRGB555) { foreach (Scanline scanline in bitmap) { for (int x = 0; x < scanline.Length; x++) { FI16RGB555 pixel = scanline[x]; pixel.Red = (byte)(pixel.Red & redmask); pixel.Green = (byte)(pixel.Green & greenmask); pixel.Blue = (byte)(pixel.Blue & bluemask); scanline[x] = pixel; } } } else if (bitmap.IsRGB565) { foreach (Scanline scanline in bitmap) { for (int x = 0; x < scanline.Length; x++) { FI16RGB565 pixel = scanline[x]; pixel.Red = (byte)(pixel.Red & redmask); pixel.Green = (byte)(pixel.Green & greenmask); pixel.Blue = (byte)(pixel.Blue & bluemask); scanline[x] = pixel; } } } } else if (bitmap.ColorDepth == 24) { // Iterate over each scanline // For 24bpp Scanline must be used foreach (Scanline scanline in bitmap) { for (int x = 0; x < scanline.Length; x++) { RGBTRIPLE pixel = scanline[x]; pixel.rgbtRed = (byte)(pixel.rgbtRed & redmask); pixel.rgbtGreen = (byte)(pixel.rgbtGreen & greenmask); pixel.rgbtBlue = (byte)(pixel.rgbtBlue & bluemask); scanline[x] = pixel; } } } else if (bitmap.ColorDepth == 32) { // Iterate over each scanline // For 32bpp Scanline must be used foreach (Scanline scanline in bitmap) { for (int x = 0; x < scanline.Length; x++) { RGBQUAD pixel = scanline[x]; pixel.rgbRed = (byte)(pixel.rgbRed & redmask); pixel.rgbGreen = (byte)(pixel.rgbGreen & greenmask); pixel.rgbBlue = (byte)(pixel.rgbBlue & bluemask); scanline[x] = pixel; } } } // Dispose only the picturebox's bitmap if (pictureBox.Image != null) { pictureBox.Image.Dispose(); } pictureBox.Image = (Bitmap)bitmap; } } } } private void vRotate_Scroll(object sender, EventArgs e) { TrackBar bar = sender as TrackBar; if (bar != null) { lRotate.Text = bar.Value.ToString(); } } private void nShowMetadata_Click(object sender, EventArgs e) { if (Bitmap) { MetaDataFrame mFrame = new MetaDataFrame(); mFrame.Tag = bitmap.Metadata; mFrame.ShowDialog(this); } } } }