-
-
Notifications
You must be signed in to change notification settings - Fork 888
Add support for Portable Bitmap images #1851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 10 commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
0c45f37
Merge pull request #1 from SixLabors/master
ynse01 319beee
Merge branch 'SixLabors:master' into master
ynse01 065cb1c
Fix vanilla build on VS2019
ynse01 251e802
Revert of: Fix vanilla build on VS2019
ynse01 49d9266
Merge branch 'master' of https://github.com/ynse01/ImageSharp
ynse01 100e788
Merge branch 'SixLabors:master' into master
ynse01 a13eae6
Merge branch 'SixLabors:master' into master
ynse01 7510250
Support Pbm, Pgm and Ppm images
ynse01 b87362d
Fix style warning in BinaryDecoder
ynse01 5939bf8
Restore LangVersion
ynse01 0c8c892
Process first round of review comments
ynse01 0e984cf
Remove non existing LFS objects
ynse01 e21d2c3
Put back missing LFS objects
ynse01 7d1c3b5
Remove test images, so they can be moved to LFS
ynse01 c600274
Merge branch 'SixLabors:master' into pgm-support
ynse01 593c84c
Merge branch 'pgm-support' of https://github.com/ynse01/ImageSharp in…
ynse01 2b00a22
Put the test images back into LFS
ynse01 9599efe
Update .gitattributes file
ynse01 58a1dd8
Merge branch 'master' into pgm-support
JimBobSquarePants cf8e184
Revert stack allocation in Plain Encoder
ynse01 87ce4e5
Various review comments
ynse01 a5e1723
Dispose of images after use, in Pbm Round Trip Test
ynse01 e17ebe6
Merge branch 'master' into pgm-support
JimBobSquarePants 26b3e66
Fix bug in black and white plain decoding
ynse01 5587770
Merge branch 'pgm-support' of https://github.com/ynse01/ImageSharp in…
ynse01 c4cf012
Scale pixel value up to full allocation range
ynse01 a5af74e
Merge branch 'master' into pgm-support
antonfirsov 284772c
Push input images to LFS again
ynse01 20b0349
NeedsUpscaling code improvements
ynse01 3a0a044
Improve exception messages
ynse01 61cfa66
Make variables as const if possible
ynse01 5e27397
Merge branch 'master' into pgm-support
brianpopow dd49f9a
Single image compare utils for multiple Formats
ynse01 1aa27bd
Add Magick compatible input image
ynse01 093e1ae
Add missing using
brianpopow f09641c
Cleanup
brianpopow a581ab6
Merge branch 'master' into pgm-support
brianpopow f6301d4
Refactor Pbm option enums
ynse01 7494525
Write EOF indicated for plain encoding
ynse01 b2bc25c
No need to await async PbmDecoder methods
ynse01 efece70
Partial revert of b2bc25c
ynse01 6619809
Merge remote-tracking branch 'upstream/master' into pgm-support
ynse01 3730a02
Fix build after merge
ynse01 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ using SixLabors.ImageSharp.Advanced; | |
| "Bmp", | ||
| "Gif", | ||
| "Jpeg", | ||
| "Pbm", | ||
| "Png", | ||
| "Tga", | ||
| "Webp", | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| // Copyright (c) Six Labors. | ||
| // Licensed under the Apache License, Version 2.0. | ||
|
|
||
| using System; | ||
| using System.Buffers; | ||
| using SixLabors.ImageSharp.IO; | ||
| using SixLabors.ImageSharp.Memory; | ||
| using SixLabors.ImageSharp.PixelFormats; | ||
|
|
||
| namespace SixLabors.ImageSharp.Formats.Pbm | ||
| { | ||
| /// <summary> | ||
| /// Pixel decoding methods for the PBM binary encoding. | ||
| /// </summary> | ||
| internal class BinaryDecoder | ||
| { | ||
| /// <summary> | ||
| /// Decode the specified pixels. | ||
| /// </summary> | ||
| /// <typeparam name="TPixel">The type of pixel to encode to.</typeparam> | ||
| /// <param name="configuration">The configuration.</param> | ||
| /// <param name="pixels">The pixel array to encode into.</param> | ||
| /// <param name="stream">The stream to read the data from.</param> | ||
| /// <param name="colorType">The ColorType to decode.</param> | ||
| /// <param name="maxPixelValue">The maximum expected pixel value</param> | ||
| /// <exception cref="InvalidImageContentException"> | ||
| /// Thrown if an invalid combination of setting is requested. | ||
| /// </exception> | ||
| public static void Process<TPixel>(Configuration configuration, Buffer2D<TPixel> pixels, BufferedReadStream stream, PbmColorType colorType, int maxPixelValue) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| if (colorType == PbmColorType.Grayscale) | ||
| { | ||
| if (maxPixelValue < 256) | ||
| { | ||
| ProcessGrayscale(configuration, pixels, stream); | ||
| } | ||
| else | ||
| { | ||
| ProcessWideGrayscale(configuration, pixels, stream); | ||
| } | ||
| } | ||
| else if (colorType == PbmColorType.Rgb) | ||
| { | ||
| if (maxPixelValue < 256) | ||
| { | ||
| ProcessRgb(configuration, pixels, stream); | ||
| } | ||
| else | ||
| { | ||
| ProcessWideRgb(configuration, pixels, stream); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| ProcessBlackAndWhite(configuration, pixels, stream); | ||
| } | ||
| } | ||
|
|
||
| private static void ProcessGrayscale<TPixel>(Configuration configuration, Buffer2D<TPixel> pixels, BufferedReadStream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| int width = pixels.Width; | ||
| int height = pixels.Height; | ||
| int bytesPerPixel = 1; | ||
| MemoryAllocator allocator = configuration.MemoryAllocator; | ||
| using IMemoryOwner<byte> row = allocator.Allocate<byte>(width * bytesPerPixel); | ||
| Span<byte> rowSpan = row.GetSpan(); | ||
|
|
||
| for (int y = 0; y < height; y++) | ||
| { | ||
| stream.Read(rowSpan); | ||
| Span<TPixel> pixelSpan = pixels.GetRowSpan(y); | ||
| PixelOperations<TPixel>.Instance.FromL8Bytes( | ||
| configuration, | ||
| rowSpan, | ||
| pixelSpan, | ||
| width); | ||
| } | ||
| } | ||
|
|
||
| private static void ProcessWideGrayscale<TPixel>(Configuration configuration, Buffer2D<TPixel> pixels, BufferedReadStream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| int width = pixels.Width; | ||
| int height = pixels.Height; | ||
| int bytesPerPixel = 2; | ||
| MemoryAllocator allocator = configuration.MemoryAllocator; | ||
| using IMemoryOwner<byte> row = allocator.Allocate<byte>(width * bytesPerPixel); | ||
| Span<byte> rowSpan = row.GetSpan(); | ||
|
|
||
| for (int y = 0; y < height; y++) | ||
| { | ||
| stream.Read(rowSpan); | ||
| Span<TPixel> pixelSpan = pixels.GetRowSpan(y); | ||
| PixelOperations<TPixel>.Instance.FromL16Bytes( | ||
| configuration, | ||
| rowSpan, | ||
| pixelSpan, | ||
| width); | ||
| } | ||
| } | ||
|
|
||
| private static void ProcessRgb<TPixel>(Configuration configuration, Buffer2D<TPixel> pixels, BufferedReadStream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| int width = pixels.Width; | ||
| int height = pixels.Height; | ||
| int bytesPerPixel = 3; | ||
| MemoryAllocator allocator = configuration.MemoryAllocator; | ||
| using IMemoryOwner<byte> row = allocator.Allocate<byte>(width * bytesPerPixel); | ||
| Span<byte> rowSpan = row.GetSpan(); | ||
|
|
||
| for (int y = 0; y < height; y++) | ||
| { | ||
| stream.Read(rowSpan); | ||
| Span<TPixel> pixelSpan = pixels.GetRowSpan(y); | ||
| PixelOperations<TPixel>.Instance.FromRgb24Bytes( | ||
| configuration, | ||
| rowSpan, | ||
| pixelSpan, | ||
| width); | ||
| } | ||
| } | ||
|
|
||
| private static void ProcessWideRgb<TPixel>(Configuration configuration, Buffer2D<TPixel> pixels, BufferedReadStream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| int width = pixels.Width; | ||
| int height = pixels.Height; | ||
| int bytesPerPixel = 6; | ||
| MemoryAllocator allocator = configuration.MemoryAllocator; | ||
| using IMemoryOwner<byte> row = allocator.Allocate<byte>(width * bytesPerPixel); | ||
| Span<byte> rowSpan = row.GetSpan(); | ||
|
|
||
| for (int y = 0; y < height; y++) | ||
| { | ||
| stream.Read(rowSpan); | ||
| Span<TPixel> pixelSpan = pixels.GetRowSpan(y); | ||
| PixelOperations<TPixel>.Instance.FromRgb48Bytes( | ||
| configuration, | ||
| rowSpan, | ||
| pixelSpan, | ||
| width); | ||
| } | ||
| } | ||
|
|
||
| private static void ProcessBlackAndWhite<TPixel>(Configuration configuration, Buffer2D<TPixel> pixels, BufferedReadStream stream) | ||
| where TPixel : unmanaged, IPixel<TPixel> | ||
| { | ||
| int width = pixels.Width; | ||
| int height = pixels.Height; | ||
| int startBit = 0; | ||
| MemoryAllocator allocator = configuration.MemoryAllocator; | ||
| using IMemoryOwner<L8> row = allocator.Allocate<L8>(width); | ||
| Span<L8> rowSpan = row.GetSpan(); | ||
| var white = new L8(255); | ||
| var black = new L8(0); | ||
|
|
||
| for (int y = 0; y < height; y++) | ||
| { | ||
| for (int x = 0; x < width;) | ||
| { | ||
| int raw = stream.ReadByte(); | ||
| int bit = startBit; | ||
| startBit = 0; | ||
| for (; bit < 8; bit++) | ||
| { | ||
| bool bitValue = (raw & (0x80 >> bit)) != 0; | ||
| rowSpan[x] = bitValue ? black : white; | ||
| x++; | ||
| if (x == width) | ||
| { | ||
| startBit = (bit + 1) % 8; | ||
ynse01 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (startBit != 0) | ||
| { | ||
| stream.Seek(-1, System.IO.SeekOrigin.Current); | ||
| } | ||
|
|
||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Span<TPixel> pixelSpan = pixels.GetRowSpan(y); | ||
| PixelOperations<TPixel>.Instance.FromL8( | ||
| configuration, | ||
| rowSpan, | ||
| pixelSpan); | ||
| } | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.