From 0e2b11b73217e178de64ca227895b990a8740075 Mon Sep 17 00:00:00 2001 From: Patrick Ammann Date: Fri, 27 May 2016 16:18:54 +0200 Subject: [PATCH] #392 add support for negative height in bmp files Former-commit-id: eb6e82c54beabe1aa3b0a112561f07b0d1d290f9 Former-commit-id: d3121807246bb1798eeadabe2dcca7a7b5fea382 Former-commit-id: ece8ac1d7f29bf096d16481af5e42f63e2de71e0 --- .../Formats/Bmp/BmpDecoderCore.cs | 41 ++++++++++++------- .../ImageProcessorCore.Tests/FileTestBase.cs | 1 + .../Formats/Bmp/neg_height.bmp.REMOVED.git-id | 1 + 3 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 tests/ImageProcessorCore.Tests/TestImages/Formats/Bmp/neg_height.bmp.REMOVED.git-id diff --git a/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs b/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs index 55ec63f8c..da92e6a63 100644 --- a/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs @@ -67,6 +67,18 @@ namespace ImageProcessorCore.Formats this.ReadFileHeader(); this.ReadInfoHeader(); + // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517 + // If the height is negative, then this is a Windows bitmap whose origin + // is the upper-left corner and not the lower-left.The inverted flag + // indicates a lower-left origin.Our code will be outputting an + // upper-left origin pixel array. + bool inverted = false; + if (this.infoHeader.Height < 0) + { + inverted = true; + this.infoHeader.Height = -this.infoHeader.Height; + } + int colorMapSize = -1; if (this.infoHeader.ClrUsed == 0) @@ -118,15 +130,15 @@ namespace ImageProcessorCore.Formats if (this.infoHeader.BitsPerPixel == 32) { - this.ReadRgb32(imageData, this.infoHeader.Width, this.infoHeader.Height); + this.ReadRgb32(imageData, this.infoHeader.Width, this.infoHeader.Height, inverted); } else if (this.infoHeader.BitsPerPixel == 24) { - this.ReadRgb24(imageData, this.infoHeader.Width, this.infoHeader.Height); + this.ReadRgb24(imageData, this.infoHeader.Width, this.infoHeader.Height, inverted); } else if (this.infoHeader.BitsPerPixel == 16) { - this.ReadRgb16(imageData, this.infoHeader.Width, this.infoHeader.Height); + this.ReadRgb16(imageData, this.infoHeader.Width, this.infoHeader.Height, inverted); } else if (this.infoHeader.BitsPerPixel <= 8) { @@ -135,7 +147,8 @@ namespace ImageProcessorCore.Formats palette, this.infoHeader.Width, this.infoHeader.Height, - this.infoHeader.BitsPerPixel); + this.infoHeader.BitsPerPixel, + inverted); } break; @@ -157,11 +170,11 @@ namespace ImageProcessorCore.Formats /// The y- value representing the current row. /// The height of the bitmap. /// The representing the inverted value. - private static int Invert(int y, int height) + private static int Invert(int y, int height, bool inverted) { int row; - if (height > 0) + if (!inverted) { row = height - y - 1; } @@ -181,7 +194,7 @@ namespace ImageProcessorCore.Formats /// The width of the bitmap. /// The height of the bitmap. /// The number of bits per pixel. - private void ReadRgbPalette(float[] imageData, byte[] colors, int width, int height, int bits) + private void ReadRgbPalette(float[] imageData, byte[] colors, int width, int height, int bits, bool inverted) { // Pixels per byte (bits per pixel) int ppb = 8 / bits; @@ -214,7 +227,7 @@ namespace ImageProcessorCore.Formats int offset = rowOffset + x; // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height); + int row = Invert(y, height, inverted); int colOffset = x * ppb; @@ -240,7 +253,7 @@ namespace ImageProcessorCore.Formats /// The image data to assign the palette to. /// The width of the bitmap. /// The height of the bitmap. - private void ReadRgb16(float[] imageData, int width, int height) + private void ReadRgb16(float[] imageData, int width, int height, bool inverted) { // We divide here as we will store the colors in our floating point format. const float ScaleR = 0.25F; // (256 / 32) / 32 @@ -257,7 +270,7 @@ namespace ImageProcessorCore.Formats int rowOffset = y * ((width * 2) + alignment); // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height); + int row = Invert(y, height, inverted); for (int x = 0; x < width; x++) { @@ -286,7 +299,7 @@ namespace ImageProcessorCore.Formats /// The image data to assign the palette to. /// The width of the bitmap. /// The height of the bitmap. - private void ReadRgb24(float[] imageData, int width, int height) + private void ReadRgb24(float[] imageData, int width, int height, bool inverted) { int alignment; byte[] data = this.GetImageArray(width, height, 3, out alignment); @@ -299,7 +312,7 @@ namespace ImageProcessorCore.Formats int rowOffset = y * ((width * 3) + alignment); // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height); + int row = Invert(y, height, inverted); for (int x = 0; x < width; x++) { @@ -322,7 +335,7 @@ namespace ImageProcessorCore.Formats /// The image data to assign the palette to. /// The width of the bitmap. /// The height of the bitmap. - private void ReadRgb32(float[] imageData, int width, int height) + private void ReadRgb32(float[] imageData, int width, int height, bool inverted) { int alignment; byte[] data = this.GetImageArray(width, height, 4, out alignment); @@ -335,7 +348,7 @@ namespace ImageProcessorCore.Formats int rowOffset = y * ((width * 4) + alignment); // Revert the y value, because bitmaps are saved from down to top - int row = Invert(y, height); + int row = Invert(y, height, inverted); for (int x = 0; x < width; x++) { diff --git a/tests/ImageProcessorCore.Tests/FileTestBase.cs b/tests/ImageProcessorCore.Tests/FileTestBase.cs index d5471f429..100e74d0f 100644 --- a/tests/ImageProcessorCore.Tests/FileTestBase.cs +++ b/tests/ImageProcessorCore.Tests/FileTestBase.cs @@ -25,6 +25,7 @@ namespace ImageProcessorCore.Tests //"TestImages/Formats/Jpg/progress.jpg", // Perf: Enable for local testing only //"TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg", // Perf: Enable for local testing only "TestImages/Formats/Bmp/Car.bmp", + // "TestImages/Formats/Bmp/neg_height.bmp", // Perf: Enable for local testing only //"TestImages/Formats/Png/blur.png", // Perf: Enable for local testing only //"TestImages/Formats/Png/indexed.png", // Perf: Enable for local testing only "TestImages/Formats/Png/splash.png", diff --git a/tests/ImageProcessorCore.Tests/TestImages/Formats/Bmp/neg_height.bmp.REMOVED.git-id b/tests/ImageProcessorCore.Tests/TestImages/Formats/Bmp/neg_height.bmp.REMOVED.git-id new file mode 100644 index 000000000..5440f235d --- /dev/null +++ b/tests/ImageProcessorCore.Tests/TestImages/Formats/Bmp/neg_height.bmp.REMOVED.git-id @@ -0,0 +1 @@ +8f864b82464c595d7a81087d018db9994506e221 \ No newline at end of file