Equality operator in PixelBuffer

This commit is contained in:
Matthias Koefferlein 2022-05-07 18:48:45 +02:00
parent 958e1f7c59
commit 101544ab78
5 changed files with 134 additions and 30 deletions

View File

@ -143,6 +143,12 @@ Class<lay::PixelBuffer> 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<lay::PixelBuffer> 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<lay::BitmapBuffer> 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<lay::BitmapBuffer> 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."
);
}

View File

@ -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)
{

View File

@ -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
*/

View File

@ -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)

View File

@ -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