private static RGBQUAD ConvertYCrCbToRGB(byte y, byte cr, byte cb) { RGBQUAD rgbq = new RGBQUAD(); int c = y - 16; int d = cb - 128; int e = cr - 128; rgbq.R = Clip((298 * c + 409 * e + 128) >> 8); rgbq.G = Clip((298 * c - 100 * d - 208 * e + 128) >> 8); rgbq.B = Clip((298 * c + 516 * d + 128) >> 8); return(rgbq); }
public void CreateDIBitmapTest2() { BITMAPINFO bmi = new() { bmiHeader = new(4, 4, 8) { biXPelsPerMeter = 1, biYPelsPerMeter = 1, biClrUsed = 1, }, bmiColors = new RGBQUAD[1] }; BITMAPINFO bmiBroken = new() { bmiHeader = new(-2, -4, 42) { biPlanes = 55, biXPelsPerMeter = 1, biYPelsPerMeter = 1, biClrUsed = 1, }, bmiColors = new RGBQUAD[1] }; byte[] ajBits = new byte[10]; using var hdc = CreateCompatibleDC(); Assert.That(hdc, ResultIs.ValidHandle); var hbmp = CreateDIBitmap(hdc, bmi.bmiHeader, CBM.CBM_INIT, ajBits, bmi, DIBColorMode.DIB_PAL_COLORS); Assert.That(hbmp, ResultIs.ValidHandle); hbmp = CreateDIBitmap(hdc, bmi.bmiHeader, CBM.CBM_INIT, default, bmi, DIBColorMode.DIB_PAL_COLORS);
public unsafe override void Read(Stream stream, int resourceSize) { // BitmapInfoHeader mHeader.Read(stream); // Palette mColors = new RGBQUAD[ColorsInPalette]; byte[] colorBuffer = new byte[mColors.Length * sizeof(RGBQUAD)]; stream.Read(colorBuffer, 0, colorBuffer.Length); GCHandle handle = GCHandle.Alloc(mColors, GCHandleType.Pinned); Marshal.Copy(colorBuffer, 0, handle.AddrOfPinnedObject(), colorBuffer.Length); handle.Free(); // XOR Image int stride = (int)((mHeader.biWidth * mHeader.biBitCount + 31) & ~31) >> 3; mXOR = new byte[stride * (mHeader.biHeight / 2)]; stream.Read(mXOR, 0, mXOR.Length); // AND Image stride = (int)((mHeader.biWidth * 1 + 31) & ~31) >> 3; mAND = new byte[stride * (mHeader.biHeight / 2)]; stream.Read(mAND, 0, mAND.Length); }
private static int InitPalette(RGBQUAD[] targetPalette, int bpp, ColorPalette originalPalette, Color[] desiredPalette, out int transparentIndex) { int maxColors = 1 << bpp; // using desired palette Color[] sourcePalette = desiredPalette; // or, using original palette if it has fewer or the same amount of colors as requested if (sourcePalette == null && originalPalette != null && originalPalette.Entries.Length > 0 && originalPalette.Entries.Length <= maxColors) { sourcePalette = originalPalette.Entries; } // or, using default system palette if (sourcePalette == null) { using (Bitmap bmpReference = new Bitmap(1, 1, GetPixelFormat(bpp))) { sourcePalette = bmpReference.Palette.Entries; } } // it is ignored if source has too few colors (rest of the entries will be black) transparentIndex = -1; bool hasBlack = false; int colorCount = Math.Min(maxColors, sourcePalette.Length); for (int i = 0; i < colorCount; i++) { targetPalette[i] = new RGBQUAD(sourcePalette[i]); if (transparentIndex == -1 && sourcePalette[i].A == 0) { transparentIndex = i; } if (!hasBlack && (sourcePalette[i].ToArgb() & 0xFFFFFF) == 0) { hasBlack = true; } } // if transparent index is 0, relocating it and setting transparent index to 1 if (transparentIndex == 0) { targetPalette[0] = targetPalette[1]; transparentIndex = 1; } // otherwise, setting the color of transparent index the same as the previous color, so it will not be used during the conversion else if (transparentIndex != -1) { targetPalette[transparentIndex] = targetPalette[transparentIndex - 1]; } // if black color is not found in palette, counting 1 extra colors because it can be used in conversion if (colorCount < maxColors && !hasBlack) { colorCount++; } return(colorCount); }
public static unsafe RGBQUAD[] TransformColorsTo_sRGB(SafeProfileHandle source, RGBQUAD[] color, mscmsIntent dwIntent) { var colorSize = Environment.Is64BitProcess ? 16 : 8; var size = colorSize * color.Length; // https://docs.microsoft.com/en-us/windows/win32/api/icm/nf-icm-translatecolors // https://docs.microsoft.com/en-us/windows/win32/api/icm/ns-icm-color IntPtr paInputColors = Marshal.AllocHGlobal(size); IntPtr paOutputColors = Marshal.AllocHGlobal(size); const double cmax = 255d; const double nmax = 0xFFFF; const ushort nmask = 0xFFFF; try { var inputPtr = (byte *)paInputColors; foreach (var c in color) { var nclr = (long)(c.rgbRed / cmax * nmax) | ((long)(c.rgbGreen / cmax * nmax) << 16) | ((long)(c.rgbBlue / cmax * nmax) << 32); *((long *)inputPtr) = nclr; inputPtr += colorSize; } using (var dest = OpenProfile_sRGB()) using (var transform = CreateTransform(source, dest, dwIntent)) { var success = TranslateColors(transform, paInputColors, (uint)color.Length, COLOR_TYPE.COLOR_3_CHANNEL, paOutputColors, COLOR_TYPE.COLOR_3_CHANNEL); if (!success) { throw new Win32Exception(); } var outputPtr = (byte *)paOutputColors; var output = new RGBQUAD[color.Length]; for (int i = 0; i < color.Length; i++) { long nclr = *((long *)outputPtr); output[i] = new RGBQUAD { rgbRed = (byte)((nclr & nmask) / nmax * cmax), rgbGreen = (byte)(((nclr >> 16) & nmask) / nmax * cmax), rgbBlue = (byte)(((nclr >> 32) & nmask) / nmax * cmax), }; outputPtr += colorSize; } return(output); } } finally { Marshal.FreeHGlobal(paInputColors); Marshal.FreeHGlobal(paOutputColors); } }
public static RGBQUAD[] GetL8Palette() { RGBQUAD[] quad = new RGBQUAD[256]; for (int i = 0; i < 256; i++) { quad[i] = Color.FromArgb(i, 255, 255, 255); } return(quad); }
public void PopulateWithData(byte[] data, int StartAddress) { bmiHeader = new BITMAPINFOHEADER(); bmiHeader.PopulateWithData(data, StartAddress + 0); bmiColors = new RGBQUAD(); bmiColors.PopulateWithData(data, StartAddress + 40); }
public void ApplyFilters(List <Schema.SkinFile.Attachment.Filter> filters) { if (dib.IsNull) { return; } foreach (Schema.SkinFile.Attachment.Filter filter in filters) { switch (filter.name) { case "invert": { /// /// TODO: Variable invertion using amount property /// FreeImage.AdjustColors(dib, 0, 0, 0, true); break; } case "colorOverlay": { try { /// /// TODO: Variable overlay using amount property /// RGBQUAD overlayColor = new RGBQUAD(), oldColor; overlayColor.uintValue = Convert.ToUInt32(filter.color, 16); //Console.WriteLine((double)filter.amount / 100); for (uint y = 0; y < FreeImage.GetHeight(dib); y++) { for (uint x = 0; x < FreeImage.GetWidth(dib); x++) { FreeImage.GetPixelColor(dib, x, y, out oldColor); overlayColor.rgbReserved = oldColor.rgbReserved; FreeImage.SetPixelColor(dib, x, y, ref overlayColor); } } } catch { } break; } } } }
// Таблица цветов из WallControll-a private static RGBQUAD[] GetColourMask(PixelFormat format) { RGBQUAD[] array = new RGBQUAD[3]; if (format == PixelFormat.Format16bppRgb555) { array[0].rgbBlue = 0; array[0].rgbGreen = 124; array[0].rgbRed = 0; array[1].rgbBlue = 224; array[1].rgbGreen = 3; array[1].rgbRed = 0; array[2].rgbBlue = 31; array[2].rgbGreen = 0; array[2].rgbRed = 0; } else if (format == PixelFormat.Format16bppRgb565) { array[0].rgbBlue = 0; array[0].rgbGreen = 248; array[0].rgbRed = 0; array[1].rgbBlue = 224; array[1].rgbGreen = 7; array[1].rgbRed = 0; array[2].rgbBlue = 31; array[2].rgbGreen = 0; array[2].rgbRed = 0; } else if (format == PixelFormat.Format32bppRgb) { array[0].rgbBlue = 0; array[0].rgbGreen = 0; array[0].rgbRed = byte.MaxValue; array[1].rgbBlue = 0; array[1].rgbGreen = byte.MaxValue; array[1].rgbRed = 0; array[2].rgbBlue = byte.MaxValue; array[2].rgbGreen = 0; array[2].rgbRed = 0; } else { throw new Exception("Invalid Pixel Format"); } return(array); }
public void RGBQUAD() { RGBQUAD rgbq = new RGBQUAD(); Assert.AreEqual(0, rgbq.rgbBlue); Assert.AreEqual(0, rgbq.rgbGreen); Assert.AreEqual(0, rgbq.rgbRed); Assert.AreEqual(0, rgbq.rgbReserved); rgbq = new RGBQUAD(Color.Chartreuse); Assert.That(EqualColors(Color.Chartreuse, rgbq.Color)); rgbq = new RGBQUAD(Color.FromArgb(133, 83, 95, 173)); Assert.AreEqual(173, rgbq.rgbBlue); Assert.AreEqual(95, rgbq.rgbGreen); Assert.AreEqual(83, rgbq.rgbRed); Assert.AreEqual(133, rgbq.rgbReserved); rgbq.Color = Color.Crimson; Assert.That(EqualColors(Color.Crimson, rgbq.Color)); rgbq.Color = Color.MidnightBlue; Assert.That(EqualColors(Color.MidnightBlue, rgbq.Color)); rgbq.Color = Color.White; Assert.AreEqual(255, rgbq.rgbBlue); Assert.AreEqual(255, rgbq.rgbGreen); Assert.AreEqual(255, rgbq.rgbRed); Assert.AreEqual(255, rgbq.rgbReserved); rgbq.Color = Color.Black; Assert.AreEqual(0, rgbq.rgbBlue); Assert.AreEqual(0, rgbq.rgbGreen); Assert.AreEqual(0, rgbq.rgbRed); Assert.AreEqual(255, rgbq.rgbReserved); rgbq = Color.DarkGoldenrod; Color color = rgbq; Assert.That(EqualColors(Color.DarkGoldenrod, color)); }
public unsafe override void Read(Stream stream, int resourceSize) { // BitmapInfoHeader mHeader.Read(stream); // Palette mColors = new RGBQUAD[ColorsInPalette]; byte[] colorBuffer = new byte[mColors.Length * sizeof(RGBQUAD)]; stream.Read(colorBuffer, 0, colorBuffer.Length); GCHandle handle = GCHandle.Alloc(mColors, GCHandleType.Pinned); Marshal.Copy(colorBuffer, 0, handle.AddrOfPinnedObject(), colorBuffer.Length); handle.Free(); // XOR Image int stride = (int) ((mHeader.biWidth * mHeader.biBitCount + 31) & ~31) >> 3; mXOR = new byte[stride * (mHeader.biHeight / 2)]; stream.Read(mXOR, 0, mXOR.Length); // AND Image stride = (int) ((mHeader.biWidth * 1 + 31) & ~31) >> 3; mAND = new byte[stride * (mHeader.biHeight / 2)]; stream.Read(mAND, 0, mAND.Length); }
/// <summary> /// Builds an FIBitmap from the stream and job.Settings /// </summary> /// <param name="original"></param> /// <param name="supportsTransparency"></param> /// <param name="mayUnloadOriginal"></param> /// <param name="job"></param> /// <returns></returns> protected FIBITMAP buildFiBitmap(ref FIBITMAP original, ImageJob job, bool supportsTransparency, bool mayUnloadOriginal) { ResizeSettings settings = job.Settings; if (original.IsNull) { return(FIBITMAP.Zero); } FIBITMAP final = FIBITMAP.Zero; //Find the image size Size orig = new Size((int)FreeImage.GetWidth(original), (int)FreeImage.GetHeight(original)); //Calculate the new size of the image and the canvas. ImageState state = new ImageState(settings, orig, true); state.Job = job; c.CurrentImageBuilder.Process(state); RectangleF imageDest = PolygonMath.GetBoundingBox(state.layout["image"]); if (imageDest.Width != orig.Width || imageDest.Height != orig.Height) { //Rescale bool temp; final = FreeImage.Rescale(original, (int)imageDest.Width, (int)imageDest.Height, FreeImageScalingPlugin.ParseResizeAlgorithm(settings["fi.scale"], FREE_IMAGE_FILTER.FILTER_BOX, out temp)); if (mayUnloadOriginal) { FreeImage.UnloadEx(ref original); } if (final.IsNull) { return(FIBITMAP.Zero); } } else { final = original; } RGBQUAD bgcolor = default(RGBQUAD); bgcolor.Color = settings.BackgroundColor; if (settings.BackgroundColor == Color.Transparent && !supportsTransparency) { bgcolor.Color = Color.White; } //If we need to leave padding, do so. BoxPadding outsideImage = new BoxPadding(imageDest.Left, imageDest.Top, state.destSize.Width - imageDest.Right, state.destSize.Height - imageDest.Bottom); if (outsideImage.All != 0) { var old = final; //Extend canvas final = FreeImage.EnlargeCanvas <RGBQUAD>(old, (int)outsideImage.Left, (int)outsideImage.Top, (int)outsideImage.Right, (int)outsideImage.Bottom, bgcolor.Color != Color.Transparent ? new Nullable <RGBQUAD>(bgcolor) : null, FREE_IMAGE_COLOR_OPTIONS.FICO_RGBA); if (old == original) { if (mayUnloadOriginal) { FreeImage.UnloadEx(ref original); old = original; } } else { FreeImage.UnloadEx(ref old); //'old' has the original value of 'final', which we allocated. } if (final.IsNull) { return(FIBITMAP.Zero); } } if (!final.IsNull) { job.ResultInfo["final.width"] = (int)FreeImage.GetWidth(final); job.ResultInfo["final.height"] = (int)FreeImage.GetHeight(final); } return(final); }
public void Write(System.Drawing.Image i, System.IO.Stream s) { if (!(i is Bitmap)) { throw new ArgumentException("FreeImageEncoder only works with bitmaps"); } FIBITMAP bit = FreeImage.CreateFromBitmap(i as Bitmap); if (bit.IsNull) { throw new ImageProcessingException("FreeImageEncoder failed to convert System.Drawing.Bitmap to FIBITMAP"); } if (Format == FREE_IMAGE_FORMAT.FIF_GIF || (Format == FREE_IMAGE_FORMAT.FIF_PNG && colors != -1)) { FreeImage.SetTransparent(bit, true); FIBITMAP old = bit; //TODO - ColorQuantizeEx returns null no matter what we do.. Is it because the image is 32-bit? bit = FreeImage.ColorQuantizeEx(bit, FREE_IMAGE_QUANTIZE.FIQ_NNQUANT, 256, 1, RGBQUAD.ToRGBQUAD(new Color[] { Color.Transparent })); if (bit.IsNull) { bit = old; } else if (bit != old) { FreeImage.UnloadEx(ref old); } } FreeImage.SaveToStream(ref bit, s, Format, EncodingOptions, true); }
public static void ReadHeader(byte *source, int sourceLength, out BITMAP_READ_DETAILS info, uint bcrFlags) { var ptr = source; if ((sourceLength) < 12) // min header size { throw new InvalidOperationException(ERR_HEOF); } bool hasFileHeader = StructUtil.ReadU16(ptr) == BFH_BM; var size_fh = Marshal.SizeOf <BITMAPFILEHEADER>(); int offset = 0; var fh = default(BITMAPFILEHEADER); if (hasFileHeader) { var fhsize = Marshal.SizeOf <BITMAPFILEHEADER>(); if (offset + fhsize > sourceLength) { throw new InvalidOperationException(ERR_HEOF); } fh = StructUtil.Deserialize <BITMAPFILEHEADER>(ptr); ptr += fhsize; offset += fhsize; } // we'll just unpack all the various header types we support into a standard BMPV5 header // this makes subsequent code easier to maintain as it only needs to refer to one place if ((sourceLength - offset) < 12) // min header size { throw new InvalidOperationException(ERR_HEOF); } var header_size = StructUtil.ReadU32(ptr); var bi = default(BITMAPV5HEADER); bool is_os21x_ = false; if (header_size == 12) { var bich = StructUtil.Deserialize <BITMAPCOREHEADER>(ptr); bi.bV5Size = bich.bcSize; bi.bV5Width = bich.bcWidth; bi.bV5Height = bich.bcHeight; bi.bV5Planes = bich.bcPlanes; bi.bV5BitCount = bich.bcBitCount; bi.bV5CSType = ColorSpaceType.LCS_sRGB; is_os21x_ = true; } else if (/*header_size == 14 || */ header_size == 16 || header_size == 42 || header_size == 46 || header_size == 64) { var biih = StructUtil.Deserialize <BITMAPINFOHEADER>(ptr); bi.bV5Size = biih.bV5Size; bi.bV5Width = biih.bV5Width; bi.bV5Height = biih.bV5Height; bi.bV5Planes = biih.bV5Planes; bi.bV5BitCount = biih.bV5BitCount; if (header_size > 16) { bi.bV5Compression = biih.bV5Compression; bi.bV5SizeImage = biih.bV5SizeImage; bi.bV5XPelsPerMeter = biih.bV5XPelsPerMeter; bi.bV5YPelsPerMeter = biih.bV5YPelsPerMeter; bi.bV5ClrUsed = biih.bV5ClrUsed; bi.bV5ClrImportant = biih.bV5ClrImportant; } // https://www.fileformat.info/mirror/egff/ch09_05.htm (G31D) if (bi.bV5Compression == (BitmapCompressionMode)3 && bi.bV5BitCount == 1) { bi.bV5Compression = BitmapCompressionMode.OS2_HUFFMAN1D; } else if (bi.bV5Compression == (BitmapCompressionMode)4 && bi.bV5BitCount == 24) { bi.bV5Compression = BitmapCompressionMode.OS2_RLE24; } bi.bV5CSType = ColorSpaceType.LCS_sRGB; } else if (header_size == 40) { var biih = StructUtil.Deserialize <BITMAPINFOHEADER>(ptr); bi.bV5Size = biih.bV5Size; bi.bV5Width = biih.bV5Width; bi.bV5Height = biih.bV5Height; bi.bV5Planes = biih.bV5Planes; bi.bV5BitCount = biih.bV5BitCount; bi.bV5Compression = biih.bV5Compression; bi.bV5SizeImage = biih.bV5SizeImage; bi.bV5XPelsPerMeter = biih.bV5XPelsPerMeter; bi.bV5YPelsPerMeter = biih.bV5YPelsPerMeter; bi.bV5ClrUsed = biih.bV5ClrUsed; bi.bV5ClrImportant = biih.bV5ClrImportant; bi.bV5CSType = ColorSpaceType.LCS_sRGB; } else if (header_size == 52 || header_size == 56) { var biih = StructUtil.Deserialize <BITMAPV3INFOHEADER>(ptr); bi.bV5Size = biih.bV5Size; bi.bV5Width = biih.bV5Width; bi.bV5Height = biih.bV5Height; bi.bV5Planes = biih.bV5Planes; bi.bV5BitCount = biih.bV5BitCount; bi.bV5Compression = biih.bV5Compression; bi.bV5SizeImage = biih.bV5SizeImage; bi.bV5XPelsPerMeter = biih.bV5XPelsPerMeter; bi.bV5YPelsPerMeter = biih.bV5YPelsPerMeter; bi.bV5ClrUsed = biih.bV5ClrUsed; bi.bV5ClrImportant = biih.bV5ClrImportant; bi.bV5RedMask = biih.bV5RedMask; bi.bV5GreenMask = biih.bV5GreenMask; bi.bV5BlueMask = biih.bV5BlueMask; if (header_size == 56) // 56b header adds alpha mask { bi.bV5AlphaMask = biih.bV5AlphaMask; } bi.bV5CSType = ColorSpaceType.LCS_sRGB; } else if (header_size == 108) { var biih = StructUtil.Deserialize <BITMAPV4HEADER>(ptr); bi.bV5Size = biih.bV5Size; bi.bV5Width = biih.bV5Width; bi.bV5Height = biih.bV5Height; bi.bV5Planes = biih.bV5Planes; bi.bV5BitCount = biih.bV5BitCount; bi.bV5Compression = biih.bV5Compression; bi.bV5SizeImage = biih.bV5SizeImage; bi.bV5XPelsPerMeter = biih.bV5XPelsPerMeter; bi.bV5YPelsPerMeter = biih.bV5YPelsPerMeter; bi.bV5ClrUsed = biih.bV5ClrUsed; bi.bV5ClrImportant = biih.bV5ClrImportant; bi.bV5RedMask = biih.bV5RedMask; bi.bV5GreenMask = biih.bV5GreenMask; bi.bV5BlueMask = biih.bV5BlueMask; bi.bV5AlphaMask = biih.bV5AlphaMask; bi.bV5CSType = biih.bV5CSType; bi.bV5Endpoints_1x = biih.bV5Endpoints_1x; bi.bV5Endpoints_1y = biih.bV5Endpoints_1y; bi.bV5Endpoints_1z = biih.bV5Endpoints_1z; bi.bV5Endpoints_2x = biih.bV5Endpoints_2x; bi.bV5Endpoints_2y = biih.bV5Endpoints_2y; bi.bV5Endpoints_2z = biih.bV5Endpoints_2z; bi.bV5Endpoints_3x = biih.bV5Endpoints_3x; bi.bV5Endpoints_3y = biih.bV5Endpoints_3y; bi.bV5Endpoints_3z = biih.bV5Endpoints_3z; bi.bV5GammaRed = biih.bV5GammaRed; bi.bV5GammaGreen = biih.bV5GammaGreen; bi.bV5GammaBlue = biih.bV5GammaBlue; } else if (header_size == 124) { bi = StructUtil.Deserialize <BITMAPV5HEADER>(ptr); } else { throw new NotSupportedException($"Bitmap header size '{header_size}' not known / supported."); } ptr += header_size; offset += (int)header_size; ushort nbits = bi.bV5BitCount; //if (bi.bV5Planes != 1) // throw new NotSupportedException($"Bitmap bV5Planes of '{bi.bV5Planes}' is not supported."); // we don't support linked profiles, custom windows profiles, etc - so default to sRGB instead of throwing... if (bi.bV5CSType != ColorSpaceType.LCS_CALIBRATED_RGB && bi.bV5CSType != ColorSpaceType.PROFILE_EMBEDDED) { bi.bV5CSType = ColorSpaceType.LCS_sRGB; } uint maskR = 0; uint maskG = 0; uint maskB = 0; uint maskA = 0; bool hasAlphaChannel = false; bool skipVerifyBppAndMasks = false; switch (bi.bV5Compression) { case BitmapCompressionMode.BI_BITFIELDS: var rgb = StructUtil.Deserialize <MASKTRIPLE>(ptr); maskR = rgb.rgbRed; maskG = rgb.rgbGreen; maskB = rgb.rgbBlue; offset += Marshal.SizeOf <MASKTRIPLE>(); break; case BitmapCompressionMode.BI_ALPHABITFIELDS: var rgba = StructUtil.Deserialize <MASKQUAD>(ptr); maskR = rgba.rgbRed; maskG = rgba.rgbGreen; maskB = rgba.rgbBlue; maskA = rgba.rgbAlpha; offset += Marshal.SizeOf <MASKQUAD>(); hasAlphaChannel = true; break; case BitmapCompressionMode.BI_RGB: switch (nbits) { case 32: // windows wrongly uses the 4th byte of BI_RGB 32bit dibs as alpha // but we need to do it too if we have any hope of reading alpha data maskB = 0xff; maskG = 0xff00; maskR = 0xff0000; maskA = 0xff000000; // fake transparency? break; case 24: maskB = 0xff; maskG = 0xff00; maskR = 0xff0000; break; case 16: maskB = 0x001f; maskG = 0x03e0; maskR = 0x7c00; // we can check for transparency in 16b RGB but it is slower and is very uncommon // maskA = 0x8000; // fake transparency? break; } break; case BitmapCompressionMode.BI_JPEG: case BitmapCompressionMode.BI_PNG: case BitmapCompressionMode.BI_RLE4: case BitmapCompressionMode.BI_RLE8: case BitmapCompressionMode.OS2_RLE24: if (bi.bV5Height < 0) { throw new NotSupportedException("Top-down bitmaps are not supported with RLE/JPEG/PNG compression."); } skipVerifyBppAndMasks = true; break; case BitmapCompressionMode.OS2_HUFFMAN1D: if (bi.bV5Height < 0) { throw new NotSupportedException("Top-down bitmaps are not supported with Huffman1D compression."); } if (bi.bV5BitCount != 1) { throw new NotSupportedException("Huffman1D compression is only supported with 1bpp bitmaps"); } skipVerifyBppAndMasks = true; break; default: throw new NotSupportedException($"Bitmap with bV5Compression of '{bi.bV5Compression.ToString()}' is not supported."); } // lets use the v3/v4/v5 masks if present instead of RGB // according to some readers (FIREFOX!) these masks are only valid if the compression mode is // BI_BITFIELDS, meaning they might write garbage here when the compression is RGB if (bi.bV5Size >= 52 && bi.bV5Compression == BitmapCompressionMode.BI_BITFIELDS) { if (bi.bV5RedMask != 0) { maskR = bi.bV5RedMask; } if (bi.bV5BlueMask != 0) { maskB = bi.bV5BlueMask; } if (bi.bV5GreenMask != 0) { maskG = bi.bV5GreenMask; } } // if an alpha mask has been provided in the header, lets use it. if (bi.bV5Size >= 56 && bi.bV5AlphaMask != 0) { maskA = bi.bV5AlphaMask; hasAlphaChannel = true; } // try to infer alpha if 32bpp & no alpha mask was set (ie, BI_BITFIELDS) // this will only be used if the PRESERVE_FAKE_ALPHA flag is set if (maskA == 0 && nbits == 32) { maskA = (maskB | maskG | maskR) ^ 0xFFFFFFFF; } bool smBit = nbits == 1 || nbits == 2 || nbits == 4 || nbits == 8; bool lgBit = nbits == 16 || nbits == 24 || nbits == 32; if (!skipVerifyBppAndMasks) { if (!lgBit && !smBit) { throw new NotSupportedException($"Bitmap with bits per pixel of '{nbits}' are not valid."); } if (lgBit && maskR == 0 && maskB == 0 && maskG == 0) { throw new NotSupportedException($"Bitmap (bbp {nbits}) color masks could not be determined, this usually indicates a malformed bitmap file."); } } // The number of entries in the palette is either 2n (where n is the number of bits per pixel) or a smaller number specified in the header // always allocate at least 256 entries so we can ignore bad data which seeks past the end of palette data. var pallength = nbits < 16 ? (1 << nbits) : 0; if (bi.bV5ClrUsed > 0) { pallength = (int)bi.bV5ClrUsed; } if (pallength > 256) // technically the max is 256..? some bitmaps have invalidly/absurdly large palettes { if (hasFileHeader) { // if we have a file header, we can correct our pixel data offset below, so the only // important thing is that we don't read too many colors. pallength = 256; } else { throw new NotSupportedException("Bitmap has an oversized/invalid color palette."); } } RGBQUAD[] palette = new RGBQUAD[pallength]; var clrSize = is_os21x_ ? Marshal.SizeOf <RGBTRIPLE>() : Marshal.SizeOf <RGBQUAD>(); for (int i = 0; i < palette.Length; i++) { if (is_os21x_) { var small = StructUtil.Deserialize <RGBTRIPLE>(ptr); palette[i] = new RGBQUAD { rgbBlue = small.rgbBlue, rgbGreen = small.rgbGreen, rgbRed = small.rgbRed }; } else { palette[i] = StructUtil.Deserialize <RGBQUAD>(ptr); } ptr += clrSize; } offset += pallength * clrSize; // For RGB DIBs, the image orientation is indicated by the biHeight member of the BITMAPINFOHEADER structure. // If biHeight is positive, the image is bottom-up. If biHeight is negative, the image is top-down. // DirectDraw uses top-down DIBs. In GDI, all DIBs are bottom-up. // Also, any DIB type that uses a FOURCC in the biCompression member, should express its biHeight as a positive number // no matter what its orientation is, since the FOURCC itself identifies a compression scheme whose image orientation // should be understood by any compatible filter. Common YUV formats such as UYVY, YV12, and YUY2 are top-down oriented. // It is invalid to store an image with these compression types in bottom-up orientation. // The sign of biHeight for such formats must always be set positive var width = bi.bV5Width; var height = bi.bV5Height; bool topDown = false; if (height < 0) { height = -height; topDown = true; } if (width < 0) { throw new NotSupportedException("Bitmap with negative width is not allowed"); } uint source_stride = StructUtil.CalcStride(nbits, width); uint dataOffset = hasFileHeader ? fh.bfOffBits : (uint)offset; uint dataSize = bi.bV5SizeImage > 0 ? bi.bV5SizeImage : (source_stride * (uint)height); if (dataOffset + dataSize > sourceLength) { throw new InvalidOperationException(ERR_HEOF); } var profileSize = bi.bV5ProfileSize; uint profileOffset = (hasFileHeader ? (uint)size_fh : 0) + bi.bV5ProfileData; if (profileOffset + profileSize > sourceLength) { throw new InvalidOperationException(ERR_HEOF); } var masks = new BITMASKS { maskRed = maskR, maskGreen = maskG, maskBlue = maskB, maskAlpha = maskA, }; var fmt = BitmapCorePixelFormat.Formats.SingleOrDefault(f => f.IsMatch(nbits, masks)); // currently we only support RLE -> Bgra32 if (bi.bV5Compression == BitmapCompressionMode.BI_RLE4 || bi.bV5Compression == BitmapCompressionMode.BI_RLE8 || bi.bV5Compression == BitmapCompressionMode.OS2_RLE24) { fmt = null; } double pixelPerMeterToDpi(int pels) { if (pels == 0) { return(96); } return(pels * 0.0254d); } mscms.SafeProfileHandle clrsource = null; mscms.mscmsIntent clrintent = mscms.mscmsIntent.INTENT_PERCEPTUAL; bool ignoreColorProfile = (bcrFlags & BC_READ_IGNORE_COLOR_PROFILE) > 0; if (!ignoreColorProfile) { try { if (bi.bV5CSType == ColorSpaceType.LCS_CALIBRATED_RGB) { clrsource = mscms.CreateProfileFromLogicalColorSpace(bi); } else if (bi.bV5CSType == ColorSpaceType.PROFILE_EMBEDDED) { clrsource = mscms.OpenProfile((source + profileOffset), profileSize); } switch (bi.bV5Intent) { case Bv5Intent.LCS_GM_BUSINESS: clrintent = mscms.mscmsIntent.INTENT_RELATIVE_COLORIMETRIC; break; case Bv5Intent.LCS_GM_GRAPHICS: clrintent = mscms.mscmsIntent.INTENT_SATURATION; break; case Bv5Intent.LCS_GM_ABS_COLORIMETRIC: clrintent = mscms.mscmsIntent.INTENT_ABSOLUTE_COLORIMETRIC; break; } if (clrsource != null && fmt != null && fmt.MscmsFormat.HasValue && fmt.IsIndexed) { // transform color table if indexed image palette = mscms.TransformColorsTo_sRGB(clrsource, palette, clrintent); } } catch { // ignore color profile errors } } info = new BITMAP_READ_DETAILS { dibHeader = bi, bbp = nbits, compression = bi.bV5Compression, dpiX = pixelPerMeterToDpi(bi.bV5XPelsPerMeter), dpiY = pixelPerMeterToDpi(bi.bV5YPelsPerMeter), cMasks = masks, cIndexed = smBit, cTrueAlpha = hasAlphaChannel, imgColorTable = palette, imgHeight = height, imgTopDown = topDown, imgWidth = width, imgDataOffset = dataOffset, imgDataSize = dataSize, imgStride = source_stride, imgSourceFmt = fmt, colorProfile = clrsource, colorProfileIntent = clrintent, }; }
/** Get a deep copy of the image palette. @param bitmap Pointer to a loaded image. @return Array or RGBQUAD values representing the image palette. */ public static unsafe RGBQUAD[] GetPaletteCopy(FIBITMAP dib) { RGBQUAD [] paletteCopy = new RGBQUAD[256]; // Only interested in indexed images. if (GetBPP(dib) <= 8) { UIntPtr palette = GetRawPalette(dib); byte * ptr = (byte *)(void*)palette; for (int q = 0; q < 256; q++) { paletteCopy[q] = new RGBQUAD(); paletteCopy[q].rgbBlue = (byte)*ptr; ptr += 1; paletteCopy[q].rgbGreen = (byte)*ptr; ptr += 1; paletteCopy[q].rgbRed = (byte)*ptr; ptr += 1; paletteCopy[q].rgbReserved = (byte)*ptr; ptr += 1; } } return paletteCopy; }
//------------------------------------------------------------------- // TransformImage_NV12 // // NV12 to RGB-32 //------------------------------------------------------------------- unsafe private static void TransformImage_NV12(IntPtr pDest, int lDestStride, IntPtr pSrc, int lSrcStride, int dwWidthInPixels, int dwHeightInPixels) { Byte *lpBitsY = (byte *)pSrc; Byte *lpBitsCb = lpBitsY + (dwHeightInPixels * lSrcStride); Byte *lpBitsCr = lpBitsCb + 1; Byte *lpLineY1; Byte *lpLineY2; Byte *lpLineCr; Byte *lpLineCb; Byte *lpDibLine1 = (Byte *)pDest; for (UInt32 y = 0; y < dwHeightInPixels; y += 2) { lpLineY1 = lpBitsY; lpLineY2 = lpBitsY + lSrcStride; lpLineCr = lpBitsCr; lpLineCb = lpBitsCb; Byte *lpDibLine2 = lpDibLine1 + lDestStride; for (UInt32 x = 0; x < dwWidthInPixels; x += 2) { byte y0 = lpLineY1[0]; byte y1 = lpLineY1[1]; byte y2 = lpLineY2[0]; byte y3 = lpLineY2[1]; byte cb = lpLineCb[0]; byte cr = lpLineCr[0]; RGBQUAD r = ConvertYCrCbToRGB(y0, cr, cb); lpDibLine1[0] = r.B; lpDibLine1[1] = r.G; lpDibLine1[2] = r.R; lpDibLine1[3] = 0; // Alpha r = ConvertYCrCbToRGB(y1, cr, cb); lpDibLine1[4] = r.B; lpDibLine1[5] = r.G; lpDibLine1[6] = r.R; lpDibLine1[7] = 0; // Alpha r = ConvertYCrCbToRGB(y2, cr, cb); lpDibLine2[0] = r.B; lpDibLine2[1] = r.G; lpDibLine2[2] = r.R; lpDibLine2[3] = 0; // Alpha r = ConvertYCrCbToRGB(y3, cr, cb); lpDibLine2[4] = r.B; lpDibLine2[5] = r.G; lpDibLine2[6] = r.R; lpDibLine2[7] = 0; // Alpha lpLineY1 += 2; lpLineY2 += 2; lpLineCr += 2; lpLineCb += 2; lpDibLine1 += 8; lpDibLine2 += 8; } pDest += (2 * lDestStride); lpBitsY += (2 * lSrcStride); lpBitsCr += lSrcStride; lpBitsCb += lSrcStride; } }
public static bool CompareRGBQUADToColor(RGBQUAD rgbQuad, Color color) { return(rgbQuad.rgbRed == color.R && rgbQuad.rgbGreen == color.G && rgbQuad.rgbBlue == color.B); }
private static Image ConvertPixelFormat(Image image, PixelFormat newPixelFormat, Color[] palette) { int bpp = Image.GetPixelFormatSize(newPixelFormat); if (newPixelFormat == PixelFormat.Format16bppArgb1555 || newPixelFormat == PixelFormat.Format16bppGrayScale) { throw new NotSupportedException("This pixel format is not supported by GDI+"); } Bitmap result; // non-indexed target image (transparency preserved automatically) if (bpp > 8) { result = new Bitmap(image.Width, image.Height, newPixelFormat); using (Graphics g = Graphics.FromImage(result)) { g.DrawImage(image, 0, 0, image.Width, image.Height); } return(result); } int transparentIndex; Bitmap bmp; // indexed colors: using GDI+ natively RGBQUAD[] targetPalette = new RGBQUAD[256]; int colorCount = InitPalette(targetPalette, bpp, (image is Bitmap) ? image.Palette : null, palette, out transparentIndex); BITMAPINFO bmi = new BITMAPINFO(); bmi.icHeader.biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER)); bmi.icHeader.biWidth = image.Width; bmi.icHeader.biHeight = image.Height; bmi.icHeader.biPlanes = 1; bmi.icHeader.biBitCount = (ushort)bpp; bmi.icHeader.biCompression = BI_RGB; bmi.icHeader.biSizeImage = (uint)(((image.Width + 7) & 0xFFFFFFF8) * image.Height / (8 / bpp)); bmi.icHeader.biXPelsPerMeter = 0; bmi.icHeader.biYPelsPerMeter = 0; bmi.icHeader.biClrUsed = (uint)colorCount; bmi.icHeader.biClrImportant = (uint)colorCount; bmi.icColors = targetPalette; bmp = (image as Bitmap) ?? new Bitmap(image); // Creating the indexed bitmap IntPtr bits; IntPtr hbmResult = CreateDIBSection(IntPtr.Zero, ref bmi, DIB_RGB_COLORS, out bits, IntPtr.Zero, 0); // Obtaining screen DC IntPtr dcScreen = GetDC(IntPtr.Zero); // DC for the original hbitmap IntPtr hbmSource = bmp.GetHbitmap(); IntPtr dcSource = CreateCompatibleDC(dcScreen); SelectObject(dcSource, hbmSource); // DC for the indexed hbitmap IntPtr dcTarget = CreateCompatibleDC(dcScreen); SelectObject(dcTarget, hbmResult); // Copy content BitBlt(dcTarget, 0, 0, image.Width, image.Height, dcSource, 0, 0, 0x00CC0020 /*TernaryRasterOperations.SRCCOPY*/); // obtaining result result = Image.FromHbitmap(hbmResult); result.SetResolution(image.HorizontalResolution, image.VerticalResolution); // cleanup DeleteDC(dcSource); DeleteDC(dcTarget); ReleaseDC(IntPtr.Zero, dcScreen); DeleteObject(hbmSource); DeleteObject(hbmResult); ColorPalette resultPalette = result.Palette; bool resetPalette = false; // restoring transparency if (transparentIndex >= 0) { // updating palette if transparent color is not actually transparent if (resultPalette.Entries[transparentIndex].A != 0) { resultPalette.Entries[transparentIndex] = Color.Transparent; resetPalette = true; } ToIndexedTransparentByArgb(result, bmp, transparentIndex); } if (resetPalette) { result.Palette = resultPalette; } if (!ReferenceEquals(bmp, image)) { bmp.Dispose(); } return(result); }
private static FIBITMAP NewFiBitMap(PixImage <byte> pi) { FreeImageCheck(pi.Volume.Info); var sx = pi.Size.X; var sy = pi.Size.Y; var bpp = pi.ChannelCount == 1 && pi.Format == Col.Format.BW ? 1 : pi.ChannelCount * 8; var dib = FreeImage.Allocate(sx, sy, bpp); var delta = (int)FreeImage.GetPitch(dib); var data = pi.Volume.Data; long i = pi.Volume.FirstIndex; long j = pi.Volume.JY; var bits = FreeImage.GetBits(dib) + sy * delta; switch (bpp) { case 1: { var palette = FreeImage.GetPaletteEx(dib); if (palette != null) // should alway be != null { palette[0] = new RGBQUAD { rgbRed = 0, rgbGreen = 0, rgbBlue = 0 }; palette[1] = new RGBQUAD { rgbRed = 255, rgbGreen = 255, rgbBlue = 255 }; } for (var y = 0; y < sy; y++) { bits = bits - delta; byte bit = 0x80; int bi = 0; unsafe { byte *pixel = (byte *)bits; for (var x = 0; x < sx; x++) { if ((data[i++] & 0x80) != 0) { pixel[bi] |= bit; } bit >>= 1; if (bit == 0) { bit = 0x80; bi++; } } } i += j; } } break; case 8: { for (var y = 0; y < sy; y++) { bits = bits - delta; unsafe { byte *pixel = (byte *)bits; for (var x = 0; x < sx; x++) { pixel[x] = data[i++]; } } i += j; } } break; case 24: { for (var y = 0; y < sy; y++) { bits = bits - delta; unsafe { Byte *pixel = (Byte *)bits; for (var x = 0; x < sx; x++) { pixel[FreeImage.FI_RGBA_BLUE] = data[i++]; pixel[FreeImage.FI_RGBA_GREEN] = data[i++]; pixel[FreeImage.FI_RGBA_RED] = data[i++]; pixel += 3; } } i += j; } } break; case 32: { for (var y = 0; y < sy; y++) { bits = bits - delta; unsafe { Byte *pixel = (Byte *)bits; for (var x = 0; x < sx; x++) { pixel[FreeImage.FI_RGBA_BLUE] = data[i++]; pixel[FreeImage.FI_RGBA_GREEN] = data[i++]; pixel[FreeImage.FI_RGBA_RED] = data[i++]; pixel[FreeImage.FI_RGBA_ALPHA] = data[i++]; pixel += 4; } } i += j; } } break; } return(dib); }
public void Transform(Schema.SkinFile.Attachment.Transform trnsfrm) { if (dib.IsNull) { return; } if (FreeImage.GetWidth(dib) <= 1 || FreeImage.GetHeight(dib) <= 1) { return; } FREE_IMAGE_FILTER filter = FREE_IMAGE_FILTER.FILTER_BSPLINE; if (trnsfrm.scaleFilter != null) { switch (trnsfrm.scaleFilter.ToUpper()) { case "BOX": filter = FREE_IMAGE_FILTER.FILTER_BOX; break; case "BICUBIC": filter = FREE_IMAGE_FILTER.FILTER_BICUBIC; break; case "BILINEAR": filter = FREE_IMAGE_FILTER.FILTER_BILINEAR; break; case "BSPLINE": filter = FREE_IMAGE_FILTER.FILTER_BSPLINE; break; case "CATMULLROM": filter = FREE_IMAGE_FILTER.FILTER_CATMULLROM; break; case "LANCZOS3": filter = FREE_IMAGE_FILTER.FILTER_LANCZOS3; break; } } RectangleF originalDimensions, rotationDimensions; GraphicsUnit pageUnit = GraphicsUnit.Pixel; dib = FreeImage.Rescale(dib, (int)(FreeImage.GetWidth(dib) * trnsfrm.scaleX), (int)(FreeImage.GetHeight(dib) * trnsfrm.scaleY), filter); originalDimensions = FreeImage.GetBitmap(dib).GetBounds(ref pageUnit); RGBQUAD bgColor = new RGBQUAD(); bgColor.rgbRed = 0x00; bgColor.rgbGreen = 0x00; bgColor.rgbBlue = 0x00; bgColor.rgbReserved = 0x00; // TODO: вычесть из положения разницу между оригинальными размерами и размерами после поворота (по крайней мере сверху) //int size = (int)(trnsfrm.x > 0 ? trnsfrm.x : 0) + (int)(trnsfrm.y > 0 ? trnsfrm.y : 0); //trnsfrm.angle = -45; /* * double cos = Math.Cos(-trnsfrm.angle * Math.PI / 180), sin = Math.Sin(-trnsfrm.angle * Math.PI / 180); * Point[] points = new Point[4] { * new Point((int)(originalDimensions.Width / 2), (int)(originalDimensions.Height / 2)), // top left //(int)(originalDimensions.Width / 2 * cos - originalDimensions.Height / 2 * sin), (int)(originalDimensions.Width / 2 * sin + originalDimensions.Height / 2 * cos)), * new Point((int)(originalDimensions.Width / 2), (int)(-originalDimensions.Height / 2)), // top right * new Point((int)(-originalDimensions.Width / 2), (int)(originalDimensions.Height / 2)), // bottom left * new Point((int)(-originalDimensions.Width / 2), (int)(-originalDimensions.Height / 2)) // bottom right * }; * for (int i = 0; i < points.Length; i++) * { * points[i].X = (int)(points[i].X * cos - points[i].Y * sin); * points[i].Y = (int)(points[i].X * sin + points[i].Y * cos); * } * int maxRight = points[0].X, maxBottom = points[0].Y; * for (int i = 0; i < points.Length; i++) * { * if (points[i].X > maxRight) maxRight = points[i].X; * if (points[i].Y > maxBottom) maxBottom = points[i].Y; * } * * Console.WriteLine(points[0]); * Console.WriteLine(points[1]); * Console.WriteLine(points[2]); * Console.WriteLine(points[3]); * * Console.WriteLine(maxRight); * Console.WriteLine(maxBottom); * int rightOffset = (int)(maxRight - originalDimensions.Width / 2), bottomOffset = (int)(maxBottom - originalDimensions.Height / 2); * Console.WriteLine(rightOffset); * Console.WriteLine(bottomOffset); */ /* * Console.WriteLine(originalDimensions); * Console.WriteLine(originalDimensions.Width / 2 * Math.Cos(trnsfrm.angle * Math.PI / 180) - originalDimensions.Height / 2 * Math.Sin(trnsfrm.angle * Math.PI / 180)); * Console.WriteLine(originalDimensions.Width / 2 * Math.Sin(trnsfrm.angle * Math.PI / 180) + originalDimensions.Height / 2 * Math.Cos(trnsfrm.angle * Math.PI / 180)); */ dib = FreeImage.Rotate <RGBQUAD>(dib, -trnsfrm.angle, bgColor); rotationDimensions = FreeImage.GetBitmap(dib).GetBounds(ref pageUnit); dib = FreeImage.EnlargeCanvas <RGBQUAD>(dib, 0, 0, (int)(trnsfrm.x > 0 ? trnsfrm.x : 0), // + rightOffset,//(int)(originalDimensions.Width / 2 * Math.Cos(trnsfrm.angle * Math.PI / 180) - originalDimensions.Height / 2 * Math.Sin(trnsfrm.angle * Math.PI / 180) - originalDimensions.Width / 2) + 2, (int)(trnsfrm.y > 0 ? trnsfrm.y : 0), // + bottomOffset,//(int)(originalDimensions.Width / 2 * Math.Sin(trnsfrm.angle * Math.PI / 180) + originalDimensions.Height / 2 * Math.Cos(trnsfrm.angle * Math.PI / 180)), bgColor, FREE_IMAGE_COLOR_OPTIONS.FICO_RGBA ); //dib = FreeImage.RotateEx(dib, 0, trnsfrm.x, trnsfrm.y, 0, 0, true); //dib = FreeImage.Rotate<RGBQUAD>(dib, trnsfrm.angle, bgColor); //dib = FreeImage.RotateEx(dib, 0, trnsfrm.x, trnsfrm.y, originalDimensions.Width / 2, originalDimensions.Height / 2, true); dib = FreeImage.RotateEx(dib, 0, trnsfrm.x, trnsfrm.y, 0, 0, true); dib = FreeImage.EnlargeCanvas <RGBQUAD>(dib, (int)(rotationDimensions.Width - originalDimensions.Width) / -2, (int)(rotationDimensions.Height - originalDimensions.Height) / -2, 0, 0, bgColor, FREE_IMAGE_COLOR_OPTIONS.FICO_RGBA ); //dib = FreeImage.RotateEx(dib, 0, trnsfrm.x - (rotationDimensions.Width - originalDimensions.Width) / 2, trnsfrm.y - (rotationDimensions.Height - originalDimensions.Height) / 2, 0, 0, true); //dib = FreeImage.RotateEx(dib, 0, trnsfrm.x, trnsfrm.y, 0, 0, true); }
public static BitmapData LoadBmpIconFrame(Stream stream, int offset, int length) { stream.Position = offset; using (var reader = new BinaryReader(stream, Encoding.Default, true)) { var info = new BITMAPINFOHEADER { biSize = reader.ReadInt32(), biWidth = reader.ReadInt32(), biHeight = reader.ReadInt32(), biPlanes = reader.ReadInt16(), biBitCount = reader.ReadInt16(), biCompression = (BitmapCompression)reader.ReadInt32(), biSizeImage = reader.ReadInt32(), biXPelsPerMeter = reader.ReadInt32(), biYPelsPerMeter = reader.ReadInt32(), biClrUsed = reader.ReadInt32(), biClrImportant = reader.ReadInt32(), }; int height = Math.Abs(info.biHeight) / 2; BitmapData bitmapData = null; if (info.biCompression == BitmapCompression.BI_BITFIELDS) { bitmapData = LoadBmpData_BITFIELDS(reader, info, height); } else { int colorTableSize = (info.biBitCount <= 8 && info.biClrUsed == 0) ? (int)Math.Pow(2, info.biBitCount) : info.biClrUsed; Color[] colorTable = null; if (colorTableSize > 0) { colorTable = new Color[colorTableSize]; for (int i = 0; i < colorTableSize; i++) { var rgb = new RGBQUAD { rgbBlue = reader.ReadByte(), rgbGreen = reader.ReadByte(), rgbRed = reader.ReadByte(), rgbReserved = reader.ReadByte() }; colorTable[i] = Color.FromArgb(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); } } if (info.biCompression == BitmapCompression.BI_RLE4) { bitmapData = LoadBmpData_RLE4(reader, info, height, colorTable); } else if (info.biCompression == BitmapCompression.BI_RLE8) { bitmapData = LoadBmpData_RLE8(reader, info, height, colorTable); } else if (colorTable != null) { bitmapData = LoadBitmapData(stream, info, height, colorTable); } else { bitmapData = LoadBitmapData(stream, info, height); } } // load AND mask var andMask = new List <bool[]>(); int stride = (info.biWidth + 31) / 32 * 4; for (int y = 0; y < height; y++) { byte[] line = new byte[stride]; stream.Read(line, 0, line.Length); var lineMask = new List <bool>(); foreach (var lb in line) { lineMask.Add((lb & 0b_1000_0000) == 0); lineMask.Add((lb & 0b_0100_0000) == 0); lineMask.Add((lb & 0b_0010_0000) == 0); lineMask.Add((lb & 0b_0001_0000) == 0); lineMask.Add((lb & 0b_0000_1000) == 0); lineMask.Add((lb & 0b_0000_0100) == 0); lineMask.Add((lb & 0b_0000_0010) == 0); lineMask.Add((lb & 0b_0000_0001) == 0); } andMask.Add(lineMask.ToArray()); } andMask.Reverse(); if (info.biBitCount < 32) { bitmapData.AndMaskToAlpha(andMask); } return(bitmapData); } }
public unsafe void Properties() { string filename = iManager.GetBitmapPath(ImageType.Even, ImageColorType.Type_32); Assert.IsNotNull(filename); Assert.IsTrue(File.Exists(filename)); FreeImageBitmap fib = new FreeImageBitmap(filename); Assert.IsFalse(fib.HasPalette); try { Palette palette = fib.Palette; Assert.Fail(); } catch { } Assert.IsFalse(fib.HasBackgroundColor); fib.BackgroundColor = Color.LightSeaGreen; Assert.IsTrue(fib.HasBackgroundColor); Assert.That( Color.LightSeaGreen.B == fib.BackgroundColor.Value.B && Color.LightSeaGreen.G == fib.BackgroundColor.Value.G && Color.LightSeaGreen.R == fib.BackgroundColor.Value.R); fib.BackgroundColor = null; Assert.IsFalse(fib.HasBackgroundColor); fib.Dispose(); fib = new FreeImageBitmap(100, 100, PixelFormat.Format1bppIndexed); ImageFlags flags = (ImageFlags)fib.Flags; Assert.That((flags & ImageFlags.ColorSpaceRgb) == ImageFlags.ColorSpaceRgb); Assert.That((flags & ImageFlags.HasAlpha) != ImageFlags.HasAlpha); Assert.That((flags & ImageFlags.HasRealDpi) != ImageFlags.HasRealDpi); Assert.That((flags & ImageFlags.HasTranslucent) != ImageFlags.HasTranslucent); fib.Dispose(); dib = FreeImage.Allocate(100, 100, 32, 0xFF0000, 0xFF00, 0xFF); FIICCPROFILE *prof = (FIICCPROFILE *)FreeImage.CreateICCProfile(dib, new byte[] { 0, 1, 2, 3 }, 4); fib = new FreeImageBitmap(dib); Scanline <RGBQUAD> sc = (Scanline <RGBQUAD>)fib.GetScanline(0); RGBQUAD rgbq = sc[0]; rgbq.rgbReserved = 127; sc[0] = rgbq; flags = (ImageFlags)fib.Flags; Assert.That((flags & ImageFlags.HasAlpha) == ImageFlags.HasAlpha); Assert.That((flags & ImageFlags.HasRealDpi) != ImageFlags.HasRealDpi); Assert.That((flags & ImageFlags.HasTranslucent) == ImageFlags.HasTranslucent); fib.Dispose(); fib = null; GC.Collect(2, GCCollectionMode.Forced); GC.WaitForPendingFinalizers(); fib = new FreeImageBitmap(iManager.GetBitmapPath(ImageType.Metadata, ImageColorType.Type_01_Dither)); int[] propList = fib.PropertyIdList; Assert.IsNotNull(propList); Assert.Greater(propList.Length, 0); PropertyItem[] propItemList = fib.PropertyItems; Assert.IsNotNull(propItemList); Assert.Greater(propItemList.Length, 0); Assert.IsNotNull(fib.RawFormat); fib.Dispose(); fib = new FreeImageBitmap(iManager.GetBitmapPath(ImageType.Multipaged, ImageColorType.Type_01_Dither)); Assert.Greater(fib.FrameCount, 1); fib.Dispose(); }
public void MetadataTag() { FITAG tag; MetadataTag metaTag; Random rand = new Random(); dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither); Assert.IsFalse(dib.IsNull); Assert.That(FreeImage.GetMetadataCount(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib) > 0); FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib, out tag); Assert.IsFalse(tag.IsNull); Assert.IsFalse(mData.IsNull); // // Constructors // metaTag = new MetadataTag(tag, dib); Assert.That(metaTag.Model == FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN); metaTag = new MetadataTag(tag, FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN); Assert.That(metaTag.Model == FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN); // // Properties // metaTag.ID = ushort.MinValue; Assert.That(metaTag.ID == ushort.MinValue); metaTag.ID = ushort.MaxValue; Assert.That(metaTag.ID == ushort.MaxValue); metaTag.ID = ushort.MaxValue / 2; Assert.That(metaTag.ID == ushort.MaxValue / 2); metaTag.Description = ""; Assert.That(metaTag.Description == ""); metaTag.Description = "A"; Assert.That(metaTag.Description == "A"); metaTag.Description = "ABCDEFG"; Assert.That(metaTag.Description == "ABCDEFG"); metaTag.Key = ""; Assert.That(metaTag.Key == ""); metaTag.Key = "A"; Assert.That(metaTag.Key == "A"); metaTag.Key = "ABCDEFG"; Assert.That(metaTag.Key == "ABCDEFG"); // // SetValue // try { metaTag.SetValue(null, FREE_IMAGE_MDTYPE.FIDT_ASCII); Assert.Fail(); } catch { } // // FREE_IMAGE_MDTYPE.FIDT_ASCII // string testString = ""; Assert.IsTrue(metaTag.SetValue(testString, FREE_IMAGE_MDTYPE.FIDT_ASCII)); Assert.IsNotNull(metaTag.Value); Assert.That(((string)metaTag.Value).Length == 0); testString = "X"; Assert.IsTrue(metaTag.SetValue(testString, FREE_IMAGE_MDTYPE.FIDT_ASCII)); Assert.IsNotNull(metaTag.Value); Assert.That(((string)metaTag.Value).Length == testString.Length); Assert.That(((string)metaTag.Value) == testString); testString = "TEST-STRING"; Assert.IsTrue(metaTag.SetValue(testString, FREE_IMAGE_MDTYPE.FIDT_ASCII)); Assert.IsNotNull(metaTag.Value); Assert.That(((string)metaTag.Value).Length == testString.Length); Assert.That(((string)metaTag.Value) == testString); // // FREE_IMAGE_MDTYPE.FIDT_BYTE // byte testByte; byte[] testByteArray; Assert.IsTrue(metaTag.SetValue(byte.MinValue, FREE_IMAGE_MDTYPE.FIDT_BYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == 1); Assert.That(((byte[])metaTag.Value)[0] == byte.MinValue); Assert.IsTrue(metaTag.SetValue(byte.MaxValue, FREE_IMAGE_MDTYPE.FIDT_BYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == 1); Assert.That(((byte[])metaTag.Value)[0] == byte.MaxValue); for (int i = 0; i < 10; i++) { testByte = (byte)rand.Next(byte.MinValue, byte.MaxValue); testByteArray = new byte[rand.Next(0, 31)]; for (int j = 0; j < testByteArray.Length; j++) { testByteArray[j] = (byte)rand.Next(); } Assert.IsTrue(metaTag.SetValue(testByte, FREE_IMAGE_MDTYPE.FIDT_BYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 1); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_BYTE); Assert.That(((byte[])metaTag.Value)[0] == testByte); Assert.IsTrue(metaTag.SetValue(testByteArray, FREE_IMAGE_MDTYPE.FIDT_BYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == testByteArray.Length); Assert.That(metaTag.Count == testByteArray.Length); Assert.That(metaTag.Length == testByteArray.Length * 1); byte[] value = (byte[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testByteArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_DOUBLE // double testDouble; double[] testDoubleArray; Assert.IsTrue(metaTag.SetValue(double.MinValue, FREE_IMAGE_MDTYPE.FIDT_DOUBLE)); Assert.IsNotNull(metaTag.Value); Assert.That(((double[])metaTag.Value).Length == 1); Assert.That(((double[])metaTag.Value)[0] == double.MinValue); Assert.IsTrue(metaTag.SetValue(double.MaxValue, FREE_IMAGE_MDTYPE.FIDT_DOUBLE)); Assert.IsNotNull(metaTag.Value); Assert.That(((double[])metaTag.Value).Length == 1); Assert.That(((double[])metaTag.Value)[0] == double.MaxValue); for (int i = 0; i < 10; i++) { testDouble = (double)rand.NextDouble(); testDoubleArray = new double[rand.Next(0, 31)]; for (int j = 0; j < testDoubleArray.Length; j++) { testDoubleArray[j] = rand.NextDouble(); } Assert.IsTrue(metaTag.SetValue(testDouble, FREE_IMAGE_MDTYPE.FIDT_DOUBLE)); Assert.IsNotNull(metaTag.Value); Assert.That(((double[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 8); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_DOUBLE); Assert.That(((double[])metaTag.Value)[0] == testDouble); Assert.IsTrue(metaTag.SetValue(testDoubleArray, FREE_IMAGE_MDTYPE.FIDT_DOUBLE)); Assert.IsNotNull(metaTag.Value); Assert.That(((double[])metaTag.Value).Length == testDoubleArray.Length); Assert.That(metaTag.Count == testDoubleArray.Length); Assert.That(metaTag.Length == testDoubleArray.Length * 8); double[] value = (double[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testDoubleArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_FLOAT // float testfloat; float[] testFloatArray; Assert.IsTrue(metaTag.SetValue(float.MinValue, FREE_IMAGE_MDTYPE.FIDT_FLOAT)); Assert.IsNotNull(metaTag.Value); Assert.That(((float[])metaTag.Value).Length == 1); Assert.That(((float[])metaTag.Value)[0] == float.MinValue); Assert.IsTrue(metaTag.SetValue(float.MaxValue, FREE_IMAGE_MDTYPE.FIDT_FLOAT)); Assert.IsNotNull(metaTag.Value); Assert.That(((float[])metaTag.Value).Length == 1); Assert.That(((float[])metaTag.Value)[0] == float.MaxValue); for (int i = 0; i < 10; i++) { testfloat = (float)rand.NextDouble(); testFloatArray = new float[rand.Next(0, 31)]; for (int j = 0; j < testFloatArray.Length; j++) { testFloatArray[j] = (float)rand.NextDouble(); } Assert.IsTrue(metaTag.SetValue(testfloat, FREE_IMAGE_MDTYPE.FIDT_FLOAT)); Assert.IsNotNull(metaTag.Value); Assert.That(((float[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 4); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_FLOAT); Assert.That(((float[])metaTag.Value)[0] == testfloat); Assert.IsTrue(metaTag.SetValue(testFloatArray, FREE_IMAGE_MDTYPE.FIDT_FLOAT)); Assert.IsNotNull(metaTag.Value); Assert.That(((float[])metaTag.Value).Length == testFloatArray.Length); Assert.That(metaTag.Count == testFloatArray.Length); Assert.That(metaTag.Length == testFloatArray.Length * 4); float[] value = (float[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testFloatArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_IFD // uint testUint; uint[] testUintArray; Assert.IsTrue(metaTag.SetValue(uint.MinValue, FREE_IMAGE_MDTYPE.FIDT_IFD)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == 1); Assert.That(((uint[])metaTag.Value)[0] == uint.MinValue); Assert.IsTrue(metaTag.SetValue(uint.MaxValue, FREE_IMAGE_MDTYPE.FIDT_IFD)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == 1); Assert.That(((uint[])metaTag.Value)[0] == uint.MaxValue); for (int i = 0; i < 10; i++) { testUint = (uint)rand.NextDouble(); testUintArray = new uint[rand.Next(0, 31)]; for (int j = 0; j < testUintArray.Length; j++) { testUintArray[j] = (uint)rand.Next(); } Assert.IsTrue(metaTag.SetValue(testUint, FREE_IMAGE_MDTYPE.FIDT_IFD)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 4); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_IFD); Assert.That(((uint[])metaTag.Value)[0] == testUint); Assert.IsTrue(metaTag.SetValue(testUintArray, FREE_IMAGE_MDTYPE.FIDT_IFD)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == testUintArray.Length); Assert.That(metaTag.Count == testUintArray.Length); Assert.That(metaTag.Length == testUintArray.Length * 4); uint[] value = (uint[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testUintArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_LONG // Assert.IsTrue(metaTag.SetValue(uint.MinValue, FREE_IMAGE_MDTYPE.FIDT_LONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == 1); Assert.That(((uint[])metaTag.Value)[0] == uint.MinValue); Assert.IsTrue(metaTag.SetValue(uint.MaxValue, FREE_IMAGE_MDTYPE.FIDT_LONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == 1); Assert.That(((uint[])metaTag.Value)[0] == uint.MaxValue); for (int i = 0; i < 10; i++) { testUint = (uint)rand.NextDouble(); testUintArray = new uint[rand.Next(0, 31)]; for (int j = 0; j < testUintArray.Length; j++) { testUintArray[j] = (uint)rand.Next(); } Assert.IsTrue(metaTag.SetValue(testUint, FREE_IMAGE_MDTYPE.FIDT_LONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 4); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_LONG); Assert.That(((uint[])metaTag.Value)[0] == testUint); Assert.IsTrue(metaTag.SetValue(testUintArray, FREE_IMAGE_MDTYPE.FIDT_LONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((uint[])metaTag.Value).Length == testUintArray.Length); Assert.That(metaTag.Count == testUintArray.Length); Assert.That(metaTag.Length == testUintArray.Length * 4); uint[] value = (uint[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testUintArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_NOTYPE // try { metaTag.SetValue(new object(), FREE_IMAGE_MDTYPE.FIDT_NOTYPE); Assert.Fail(); } catch (NotSupportedException) { } // // FREE_IMAGE_MDTYPE.FIDT_PALETTE // RGBQUAD testRGBQUAD; RGBQUAD[] testRGBQUADArray; for (int i = 0; i < 10; i++) { testRGBQUAD = new RGBQUAD(Color.FromArgb(rand.Next())); testRGBQUADArray = new RGBQUAD[rand.Next(0, 31)]; for (int j = 0; j < testRGBQUADArray.Length; j++) { testRGBQUADArray[j] = new RGBQUAD(Color.FromArgb(rand.Next())); } Assert.IsTrue(metaTag.SetValue(testRGBQUAD, FREE_IMAGE_MDTYPE.FIDT_PALETTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((RGBQUAD[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 4); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_PALETTE); Assert.That(((RGBQUAD[])metaTag.Value)[0] == testRGBQUAD); Assert.IsTrue(metaTag.SetValue(testRGBQUADArray, FREE_IMAGE_MDTYPE.FIDT_PALETTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((RGBQUAD[])metaTag.Value).Length == testRGBQUADArray.Length); Assert.That(metaTag.Count == testRGBQUADArray.Length); Assert.That(metaTag.Length == testRGBQUADArray.Length * 4); RGBQUAD[] value = (RGBQUAD[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testRGBQUADArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_RATIONAL // FIURational testFIURational; FIURational[] testFIURationalArray; for (int i = 0; i < 10; i++) { testFIURational = new FIURational((uint)rand.Next(), (uint)rand.Next()); testFIURationalArray = new FIURational[rand.Next(0, 31)]; for (int j = 0; j < testFIURationalArray.Length; j++) { testFIURationalArray[j] = new FIURational((uint)rand.Next(), (uint)rand.Next()); } Assert.IsTrue(metaTag.SetValue(testFIURational, FREE_IMAGE_MDTYPE.FIDT_RATIONAL)); Assert.IsNotNull(metaTag.Value); Assert.That(((FIURational[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 8); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_RATIONAL); Assert.That(((FIURational[])metaTag.Value)[0] == testFIURational); Assert.IsTrue(metaTag.SetValue(testFIURationalArray, FREE_IMAGE_MDTYPE.FIDT_RATIONAL)); Assert.IsNotNull(metaTag.Value); Assert.That(((FIURational[])metaTag.Value).Length == testFIURationalArray.Length); Assert.That(metaTag.Count == testFIURationalArray.Length); Assert.That(metaTag.Length == testFIURationalArray.Length * 8); FIURational[] value = (FIURational[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testFIURationalArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_SBYTE // sbyte testSByte; sbyte[] testSByteArray; Assert.IsTrue(metaTag.SetValue(sbyte.MinValue, FREE_IMAGE_MDTYPE.FIDT_SBYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((sbyte[])metaTag.Value).Length == 1); Assert.That(((sbyte[])metaTag.Value)[0] == sbyte.MinValue); Assert.IsTrue(metaTag.SetValue(sbyte.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SBYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((sbyte[])metaTag.Value).Length == 1); Assert.That(((sbyte[])metaTag.Value)[0] == sbyte.MaxValue); for (int i = 0; i < 10; i++) { testSByte = (sbyte)rand.Next(sbyte.MinValue, sbyte.MaxValue); testSByteArray = new sbyte[rand.Next(0, 31)]; for (int j = 0; j < testSByteArray.Length; j++) { testSByteArray[j] = (sbyte)rand.Next(); } Assert.IsTrue(metaTag.SetValue(testSByte, FREE_IMAGE_MDTYPE.FIDT_SBYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((sbyte[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 1); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SBYTE); Assert.That(((sbyte[])metaTag.Value)[0] == testSByte); Assert.IsTrue(metaTag.SetValue(testSByteArray, FREE_IMAGE_MDTYPE.FIDT_SBYTE)); Assert.IsNotNull(metaTag.Value); Assert.That(((sbyte[])metaTag.Value).Length == testSByteArray.Length); Assert.That(metaTag.Count == testSByteArray.Length); Assert.That(metaTag.Length == testSByteArray.Length * 1); sbyte[] value = (sbyte[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testSByteArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_SHORT // ushort testUShort; ushort[] testUShortArray; Assert.IsTrue(metaTag.SetValue(ushort.MinValue, FREE_IMAGE_MDTYPE.FIDT_SHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((ushort[])metaTag.Value).Length == 1); Assert.That(((ushort[])metaTag.Value)[0] == ushort.MinValue); Assert.IsTrue(metaTag.SetValue(ushort.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((ushort[])metaTag.Value).Length == 1); Assert.That(((ushort[])metaTag.Value)[0] == ushort.MaxValue); for (int i = 0; i < 10; i++) { testUShort = (ushort)rand.Next(ushort.MinValue, sbyte.MaxValue); testUShortArray = new ushort[rand.Next(0, 31)]; for (int j = 0; j < testUShortArray.Length; j++) { testUShortArray[j] = (ushort)rand.Next(); } Assert.IsTrue(metaTag.SetValue(testUShort, FREE_IMAGE_MDTYPE.FIDT_SHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((ushort[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 2); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SHORT); Assert.That(((ushort[])metaTag.Value)[0] == testUShort); Assert.IsTrue(metaTag.SetValue(testUShortArray, FREE_IMAGE_MDTYPE.FIDT_SHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((ushort[])metaTag.Value).Length == testUShortArray.Length); Assert.That(metaTag.Count == testUShortArray.Length); Assert.That(metaTag.Length == testUShortArray.Length * 2); ushort[] value = (ushort[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testUShortArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_SLONG // int testInt; int[] testIntArray; Assert.IsTrue(metaTag.SetValue(int.MinValue, FREE_IMAGE_MDTYPE.FIDT_SLONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((int[])metaTag.Value).Length == 1); Assert.That(((int[])metaTag.Value)[0] == int.MinValue); Assert.IsTrue(metaTag.SetValue(int.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SLONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((int[])metaTag.Value).Length == 1); Assert.That(((int[])metaTag.Value)[0] == int.MaxValue); for (int i = 0; i < 10; i++) { testInt = (int)rand.NextDouble(); testIntArray = new int[rand.Next(0, 31)]; for (int j = 0; j < testIntArray.Length; j++) { testIntArray[j] = rand.Next(); } Assert.IsTrue(metaTag.SetValue(testInt, FREE_IMAGE_MDTYPE.FIDT_SLONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((int[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 4); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SLONG); Assert.That(((int[])metaTag.Value)[0] == testInt); Assert.IsTrue(metaTag.SetValue(testIntArray, FREE_IMAGE_MDTYPE.FIDT_SLONG)); Assert.IsNotNull(metaTag.Value); Assert.That(((int[])metaTag.Value).Length == testIntArray.Length); Assert.That(metaTag.Count == testIntArray.Length); Assert.That(metaTag.Length == testIntArray.Length * 4); int[] value = (int[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testIntArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_SRATIONAL // FIRational testFIRational; FIRational[] testFIRationalArray; for (int i = 0; i < 10; i++) { testFIRational = new FIRational(rand.Next(), rand.Next()); testFIRationalArray = new FIRational[rand.Next(0, 31)]; for (int j = 0; j < testFIRationalArray.Length; j++) { testFIRationalArray[j] = new FIRational(rand.Next(), rand.Next()); } Assert.IsTrue(metaTag.SetValue(testFIRational, FREE_IMAGE_MDTYPE.FIDT_SRATIONAL)); Assert.IsNotNull(metaTag.Value); Assert.That(((FIRational[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 8); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SRATIONAL); Assert.That(((FIRational[])metaTag.Value)[0] == testFIRational); Assert.IsTrue(metaTag.SetValue(testFIRationalArray, FREE_IMAGE_MDTYPE.FIDT_SRATIONAL)); Assert.IsNotNull(metaTag.Value); Assert.That(((FIRational[])metaTag.Value).Length == testFIRationalArray.Length); Assert.That(metaTag.Count == testFIRationalArray.Length); Assert.That(metaTag.Length == testFIRationalArray.Length * 8); FIRational[] value = (FIRational[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testFIRationalArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_SSHORT // short testShort; short[] testShortArray; Assert.IsTrue(metaTag.SetValue(short.MinValue, FREE_IMAGE_MDTYPE.FIDT_SSHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((short[])metaTag.Value).Length == 1); Assert.That(((short[])metaTag.Value)[0] == short.MinValue); Assert.IsTrue(metaTag.SetValue(short.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SSHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((short[])metaTag.Value).Length == 1); Assert.That(((short[])metaTag.Value)[0] == short.MaxValue); for (int i = 0; i < 10; i++) { testShort = (short)rand.Next(short.MinValue, short.MaxValue); testShortArray = new short[rand.Next(0, 31)]; for (int j = 0; j < testShortArray.Length; j++) { testShortArray[j] = (short)rand.Next(); } Assert.IsTrue(metaTag.SetValue(testShort, FREE_IMAGE_MDTYPE.FIDT_SSHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((short[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 2); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SSHORT); Assert.That(((short[])metaTag.Value)[0] == testShort); Assert.IsTrue(metaTag.SetValue(testShortArray, FREE_IMAGE_MDTYPE.FIDT_SSHORT)); Assert.IsNotNull(metaTag.Value); Assert.That(((short[])metaTag.Value).Length == testShortArray.Length); Assert.That(metaTag.Count == testShortArray.Length); Assert.That(metaTag.Length == testShortArray.Length * 2); short[] value = (short[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testShortArray[j] == value[j]); } } // // FREE_IMAGE_MDTYPE.FIDT_UNDEFINED // Assert.IsTrue(metaTag.SetValue(byte.MinValue, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == 1); Assert.That(((byte[])metaTag.Value)[0] == byte.MinValue); Assert.IsTrue(metaTag.SetValue(byte.MaxValue, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == 1); Assert.That(((byte[])metaTag.Value)[0] == byte.MaxValue); for (int i = 0; i < 10; i++) { testByte = (byte)rand.Next(byte.MinValue, byte.MaxValue); testByteArray = new byte[rand.Next(0, 31)]; for (int j = 0; j < testByteArray.Length; j++) { testByteArray[j] = (byte)rand.Next(); } Assert.IsTrue(metaTag.SetValue(testByte, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == 1); Assert.That(metaTag.Count == 1); Assert.That(metaTag.Length == 1); Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_UNDEFINED); Assert.That(((byte[])metaTag.Value)[0] == testByte); Assert.IsTrue(metaTag.SetValue(testByteArray, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED)); Assert.IsNotNull(metaTag.Value); Assert.That(((byte[])metaTag.Value).Length == testByteArray.Length); Assert.That(metaTag.Count == testByteArray.Length); Assert.That(metaTag.Length == testByteArray.Length * 1); byte[] value = (byte[])metaTag.Value; for (int j = 0; j < value.Length; j++) { Assert.That(testByteArray[j] == value[j]); } } FreeImage.UnloadEx(ref dib); }
private void writeColor( BinaryWriter bw, Color color ) { RGBQUAD r = new RGBQUAD(color); r.Write(bw); }
// Convert a global memory block to a bitmap private Bitmap ConvertMemoryBlockToBitmap(IntPtr hMem) { Bitmap BMP = null; BITMAPINFOHEADER BIH = new BITMAPINFOHEADER(); IntPtr bihPtr; IntPtr dataPtr; IntPtr palPtr; uint HdrSize; PixelFormat PixFormat = PixelFormat.Format1bppIndexed; uint PalEntries = 0; RGBQUAD rgb = new RGBQUAD(); bihPtr = GlobalLock(hMem); if (!bihPtr.Equals(IntPtr.Zero)) { BIH = ((BITMAPINFOHEADER)(Marshal.PtrToStructure(bihPtr, typeof(BITMAPINFOHEADER)))); HdrSize = BIH.biSize; palPtr = (IntPtr)(bihPtr.ToInt32() + HdrSize); // Most of these formats are untested switch (BIH.biBitCount) { case 1: HdrSize += (uint)(2 * Marshal.SizeOf(rgb)); PixFormat = PixelFormat.Format1bppIndexed; PalEntries = 2; break; case 4: HdrSize += (uint)(16 * Marshal.SizeOf(rgb)); PixFormat = PixelFormat.Format4bppIndexed; PalEntries = BIH.biClrUsed; break; case 8: HdrSize += (uint)(256 * Marshal.SizeOf(rgb)); PixFormat = PixelFormat.Format8bppIndexed; PalEntries = BIH.biClrUsed; break; case 16: // Account for the 3 DWORD colour mask if (BIH.biCompression == BI_BITFIELDS) { HdrSize += 12; } PixFormat = PixelFormat.Format16bppRgb555; PalEntries = 0; break; case 24: PixFormat = PixelFormat.Format24bppRgb; PalEntries = 0; break; case 32: // Account for the 3 DWORD colour mask if (BIH.biCompression == BI_BITFIELDS) { HdrSize += 12; } PixFormat = PixelFormat.Format32bppRgb; PalEntries = 0; break; default: break; } dataPtr = (IntPtr)(bihPtr.ToInt32() + HdrSize); BMP = new Bitmap(BIH.biWidth, Math.Abs(BIH.biHeight), PixFormat); if (PalEntries > 0) { palPtr = (IntPtr)(bihPtr.ToInt32() + BIH.biSize); ColorPalette Pal = BMP.Palette; for (int PalEntry = 0; PalEntry < PalEntries; PalEntry++) { rgb = ((RGBQUAD)(Marshal.PtrToStructure(palPtr, typeof(RGBQUAD)))); Pal.Entries[PalEntry] = Color.FromArgb(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); palPtr = (IntPtr)(palPtr.ToInt32() + Marshal.SizeOf(rgb)); } BMP.Palette = Pal; } BitmapData BMPData = BMP.LockBits(new Rectangle(new Point(), BMP.Size), ImageLockMode.ReadWrite, PixFormat); CopyMemory((uint)BMPData.Scan0.ToInt32(), dataPtr, (uint)(BMPData.Stride * BMP.Height)); BMP.UnlockBits(BMPData); // Flip the bitmap (GDI+ bitmap scan lines are top down, GDI are bottom up) BMP.RotateFlip(RotateFlipType.RotateNoneFlipY); // Reset the resolutions BMP.SetResolution((float)((int)(BIH.biXPelsPerMeter * 2.54 / 100 + 0.5)), (float)((int)(BIH.biYPelsPerMeter * 2.54 / 100 + 0.5))); GlobalUnlock(hMem); } return(BMP); }
private int XorImageIndex( BITMAPINFOHEADER bmInfoHeader) { // Returns the position of the DIB bitmap bits within a // DIB bitmap array: RGBQUAD rgbq = new RGBQUAD(); return Marshal.SizeOf(bmInfoHeader) + dibNumColors(bmInfoHeader) * Marshal.SizeOf(rgbq); }
public static Bitmap GetThumbnail(string strFile, bool boolRetainBackColor, bool boolSaveToFile, string strSaveName) { Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed); byte bytCnt; byte[] bytBMPBuff; int lngImgLoc; FileStream fs = null; BinaryReader br = null; int lngCurLoc; int lngY; int lngX; int lngColor; int lngCnt; short intCnt; IMGREC udtRec; RGBQUAD[] udtColors; RGBQUAD udtColor; BITMAPINFOHEADER udtHeader; short intRed; short intGreen; short intBlue; try { if (File.Exists(strFile)) { fs = File.OpenRead(strFile); using (br = new BinaryReader(fs)) { fs.Seek(13, SeekOrigin.Begin); lngImgLoc = br.ReadInt32(); fs.Seek(lngImgLoc + 17, SeekOrigin.Begin); lngCurLoc = lngImgLoc + 17; fs.Seek(lngCurLoc + 3, SeekOrigin.Begin); bytCnt = br.ReadByte(); if (bytCnt > 1) { for (intCnt = 0; intCnt < bytCnt; intCnt++) { udtRec.bytType = br.ReadByte(); udtRec.lngStart = br.ReadInt32(); udtRec.lngLen = br.ReadInt32(); if (udtRec.bytType == 2) { fs.Seek(udtRec.lngStart, SeekOrigin.Begin); udtHeader.biSize = br.ReadInt32(); udtHeader.biWidth = br.ReadInt32(); udtHeader.biHeight = br.ReadInt32(); udtHeader.biPlanes = br.ReadInt16(); udtHeader.biBitCount = br.ReadInt16(); udtHeader.biCompression = br.ReadInt32(); udtHeader.biSizeImage = br.ReadInt32(); udtHeader.biXPelsPerMeter = br.ReadInt32(); udtHeader.biYPelsPerMeter = br.ReadInt32(); udtHeader.biClrUsed = br.ReadInt32(); udtHeader.biClrImportant = br.ReadInt32(); bytBMPBuff = new byte[udtRec.lngLen + 1]; if (udtHeader.biBitCount == 8) { udtColors = new RGBQUAD[256]; for (int count = 0; count < 256; count++) { udtColors[count].rgbBlue = br.ReadByte(); udtColors[count].rgbGreen = br.ReadByte(); udtColors[count].rgbRed = br.ReadByte(); udtColors[count].rgbReserved = br.ReadByte(); } fs.Seek(udtRec.lngStart - 1, SeekOrigin.Begin); for (int count = 0; count <= udtRec.lngLen; count++) { bytBMPBuff[count] = br.ReadByte(); } bmp = new Bitmap(udtHeader.biWidth, udtHeader.biHeight); lngCnt = 0; for (lngY = 1; lngY <= udtHeader.biHeight; lngY++) { for (lngX = udtHeader.biWidth; lngX >= 1; lngX--) { lngColor = bytBMPBuff[bytBMPBuff.GetUpperBound(0) - lngCnt]; udtColor = udtColors[lngColor]; intRed = Convert.ToInt16(udtColor.rgbRed); intGreen = Convert.ToInt16(udtColor.rgbGreen); intBlue = Convert.ToInt16(udtColor.rgbBlue); lngColor = ColorTranslator.ToOle(Color.FromArgb(intRed, intGreen, intBlue)); if (boolRetainBackColor == false) { if (lngColor == ColorTranslator.ToOle(Color.Black)) { lngColor = ColorTranslator.ToOle(Color.White); } else { if (lngColor == ColorTranslator.ToOle(Color.White)) { lngColor = ColorTranslator.ToOle(Color.Black); } } } bmp.SetPixel(lngX - 1, lngY - 1, ColorTranslator.FromOle(lngColor)); lngCnt++; } } } goto Exit_Here; } else { if (udtRec.bytType == 3) { goto Exit_Here; } } } } } } } catch (Exception ex) { MessageBox.Show(ex.Message); } Exit_Here: //if (br != null) //{ // br.Close(); // fs.Close(); // fs.Dispose(); //} if (boolSaveToFile == true) { if (strSaveName == "") { string fName; fName = String.Concat(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()), ".bmp"); bmp.Save(fName); } else { bmp.Save(strSaveName); } } return(bmp); }
/// <summary> /// Compile input images into WAD texture file. /// </summary> /// <param name="outputFilename">Output wad file path.</param> /// <param name="images">Input image files.</param> /// <param name="names">Names of textures.</param> /// <param name="reserverLastPalColor">Reserve last color in palette if name starts with {.</param> public static void CreateWad(string outputFilename, string[] images, string[] names, Color alphaReplacementColor, bool reserverLastPalColor = false) { using (FileStream fs = new FileStream(outputFilename, FileMode.Create)) using (BinaryWriter bw = new BinaryWriter(fs)) { //Convert bitmaps to 8bpp format List <FreeImageBitmap> imgs = new List <FreeImageBitmap>(); for (int i = 0; i < images.Length; i++) { //Quantize images FreeImageBitmap originalImage = new FreeImageBitmap(images[i]); //If texture will be transparent, reserve last color if enabled bool reserveLastClr = (names[i].StartsWith("{") && reserverLastPalColor); bool isTransparentImage = originalImage.IsTransparent; bool is8Bpp = originalImage.BitsPerPixel == 8; int r = reserveLastClr ? 1 : 0; if (isTransparentImage) { originalImage.SwapColors(new RGBQUAD(Color.Transparent), new RGBQUAD(alphaReplacementColor), false); } originalImage.Quantize(FREE_IMAGE_QUANTIZE.FIQ_NNQUANT, MaxPaletteColors - r); originalImage.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP); if (reserveLastClr) { if (isTransparentImage) { bool foundReplacementColor = false; for (int pindex = 0; pindex < originalImage.Palette.Length; pindex++) { RGBQUAD rgb = originalImage.Palette.GetValue(pindex); if (rgb.rgbRed == alphaReplacementColor.R && rgb.rgbGreen == alphaReplacementColor.G && rgb.rgbBlue == alphaReplacementColor.B) { var lastColor = originalImage.Palette.GetValue(MaxPaletteColors - 1); originalImage.Palette[pindex] = lastColor; originalImage.Palette[MaxPaletteColors - 1] = new RGBQUAD(alphaReplacementColor); originalImage.SwapPaletteIndices((byte)pindex, MaxPaletteColors - 1); foundReplacementColor = true; break; } } // If didn't found replacement, set directly last alpha color if (!foundReplacementColor) { originalImage.Palette[MaxPaletteColors - 1] = new RGBQUAD(alphaReplacementColor); } } else { originalImage.Palette[MaxPaletteColors - 1] = new RGBQUAD(alphaReplacementColor); } } imgs.Add(originalImage); } uint[] offsets = new uint[images.Length]; uint[] sizes = new uint[images.Length]; //WAD header bw.Write(WadHeaderId); bw.Write(images.Length); bw.Write(0); //This will be changed later //Write textures for (int i = 0; i < images.Length; i++) { uint posTextureStart = (uint)bw.BaseStream.Position; offsets[i] = posTextureStart; //Texture name byte[] name = CreateTextureName(names[i]); bw.Write(name, 0, name.Length); //Texture dimensions bw.Write(imgs[i].Width); bw.Write(imgs[i].Height); //Offsets uint posImage = (uint)(bw.BaseStream.Position - posTextureStart); bw.Write(posImage + 16); //image int pixelSize = ((imgs[i].Width) * (imgs[i].Height)); int m1 = ((imgs[i].Width / 2) * (imgs[i].Height / 2)); int m2 = ((imgs[i].Width / 4) * (imgs[i].Height / 4)); int m3 = ((imgs[i].Width / 8) * (imgs[i].Height / 8)); bw.Write((uint)(posImage + pixelSize + 16)); //mipmap1 bw.Write((uint)(posImage + pixelSize + m1 + 16)); //mipmap2 bw.Write((uint)(posImage + pixelSize + m1 + m2 + 16)); //mipmap3 //Write pixel data imgs[i].RotateFlip(RotateFlipType.RotateNoneFlipX); byte[] arr = new byte[imgs[i].Width * imgs[i].Height]; System.Runtime.InteropServices.Marshal.Copy(imgs[i].GetScanlinePointer(0), arr, 0, arr.Length); Array.Reverse(arr); bw.Write(arr); // //Mip map data int factor = 2; for (int a = 0; a < 3; a++) { int widthMM = (imgs[i].Width / factor); int heightMM = (imgs[i].Height / factor); using (FreeImageBitmap clBmp = new FreeImageBitmap(imgs[i])) { //TODO: Transparent png clBmp.Rescale(widthMM, heightMM, FREE_IMAGE_FILTER.FILTER_LANCZOS3); clBmp.Quantize(FREE_IMAGE_QUANTIZE.FIQ_NNQUANT, MaxPaletteColors, imgs[i].Palette); byte[] arrMM = new byte[widthMM * heightMM]; System.Runtime.InteropServices.Marshal.Copy(clBmp.GetScanlinePointer(0), arrMM, 0, arrMM.Length); Array.Reverse(arrMM); bw.Write(arrMM); } factor *= 2; } //Unknown 2 bytes bw.Write(new byte[] { 0x00, 0x01 }); //Write color palette for (int p = 0; p < imgs[i].Palette.Length; p++) { bw.Write(imgs[i].Palette[p].rgbRed); bw.Write(imgs[i].Palette[p].rgbGreen); bw.Write(imgs[i].Palette[p].rgbBlue); } //Padding bw.Write(new byte[] { 0x00, 0x00 }); sizes[i] = (uint)bw.BaseStream.Position - posTextureStart; } long posLumps = bw.BaseStream.Position; bw.Seek(8, SeekOrigin.Begin); bw.Write((uint)posLumps); bw.Seek((int)posLumps, SeekOrigin.Begin); //Write Lumps infos for (int i = 0; i < images.Length; i++) { bw.Write(offsets[i]); bw.Write(sizes[i]); bw.Write(sizes[i]); bw.Write((byte)0x43); bw.Write((byte)0); bw.Write(new byte[] { 0x00, 0x00 }); byte[] name = CreateTextureName(names[i]); bw.Write(name, 0, name.Length); } //Free resources for (int i = 0; i < imgs.Count; i++) { imgs[i].Dispose(); } } }
private void setMaskBitsFromBitmap( Bitmap bm ) { IntPtr hdcc = CreateDC("DISPLAY", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); IntPtr hdc = CreateCompatibleDC(hdcc); DeleteDC(hdcc); IntPtr hBmp = bm.GetHbitmap(); BITMAPINFOHEADER bmInfoHdr = new BITMAPINFOHEADER( this.size, this.colorDepth); // Now prepare the for GetDIBits call: RGBQUAD rgbQuad = new RGBQUAD(); int monoBmHdrSize = bmInfoHdr.biSize + Marshal.SizeOf(rgbQuad)* 2; IntPtr bitsInfo = Marshal.AllocCoTaskMem( monoBmHdrSize); Marshal.WriteInt32(bitsInfo, Marshal.SizeOf(bmInfoHdr)); Marshal.WriteInt32(bitsInfo, 4, this.size.Width); Marshal.WriteInt32(bitsInfo, 8, this.size.Height); Marshal.WriteInt16(bitsInfo, 12, 1); Marshal.WriteInt16(bitsInfo, 14, 1); Marshal.WriteInt32(bitsInfo, 16, BI_RGB); Marshal.WriteInt32(bitsInfo, 20, 0); Marshal.WriteInt32(bitsInfo, 24, 0); Marshal.WriteInt32(bitsInfo, 28, 0); Marshal.WriteInt32(bitsInfo, 32, 0); Marshal.WriteInt32(bitsInfo, 36, 0); // Write the black and white colour indices: Marshal.WriteInt32(bitsInfo, 40, 0); Marshal.WriteByte(bitsInfo, 44, 255); Marshal.WriteByte(bitsInfo, 45, 255); Marshal.WriteByte(bitsInfo, 46, 255); Marshal.WriteByte(bitsInfo, 47, 0); int maskImageBytes = MaskImageSize(bmInfoHdr); IntPtr bits = Marshal.AllocCoTaskMem(maskImageBytes); int success = GetDIBits(hdc, hBmp, 0, this.size.Height, bits, bitsInfo, DIB_RGB_COLORS); Marshal.Copy(bits, data, MaskImageIndex(bmInfoHdr), maskImageBytes); // Free memory: Marshal.FreeCoTaskMem(bits); Marshal.FreeCoTaskMem(bitsInfo); DeleteObject(hBmp); DeleteDC(hdc); createIcon(); }
public void Open(System.IO.Stream Source) { File iconFile = new File(); iconFile.Read(Source); foreach (Frame iconFrame in iconFile.Frames) { System.Windows.Media.Imaging.BitmapFrame frame = null; if (iconFrame.type == FrameType.BITMAP) { if (iconFrame.iconImage.icHeader.biBitCount == 32) { byte[] pixels = iconFrame.iconImage.icXOR; pixels = Utilities.FlipYBuffer(pixels, iconFrame.Width, iconFrame.Height, iconFrame.iconImage.XorStride); BitmapSource bp = BitmapSource.Create(iconFrame.Width, iconFrame.Height, 96, 96, PixelFormats.Bgra32, null, pixels, iconFrame.iconImage.XorStride); frame = BitmapFrame.Create(bp); } else if (iconFrame.iconImage.icHeader.biBitCount == 24) { byte[] pixels = iconFrame.iconImage.icXOR; pixels = Utilities.FlipYBuffer(pixels, iconFrame.Width, iconFrame.Height, iconFrame.iconImage.XorStride); BitmapSource bp = BitmapSource.Create(iconFrame.Width, iconFrame.Height, 96, 96, PixelFormats.Bgr24, null, pixels, iconFrame.iconImage.XorStride); frame = BitmapFrame.Create(bp); } else if (iconFrame.iconImage.icHeader.biBitCount == 8) { byte[] pixels = iconFrame.iconImage.icXOR; pixels = Utilities.FlipYBuffer(pixels, iconFrame.Width, iconFrame.Height, iconFrame.iconImage.XorStride); BitmapSource bp = BitmapSource.Create(iconFrame.Width, iconFrame.Height, 96, 96, PixelFormats.Indexed8, GetPalette(iconFrame.iconImage.icColors, true), pixels, iconFrame.iconImage.XorStride); frame = BitmapFrame.Create(bp); } else if (iconFrame.iconImage.icHeader.biBitCount == 4) { byte[] pixels = iconFrame.iconImage.icXOR; pixels = Utilities.FlipYBuffer(pixels, iconFrame.Width, iconFrame.Height, iconFrame.iconImage.XorStride); BitmapSource bp = BitmapSource.Create(iconFrame.Width, iconFrame.Height, 96, 96, PixelFormats.Indexed4, GetPalette(iconFrame.iconImage.icColors, true), pixels, iconFrame.iconImage.XorStride); frame = BitmapFrame.Create(bp); } else { try { byte[] pixels = iconFrame.iconImage.icXOR; pixels = Utilities.FlipYBuffer(pixels, iconFrame.Width, iconFrame.Height, iconFrame.iconImage.XorStride); BitmapSource bp = BitmapSource.Create(iconFrame.Width, iconFrame.Height, 96, 96, PixelFormats.Indexed1, GetPalette(iconFrame.iconImage.icColors, true), pixels, iconFrame.iconImage.XorStride); frame = BitmapFrame.Create(bp); } catch { continue; } } if (iconFrame.iconImage.icAND?.Length > 0) { RGBQUAD[] palette = new RGBQUAD[2] { RGBQUAD.FromRGBA(0, 0, 0, 0), RGBQUAD.FromRGBA(255, 255, 255, 255) }; byte[] pixels = iconFrame.iconImage.icAND; pixels = Utilities.FlipYBuffer(pixels, iconFrame.Width, iconFrame.Height, iconFrame.iconImage.AndStride); BitmapSource AND = BitmapSource.Create(iconFrame.Width, iconFrame.Height, 96, 96, PixelFormats.Indexed1, GetPalette(palette, true), pixels, iconFrame.iconImage.AndStride); EditableBitmapImage editableXOR = new EditableBitmapImage(frame); EditableBitmapImage editableAND = new EditableBitmapImage(AND); for (int x = 0; x < editableXOR.PixelWidth; x++) { for (int y = 0; y < editableXOR.PixelHeight; y++) { Color px = editableAND.GetPixel(x, y); if (px == Colors.White) { Color c = editableXOR.GetPixel(x, y); c.A = 0; editableXOR.SetPixel(x, y, c); } } } if (frame.Format.BitsPerPixel == 32) { // Do nothing } else if (frame.Format.BitsPerPixel == 24) { frame = BitmapFrame.Create(editableXOR); } else if (frame.Format.BitsPerPixel == 8) { BitmapSource s = Helpers.Get8BitImage(editableXOR); frame = BitmapFrame.Create(s); } else if (frame.Format.BitsPerPixel == 4) { BitmapSource s = Helpers.Get4BitImage(editableXOR); frame = BitmapFrame.Create(s); } } } else { try { PngBitmapDecoder decoder = new PngBitmapDecoder(new System.IO.MemoryStream(iconFrame.pngBuffer), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); frame = decoder.Frames[0]; } catch { frame = BitmapFrame.Create(CreateEmptyBitmap(iconFrame.Width)); } } _Frames.Add(frame); } }
private Bitmap getIconBitmap( bool mask, bool returnHandle, ref IntPtr hBmp ) { // Bitmap to return Bitmap bm = null; // Get bitmap info: BITMAPINFOHEADER bmInfoHdr = new BITMAPINFOHEADER(data); if (mask) { // extract monochrome mask IntPtr hdc = CreateCompatibleDC(IntPtr.Zero); hBmp = CreateCompatibleBitmap(hdc, bmInfoHdr.biWidth, bmInfoHdr.biHeight / 2); IntPtr hBmpOld = SelectObject(hdc, hBmp); // Prepare BitmapInfoHeader for mono bitmap: RGBQUAD rgbQuad = new RGBQUAD(); int monoBmHdrSize = bmInfoHdr.biSize + Marshal.SizeOf(rgbQuad)* 2; IntPtr bitsInfo = Marshal.AllocCoTaskMem( monoBmHdrSize); Marshal.WriteInt32(bitsInfo, Marshal.SizeOf(bmInfoHdr)); Marshal.WriteInt32(bitsInfo, 4, bmInfoHdr.biWidth); Marshal.WriteInt32(bitsInfo, 8, bmInfoHdr.biHeight / 2); Marshal.WriteInt16(bitsInfo, 12, 1); Marshal.WriteInt16(bitsInfo, 14, 1); Marshal.WriteInt32(bitsInfo, 16, BI_RGB); Marshal.WriteInt32(bitsInfo, 20, 0); Marshal.WriteInt32(bitsInfo, 24, 0); Marshal.WriteInt32(bitsInfo, 28, 0); Marshal.WriteInt32(bitsInfo, 32, 0); Marshal.WriteInt32(bitsInfo, 36, 0); // Write the black and white colour indices: Marshal.WriteInt32(bitsInfo, 40, 0); Marshal.WriteByte(bitsInfo, 44, 255); Marshal.WriteByte(bitsInfo, 45, 255); Marshal.WriteByte(bitsInfo, 46, 255); Marshal.WriteByte(bitsInfo, 47, 0); // Prepare Mask bits: int maskImageBytes = MaskImageSize(bmInfoHdr); IntPtr bits = Marshal.AllocCoTaskMem(maskImageBytes); Marshal.Copy(data, MaskImageIndex(bmInfoHdr), bits, maskImageBytes); int success = SetDIBitsToDevice( hdc, 0, 0, bmInfoHdr.biWidth, bmInfoHdr.biHeight / 2, 0, 0, 0, bmInfoHdr.biHeight / 2, bits, bitsInfo, DIB_RGB_COLORS); Marshal.FreeCoTaskMem(bits); Marshal.FreeCoTaskMem(bitsInfo); SelectObject(hdc, hBmpOld); DeleteObject(hdc); } else { // extract colour (XOR) part of image: // Create bitmap: IntPtr hdcDesktop = CreateDC("DISPLAY", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); IntPtr hdc = CreateCompatibleDC(hdcDesktop); hBmp = CreateCompatibleBitmap(hdcDesktop, bmInfoHdr.biWidth, bmInfoHdr.biHeight / 2); DeleteDC(hdcDesktop); IntPtr hBmpOld = SelectObject(hdc, hBmp); // Find the index of the XOR bytes: int xorIndex = XorImageIndex(bmInfoHdr); int xorImageSize = XorImageSize(bmInfoHdr); // Get Bitmap info header to a pointer: IntPtr bitsInfo = Marshal.AllocCoTaskMem(xorIndex); Marshal.Copy(data, 0, bitsInfo, xorIndex); // fix the height: Marshal.WriteInt32(bitsInfo, 8, bmInfoHdr.biHeight / 2); // Get the XOR bits: IntPtr bits = Marshal.AllocCoTaskMem(xorImageSize); Marshal.Copy(data, xorIndex, bits, xorImageSize); int success = SetDIBitsToDevice( hdc, 0, 0, bmInfoHdr.biWidth, bmInfoHdr.biHeight/2, 0, 0, 0, bmInfoHdr.biHeight/2, bits, bitsInfo, DIB_RGB_COLORS); Marshal.FreeCoTaskMem(bits); Marshal.FreeCoTaskMem(bitsInfo); SelectObject(hdc, hBmpOld); DeleteObject(hdc); } if (!returnHandle) { // the bitmap will own the handle and clear // it up when it is disposed. Otherwise // need to call DeleteObject on hBmp // returned. bm = Bitmap.FromHbitmap(hBmp); } return bm; }
private unsafe void SetPalette(ColorPalette colorPalette, BITMAPINFO info) { ushort bitCount = info.bmiHeader.biBitCount; RGBQUAD rgb = new RGBQUAD(); int* pRgb = info.bmiColors; if (bitCount==1 || bitCount==4 || bitCount==8) { for (int i = 0; i < colorPalette.Entries.Length; i++) { int value = *(pRgb+i); rgb.value = value; int r = rgb.rgbRed; int g = rgb.rgbGreen; int b = rgb.rgbBlue; colorPalette.Entries[i] = Color.FromArgb(r, g, b); } } }
public unsafe static extern void CopyMemory(RGBQUAD* dest, byte* src, int cb);
private static RGBQUAD ConvertYCrCbToRGB(byte y, byte cr, byte cb) { RGBQUAD rgbq = new RGBQUAD(); int c = y - 16; int d = cb - 128; int e = cr - 128; rgbq.R = Clip((298 * c + 409 * e + 128) >> 8); rgbq.G = Clip((298 * c - 100 * d - 208 * e + 128) >> 8); rgbq.B = Clip((298 * c + 516 * d + 128) >> 8); return rgbq; }
static void Main(string[] args) { if (args.Length < 2) { PrintHelp(); return; } try { string inputFile = args[0]; string outputFile = args[1]; Console.WriteLine(String.Format("Loading file: {0}", inputFile)); FIBITMAP image = FreeImage.LoadEx(inputFile); // Make sure the image is one of the supported types FREE_IMAGE_TYPE imgType = FreeImage.GetImageType(image); switch (imgType) { case FREE_IMAGE_TYPE.FIT_INT16: Console.WriteLine("Detected 16-bit short"); break; case FREE_IMAGE_TYPE.FIT_INT32: Console.WriteLine("Detected 32-bit int"); break; case FREE_IMAGE_TYPE.FIT_UINT16: Console.WriteLine("Detected 16-bit ushort"); break; case FREE_IMAGE_TYPE.FIT_UINT32: Console.WriteLine("Detected 32-bit uint"); break; default: Console.WriteLine(String.Format("Unsupported file type: {0}", imgType.ToString())); return; } uint width = FreeImage.GetWidth(image); uint height = FreeImage.GetHeight(image); uint fileBPP = FreeImage.GetBPP(image); // Allocate new RGB Image FIBITMAP newMap = FreeImage.Allocate((int)width, (int)height, 8 /*BitsPerPixel*/ * 3); RGBQUAD outQuad = new RGBQUAD(); // Multiplier for the byte offset into the scaline int iterations = 0; int lateralMultipler = fileBPP == 16 ? 2 : 4; for (uint x = 0; x < width; ++x, ++iterations) { float progress = ((float)(iterations)) / ((float)(width * height)); Console.Write(String.Format("\rProgress {0:000.0}% ", progress * 100.0f)); for (uint y = 0; y < height; ++y, ++iterations) { IntPtr line = FreeImage.GetScanLine(image, (int)y); if (fileBPP >= 16) { line = new IntPtr(line.ToInt64() + lateralMultipler * x); if (imgType == FREE_IMAGE_TYPE.FIT_UINT16) { ushort value = (ushort)System.Runtime.InteropServices.Marshal.ReadInt16(line); outQuad.rgbRed = (byte)(value / 256); outQuad.rgbGreen = (byte)(value % 256); } else if (imgType == FREE_IMAGE_TYPE.FIT_UINT32) { uint value = (uint)System.Runtime.InteropServices.Marshal.ReadInt32(line); outQuad.rgbRed = (byte)(value / 256); outQuad.rgbGreen = (byte)(value % 256); } else if (imgType == FREE_IMAGE_TYPE.FIT_INT16) { short value = (short)System.Runtime.InteropServices.Marshal.ReadInt16(line); outQuad.rgbRed = (byte)(value / 256); outQuad.rgbGreen = (byte)(value % 256); } else if (imgType == FREE_IMAGE_TYPE.FIT_INT32) { int value = (int)System.Runtime.InteropServices.Marshal.ReadInt32(line); outQuad.rgbRed = (byte)(value / 256); outQuad.rgbGreen = (byte)(value % 256); } FreeImage.SetPixelColor(newMap, x, y, ref outQuad); } else { } } } Console.WriteLine(" "); //empty space Console.WriteLine(String.Format("Writing file: {0}", outputFile)); if (FreeImage.SaveEx(newMap, outputFile)) { Console.WriteLine("Finished"); } else { Console.WriteLine("ERROR: Failed to write file"); } } catch (Exception ex) { Console.WriteLine("ERROR: "); Console.Write(ex.Message); } }
public void Example03() { dib = FreeImage.LoadEx("Sample.tif"); // Check whether loading succeeded if (dib.IsNull) { Console.WriteLine("Sample.tif could not be loaded. Aborting."); return; } // Check whether the bitmap has 4 bpp color depth to ensure // using FI4B is correct. if (FreeImage.GetBPP(dib) != 4) { Console.WriteLine("Sample.tif is no 4 bpp bitmap. Aborting."); FreeImage.UnloadEx(ref dib); return; } // Get the bitmaps palette Palette palette = FreeImage.GetPaletteEx(dib); int size = (int)palette.Length; // Check whether the palette has a color (is valid) if (size == 0) { Console.WriteLine("Sample.tif has no valid palette. Aborting."); FreeImage.UnloadEx(ref dib); return; } // Swapping the palette for (int i = 0; i < size / 2; i++) { RGBQUAD temp = palette[i]; palette[i] = palette[size - 1 - i]; palette[size - 1 - i] = temp; } // Iterate over each scanline for (int i = 0; i < FreeImage.GetHeight(dib); i++) { // Get scanline Scanline <FI4BIT> scanline = new Scanline <FI4BIT>(dib, i); // Iterate over all pixels swapping the palette index // so that the color will stay the same for (int j = 0; j < scanline.Length; j++) { scanline[j] = (byte)(size - 1 - scanline[j]); } } // Save the bitmap to disk if (!FreeImage.SaveEx(ref dib, "SampleOut03.tif", FREE_IMAGE_SAVE_FLAGS.TIFF_LZW, true)) { Console.WriteLine("Error while saving 'SampleOut03.tif'"); FreeImage.UnloadEx(ref dib); } }
private static extern bool FreeImage_GetPixelColor(FIBITMAP dib, int x, int y, RGBQUAD value);
private Bitmap getIconBitmap(bool mask, bool returnHandle, ref IntPtr hBmp) { Bitmap bitmap = null; BITMAPINFOHEADER structure = new BITMAPINFOHEADER(this.data); if (mask) { IntPtr hdc = CreateCompatibleDC(IntPtr.Zero); hBmp = CreateCompatibleBitmap(hdc, structure.biWidth, structure.biHeight / 2); IntPtr hObject = SelectObject(hdc, hBmp); RGBQUAD rgbquad = new RGBQUAD(); int cb = structure.biSize + (Marshal.SizeOf(rgbquad) * 2); IntPtr ptr = Marshal.AllocCoTaskMem(cb); Marshal.WriteInt32(ptr, Marshal.SizeOf(structure)); Marshal.WriteInt32(ptr, 4, structure.biWidth); Marshal.WriteInt32(ptr, 8, structure.biHeight / 2); Marshal.WriteInt16(ptr, 12, (short)1); Marshal.WriteInt16(ptr, 14, (short)1); Marshal.WriteInt32(ptr, 0x10, 0); Marshal.WriteInt32(ptr, 20, 0); Marshal.WriteInt32(ptr, 0x18, 0); Marshal.WriteInt32(ptr, 0x1c, 0); Marshal.WriteInt32(ptr, 0x20, 0); Marshal.WriteInt32(ptr, 0x24, 0); Marshal.WriteInt32(ptr, 40, 0); Marshal.WriteByte(ptr, 0x2c, 0xff); Marshal.WriteByte(ptr, 0x2d, 0xff); Marshal.WriteByte(ptr, 0x2e, 0xff); Marshal.WriteByte(ptr, 0x2f, 0); int num2 = this.MaskImageSize(structure); IntPtr destination = Marshal.AllocCoTaskMem(num2); Marshal.Copy(this.data, this.MaskImageIndex(structure), destination, num2); SetDIBitsToDevice(hdc, 0, 0, structure.biWidth, structure.biHeight / 2, 0, 0, 0, structure.biHeight / 2, destination, ptr, 0); Marshal.FreeCoTaskMem(destination); Marshal.FreeCoTaskMem(ptr); SelectObject(hdc, hObject); DeleteObject(hdc); } else { IntPtr ptr5 = CreateDC("DISPLAY", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); IntPtr ptr6 = CreateCompatibleDC(ptr5); hBmp = CreateCompatibleBitmap(ptr5, structure.biWidth, structure.biHeight / 2); DeleteDC(ptr5); IntPtr ptr7 = SelectObject(ptr6, hBmp); int num3 = this.XorImageIndex(structure); int num4 = this.XorImageSize(structure); IntPtr ptr8 = Marshal.AllocCoTaskMem(num3); Marshal.Copy(this.data, 0, ptr8, num3); Marshal.WriteInt32(ptr8, 8, structure.biHeight / 2); IntPtr ptr9 = Marshal.AllocCoTaskMem(num4); Marshal.Copy(this.data, num3, ptr9, num4); SetDIBitsToDevice(ptr6, 0, 0, structure.biWidth, structure.biHeight / 2, 0, 0, 0, structure.biHeight / 2, ptr9, ptr8, 0); Marshal.FreeCoTaskMem(ptr9); Marshal.FreeCoTaskMem(ptr8); SelectObject(ptr6, ptr7); DeleteObject(ptr6); } if (!returnHandle) { bitmap = Image.FromHbitmap(hBmp); } return bitmap; }
private FIBITMAP formatImage(FIBITMAP dib, int icoSize, int dstBpp) { const int hideOpacity = 128; //FIBITMAP dibTmp = FreeImage.Rescale(dib, icoSize, icoSize, FREE_IMAGE_FILTER.FILTER_BICUBIC); FIBITMAP dibTmp = FreeImage.Rescale(dib, icoSize, icoSize, FREE_IMAGE_FILTER.FILTER_LANCZOS3); if (dstBpp >= 32) { return(dibTmp); } int paletteSize = (int)Math.Pow(2, dstBpp); byte lastPaletteIdx = (byte)(paletteSize - 1); // quantize ico // reserve last one palette, to set transparent //FIBITMAP dibTmp2 = FreeImage.ConvertColorDepth(dibTmp, FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP); FIBITMAP dibOut = FreeImage.ColorQuantizeEx(dibTmp, FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, paletteSize - 1, null, dstBpp); // set transparent color index to last one palette RGBQUAD rgb = new RGBQUAD(); byte val = 0; for (int m = icoSize - 1; m >= 0; --m) { string str = ""; for (int n = icoSize - 1; n >= 0; --n) { FreeImage.GetPixelIndex(dibOut, (uint)n, (uint)m, out val); FreeImage.GetPixelColor(dibTmp, (uint)n, (uint)m, out rgb); //uint val = rgb.uintValue & 0x00FFFFFF; if (rgb.rgbReserved <= hideOpacity) { FreeImage.SetPixelIndex(dibOut, (uint)n, (uint)m, ref lastPaletteIdx); } str += val + ","; } } FreeImage.Unload(dibTmp); //uint bpp = FreeImage.GetBPP(dibOut); // set transarency table try { RGBQUAD[] palette = new Palette(dibOut).AsArray; byte[] transparency = new byte[palette.Length]; for (int m = 0; m < palette.Length; ++m) { transparency[m] = 0xFF; if (m == lastPaletteIdx) { transparency[m] = 0; } } FreeImage.SetTransparencyTable(dibOut, transparency); } catch (Exception) { } return(dibOut); }
private void setMaskBitsFromBitmap(Bitmap bm) { IntPtr hdc = CreateDC("DISPLAY", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); IntPtr ptr2 = CreateCompatibleDC(hdc); DeleteDC(hdc); IntPtr hbitmap = bm.GetHbitmap(); BITMAPINFOHEADER structure = new BITMAPINFOHEADER(this.size, this.colorDepth); RGBQUAD rgbquad = new RGBQUAD(); int cb = structure.biSize + (Marshal.SizeOf(rgbquad) * 2); IntPtr ptr = Marshal.AllocCoTaskMem(cb); Marshal.WriteInt32(ptr, Marshal.SizeOf(structure)); Marshal.WriteInt32(ptr, 4, this.size.Width); Marshal.WriteInt32(ptr, 8, this.size.Height); Marshal.WriteInt16(ptr, 12, (short)1); Marshal.WriteInt16(ptr, 14, (short)1); Marshal.WriteInt32(ptr, 0x10, 0); Marshal.WriteInt32(ptr, 20, 0); Marshal.WriteInt32(ptr, 0x18, 0); Marshal.WriteInt32(ptr, 0x1c, 0); Marshal.WriteInt32(ptr, 0x20, 0); Marshal.WriteInt32(ptr, 0x24, 0); Marshal.WriteInt32(ptr, 40, 0); Marshal.WriteByte(ptr, 0x2c, 0xff); Marshal.WriteByte(ptr, 0x2d, 0xff); Marshal.WriteByte(ptr, 0x2e, 0xff); Marshal.WriteByte(ptr, 0x2f, 0); int num2 = this.MaskImageSize(structure); IntPtr bits = Marshal.AllocCoTaskMem(num2); GetDIBits(ptr2, hbitmap, 0, this.size.Height, bits, ptr, 0); Marshal.Copy(bits, this.data, this.MaskImageIndex(structure), num2); Marshal.FreeCoTaskMem(bits); Marshal.FreeCoTaskMem(ptr); DeleteObject(hbitmap); DeleteDC(ptr2); this.createIcon(); }
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 int XorImageIndex(BITMAPINFOHEADER bmInfoHeader) { RGBQUAD structure = new RGBQUAD(); return (Marshal.SizeOf(bmInfoHeader) + (this.dibNumColors(bmInfoHeader) * Marshal.SizeOf(structure))); }