Skip to content

Commit f88ec76

Browse files
Merge pull request #2481 from ynse01/issue-2477
Fix for B&W pbm images with width not dividable by 8
2 parents bf43044 + 4c70682 commit f88ec76

File tree

7 files changed

+38
-32
lines changed

7 files changed

+38
-32
lines changed

src/ImageSharp/Formats/Pbm/BinaryDecoder.cs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ private static void ProcessBlackAndWhite<TPixel>(Configuration configuration, Bu
152152
{
153153
int width = pixels.Width;
154154
int height = pixels.Height;
155-
int startBit = 0;
156155
MemoryAllocator allocator = configuration.MemoryAllocator;
157156
using IMemoryOwner<L8> row = allocator.Allocate<L8>(width);
158157
Span<L8> rowSpan = row.GetSpan();
@@ -162,23 +161,12 @@ private static void ProcessBlackAndWhite<TPixel>(Configuration configuration, Bu
162161
for (int x = 0; x < width;)
163162
{
164163
int raw = stream.ReadByte();
165-
int bit = startBit;
166-
startBit = 0;
167-
for (; bit < 8; bit++)
164+
int stopBit = Math.Min(8, width - x);
165+
for (int bit = 0; bit < stopBit; bit++)
168166
{
169167
bool bitValue = (raw & (0x80 >> bit)) != 0;
170168
rowSpan[x] = bitValue ? black : white;
171169
x++;
172-
if (x == width)
173-
{
174-
startBit = (bit + 1) & 7; // Round off to below 8.
175-
if (startBit != 0)
176-
{
177-
stream.Seek(-1, System.IO.SeekOrigin.Current);
178-
}
179-
180-
break;
181-
}
182170
}
183171
}
184172

src/ImageSharp/Formats/Pbm/BinaryEncoder.cs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,40 @@ public static void WritePixels<TPixel>(Configuration configuration, Stream strea
3333
{
3434
WriteGrayscale(configuration, stream, image);
3535
}
36-
else
36+
else if (componentType == PbmComponentType.Short)
3737
{
3838
WriteWideGrayscale(configuration, stream, image);
3939
}
40+
else
41+
{
42+
throw new ImageFormatException("Component type not supported for Grayscale PBM.");
43+
}
4044
}
4145
else if (colorType == PbmColorType.Rgb)
4246
{
4347
if (componentType == PbmComponentType.Byte)
4448
{
4549
WriteRgb(configuration, stream, image);
4650
}
47-
else
51+
else if (componentType == PbmComponentType.Short)
4852
{
4953
WriteWideRgb(configuration, stream, image);
5054
}
55+
else
56+
{
57+
throw new ImageFormatException("Component type not supported for Color PBM.");
58+
}
5159
}
5260
else
5361
{
54-
WriteBlackAndWhite(configuration, stream, image);
62+
if (componentType == PbmComponentType.Bit)
63+
{
64+
WriteBlackAndWhite(configuration, stream, image);
65+
}
66+
else
67+
{
68+
throw new ImageFormatException("Component type not supported for Black & White PBM.");
69+
}
5570
}
5671
}
5772

@@ -164,8 +179,6 @@ private static void WriteBlackAndWhite<TPixel>(Configuration configuration, Stre
164179
using IMemoryOwner<L8> row = allocator.Allocate<L8>(width);
165180
Span<L8> rowSpan = row.GetSpan();
166181

167-
int previousValue = 0;
168-
int startBit = 0;
169182
for (int y = 0; y < height; y++)
170183
{
171184
Span<TPixel> pixelSpan = pixelBuffer.DangerousGetRowSpan(y);
@@ -177,28 +190,19 @@ private static void WriteBlackAndWhite<TPixel>(Configuration configuration, Stre
177190

178191
for (int x = 0; x < width;)
179192
{
180-
int value = previousValue;
181-
for (int i = startBit; i < 8; i++)
193+
int value = 0;
194+
int stopBit = Math.Min(8, width - x);
195+
for (int i = 0; i < stopBit; i++)
182196
{
183197
if (rowSpan[x].PackedValue < 128)
184198
{
185199
value |= 0x80 >> i;
186200
}
187201

188202
x++;
189-
if (x == width)
190-
{
191-
previousValue = value;
192-
startBit = (i + 1) & 7; // Round off to below 8.
193-
break;
194-
}
195203
}
196204

197-
if (startBit == 0)
198-
{
199-
stream.WriteByte((byte)value);
200-
previousValue = 0;
201-
}
205+
stream.WriteByte((byte)value);
202206
}
203207
}
204208
}

tests/ImageSharp.Tests/Formats/Pbm/PbmDecoderTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public void ImageLoadRgb24CanDecode(string imagePath)
8181
[Theory]
8282
[WithFile(BlackAndWhitePlain, PixelTypes.L8, "pbm")]
8383
[WithFile(BlackAndWhiteBinary, PixelTypes.L8, "pbm")]
84+
[WithFile(Issue2477, PixelTypes.L8, "pbm")]
8485
[WithFile(GrayscalePlain, PixelTypes.L8, "pgm")]
8586
[WithFile(GrayscalePlainNormalized, PixelTypes.L8, "pgm")]
8687
[WithFile(GrayscaleBinary, PixelTypes.L8, "pgm")]

tests/ImageSharp.Tests/Formats/Pbm/PbmEncoderTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class PbmEncoderTests
2626
{
2727
{ BlackAndWhiteBinary, PbmColorType.BlackAndWhite },
2828
{ BlackAndWhitePlain, PbmColorType.BlackAndWhite },
29+
{ Issue2477, PbmColorType.BlackAndWhite },
2930
{ GrayscaleBinary, PbmColorType.Grayscale },
3031
{ GrayscaleBinaryWide, PbmColorType.Grayscale },
3132
{ GrayscalePlain, PbmColorType.Grayscale },
@@ -96,6 +97,11 @@ public void PbmEncoder_P1_Works<TPixel>(TestImageProvider<TPixel> provider)
9697
public void PbmEncoder_P4_Works<TPixel>(TestImageProvider<TPixel> provider)
9798
where TPixel : unmanaged, IPixel<TPixel> => TestPbmEncoderCore(provider, PbmColorType.BlackAndWhite, PbmEncoding.Binary);
9899

100+
[Theory]
101+
[WithFile(Issue2477, PixelTypes.Rgb24)]
102+
public void PbmEncoder_P4_Irregular_Works<TPixel>(TestImageProvider<TPixel> provider)
103+
where TPixel : unmanaged, IPixel<TPixel> => TestPbmEncoderCore(provider, PbmColorType.BlackAndWhite, PbmEncoding.Binary);
104+
99105
[Theory]
100106
[WithFile(GrayscalePlainMagick, PixelTypes.Rgb24)]
101107
public void PbmEncoder_P2_Works<TPixel>(TestImageProvider<TPixel> provider)

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,5 +1038,6 @@ public static class Pbm
10381038
public const string RgbPlain = "Pbm/rgb_plain.ppm";
10391039
public const string RgbPlainNormalized = "Pbm/rgb_plain_normalized.ppm";
10401040
public const string RgbPlainMagick = "Pbm/rgb_plain_magick.ppm";
1041+
public const string Issue2477 = "Pbm/issue2477.pbm";
10411042
}
10421043
}
Lines changed: 3 additions & 0 deletions
Loading

tests/Images/Input/Pbm/issue2477.pbm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:d625635f7be760fbea935056c0f6d046832dd74bba33a1597b52ab3dfe0c5e4e
3+
size 4956

0 commit comments

Comments
 (0)