public static void ReadRgb16(ImageBinReader reader, Span <byte> destination) { Debug.Assert(reader != null); const ushort fiveBitMask = 31; var px = (ushort)reader.ReadInt16LE(); int b = px & fiveBitMask; int g = (px >> 5) & fiveBitMask; int r = (px >> 10) & fiveBitMask; destination[2] = (byte)(b * 255 / 31); destination[1] = (byte)(g * 255 / 31); destination[0] = (byte)(r * 255 / 31); }
public static BmpInfo?ParseHeader(ImageBinReader s, ReadState ri) { if (s == null) { throw new ArgumentNullException(nameof(s)); } if (ri == null) { throw new ArgumentNullException(nameof(ri)); } Span <byte> tmp = stackalloc byte[HeaderSize]; if (!s.TryReadBytes(tmp)) { return(null); } if (!Test(tmp)) { throw new StbImageReadException(ErrorCode.UnknownFormat); } var info = new BmpInfo(); s.ReadInt32LE(); s.ReadInt16LE(); s.ReadInt16LE(); info.offset = s.ReadInt32LE(); info.headerSize = s.ReadInt32LE(); info.mr = info.mg = info.mb = info.ma = 0; if (info.headerSize != 12 && info.headerSize != 40 && info.headerSize != 56 && info.headerSize != 108 && info.headerSize != 124) { throw new StbImageReadException(ErrorCode.UnknownHeader); } if (info.headerSize == 12) { ri.Width = s.ReadInt16LE(); ri.Height = s.ReadInt16LE(); } else { ri.Width = s.ReadInt32LE(); ri.Height = s.ReadInt32LE(); } ri.Orientation = ri.Height > 0 ? ImageOrientation.BottomLeftOrigin : ImageOrientation.TopLeftOrigin; ri.Height = Math.Abs(ri.Height); if (s.ReadInt16LE() != 1) { throw new StbImageReadException(ErrorCode.BadColorPlane); } info.bitsPerPixel = s.ReadInt16LE(); if (info.bitsPerPixel == 1) { throw new StbImageReadException(ErrorCode.MonochromeNotSupported); } if (info.headerSize != 12) { int compress = s.ReadInt32LE(); if ((compress == 1) || (compress == 2)) { throw new StbImageReadException(ErrorCode.RLENotSupported); } s.ReadInt32LE(); s.ReadInt32LE(); s.ReadInt32LE(); s.ReadInt32LE(); s.ReadInt32LE(); if (info.headerSize == 40 || info.headerSize == 56) { if (info.headerSize == 56) { s.ReadInt32LE(); s.ReadInt32LE(); s.ReadInt32LE(); s.ReadInt32LE(); } if ((info.bitsPerPixel == 16) || (info.bitsPerPixel == 32)) { if (compress == 0) { if (info.bitsPerPixel == 32) { info.mr = 0xffu << 16; info.mg = 0xffu << 8; info.mb = 0xffu << 0; info.ma = 0xffu << 24; } else { info.mr = 31 << 10; info.mg = 31 << 5; info.mb = 31 << 0; } } else if (compress == 3) { info.mr = s.ReadUInt32LE(); info.mg = s.ReadUInt32LE(); info.mb = s.ReadUInt32LE(); if ((info.mr == info.mg) && (info.mg == info.mb)) { throw new StbImageReadException(ErrorCode.BadMasks); } } else { throw new StbImageReadException(ErrorCode.BadCompression); } } } else { if (info.headerSize != 108 && info.headerSize != 124) { throw new StbImageReadException(ErrorCode.UnknownHeader); } info.mr = s.ReadUInt32LE(); info.mg = s.ReadUInt32LE(); info.mb = s.ReadUInt32LE(); info.ma = s.ReadUInt32LE(); s.ReadInt32LE(); for (int i = 0; i < 12; ++i) { s.ReadInt32LE(); } if (info.headerSize == 124) { for (int i = 0; i < 4; ++i) { s.ReadInt32LE(); } } } } if (info.bitsPerPixel == 24 && info.ma == 0xffu << 24) { ri.Components = 3; } else { ri.Components = info.ma != 0 ? 4 : 3; } ri.Depth = info.bitsPerPixel / ri.Components; return(info); }
public static TgaInfo ParseHeader(ImageBinReader reader, ReadState state) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (state == null) { throw new ArgumentNullException(nameof(state)); } Span <byte> tmp = stackalloc byte[HeaderSize]; if (!reader.TryReadBytes(tmp)) { throw new EndOfStreamException(); } bool test = TestCore(tmp, out var info); if (info.colormap_type == 1) { if (info.image_type != 1 && info.image_type != 9) { throw new StbImageReadException(ErrorCode.BadImageType); } info.palette_start = reader.ReadInt16LE(); info.palette_len = reader.ReadInt16LE(); info.palette_bpp = reader.ReadByte(); if (info.palette_bpp != 8 && info.palette_bpp != 15 && info.palette_bpp != 16 && info.palette_bpp != 24 && info.palette_bpp != 32) { throw new StbImageReadException(ErrorCode.BadPalette); } } else { if (info.image_type != 2 && info.image_type != 3 && info.image_type != 10 && info.image_type != 11) { throw new StbImageReadException(ErrorCode.BadImageType); } reader.Skip(5); // 16bit: Color Map Origin // 16bit: Color Map Length // 8bit: Color Map Entry Size } Debug.Assert(test); // Prior checks should throw if test was unsucessful. info.x_origin = reader.ReadInt16LE(); info.y_origin = reader.ReadInt16LE(); state.Width = reader.ReadUInt16LE(); if (state.Width < 1) { throw new StbImageReadException(ErrorCode.ZeroWidth); } state.Height = reader.ReadUInt16LE(); if (state.Height < 1) { throw new StbImageReadException(ErrorCode.ZeroHeight); } info.bits_per_pixel = reader.ReadByte(); info.inverted = reader.ReadByte(); info.inverted = 1 - ((info.inverted >> 5) & 1); // use the number of bits from the palette if paletted if (info.palette_bpp != 0) { if (info.bits_per_pixel != 8 && info.bits_per_pixel != 16) { throw new StbImageReadException(ErrorCode.BadBitsPerPixel); } state.Components = GetComponentCount( info.palette_bpp, false, out state.Depth); } else { state.Components = GetComponentCount( info.bits_per_pixel, info.image_type == 3, out state.Depth); } if (state.Components == 0) { throw new StbImageReadException(ErrorCode.BadComponentCount); } state.OutComponents = state.Components; state.OutDepth = state.Depth; state.Orientation = ImageOrientation.LeftToRight | (info.inverted != 0 ? ImageOrientation.BottomToTop : ImageOrientation.TopToBottom); state.StateReady(); return(info); }