public override ImageData Read(IBinaryStream stream, ImageMetaData info) { var meta = (DwqMetaData)info; BitmapSource bitmap = null; using (var sreg = new StreamRegion(stream.AsStream, 0x40, meta.PackedSize, true)) using (var input = new BinaryStream(sreg, stream.Name)) { switch (meta.PackType) { case 5: // JPEG return(Jpeg.Read(input, info)); case 8: // PNG return(Png.Read(input, info)); case 0: // BMP case 2: // BMP+MASK bitmap = ReadFuckedUpBmpImage(input, info); break; case 7: // JPEG+MASK { var decoder = new JpegBitmapDecoder(input, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); bitmap = decoder.Frames[0]; break; } case 1: case 3: // PACKBMP+MASK { var reader = new DwqBmpReader(input, meta); reader.Unpack(); bitmap = BitmapSource.Create((int)info.Width, (int)info.Height, ImageData.DefaultDpiX, ImageData.DefaultDpiY, reader.Format, reader.Palette, reader.Data, reader.Stride); break; } } } if (null == bitmap) { throw new NotImplementedException(); } if (meta.HasAlpha) { int mask_offset = 0x40 + meta.PackedSize; if (mask_offset != stream.Length) { using (var mask = new StreamRegion(stream.AsStream, mask_offset, true)) { var reader = new DwqBmpReader(mask, meta); if (8 == reader.Format.BitsPerPixel) // mask should be represented as 8bpp bitmap { reader.Unpack(); var alpha = reader.Data; var palette = reader.Palette.Colors; for (int i = 0; i < alpha.Length; ++i) { int color_idx = alpha[i]; if (color_idx < palette.Count) { var color = palette[color_idx]; int A = (color.R + color.G + color.B) / 3; alpha[i] = (byte)A; } } bitmap = ApplyAlphaChannel(bitmap, alpha); } } } } bitmap.Freeze(); return(new ImageData(bitmap, meta)); }
private BitmapSource ReadFuckedUpBmpImage(Stream file, ImageMetaData info) { var header = new byte[0x36]; if (header.Length != file.Read(header, 0, header.Length)) { throw new InvalidFormatException(); } int w = LittleEndian.ToInt32(header, 0x12); int h = LittleEndian.ToInt32(header, 0x16); if (w != info.Width || h != info.Height) { throw new InvalidFormatException(); } int bpp = LittleEndian.ToUInt16(header, 0x1c); PixelFormat format; switch (bpp) { case 32: format = PixelFormats.Bgr32; break; case 24: format = PixelFormats.Bgr24; break; case 16: format = PixelFormats.Bgr565; break; case 8: format = PixelFormats.Indexed8; break; default: throw new NotImplementedException(); } BitmapPalette palette = null; if (8 == bpp) { int colors = Math.Min(LittleEndian.ToInt32(header, 0x2E), 0x100); palette = DwqBmpReader.ReadPalette(file, colors); } int pixel_size = bpp / 8; int stride = ((int)info.Width * pixel_size + 3) & ~3; var pixels = new byte[stride * info.Height]; if (pixels.Length != file.Read(pixels, 0, pixels.Length)) { throw new EndOfStreamException(); } if (bpp >= 24) { for (int row = 0; row < pixels.Length; row += stride) { for (int i = 2; i < stride; i += pixel_size) { var t = pixels[row + i]; pixels[row + i] = pixels[row + i - 2]; pixels[row + i - 2] = t; } } } return(BitmapSource.Create((int)info.Width, (int)info.Height, ImageData.DefaultDpiX, ImageData.DefaultDpiY, format, palette, pixels, stride)); }