| 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<FI16RGB555> or Scanline<FI16RGB565> |
| if (bitmap.IsRGB555) |
| { |
| foreach (Scanline<FI16RGB555> 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<FI16RGB565> 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<RGBTRIPLE> must be used |
| foreach (Scanline<RGBTRIPLE> 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<RGBQUAD> must be used |
| foreach (Scanline<RGBQUAD> 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); |
| } |
| } |
| } |
| } |