private static byte[] GetBGRFromBitmap(FreeImageBitmap bitmap, int w, int h) { byte[] pic = new byte[(w + 10) * (h + 10) * 3]; int o = 0; //get pic from bitmap for (int y = 0; y < h; y++) { var scanline = bitmap.GetScanlineFromTop8Bit(y); if (bitmap.ColorDepth == 24) { for (int x = 0; x < w; x++) { //get image data from RGB to BGR pic[o++] = scanline[x * 3 + 2]; pic[o++] = scanline[x * 3 + 1]; pic[o++] = scanline[x * 3 + 0]; } } else if (bitmap.ColorDepth == 32) { for (int x = 0; x < w; x++) { //get image data from RGB to BGR pic[o++] = scanline[x * 4 + 2]; pic[o++] = scanline[x * 4 + 1]; pic[o++] = scanline[x * 4 + 0]; } } } return(pic); }
private static bool AllPixelsOpaque(FreeImageBitmap existingAlphaChannel) { //all pixels opaque? for (int y = 0; y < existingAlphaChannel.Height; y++) { var scanline = existingAlphaChannel.GetScanlineFromTop8Bit(y); for (int x = 0; x < existingAlphaChannel.Width; x++) { if (scanline[x] != 255) { return(false); } } } return(true); }
private static byte[] GetAlphaFromBitmap(FreeImageBitmap bitmap, int w, int h) { byte[] pic = new byte[(w + 10) * (h + 10)]; int o = 0; //get pic from bitmap for (int y = 0; y < h; y++) { var scanline = bitmap.GetScanlineFromTop8Bit(y); for (int x = 0; x < w; x++) { //get alpha channel pic[o++] = scanline[x * 4 + 3]; } } return(pic); }
internal static void SaveImageData8Bit(Stream stream, FreeImageBitmap bitmap) { int width = bitmap.Width; int height = bitmap.Height; byte[] pic = new byte[width * height]; int o = 0; for (int y = 0; y < height; y++) { var scanline = bitmap.GetScanlineFromTop8Bit(y); for (int x = 0; x < width; x++) { pic[o++] = scanline[x]; } } SaveImageData8Bit(stream, pic, width, height); }
public static unsafe void RemapPalette(FreeImageBitmap bitmap, FreeImageBitmap referenceImage, int numberOfColors) { using (FreeImageBitmap bitmap32 = bitmap.GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP)) { if (referenceImage.Height < bitmap.Height || referenceImage.Width < bitmap.Width) { int h2 = referenceImage.Height; if (h2 < bitmap.Height) { h2 = bitmap.Height; } int w2 = referenceImage.Width; if (w2 < bitmap.Width) { w2 = bitmap.Width; } referenceImage.EnlargeCanvas <byte>(0, 0, w2 - referenceImage.Width, h2 - referenceImage.Height, 0); } //FreeImageBitmap reference32 = bitmap.GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP); if (bitmap.ColorDepth != 8) { bitmap.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP); } int *newPalette = (int *)(referenceImage.Palette.BaseAddress); int h = bitmap.Height; int w = bitmap.Width; //Ties are broken in ColorToIndex by popularity in the original image Dictionary <int, int> ColorToIndex = new Dictionary <int, int>(); int[] ColorHistogram = new int[256]; for (int y = 0; y < h; y++) { byte *srcScanline = (byte *)(referenceImage.GetScanlineFromTop8Bit(y).BaseAddress); for (int x = 0; x < w; x++) { int c = srcScanline[x]; ColorHistogram[c]++; } } //add each palette color to the dictionary for (int i = 0; i < numberOfColors; i++) { int c = newPalette[i] & 0xFFFFFF; if (ColorToIndex.ContainsKey(c)) { int otherIndex = ColorToIndex[c]; if (ColorHistogram[i] > ColorHistogram[otherIndex]) { ColorToIndex[c] = i; } } else { ColorToIndex[c] = i; } } for (int y = 0; y < h; y++) { int * trueColorScanline = (int *)(bitmap32.GetScanlineFromTop32Bit(y).BaseAddress); byte *srcScanline = (byte *)(bitmap.GetScanlineFromTop8Bit(y).BaseAddress); byte *referenceScanline = (byte *)(referenceImage.GetScanlineFromTop8Bit(y).BaseAddress); for (int x = 0; x < w; x++) { int srcColor = trueColorScanline[x] & 0xFFFFFF; int refIndex = referenceScanline[x]; int refColor = newPalette[refIndex] & 0xFFFFFF; if (srcColor == refColor) { srcScanline[x] = (byte)refIndex; } else { if (ColorToIndex.ContainsKey(srcColor)) { int newColorIndex = ColorToIndex[srcColor]; if (refColor == (newPalette[newColorIndex] & 0xFFFFFF)) { srcScanline[x] = (byte)refIndex; } else { srcScanline[x] = (byte)newColorIndex; } } else { float minDistance = float.MaxValue; int minIndex = 0; for (int i = 0; i < numberOfColors; i++) { int c = newPalette[i] & 0xFFFFFF; float distance = GetDistanceF(srcColor, c); if (distance < minDistance) { minIndex = i; minDistance = distance; } else if (distance == minDistance && ColorHistogram[i] > ColorHistogram[minIndex]) { minIndex = i; } } if (refColor == (newPalette[minIndex] & 0xFFFFFF)) { srcScanline[x] = (byte)refIndex; } else { srcScanline[x] = (byte)minIndex; } ColorToIndex.Add(srcColor, minIndex); } } } } bitmap.Palette.AsArray = referenceImage.Palette.AsArray; } }
public static void SaveImageData(Stream stream, FreeImageBitmap image) { byte[] imageData = new byte[image.Width * image.Height / 2]; int o = 0; for (int y = 0; y < image.Height; y++) { if (image.ColorDepth == 4) { var scanline = image.GetScanlineFromTop4Bit(y); for (int x = 0; x < image.Width; x += 2) { int p1 = scanline[x]; int p2 = scanline[x + 1]; imageData[o++] = (byte)((p1 << 4) + p2); } } else if (image.ColorDepth == 8) { var scanline = image.GetScanlineFromTop8Bit(y); for (int x = 0; x < image.Width; x += 2) { int p1 = scanline[x] & 0x0F; int p2 = scanline[x + 1] & 0x0F; imageData[o++] = (byte)((p1 << 4) + p2); } } } byte[] bytes = new byte[imageData.Length]; int[] lengths = new int[9]; TransformImage(bytes, imageData, image.Width, image.Height); int height = image.Height; //encode the bytes for (int i = 0; i < bytes.Length; i++) { int x = i / image.Height; int p = x & 3; Array.Clear(lengths, 0, lengths.Length); lengths[0] = MeasureRleRun(bytes, i, height); lengths[1] = MeasureRleRun2(bytes, i, height); lengths[2] = MeasurePreviousColumnRun(bytes, i, height, height * 4, 0); if (p >= 1) { lengths[3] = MeasurePreviousColumnRun(bytes, i, height, height * p, 0); lengths[6] = MeasurePreviousColumnRun(bytes, i, height, height * p, 255); } if (p >= 2) { lengths[4] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 1), 0); lengths[7] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 1), 255); } if (p >= 3) { lengths[5] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 2), 0); lengths[8] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 2), 255); } int maxIndex; int max = lengths.Max(out maxIndex); byte b = bytes[i]; if (max < 2) { maxIndex = -1; } else if (max == 2) { if (b >= 0x08) { maxIndex = -1; } else { if (maxIndex < 2 || maxIndex >= 6) { maxIndex = -1; } } } else if (max == 3) { //don't compress 3 bytes to 3 bytes unless first byte would be a literal if (b >= 0x08 && maxIndex < 2 || maxIndex >= 6) { maxIndex = -1; } } switch (maxIndex) { default: { //No compression - raw byte or escaped literal if (b >= 0x08) { //raw byte stream.WriteByte((byte)b); } else { //encode a literal as 2 bytes stream.WriteByte((byte)0x07); stream.WriteByte((byte)b); } i++; } break; case 0: { //RLE - 01 stream.WriteByte(0x01); stream.WriteByte((byte)(max - 1)); stream.WriteByte(b); i += max; } break; case 1: { //Alternating RLE - 02 stream.WriteByte(0x02); stream.WriteByte((byte)(max / 2 - 1)); stream.WriteByte(b); stream.WriteByte(bytes[i + 1]); i += max; } break; case 2: { //from previous column (same plane) - 00 stream.WriteByte(0x00); stream.WriteByte((byte)(max - 1)); i += max; } break; case 3: { //from plane 0 without mask - 03 stream.WriteByte(0x03); stream.WriteByte((byte)(max - 1)); i += max; } break; case 6: { //from plane 0 with mask - 06 03 stream.WriteByte(0x06); stream.WriteByte(0x03); stream.WriteByte((byte)(max - 1)); i += max; } break; case 4: { //from plane 1 without mask - 04 stream.WriteByte(0x04); stream.WriteByte((byte)(max - 1)); i += max; } break; case 7: { //from plane 1 with mask - 06 04 stream.WriteByte(0x06); stream.WriteByte(0x04); stream.WriteByte((byte)(max - 1)); i += max; } break; case 5: { //from plane 2 without mask - 05 stream.WriteByte(0x05); stream.WriteByte((byte)(max - 1)); i += max; } break; case 8: { //from plane 2 with mask - 06 05 stream.WriteByte(0x06); stream.WriteByte(0x05); stream.WriteByte((byte)(max - 1)); i += max; } break; } i--; } }