' ' Asserts that a created image, 'originalActualImage', is identical to the provide expected image, 'expectedFileName' ' ' The created image is converted to 32-bit and saved to the results folder. ' We then load the expected image as a 32-bit image, compare file sizes, ' width/height, and each pixel. ' SUB AssertImage (originalActualImage AS LONG, expectedFileName AS STRING) DIM actualImage AS LONG DIM ResultsDir AS STRING, TestPrefix AS STRING ResultsDir = COMMAND$(1) TestPrefix = COMMAND$(2) ' Make sure the test result will be seen _DEST _CONSOLE ' Convert to 32-bit for comparisons actualImage = _NEWIMAGE(_WIDTH(originalActualImage), _HEIGHT(originalActualImage), 32) _PUTIMAGE , originalActualImage, actualImage 'First save the result SaveImage actualImage, ResultsDir + "/" + TestPrefix + "_result.bmp" 'Compare both images, print whether they are identical DIM expectedImage AS LONG expectedImage = _LOADIMAGE(expectedFileName, 32) IF _WIDTH(actualImage) <> _WIDTH(expectedImage) THEN PRINT "Failure! Image width differs, actual:"; _WIDTH(actualImage); ", Expected:"; _WIDTH(expectedImage) GOTO freeImages END IF IF _HEIGHT(actualImage) <> _HEIGHT(expectedImage) THEN PRINT "Failure! Image height differs, actual:"; _HEIGHT(actualImage); ", Expected:"; _HEIGHT(expectedImage) GOTO freeImages END IF DIM actual AS _MEM, expected AS _MEM actual = _MEMIMAGE(actualImage) expected = _MEMIMAGE(expectedImage) IF actual.SIZE <> expected.SIZE THEN PRINT "Failure! Image sizes differ, Actual:"; actual.SIZE; ", Expected:"; expected.SIZE GOTO freeImages END IF DIM w&: w& = _WIDTH(expectedImage) DIM h&: h& = _HEIGHT(expectedImage) DIM x&, y&, actualPixel&, expectedPixel&, pixelOffset AS _OFFSET FOR x& = 0 TO w& - 1 FOR y& = 0 TO h& - 1 pixelOffset = (y& * w& + x&) * 4 actualPixel& = _MEMGET(actual, actual.OFFSET + pixelOffset, LONG) expectedPixel& = _MEMGET(expected, expected.OFFSET + pixelOffset, LONG) IF actualPixel& <> expectedPixel& THEN PRINT "Failure! Image pixels at ("; x&; ","; y&; ") differ, actual: 0x"; HEX$(actualPixel&); ", expected: 0x"; HEX$(expectedPixel&) GOTO freeImages END IF NEXT NEXT PRINT "Success, images are identical!" freeImages: _MEMFREE actual _MEMFREE expected _FREEIMAGE actualImage END SUB ' From the QB64-PE Wiki: https://qb64phoenix.com/qb64wiki/index.php/SAVEIMAGE SUB SaveImage (image AS LONG, filename AS STRING) DIM bytesperpixel&, bpp& bytesperpixel& = _PIXELSIZE(image&) IF bytesperpixel& = 0 THEN PRINT "Text modes unsupported!": END IF bytesperpixel& = 1 THEN bpp& = 8 ELSE bpp& = 24 DIM x&: x& = _WIDTH(image&) DIM y&: y& = _HEIGHT(image&) DIM b$: b$ = "BM????QB64????" + MKL$(40) + MKL$(x&) + MKL$(y&) + MKI$(1) + MKI$(bpp&) + MKL$(0) + "????" + STRING$(16, 0) 'partial BMP header info(???? to be filled later) DIM c&, cv& IF bytesperpixel& = 1 THEN FOR c& = 0 TO 255 ' read BGR color settings from JPG image + 1 byte spacer(CHR$(0)) cv& = _PALETTECOLOR(c&, image&) ' color attribute to read. b$ = b$ + CHR$(_BLUE32(cv&)) + CHR$(_GREEN32(cv&)) + CHR$(_RED32(cv&)) + CHR$(0) 'spacer byte NEXT END IF MID$(b$, 11, 4) = MKL$(LEN(b$)) ' image pixel data offset(BMP header) DIM lastsource&: lastsource& = _SOURCE _SOURCE image& DIM padder$ IF ((x& * 3) MOD 4) THEN padder$ = STRING$(4 - ((x& * 3) MOD 4), 0) DIM px&, py&, r$, d$ FOR py& = y& - 1 TO 0 STEP -1 ' read JPG image pixel color data r$ = "" FOR px& = 0 TO x& - 1 c& = POINT(px&, py&) 'POINT 32 bit values are large LONG values IF bytesperpixel& = 1 THEN r$ = r$ + CHR$(c&) ELSE r$ = r$ + LEFT$(MKL$(c&), 3) NEXT px& d$ = d$ + r$ + padder$ NEXT py& _SOURCE lastsource& MID$(b$, 35, 4) = MKL$(LEN(d$)) ' image size(BMP header) b$ = b$ + d$ ' total file data bytes to create file MID$(b$, 3, 4) = MKL$(LEN(b$)) ' size of data file(BMP header) DIM ext$ IF LCASE$(RIGHT$(filename$, 4)) <> ".bmp" THEN ext$ = ".bmp" DIM f&: f& = FREEFILE OPEN filename$ + ext$ FOR OUTPUT AS #f&: CLOSE #f& ' erases an existing file OPEN filename$ + ext$ FOR BINARY AS #f& PUT #f&, , b$ CLOSE #f& END SUB FUNCTION GetColorDelta~& (color1 AS _UNSIGNED LONG, color2 AS _UNSIGNED LONG) GetColorDelta = ABS(_RED32(color1) - _RED32(color2)) + ABS(_GREEN32(color1) - _GREEN32(color2)) + ABS(_BLUE32(color1) - _BLUE32(color2)) + ABS(_ALPHA32(color1) - _ALPHA32(color2)) END FUNCTION ' Same as AssertImage() but is a bit more forgiving SUB AssertImage2 (originalActualImage AS LONG, expectedFileName AS STRING, toleranceLimit AS LONG) DIM actualImage AS LONG DIM ResultsDir AS STRING, TestPrefix AS STRING ResultsDir = COMMAND$(1) TestPrefix = COMMAND$(2) ' Make sure the test result will be seen _DEST _CONSOLE ' Convert to 32-bit for comparisons actualImage = _NEWIMAGE(_WIDTH(originalActualImage), _HEIGHT(originalActualImage), 32) _PUTIMAGE , originalActualImage, actualImage 'First save the result IF LEN(ResultsDir) THEN _SAVEIMAGE ResultsDir + "/" + TestPrefix + "_" + expectedFileName + "_result.bmp", actualImage 'Compare both images, print whether they are identical DIM expectedImage AS LONG expectedImage = _LOADIMAGE(expectedFileName, 32) DIM actual AS _MEM, expected AS _MEM actual = _MEMIMAGE(actualImage) expected = _MEMIMAGE(expectedImage) IF _WIDTH(actualImage) <> _WIDTH(expectedImage) THEN PRINT "Failure! Image width differs, actual:"; _WIDTH(actualImage); ", Expected:"; _WIDTH(expectedImage) GOTO freeImages END IF IF _HEIGHT(actualImage) <> _HEIGHT(expectedImage) THEN PRINT "Failure! Image height differs, actual:"; _HEIGHT(actualImage); ", Expected:"; _HEIGHT(expectedImage) GOTO freeImages END IF IF actual.SIZE <> expected.SIZE THEN PRINT "Failure! Image sizes differ, Actual:"; actual.SIZE; ", Expected:"; expected.SIZE GOTO freeImages END IF DIM w&: w& = _WIDTH(expectedImage) DIM h&: h& = _HEIGHT(expectedImage) DIM x&, y&, pixelOffset AS _OFFSET DIM AS _UNSIGNED LONG actualPixel, expectedPixel FOR x& = 0 TO w& - 1 FOR y& = 0 TO h& - 1 pixelOffset = (y& * w& + x&) * 4 actualPixel = _MEMGET(actual, actual.OFFSET + pixelOffset, _UNSIGNED LONG) expectedPixel = _MEMGET(expected, expected.OFFSET + pixelOffset, _UNSIGNED LONG) IF actualPixel <> expectedPixel _ANDALSO GetColorDelta(actualPixel, expectedPixel) > toleranceLimit THEN PRINT "Failure! Image pixels at ("; x&; ","; y&; ") differ, actual: 0x"; HEX$(actualPixel); ", expected: 0x"; HEX$(expectedPixel) GOTO freeImages END IF NEXT NEXT PRINT "Success, images are identical!" freeImages: _MEMFREE actual _MEMFREE expected _FREEIMAGE actualImage END SUB