diff --git a/cderror.h b/cderror.h index a6875dcd..e935ce1d 100644 --- a/cderror.h +++ b/cderror.h @@ -126,6 +126,7 @@ JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") #ifdef PNG_SUPPORTED JMESSAGE(JERR_PNG_ERROR, "Unable to read PNG file: %s") +JMESSAGE(JERR_PNG_PROFILETOOLARGE, "Embedded profile was too large for this tool - dropped.") #endif #ifdef JMAKE_ENUM_LIST diff --git a/cjpeg.c b/cjpeg.c index 22c6175d..9c8e02e8 100644 --- a/cjpeg.c +++ b/cjpeg.c @@ -81,6 +81,7 @@ static const char * const cdjpeg_message_table[] = { static boolean is_targa; /* records user -targa switch */ static boolean is_jpeg; +static boolean copy_markers; LOCAL(cjpeg_source_ptr) select_file_type (j_compress_ptr cinfo, FILE *infile) @@ -115,6 +116,7 @@ select_file_type (j_compress_ptr cinfo, FILE *infile) #endif #ifdef PNG_SUPPORTED case 0x89: + copy_markers = TRUE; return jinit_read_png(cinfo); #endif #ifdef RLE_SUPPORTED @@ -127,6 +129,7 @@ select_file_type (j_compress_ptr cinfo, FILE *infile) #endif case 0xff: is_jpeg = TRUE; + copy_markers = TRUE; return jinit_read_jpeg(cinfo); default: ERREXIT(cinfo, JERR_UNKNOWN_FORMAT); @@ -766,7 +769,7 @@ main (int argc, char **argv) jpeg_start_compress(&cinfo, TRUE); /* Copy metadata */ - if (is_jpeg) { + if (copy_markers) { jpeg_saved_marker_ptr marker; /* In the current implementation, we don't actually need to examine the diff --git a/rdpng.c b/rdpng.c index d74aa9c4..4e373845 100644 --- a/rdpng.c +++ b/rdpng.c @@ -97,6 +97,30 @@ start_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) cinfo->input_gamma = gamma; sinfo->get_pixel_rows = get_pixel_rows_png; + source->pub.marker_list = NULL; + png_bytep profile = NULL; + png_charp unused1 = NULL; + int unused2 = 0; + png_uint_32 proflen = 0; + if (png_get_iCCP(source->png_ptr, source->info_ptr, &unused1, &unused2, &profile, &proflen) && /* your libpng is out of date if you get a warning here */ + profile && proflen) { + if (proflen < 65535-14) { + size_t datalen = proflen + 14; + JOCTET *dataptr = (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_IMAGE, datalen); + memcpy(dataptr, "ICC_PROFILE\0\x01\x01", 14); + memcpy(dataptr + 14, profile, proflen); + struct jpeg_marker_struct *marker = (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(struct jpeg_marker_struct)); + marker->next = NULL; + marker->marker = JPEG_APP0+2; + marker->original_length = 0; + marker->data_length = datalen; + marker->data = dataptr; + source->pub.marker_list = marker; + } else { + WARNMS(cinfo, JERR_PNG_PROFILETOOLARGE); + } + } + png_read_update_info(source->png_ptr, source->info_ptr); png_size_t rowbytes = png_get_rowbytes(source->png_ptr, source->info_ptr);