diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/tools/pngcmp.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/tools/pngcmp.cpp')
-rw-r--r-- | src/tools/pngcmp.cpp | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/tools/pngcmp.cpp b/src/tools/pngcmp.cpp new file mode 100644 index 00000000000..4b0974d824f --- /dev/null +++ b/src/tools/pngcmp.cpp @@ -0,0 +1,198 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + pngcmp.c + + PNG comparison (based on regrep.c) + +****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include "osdcore.h" +#include "png.h" + +#include <new> + +/*************************************************************************** + CONSTANTS & DEFINES +***************************************************************************/ + +#define BITMAP_SPACE 4 + +/*************************************************************************** + PROTOTYPES +***************************************************************************/ + +static int generate_png_diff(const std::string& imgfile1, const std::string& imgfile2, const std::string& outfilename); + +/*************************************************************************** + MAIN +***************************************************************************/ + +/*------------------------------------------------- + main - main entry point +-------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + /* first argument is the directory */ + if (argc < 4) + { + fprintf(stderr, "Usage:\npngcmp <image1> <image2> <outfile>\n"); + return 10; + } + std::string imgfilename1(argv[1]); + std::string imgfilename2(argv[2]); + std::string outfilename(argv[3]); + + try { + return generate_png_diff(imgfilename1, imgfilename2, outfilename); + } + catch(...) + { + printf("Exception occurred"); + return 1000; + } +} + +/*------------------------------------------------- + generate_png_diff - create a new PNG file + that shows multiple differing PNGs side by + side with a third set of differences +-------------------------------------------------*/ + +static int generate_png_diff(const std::string& imgfile1, const std::string& imgfile2, const std::string& outfilename) +{ + bitmap_argb32 bitmap1; + bitmap_argb32 bitmap2; + bitmap_argb32 finalbitmap; + int width, height, maxwidth; + core_file *file = NULL; + file_error filerr; + png_error pngerr; + int error = 100; + bool bitmaps_differ; + int x, y; + + /* open the source image */ + filerr = core_fopen(imgfile1.c_str(), OPEN_FLAG_READ, &file); + if (filerr != FILERR_NONE) + { + printf("Could not open %s (%d)\n", imgfile1.c_str(), filerr); + goto error; + } + + /* load the source image */ + pngerr = png_read_bitmap(file, bitmap1); + core_fclose(file); + if (pngerr != PNGERR_NONE) + { + printf("Could not read %s (%d)\n", imgfile1.c_str(), pngerr); + goto error; + } + + /* open the source image */ + filerr = core_fopen(imgfile2.c_str(), OPEN_FLAG_READ, &file); + if (filerr != FILERR_NONE) + { + printf("Could not open %s (%d)\n", imgfile2.c_str(), filerr); + goto error; + } + + /* load the source image */ + pngerr = png_read_bitmap(file, bitmap2); + core_fclose(file); + if (pngerr != PNGERR_NONE) + { + printf("Could not read %s (%d)\n", imgfile2.c_str(), pngerr); + goto error; + } + + /* if the sizes are different, we differ; otherwise start off assuming we are the same */ + bitmaps_differ = (bitmap2.width() != bitmap1.width() || bitmap2.height() != bitmap1.height()); + + /* compare scanline by scanline */ + for (y = 0; y < bitmap2.height() && !bitmaps_differ; y++) + { + UINT32 *base = &bitmap1.pix32(y); + UINT32 *curr = &bitmap2.pix32(y); + + /* scan the scanline */ + for (x = 0; x < bitmap2.width(); x++) + if (*base++ != *curr++) + break; + bitmaps_differ = (x != bitmap2.width()); + } + + if (bitmaps_differ) + { + /* determine the size of the final bitmap */ + height = width = 0; + { + /* determine the maximal width */ + maxwidth = MAX(bitmap1.width(), bitmap2.width()); + width = bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE + maxwidth; + + /* add to the height */ + height += MAX(bitmap1.height(), bitmap2.height()); + } + + /* allocate the final bitmap */ + finalbitmap.allocate(width, height); + + /* now copy and compare each set of bitmaps */ + int curheight = MAX(bitmap1.height(), bitmap2.height()); + /* iterate over rows in these bitmaps */ + for (y = 0; y < curheight; y++) + { + UINT32 *src1 = (y < bitmap1.height()) ? &bitmap1.pix32(y) : NULL; + UINT32 *src2 = (y < bitmap2.height()) ? &bitmap2.pix32(y) : NULL; + UINT32 *dst1 = &finalbitmap.pix32(y); + UINT32 *dst2 = &finalbitmap.pix32(y, bitmap1.width() + BITMAP_SPACE); + UINT32 *dstdiff = &finalbitmap.pix32(y, bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE); + + /* now iterate over columns */ + for (x = 0; x < maxwidth; x++) + { + int pix1 = -1, pix2 = -2; + + if (src1 != NULL && x < bitmap1.width()) + pix1 = dst1[x] = src1[x]; + if (src2 != NULL && x < bitmap2.width()) + pix2 = dst2[x] = src2[x]; + dstdiff[x] = (pix1 != pix2) ? 0xffffffff : 0xff000000; + } + } + + /* write the final PNG */ + filerr = core_fopen(outfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file); + if (filerr != FILERR_NONE) + { + printf("Could not open %s (%d)\n", outfilename.c_str(), filerr); + goto error; + } + pngerr = png_write_bitmap(file, NULL, finalbitmap, 0, NULL); + core_fclose(file); + if (pngerr != PNGERR_NONE) + { + printf("Could not write %s (%d)\n", outfilename.c_str(), pngerr); + goto error; + } + } + + /* if we get here, we are error free */ + if (bitmaps_differ) + error = 1; + else + error = 0; + +error: + if (error == -1) + osd_rmfile(outfilename.c_str()); + return error; +} |