iccdump .pngs if we have zlib
Change-Id: Ide5e21598563d58dc5813a09b8a6158ca7b15fdc
Reviewed-on: https://skia-review.googlesource.com/121780
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/build/common b/build/common
index 0acdddf..86f4558 100644
--- a/build/common
+++ b/build/common
@@ -9,7 +9,7 @@
description = compile $out
rule link
- command = $disabled && touch $out || $cc $ldflags $extra_ldflags -pthread $in -o $out
+ command = $disabled && touch $out || $cc $ldflags $extra_ldflags -ldl -pthread $in -o $out
description = link $out
include build/targets
diff --git a/iccdump.c b/iccdump.c
index aa69904..ed08707 100644
--- a/iccdump.c
+++ b/iccdump.c
@@ -9,6 +9,7 @@
#define _CRT_SECURE_NO_WARNINGS
#define SKCMS_NORETURN __declspec(noreturn)
#else
+ #include <dlfcn.h>
#include <stdnoreturn.h>
#define SKCMS_NORETURN noreturn
#endif
@@ -112,6 +113,16 @@
#endif
}
+static uint32_t read_big_u32(const uint8_t* ptr) {
+ uint32_t be;
+ memcpy(&be, ptr, sizeof(be));
+#if defined(_MSC_VER)
+ return _byteswap_ulong(be);
+#else
+ return __builtin_bswap32(be);
+#endif
+}
+
// TODO: Put state into struct with FP
static int desmos_id = 0;
@@ -362,6 +373,81 @@
svg_close(fp);
}
+static const uint8_t png_signature[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
+
+#if defined(_MSC_VER)
+ static bool parse_png_profile(const uint8_t* buf, size_t len, skcms_ICCProfile* profile) {
+ (void)buf;
+ (void)len;
+ (void)profile;
+ (void)read_big_u32;
+ return false;
+ }
+#else
+ static bool parse_png_profile(const uint8_t* buf, size_t len, skcms_ICCProfile* profile) {
+ void* zlib = NULL;
+ if (!zlib) { zlib = dlopen("libz.so", RTLD_LAZY); }
+ if (!zlib) { zlib = dlopen("libz.dylib", RTLD_LAZY); }
+ if (!zlib) {
+ return false;
+ }
+
+ typedef int(*UncompressFn)(uint8_t*, unsigned long*, const uint8_t*, unsigned long);
+ UncompressFn uncompress = (UncompressFn)dlsym(zlib, "uncompress");
+ if (!uncompress) {
+ return false;
+ }
+
+ const uint8_t* end = buf+len;
+
+ // skip over signature
+ buf += sizeof(png_signature);
+
+ const uint32_t IEND = 0x49454e44,
+ iCCP = 0x69434350;
+
+ uint32_t size, tag = 0;
+
+ while (buf < end && tag != IEND) {
+ size = read_big_u32(buf+0);
+ tag = read_big_u32(buf+4);
+ buf += 8;
+
+ if (tag == iCCP) {
+ const char* name = (const char*)buf;
+ printf("Profile name from .png: '%s'\n", name);
+
+ size_t header = strlen(name)
+ + 1/*NUL*/
+ + 1/*PNG compression method, always 0 == zlib*/;
+
+ unsigned long inf_size,
+ guess = len;
+ void* inflated = NULL;
+
+ int err;
+ do {
+ inf_size = guess;
+ inflated = realloc(inflated, inf_size);
+
+ err = uncompress(inflated, &inf_size,
+ (const uint8_t*)name+header, size-header);
+ guess *= 2;
+ } while (err == -5/*Z_BUF_ERROR*/);
+
+ bool ok = err == 0/*Z_OK*/
+ && skcms_Parse(inflated, inf_size, profile);
+ free(inflated);
+ return ok;
+ }
+
+ buf += size;
+ buf += 4/*skip the PNG CRC*/;
+ }
+ return false;
+ }
+#endif
+
int main(int argc, char** argv) {
const char* filename = NULL;
bool svg = false;
@@ -389,7 +475,11 @@
}
skcms_ICCProfile profile;
- if (!skcms_Parse(buf, len, &profile)) {
+ if (len >= sizeof(png_signature) && 0 == memcmp(buf, png_signature, sizeof(png_signature))) {
+ if (!parse_png_profile(buf, len, &profile)) {
+ fatal("Could not find an ICC profile in this .png");
+ }
+ } else if (!skcms_Parse(buf, len, &profile)) {
fatal("Unable to parse ICC profile");
}