// Decodes every PNG under a directory with pngdecode.c and with macOS ImageIO (which yields // exact non-premultiplied samples on macOS) and requires byte-identical results. // Usage: png_parity DATA_DIR #import #import #import #include "pngdecode.h" int main(int argc, char **argv) { @autoreleasepool { NSString *root = @(argv[1]); long checked = 0, fallback = 0, mismatched = 0, skipped = 0; double tw = 0, ti = 0; long px = 0; for (NSString *rel in [NSFileManager.defaultManager enumeratorAtPath:root]) { if (![rel hasSuffix:@".png"]) continue; NSData *data = [NSData dataWithContentsOfFile:[root stringByAppendingPathComponent:rel]]; uint8_t *mine; int w, h, ch; double t0 = CACurrentMediaTime(); int ok = fx_png_decode(data.bytes, data.length, &mine, &w, &h, &ch); double t1 = CACurrentMediaTime(); if (!ok) { fallback++; continue; } CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); CGImageRef img = CGImageSourceCreateImageAtIndex(src, 0, NULL); CFDataRef ref = CGDataProviderCopyData(CGImageGetDataProvider(img)); double t2 = CACurrentMediaTime(); tw += t1 - t0; ti += t2 - t1; px += (long)w * h; size_t bpp = CGImageGetBitsPerPixel(img) / 8, row = CGImageGetBytesPerRow(img); CGImageAlphaInfo a = CGImageGetAlphaInfo(img); if (CGImageGetBitsPerComponent(img) != 8 || (CGImageGetBitmapInfo(img) & kCGBitmapByteOrderMask) || a == kCGImageAlphaPremultipliedLast || a == kCGImageAlphaPremultipliedFirst || a == kCGImageAlphaFirst || a == kCGImageAlphaNoneSkipFirst) { skipped++; goto next; } // Compare the channels AppKit would expose (drop ImageIO's padding byte for RGBX). for (int y = 0; y < h && !mismatched; y++) for (int x = 0; x < w; x++) { const uint8_t *r = CFDataGetBytePtr(ref) + y * row + x * bpp, *m = mine + ((size_t)y * w + x) * ch; if (memcmp(r, m, ch)) { NSLog(@"MISMATCH %@ at %d,%d ch=%d", rel, x, y, ch); mismatched++; break; } } checked++; next: CFRelease(ref); CGImageRelease(img); CFRelease(src); free(mine); } NSLog(@"checked %ld identical-format images, %ld mismatched, %ld skipped (ImageIO layout), %ld fallback to ImageIO", checked, mismatched, skipped, fallback); NSLog(@"%.0f Mpx: wuffs %.2fs (%.0f Mpx/s), ImageIO %.2fs (%.0f Mpx/s)", px / 1e6, tw, px / 1e6 / tw, ti, px / 1e6 / ti); return mismatched ? 1 : 0; } }