diff --git a/.gitattributes b/.gitattributes index 106554778a5..33d6e359783 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8718,6 +8718,7 @@ src/tools/chdman.c svneol=native#text/plain src/tools/jedutil.c svneol=native#text/plain src/tools/ldresample.c svneol=native#text/plain src/tools/ldverify.c svneol=native#text/plain +src/tools/pngcmp.c svneol=native#text/plain src/tools/regrep.c svneol=native#text/plain src/tools/romcmp.c svneol=native#text/plain src/tools/runtest.cmd svneol=CRLF#text/plain eol=crlf diff --git a/src/tools/pngcmp.c b/src/tools/pngcmp.c new file mode 100644 index 00000000000..7b1a18d3cb1 --- /dev/null +++ b/src/tools/pngcmp.c @@ -0,0 +1,226 @@ +/*************************************************************************** + + pngcmp.c + + PNG comparison (based on regrep.c) + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +****************************************************************************/ + +#include +#include +#include +#include +#include "osdcore.h" +#include "png.h" + +#include + +/*************************************************************************** + CONSTANTS & DEFINES +***************************************************************************/ + +#define BITMAP_SPACE 4 + +/*************************************************************************** + PROTOTYPES +***************************************************************************/ + +static int generate_png_diff(const astring& imgfile1, const astring& imgfile2, const astring& outfilename); + +/*************************************************************************** + MAIN +***************************************************************************/ + +/*------------------------------------------------- + main - main entry point +-------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + /* first argument is the directory */ + if (argc < 4) + { + fprintf(stderr, "Usage:\npngcmp \n"); + return 10; + } + astring imgfilename1(argv[1]); + astring imgfilename2(argv[2]); + astring outfilename(argv[3]); + + try { + return generate_png_diff(imgfilename1, imgfilename2, outfilename); + } + catch(...) + { + printf("Exception occured"); + 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 astring& imgfile1, const astring& imgfile2, const astring& 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, OPEN_FLAG_READ, &file); + if (filerr != FILERR_NONE) + { + printf("Could not open %s (%d)\n", imgfile1.cstr(), 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.cstr(), pngerr); + goto error; + } + + /* open the source image */ + filerr = core_fopen(imgfile2, OPEN_FLAG_READ, &file); + if (filerr != FILERR_NONE) + { + printf("Could not open %s (%d)\n", imgfile2.cstr(), 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.cstr(), 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, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file); + if (filerr != FILERR_NONE) + { + printf("Could not open %s (%d)\n", outfilename.cstr(), 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.cstr(), 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); + return error; +} diff --git a/src/tools/tools.mak b/src/tools/tools.mak index 105fc33678e..038250b6964 100644 --- a/src/tools/tools.mak +++ b/src/tools/tools.mak @@ -61,6 +61,7 @@ TOOLS += \ srcclean$(EXE) \ src2html$(EXE) \ split$(EXE) \ + pngcmp$(EXE) \ @@ -192,3 +193,17 @@ SPLITOBJS = \ split$(EXE): $(SPLITOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB) $(EXPAT) @echo Linking $@... $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ + + + +#------------------------------------------------- +# pngcmp +#------------------------------------------------- + +PNGCMPOBJS = \ + $(TOOLSOBJ)/pngcmp.o \ + +pngcmp$(EXE): $(PNGCMPOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB) + @echo Linking $@... + $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ +