/// <summary> /// Saves the mapping of the original RGB colors to modified ARGB colors to file. /// </summary> private void SaveMapping() { AlphaRemappingTable map = new AlphaRemappingTable(); foreach (var colorMapping in colorMappingTable) if (colorMapping.Key != colorMapping.Value) map.AddMapping( new RgbColor(colorMapping.Key.R, colorMapping.Key.G, colorMapping.Key.B), new ArgbColor(colorMapping.Value.A, colorMapping.Value.R, colorMapping.Value.G, colorMapping.Value.B)); string mapFilePath = Path.ChangeExtension(filePath, AlphaRemappingTable.FileExtension); if (map.SaveMap(mapFilePath)) MessageBox.Show(this, "Lookup mapping saved to '" + mapFilePath + "'", "Mapping Saved", MessageBoxButtons.OK, MessageBoxIcon.Information); else MessageBox.Show(this, "Source and destination colors match. Mapping file '" + mapFilePath + "' deleted.", "Mapping Deleted", MessageBoxButtons.OK, MessageBoxIcon.Information); changed = false; }
/// <summary> /// Builds the color mapping by adding all colors in the given table, and also resolving lookups according to the given alpha map. /// </summary> /// <param name="colorTable">The colors that should be added to the current lookup mapping.</param> /// <param name="alphaMap">The alpha mapping that specifies new ARGB colors that should replace any given RGB colors in the color /// table.</param> private void BuildColorMap(ArgbColor[] colorTable, AlphaRemappingTable alphaMap) { foreach (ArgbColor sourceArgbColor in colorTable) if (sourceArgbColor.A == 255) { RgbColor sourceRgbColor = (RgbColor)sourceArgbColor; Color sourceColor = Color.FromArgb(sourceRgbColor.ToArgb()); if (!colorMappingTable.ContainsKey(sourceColor)) { ArgbColor desiredArgbColor; if (!alphaMap.TryGetMapping(sourceRgbColor, out desiredArgbColor)) desiredArgbColor = sourceArgbColor; colorMappingTable.Add(sourceColor, Color.FromArgb(desiredArgbColor.ToArgb())); } } }
/// <summary> /// Raised when a new index is selected from ImageSelector. /// Loads the GIF file of that filename. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The event data.</param> private void ImageSelector_SelectedIndexChanged(object sender, EventArgs e) { if (!SavePrompt()) return; loaded = false; changed = false; filePath = Path.Combine(filesPath, (string)ImageSelector.Items[ImageSelector.SelectedIndex]); if (gifImage != null) foreach (GifFrame<Bitmap> frame in gifImage.Frames) frame.Image.Dispose(); if (desiredFrames != null) foreach (Bitmap frame in desiredFrames) frame.Dispose(); gifImage = null; frameIndex = -1; desiredFrames = null; ImageComparison.Panel1.BackgroundImage = null; ImageComparison.Panel2.BackgroundImage = null; ImageSourceColor.BackColor = Color.Transparent; ImageDesiredColor.BackColor = Color.Transparent; ImageSourcePalette.BackColor = PaletteControls.BackColor; ImageDesiredPalette.BackColor = PaletteControls.BackColor; ImageSourcePalette.Controls.Clear(); ImageDesiredPalette.Controls.Clear(); foreach (Panel panel in sourceSwatches) panel.Dispose(); foreach (Panel panel in desiredSwatches) panel.Dispose(); sourceSwatches.Clear(); desiredSwatches.Clear(); SourceAlphaCode.ResetText(); SourceColorCode.ResetText(); DesiredAlphaCode.ResetText(); DesiredColorCode.ResetText(); FrameControls.Enabled = false; PaletteControls.Enabled = false; ColorControls.Enabled = false; ErrorLabel.Visible = false; currentColor = Color.Empty; FileStream gifStream = null; try { gifStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); gifImage = GifImage.OfBitmap(gifStream); } catch (Exception) { Console.WriteLine("An error occurred attempting to load the file: " + filePath); ShowError("An error occurred attempting to load this file."); return; } finally { if (gifStream != null) gifStream.Dispose(); } Indexer.UseTimingsFrom(gifImage); AlphaRemappingTable map = new AlphaRemappingTable(); string mapFile = Path.ChangeExtension(filePath, AlphaRemappingTable.FileExtension); if (File.Exists(mapFile)) map.LoadMap(mapFile); colorMappingTable.Clear(); foreach (var frame in gifImage.Frames) BuildColorMap(frame.GetColorTable(), map); sourceSwatches.Capacity = colorMappingTable.Count; desiredSwatches.Capacity = colorMappingTable.Count; int swatchSize = ImageSourcePalette.Height - 2; Size size = new Size(swatchSize, swatchSize); Point location = new Point(1, 1); ImageSourcePalette.SuspendLayout(); ImageDesiredPalette.SuspendLayout(); int mappingIndex = 0; foreach (var colorMapping in colorMappingTable) { Panel sourcePanel = new Panel() { Size = size, Location = location }; Panel desiredPanel = new Panel() { Size = size, Location = location }; sourcePanel.Tag = desiredPanel; desiredPanel.Tag = sourcePanel; sourceSwatches.Add(sourcePanel); desiredSwatches.Add(desiredPanel); ImageSourcePalette.Controls.Add(sourcePanel); ImageDesiredPalette.Controls.Add(desiredPanel); sourceSwatches[mappingIndex].Click += Swatch_Clicked; desiredSwatches[mappingIndex].Click += Swatch_Clicked; sourceSwatches[mappingIndex].BackColor = colorMapping.Key; desiredSwatches[mappingIndex].BackColor = colorMapping.Value; if (mappingIndex == 0) currentColor = colorMapping.Key; mappingIndex++; location.X += swatchSize + 1; } location.Y = 0; Panel blankSourcePanel = new Panel() { Size = ImageSourcePalette.Size, Location = location, BackColor = SystemColors.Control }; ImageSourcePalette.Controls.Add(blankSourcePanel); Panel blankDesiredPanel = new Panel() { Size = ImageDesiredPalette.Size, Location = location, BackColor = SystemColors.Control }; ImageDesiredPalette.Controls.Add(blankDesiredPanel); ImageSourcePalette.ResumeLayout(); ImageDesiredPalette.ResumeLayout(); ImageSourcePalette.BackColor = ImageComparison.BackColor; ImageDesiredPalette.BackColor = ImageComparison.BackColor; desiredFrames = new Bitmap[gifImage.Frames.Length]; for (int i = 0; i < desiredFrames.Length; i++) desiredFrames[i] = (Bitmap)gifImage.Frames[i].Image.Clone(); UpdateDesiredFrames(); FrameControls.Enabled = true; PaletteControls.Enabled = true; ColorControls.Enabled = true; SaveCommand.Enabled = true; UpdateSelectedFrame(0); UpdateColorHex(); UpdateColorDisplay(); loaded = true; }
/// <summary> /// Creates a new <see cref="T:DesktopSprites.SpriteManagement.BitmapFrame"/> from the raw buffer, loading extra transparency /// information and adjusting the colors as required by the transparency. /// </summary> /// <param name="buffer">The raw buffer.</param> /// <param name="palette">The color palette.</param> /// <param name="transparentIndex">The index of the transparent color.</param> /// <param name="stride">The stride width of the buffer.</param> /// <param name="width">The logical width of the buffer.</param> /// <param name="height">The logical height of the buffer.</param> /// <param name="depth">The bit depth of the buffer.</param> /// <param name="hashCode">The hash code of the frame.</param> /// <param name="fileName">The path to the GIF file being loaded.</param> /// <returns>A new <see cref="T:DesktopSprites.SpriteManagement.BitmapFrame"/> for the frame held in the raw buffer.</returns> private BitmapFrame BitmapFrameFromBuffer(byte[] buffer, RgbColor[] palette, int transparentIndex, int stride, int width, int height, int depth, int hashCode, string fileName) { return Disposable.SetupSafely( BitmapFrame.FromBuffer(buffer, palette, transparentIndex, stride, width, height, depth, hashCode), frame => { if (IsAlphaBlended) { // Check for an alpha remapping table, and apply it if one exists. string mapFilePath = Path.ChangeExtension(fileName, AlphaRemappingTable.FileExtension); if (File.Exists(mapFilePath)) { AlphaRemappingTable map = new AlphaRemappingTable(); map.LoadMap(mapFilePath); ColorPalette colorPalette = frame.Image.Palette; for (int i = 0; i < colorPalette.Entries.Length; i++) { Color color = colorPalette.Entries[i]; ArgbColor argbColor; if (map.TryGetMapping(new RgbColor(color.R, color.G, color.B), out argbColor)) colorPalette.Entries[i] = Color.FromArgb(argbColor.ToArgb()); } frame.Image.Palette = colorPalette; // We only need to pre-multiply when we add an alpha channel ourselves, as GIFs only support 1 bit transparency. frame.Image.PreMultiplyAlpha(); } } else { frame.Image.RemapColors(paletteMapping); } }); }