diff --git a/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc b/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc index 7ee615853..7019aee2c 100644 --- a/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc +++ b/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc @@ -143,6 +143,12 @@ Class decl_PixelBuffer ("lay", "PixelBuffer", "\n" "The pixels are basically uninitialized. You will need to use \\fill to initialize them to a certain value." ) + + gsi::method ("==", &lay::PixelBuffer::operator==, gsi::arg ("other"), + "@brief Returns a value indicating whether self is identical to the other image\n" + ) + + gsi::method ("!=", &lay::PixelBuffer::operator!=, gsi::arg ("other"), + "@brief Returns a value indicating whether self is not identical to the other image\n" + ) + gsi::method ("transparent=", &lay::PixelBuffer::set_transparent, gsi::arg ("t"), "@brief Sets a flag indicating whether the pixel buffer supports an alpha channel\n" "\n" @@ -224,7 +230,9 @@ Class decl_PixelBuffer ("lay", "PixelBuffer", "transparency through an optional alpha channel. The color format for a pixel is " "\"0xAARRGGBB\" where 'AA' is the alpha value which is ignored in non-transparent mode.\n" "\n" - "This class supports basic operations such as initialization, single-pixel access and I/O to PNG." + "This class supports basic operations such as initialization, single-pixel access and I/O to PNG.\n" + "\n" + "This class has been introduced in version 0.28." ); @@ -335,6 +343,12 @@ Class decl_BitmapBuffer ("lay", "BitmapBuffer", "\n" "The pixels are basically uninitialized. You will need to use \\fill to initialize them to a certain value." ) + + gsi::method ("==", &lay::BitmapBuffer::operator==, gsi::arg ("other"), + "@brief Returns a value indicating whether self is identical to the other image\n" + ) + + gsi::method ("!=", &lay::BitmapBuffer::operator!=, gsi::arg ("other"), + "@brief Returns a value indicating whether self is not identical to the other image\n" + ) + gsi::method ("fill", &lay::BitmapBuffer::fill, gsi::arg ("color"), "@brief Fills the pixel buffer with the given pixel value\n" ) + @@ -391,7 +405,9 @@ Class decl_BitmapBuffer ("lay", "BitmapBuffer", "This object is mainly provided for offline rendering of layouts in Qt-less environments.\n" "It supports a rectangular pixel space with color values encoded in single bits.\n" "\n" - "This class supports basic operations such as initialization, single-pixel access and I/O to PNG." + "This class supports basic operations such as initialization, single-pixel access and I/O to PNG.\n" + "\n" + "This class has been introduced in version 0.28." ); } diff --git a/src/laybasic/laybasic/layPixelBuffer.cc b/src/laybasic/laybasic/layPixelBuffer.cc index d0e0f0d34..05aa56111 100644 --- a/src/laybasic/laybasic/layPixelBuffer.cc +++ b/src/laybasic/laybasic/layPixelBuffer.cc @@ -169,6 +169,31 @@ PixelBuffer::~PixelBuffer () // .. nothing yet .. } +bool +PixelBuffer::operator== (const PixelBuffer &other) const +{ + if (width () != other.width () || height () != other.height ()) { + return false; + } + if (transparent () != other.transparent ()) { + return false; + } + + lay::color_t m = transparent () ? 0xffffffff : 0xffffff; + for (unsigned int i = 0; i < other.height (); ++i) { + const lay::color_t *d = scan_line (i); + const lay::color_t *de = d + width (); + const lay::color_t *dd = other.scan_line (i); + while (d != de) { + if (((*d++ ^ *dd++) & m) != 0) { + return false; + } + } + } + + return true; +} + PixelBuffer & PixelBuffer::operator= (const PixelBuffer &other) { @@ -485,6 +510,34 @@ BitmapBuffer::~BitmapBuffer () // .. nothing yet .. } +bool +BitmapBuffer::operator== (const BitmapBuffer &other) const +{ + if (width () != other.width () || height () != other.height ()) { + return false; + } + + for (unsigned int i = 0; i < other.height (); ++i) { + const uint8_t *d = scan_line (i); + const uint8_t *dd = other.scan_line (i); + unsigned int bits_left = width (); + while (bits_left >= 8) { + if (*d++ != *dd++) { + return false; + } + bits_left -= 8; + } + if (bits_left > 0) { + unsigned int m = (0x01 << bits_left) - 1; + if (((*d ^ *dd) & m) != 0) { + return false; + } + } + } + + return true; +} + BitmapBuffer & BitmapBuffer::operator= (const BitmapBuffer &other) { diff --git a/src/laybasic/laybasic/layPixelBuffer.h b/src/laybasic/laybasic/layPixelBuffer.h index a5c811461..1a095f7c0 100644 --- a/src/laybasic/laybasic/layPixelBuffer.h +++ b/src/laybasic/laybasic/layPixelBuffer.h @@ -111,6 +111,19 @@ public: */ ~PixelBuffer (); + /** + * @brief Equality + */ + bool operator== (const PixelBuffer &other) const; + + /** + * @brief Inequality + */ + bool operator!= (const PixelBuffer &other) const + { + return !operator== (other); + } + /** * @brief Assignment */ @@ -334,6 +347,19 @@ public: */ BitmapBuffer (BitmapBuffer &&other); + /** + * @brief Equality + */ + bool operator== (const BitmapBuffer &other) const; + + /** + * @brief Inequality + */ + bool operator!= (const BitmapBuffer &other) const + { + return !operator== (other); + } + /** * @brief Destructor */ diff --git a/src/laybasic/unit_tests/layPixelBufferTests.cc b/src/laybasic/unit_tests/layPixelBufferTests.cc index f2a294288..b02ecc53d 100644 --- a/src/laybasic/unit_tests/layPixelBufferTests.cc +++ b/src/laybasic/unit_tests/layPixelBufferTests.cc @@ -74,35 +74,12 @@ static bool compare_images_mono (const QImage &qimg, const std::string &au) static bool compare_images (const lay::PixelBuffer &img, const lay::PixelBuffer &img2) { - if (img2.width () == img.width () && img2.height () == img.height ()) { - for (unsigned int j = 0; j < img.height (); ++j) { - for (unsigned int i = 0; i < img.width (); ++i) { - if (((const lay::color_t *) img.scan_line (j))[i] != ((const lay::color_t *) img2.scan_line (j))[i]) { - return false; - } - } - } - return true; - } else { - return false; - } + return img == img2; } static bool compare_images (const lay::BitmapBuffer &img, const lay::BitmapBuffer &img2) { - if (img2.width () == img.width () && img2.height () == img.height ()) { - // NOTE: slooooow ... - for (unsigned int j = 0; j < img.height (); ++j) { - for (unsigned int i = 0; i < img.width (); ++i) { - if ((img.scan_line (j)[i / 8] & (0x01 << (i % 8))) != (img2.scan_line (j)[i / 8] & (0x01 << (i % 8)))) { - return false; - } - } - } - return true; - } else { - return false; - } + return img == img2; } TEST(1) diff --git a/testdata/ruby/layPixelBuffer.rb b/testdata/ruby/layPixelBuffer.rb index eccaab81e..400df1338 100644 --- a/testdata/ruby/layPixelBuffer.rb +++ b/testdata/ruby/layPixelBuffer.rb @@ -41,17 +41,21 @@ class LAYPixelBuffer_TestClass < TestBase def test_1 - pb = RBA::PixelBuffer::new - assert_equal(pb.width, 0) - assert_equal(pb.height, 0) + pb_null = RBA::PixelBuffer::new + assert_equal(pb_null.width, 0) + assert_equal(pb_null.height, 0) pb = RBA::PixelBuffer::new(10, 20) + assert_equal(compare(pb_null, pb), false) + assert_equal(pb_null == pb, false) assert_equal(pb.width, 10) assert_equal(pb.height, 20) assert_equal(pb.transparent, false) + pb_copy = pb.dup pb.transparent = true assert_equal(pb.transparent, true) + assert_equal(pb_copy == pb, false) pb.fill(0xf0010203) assert_equal(pb.pixel(0, 0), 0xf0010203) @@ -66,12 +70,14 @@ class LAYPixelBuffer_TestClass < TestBase pb_copy = pb.dup assert_equal(compare(pb_copy, pb), true) + assert_equal(pb_copy == pb, true) pb.set_pixel(1, 2, 0x112233) assert_equal(pb.pixel(0, 0), 0xf0010203) assert_equal(pb.pixel(1, 2), 0xff112233) assert_equal(pb_copy.pixel(1, 2), 0xff102030) assert_equal(compare(pb_copy, pb), false) + assert_equal(pb_copy == pb, false) pb_copy.swap(pb) assert_equal(pb_copy.pixel(1, 2), 0xff112233) @@ -88,14 +94,40 @@ class LAYPixelBuffer_TestClass < TestBase pb.set_pixel(1, 2, 0x112233) assert_equal(compare(pb1, pb), false) + assert_equal(pb1 == pb, false) diff = pb1.diff(pb) pb1.patch(diff) assert_equal(compare(pb1, pb), true) + assert_equal(pb1 == pb, true) end def test_3 + + pb = RBA::PixelBuffer::new(10, 20) + pb.fill(0xf0010203) + + pb1 = pb.dup + pb.set_pixel(1, 2, 0x112233) + + pb1 = pb.dup + pb.set_pixel(1, 2, 0xf0112233) + assert_equal(compare(pb1, pb), true) + assert_equal(pb1 == pb, true) # not transparent -> alpha is ignored + + pb1.transparent = true + pb.transparent = true + assert_equal(compare(pb1, pb), true) + assert_equal(pb1 == pb, true) + + pb.set_pixel(1, 2, 0xf0112233) + assert_equal(compare(pb1, pb), false) + assert_equal(pb1 == pb, false) # now, alpha matters + + end + + def test_4 pb = RBA::PixelBuffer::new(10, 20) pb.transparent = true