Skip to content

Commit

Permalink
added parsing of the complete bitmap V4 header to get the color masks…
Browse files Browse the repository at this point in the history
… infos for the BITFIELDS compression
  • Loading branch information
brianpopow committed Dec 22, 2018
1 parent 8d44e6a commit da6c23e
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 38 deletions.
36 changes: 36 additions & 0 deletions src/ImageSharp/Formats/Bmp/BmpConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,41 @@ internal static class BmpConstants
/// The list of file extensions that equate to a bmp.
/// </summary>
public static readonly IEnumerable<string> FileExtensions = new[] { "bm", "bmp", "dip" };

/// <summary>
/// Valid magic bytes markers identifying a Bitmap file.
/// </summary>
internal static class TypeMarkers
{
/// <summary>
/// Single-image BMP file that may have been created under Windows or OS/2.
/// </summary>
public const int Bitmap = 19778;

/// <summary>
/// OS/2 Bitmap Array.
/// </summary>
public const int BitmapArray = 16706;

/// <summary>
/// OS/2 Color Icon.
/// </summary>
public const int ColorIcon = 18755;

/// <summary>
/// OS/2 Color Pointer.
/// </summary>
public const int ColorPointer = 20547;

/// <summary>
/// OS/2 Icon.
/// </summary>
public const int Icon = 17225;

/// <summary>
/// OS/2 Pointer.
/// </summary>
public const int Pointer = 21584;
}
}
}
44 changes: 30 additions & 14 deletions src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,22 +214,16 @@ private static int CalculatePadding(int width, int componentCount)
private void ReadBitFields<TPixel>(Buffer2D<TPixel> pixels, bool inverted)
where TPixel : struct, IPixel<TPixel>
{
byte[] buffer = new byte[12];
this.stream.Read(buffer, 0, 12);
Span<byte> data = buffer.AsSpan<byte>();
int redMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4));
int greenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4));
int blueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4));
if (this.infoHeader.BitsPerPixel == 16)
{
this.ReadRgb16(
pixels,
this.infoHeader.Width,
this.infoHeader.Height,
inverted,
redMask,
greenMask,
blueMask);
this.infoHeader.RedMask,
this.infoHeader.GreenMask,
this.infoHeader.BlueMask);
}
else
{
Expand All @@ -238,9 +232,9 @@ private void ReadBitFields<TPixel>(Buffer2D<TPixel> pixels, bool inverted)
this.infoHeader.Width,
this.infoHeader.Height,
inverted,
redMask,
greenMask,
blueMask);
this.infoHeader.RedMask,
this.infoHeader.GreenMask,
this.infoHeader.BlueMask);
}
}

Expand Down Expand Up @@ -601,6 +595,11 @@ private static int CalculateRightShift(uint n)
return count;
}

/// <summary>
/// Counts none zero bits.
/// </summary>
/// <param name="n">A color mask.</param>
/// <returns>The none zero bits.</returns>
private static int CountBits(uint n)
{
int count = 0;
Expand Down Expand Up @@ -651,10 +650,27 @@ private void ReadInfoHeader()
// 16 bytes
this.infoHeader = BmpInfoHeader.ParseOs22Short(buffer);
}
else if (headerSize >= BmpInfoHeader.Size)
else if (headerSize == BmpInfoHeader.SizeV3)
{
// == 40 bytes
this.infoHeader = BmpInfoHeader.ParseV3(buffer);

// if the info header is BMP version 3 and the compression type is BITFIELDS,
// color masks for each color channel follow the info header.
if (this.infoHeader.Compression == BmpCompression.BitFields)
{
byte[] bitfieldsBuffer = new byte[12];
this.stream.Read(bitfieldsBuffer, 0, 12);
Span<byte> data = bitfieldsBuffer.AsSpan<byte>();
this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4));
this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4));
this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4));
}
}
else if (headerSize >= BmpInfoHeader.SizeV3)
{
// >= 40 bytes
this.infoHeader = BmpInfoHeader.Parse(buffer);
this.infoHeader = BmpInfoHeader.ParseV4(buffer);
}
else
{
Expand Down
Loading

0 comments on commit da6c23e

Please sign in to comment.