@@ -342,6 +342,8 @@ class SourceImageTester
342
342
QMouseEvent mouseReleased (QEvent::Type::MouseButtonRelease, pos, Qt::MouseButton::LeftButton, (canceled ? Qt::MouseButton::RightButton : Qt::MouseButton::NoButton), Qt::KeyboardModifier::NoModifier);
343
343
m_imageToTest.mouseReleaseEvent (&mouseReleased);
344
344
}
345
+
346
+ inline QImage& fullImage () { return m_imageToTest.image ; }
345
347
private:
346
348
SourceImage& m_imageToTest;
347
349
};
@@ -443,6 +445,71 @@ TEST_CASE("test initial image load") {
443
445
testFileLoad (resourceUrl, testImage, QString (" Use 0, 0 (w:400, h:400)" ), expectedSize);
444
446
}
445
447
448
+ const std::string qrgbToHexString (const QRgb& in_color)
449
+ {
450
+ std::stringstream formatted{};
451
+ formatted << " #" << std::setfill (' 0' ) << std::hex;
452
+ for (auto i = 0 ; i < 4 ; ++i) {
453
+ formatted << std::setw (2 ) << (in_color >> 8 *(3 -i))%256 ;
454
+ }
455
+ return formatted.str ();
456
+ }
457
+
458
+ unsigned compareQRgb (const QRgb& value1, const QRgb& value2, uchar maxDifference = 10 )
459
+ {
460
+ auto cv1 = value1;
461
+ auto cv2 = value2;
462
+ unsigned rv = 0 ;
463
+ for (auto i = 0 ; i < 4 ; ++i) {
464
+ uchar byte1 = cv1 % 256 ;
465
+ uchar byte2 = cv2 % 256 ;
466
+ unsigned diff = std::abs (byte1 - byte2);
467
+ if (diff > rv) rv = diff;
468
+ }
469
+ return rv;
470
+ // return true;
471
+ }
472
+
473
+ struct RangeSelectionTestSet
474
+ {
475
+ QPoint topLeft;
476
+ QPoint bottomRight;
477
+ QPoint topLeftOriginal;
478
+ QSize sizeOriginal;
479
+ QSize sizeScaled () const { return QSize{ bottomRight.x () - topLeft.x () + 1 , bottomRight.y () - topLeft.y () + 1 }; }
480
+ QString toClippingString () const {
481
+ return QString (" Use " + QString::number (topLeftOriginal.x ()) + " , " + QString::number (topLeftOriginal.y ()) + " (w:" + QString::number (sizeOriginal.width ()) + " , h:" + QString::number (sizeOriginal.height ()) + " )" );
482
+ }
483
+ };
484
+
485
+ void compareSourceImageData (SourceImage& testImage, SourceImageTester& tester, const RangeSelectionTestSet& testArgs)
486
+ {
487
+ auto testCroppedSection = testImage.data ();
488
+ auto testRectangle = tester.fullImage ().copy ({ testArgs.topLeftOriginal , testArgs.sizeOriginal }).scaledToWidth (testArgs.bottomRight .x () - testArgs.topLeft .x () + 1 );
489
+ CHECK_EQ (testCroppedSection.width (), testRectangle.width ());
490
+ CHECK_EQ (testCroppedSection.height (), testRectangle.height ());
491
+ std::cout << " The comparison isn't 100% accurate around edges. Compare manually!" << std::endl;
492
+ std::cout << " The following gives an ASCII art representation of the diff between the two image sections by pixel channel values." << std::endl;
493
+ unsigned criticalCount = 0 ;
494
+ for (int y = 0 ; y < testCroppedSection.height (); y++) {
495
+ QRgb* lineToTest = (QRgb*)testCroppedSection.scanLine (y);
496
+ QRgb* lineToMatch = (QRgb*)testRectangle.scanLine (y);
497
+ std::cout << " |" ;
498
+ for (int x = 0 ; x < testCroppedSection.width (); x++) {
499
+ auto frame = compareQRgb (lineToTest[x], lineToMatch[x]);
500
+ char pixel = ' ' ;
501
+ if (frame >= 32 ) { pixel = ' X' ; ++criticalCount; }
502
+ else if (frame >= 16 ) pixel = ' x' ;
503
+ else if (frame >= 8 ) pixel = ' _' ;
504
+ else if (frame >= 4 ) pixel = ' .' ;
505
+ std::cout << pixel;
506
+ }
507
+ std::cout << " |" << std::endl;
508
+ }
509
+ auto size = testArgs.sizeScaled ();
510
+ CHECK_LT (criticalCount, size.width () * size.height () / 50 ); // less than 1% actually at high contrast by pixel
511
+ }
512
+
446
513
TEST_CASE (" test mouse based range selection" )
447
514
{
448
515
SourceImage testImage;
@@ -458,14 +525,36 @@ TEST_CASE("test mouse based range selection")
458
525
459
526
SourceImageTester tester{ testImage };
460
527
461
- // drag rectangle from 10, 10 to 200, 200 computationally
462
- tester.mouseDown ({ 10 , 10 });
463
- for (qreal pos = 20 ; pos < 200 ; pos += 10 ) tester.mouseMoved ({ pos, pos });
464
- tester.mouseUp ({ 200 , 200 });
465
-
466
- // this mouse action should result in a rectangle with 191x191 displayed pixels starting at 10x10 displayed
467
- // this rectangle, if resized to match the overall image size of 925x925, scales to a 441x441 rectangle starting at pixel 23x23.
468
- fileSizeCheck (testImage, QString{" Use 23, 23 (w:441, h:441)" }, QSize{191 , 191 });
528
+ std::vector<RangeSelectionTestSet> movements{
529
+ {
530
+ {10 , 10 },
531
+ {100 , 100 },
532
+ {23 , 23 },
533
+ {209 , 209 },
534
+ },{
535
+ {150 , 150 },
536
+ {300 , 300 },
537
+ {347 , 347 },
538
+ {349 , 349 },
539
+ },{
540
+ {250 , 250 },
541
+ {350 , 350 },
542
+ {579 , 579 },
543
+ {233 , 233 },
544
+ }
545
+ };
546
+ for (auto & parameters : movements)
547
+ {
548
+ // drag rectangle from 10, 10 to 100, 100 computationally
549
+ tester.mouseDown (parameters.topLeft );
550
+ for (qreal pos = parameters.topLeft .x () + 10 ; pos < parameters.bottomRight .x (); pos += 10 ) tester.mouseMoved ({ pos, pos });
551
+ tester.mouseUp (parameters.bottomRight );
552
+
553
+ // this mouse action should result in a rectangle with 191x191 displayed pixels starting at 10x10 displayed
554
+ // this rectangle, if resized to match the overall image size of 925x925, scales to a 441x441 rectangle starting at pixel 23x23.
555
+ fileSizeCheck (testImage, parameters.toClippingString (), parameters.sizeScaled ());
556
+ compareSourceImageData (testImage, tester, parameters);
557
+ }
469
558
}
470
559
471
560
#endif
0 commit comments