Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions src/ImageSharp/Formats/Bmp/BmpCompression.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.

namespace SixLabors.ImageSharp.Formats.Bmp
{
/// <summary>
/// Defines how the compression type of the image data
/// Defines the compression type of the image data
/// in the bitmap file.
/// </summary>
internal enum BmpCompression : int
Expand All @@ -21,7 +21,7 @@ internal enum BmpCompression : int

/// <summary>
/// Two bytes are one data record. If the first byte is not zero, the
/// next two half bytes will be repeated as much as the value of the first byte.
/// next byte will be repeated as much as the value of the first byte.
/// If the first byte is zero, the record has different meanings, depending
/// on the second byte. If the second byte is zero, it is the end of the row,
/// if it is one, it is the end of the image.
Expand All @@ -30,7 +30,7 @@ internal enum BmpCompression : int

/// <summary>
/// Two bytes are one data record. If the first byte is not zero, the
/// next byte will be repeated as much as the value of the first byte.
/// next two half bytes will be repeated as much as the value of the first byte.
/// If the first byte is zero, the record has different meanings, depending
/// on the second byte. If the second byte is zero, it is the end of the row,
/// if it is one, it is the end of the image.
Expand Down Expand Up @@ -60,6 +60,17 @@ internal enum BmpCompression : int
/// Specifies that the bitmap is not compressed and that the color table consists of four DWORD color
/// masks that specify the red, green, blue, and alpha components of each pixel.
/// </summary>
BI_ALPHABITFIELDS = 6
BI_ALPHABITFIELDS = 6,

/// <summary>
/// OS/2 specific compression type.
/// Similar to run length encoding of 4 and 8 bit.
/// The only difference is that run values encoded are three bytes in size (one byte per RGB color component),
/// rather than four or eight bits in size.
///
/// Note: Because compression value of 4 is ambiguous for BI_RGB for windows and RLE24 for OS/2, the enum value is remapped
/// to a different value.
/// </summary>
RLE24 = 100,
}
}
}
227 changes: 200 additions & 27 deletions src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions src/ImageSharp/Formats/Bmp/BmpFileMarkerType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.

namespace SixLabors.ImageSharp.Formats.Bmp
{
/// <summary>
/// Indicates which bitmap file marker was read.
/// </summary>
public enum BmpFileMarkerType
{
/// <summary>
/// Single-image BMP file that may have been created under Windows or OS/2.
/// </summary>
Bitmap,

/// <summary>
/// OS/2 Bitmap Array.
/// </summary>
BitmapArray,

/// <summary>
/// OS/2 Color Icon.
/// </summary>
ColorIcon,

/// <summary>
/// OS/2 Color Pointer.
/// </summary>
ColorPointer,

/// <summary>
/// OS/2 Icon.
/// </summary>
Icon,

/// <summary>
/// OS/2 Pointer.
/// </summary>
Pointer
}
}
6 changes: 5 additions & 1 deletion src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,12 @@ public static BmpInfoHeader ParseOs2Version2(ReadOnlySpan<byte> data)
case 2:
infoHeader.Compression = BmpCompression.RLE4;
break;
case 4:
infoHeader.Compression = BmpCompression.RLE24;
break;
default:
BmpThrowHelper.ThrowImageFormatException($"Compression type is not supported. ImageSharp only supports uncompressed, RLE4 and RLE8.");
// Compression type 3 (1DHuffman) is not supported.
BmpThrowHelper.ThrowImageFormatException("Compression type is not supported. ImageSharp only supports uncompressed, RLE4, RLE8 and RLE24.");
break;
}

Expand Down
17 changes: 17 additions & 0 deletions tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,22 @@ public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit<TPixel>(TestImageProvider
}
}

[Theory]
[WithFile(RLE24, PixelTypes.Rgba32)]
[WithFile(RLE24Cut, PixelTypes.Rgba32)]
[WithFile(RLE24Delta, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_RunLengthEncoded_24Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new BmpDecoder() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black }))
{
image.DebugSave(provider);

// TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file.
// image.CompareToOriginal(provider);
}
}

[Theory]
[WithFile(RgbaAlphaBitfields, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeAlphaBitfields<TPixel>(TestImageProvider<TPixel> provider)
Expand Down Expand Up @@ -521,6 +537,7 @@ public void BmpDecoder_CanDecode_Os2v2Header<TPixel>(TestImageProvider<TPixel> p
}

[Theory]
[WithFile(Os2BitmapArray, PixelTypes.Rgba32)]
[WithFile(Os2BitmapArray9s, PixelTypes.Rgba32)]
[WithFile(Os2BitmapArrayDiamond, PixelTypes.Rgba32)]
[WithFile(Os2BitmapArraySkater, PixelTypes.Rgba32)]
Expand Down
4 changes: 4 additions & 0 deletions tests/ImageSharp.Tests/TestImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ public static class Bmp
public const string NegHeight = "Bmp/neg_height.bmp";
public const string CoreHeader = "Bmp/BitmapCoreHeaderQR.bmp";
public const string V5Header = "Bmp/BITMAPV5HEADER.bmp";
public const string RLE24 = "Bmp/rgb24rle24.bmp";
public const string RLE24Cut = "Bmp/rle24rlecut.bmp";
public const string RLE24Delta = "Bmp/rle24rlecut.bmp";
public const string RLE8 = "Bmp/RunLengthEncoded.bmp";
public const string RLE8Cut = "Bmp/pal8rlecut.bmp";
public const string RLE8Delta = "Bmp/pal8rletrns.bmp";
Expand Down Expand Up @@ -262,6 +265,7 @@ public static class Bmp
public const string Bit8Palette4 = "Bmp/pal8-0.bmp";
public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp";
public const string Os2v2 = "Bmp/pal8os2v2.bmp";
public const string Os2BitmapArray = "Bmp/ba-bm.bmp";
public const string Os2BitmapArray9s = "Bmp/9S.BMP";
public const string Os2BitmapArrayDiamond = "Bmp/DIAMOND.BMP";
public const string Os2BitmapArrayMarble = "Bmp/GMARBLE.BMP";
Expand Down
Binary file added tests/Images/Input/Bmp/ba-bm.bmp
Binary file not shown.
Binary file added tests/Images/Input/Bmp/rgb24rle24.bmp
Binary file not shown.
Binary file added tests/Images/Input/Bmp/rle24rlecut.bmp
Binary file not shown.
Binary file added tests/Images/Input/Bmp/rle24rletrns.bmp
Binary file not shown.