diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index 631130805c..f3c7f8c040 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -533,6 +533,14 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, wxON_BLOCK_EXIT1(&BMPPalette::Free, cmap); + bool isUpsideDown = true; + + if (height < 0) + { + isUpsideDown = false; + height = -height; + } + // destroy existing here instead of: image->Destroy(); image->Create(width, height); @@ -702,9 +710,10 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, // this case (see #10915) bool hasValidAlpha = false; - /* BMPs are stored upside down */ - for ( int line = (height - 1); line >= 0; line-- ) + for ( int row = 0; row < height; row++ ) { + int line = isUpsideDown ? height - 1 - row : row; + int linepos = 0; for ( int column = 0; column < width ; ) { @@ -734,21 +743,24 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { if ( aByte == 0 ) { - if ( column > 0 ) - column = width; + // end of scanline marker + column = width; + row--; } else if ( aByte == 1 ) { + // end of RLE data marker, stop decoding column = width; - line = -1; + row = height; } else if ( aByte == 2 ) { + // delta marker, move in image aByte = stream.GetC(); column += aByte; linepos = column * bpp / 4; aByte = stream.GetC(); - line -= aByte; // upside down + row += aByte; // upside down } else { @@ -817,20 +829,24 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { if ( aByte == 0 ) { - /* column = width; */ + // end of scanline marker + column = width; + row--; } else if ( aByte == 1 ) { + // end of RLE data marker, stop decoding column = width; - line = -1; + row = height; } else if ( aByte == 2 ) { + // delta marker, move in image aByte = stream.GetC(); column += aByte; linepos = column * bpp / 8; aByte = stream.GetC(); - line += aByte; + row -= aByte; } else { diff --git a/tests/image/horse_grey.bmp b/tests/image/horse_grey.bmp new file mode 100644 index 0000000000..b99ffd63ba Binary files /dev/null and b/tests/image/horse_grey.bmp differ diff --git a/tests/image/horse_grey_flipped.bmp b/tests/image/horse_grey_flipped.bmp new file mode 100644 index 0000000000..7cd67f3cb3 Binary files /dev/null and b/tests/image/horse_grey_flipped.bmp differ diff --git a/tests/image/horse_rle4.bmp b/tests/image/horse_rle4.bmp new file mode 100644 index 0000000000..bdc43a1f36 Binary files /dev/null and b/tests/image/horse_rle4.bmp differ diff --git a/tests/image/horse_rle4_flipped.bmp b/tests/image/horse_rle4_flipped.bmp new file mode 100644 index 0000000000..6f23188428 Binary files /dev/null and b/tests/image/horse_rle4_flipped.bmp differ diff --git a/tests/image/horse_rle8.bmp b/tests/image/horse_rle8.bmp new file mode 100644 index 0000000000..31dfc87571 Binary files /dev/null and b/tests/image/horse_rle8.bmp differ diff --git a/tests/image/horse_rle8_flipped.bmp b/tests/image/horse_rle8_flipped.bmp new file mode 100644 index 0000000000..bd16370397 Binary files /dev/null and b/tests/image/horse_rle8_flipped.bmp differ diff --git a/tests/image/image.cpp b/tests/image/image.cpp index 6b98ad4f3c..ae63591d8e 100644 --- a/tests/image/image.cpp +++ b/tests/image/image.cpp @@ -77,6 +77,7 @@ private: CPPUNIT_TEST( ReadCorruptedTGA ); CPPUNIT_TEST( GIFComment ); CPPUNIT_TEST( DibPadding ); + CPPUNIT_TEST( BMPFlippingAndRLECompression ); CPPUNIT_TEST_SUITE_END(); void LoadFromSocketStream(); @@ -90,6 +91,7 @@ private: void ReadCorruptedTGA(); void GIFComment(); void DibPadding(); + void BMPFlippingAndRLECompression(); DECLARE_NO_COPY_CLASS(ImageTestCase) }; @@ -1262,6 +1264,26 @@ void ImageTestCase::DibPadding() CPPUNIT_ASSERT( image.SaveFile(memOut, wxBITMAP_TYPE_ICO) ); } +static void CompareBMPImage(const wxString& file1, const wxString& file2) +{ + wxImage image1(file1); + CPPUNIT_ASSERT( image1.IsOk() ); + + wxImage image2(file2); + CPPUNIT_ASSERT( image2.IsOk() ); + + CompareImage(*wxImage::FindHandler(wxBITMAP_TYPE_BMP), image1, 0, &image2); +} + +void ImageTestCase::BMPFlippingAndRLECompression() +{ + CompareBMPImage("image/horse_grey.bmp", "image/horse_grey_flipped.bmp"); + + CompareBMPImage("image/horse_rle8.bmp", "image/horse_grey.bmp"); + CompareBMPImage("image/horse_rle8.bmp", "image/horse_rle8_flipped.bmp"); + + CompareBMPImage("image/horse_rle4.bmp", "image/horse_rle4_flipped.bmp"); +} #endif //wxUSE_IMAGE