IccMAX 2.1.27
Color Profile Tools
Loading...
Searching...
No Matches
iccPngDump.cpp File Reference
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>
#include "IccCmm.h"
#include "IccUtil.h"
#include "IccDefs.h"
#include "IccProfLibVer.h"
#include <zlib.h>
+ Include dependency graph for iccPngDump.cpp:

Go to the source code of this file.

Macros

#define BAIL_OUT(msg)   do { LOG_ERROR(msg); TRAP(); } while (0)
 
#define LOG_ERROR(msg)   do { fprintf(stderr, "[ERROR] %s\n", msg); } while (0)
 
#define PNG_ICC_PROFILE_CAST   (png_bytepp)
 Core and external libraries necessary for the fuzzer functionality.
 
#define TRAP()   abort()
 

Typedefs

typedef png_bytep png_icc_profilep
 

Functions

int ExtractIccProfile (png_structp png_ptr, png_infop info_ptr, unsigned char **pProfMem, unsigned int *nLen)
 
bool InjectIccProfile (const std::string &inputPng, const std::string &iccFile, const std::string &outputPng)
 
int main (int argc, char *argv[])
 
void PrintIccProfileInfo (const unsigned char *pProfMem, unsigned int nLen, const char *outputFile)
 
void PrintPngInfo (png_structp png_ptr, png_infop info_ptr)
 
void safe_exit (const char *reason)
 
void Usage ()
 

Macro Definition Documentation

◆ BAIL_OUT

#define BAIL_OUT (   msg)    do { LOG_ERROR(msg); TRAP(); } while (0)

◆ LOG_ERROR

#define LOG_ERROR (   msg)    do { fprintf(stderr, "[ERROR] %s\n", msg); } while (0)

◆ PNG_ICC_PROFILE_CAST

#define PNG_ICC_PROFILE_CAST   (png_bytepp)

Core and external libraries necessary for the fuzzer functionality.

This section includes the necessary headers for the Foundation framework, UIKit, Core Graphics, standard input/output, standard library, memory management, mathematical functions, Boolean type, floating-point limits, and string functions. These libraries support image processing, UI interaction, and basic C operations essential for the application.

◆ TRAP

#define TRAP ( )    abort()

Typedef Documentation

◆ png_icc_profilep

typedef png_bytep png_icc_profilep

Function Documentation

◆ ExtractIccProfile()

int ExtractIccProfile ( png_structp  png_ptr,
png_infop  info_ptr,
unsigned char **  pProfMem,
unsigned int *  nLen 
)

Extracts the ICC profile from a PNG image.

Parameters
png_ptrPointer to the PNG structure.
info_ptrPointer to the PNG info structure.
pProfMemOutput pointer to store the ICC profile data.
nLenOutput length of the extracted ICC profile.
Returns
1 on success, 0 on failure.

Extracts the embedded ICC profile from a PNG image.

Parameters
png_ptrPointer to the PNG read structure.
info_ptrPointer to the PNG info structure.
pProfMemOutput pointer to store the ICC profile data.
nLenOutput variable to store the profile data length.
Returns
1 if an ICC profile is found and extracted successfully, 0 otherwise.
448 {
449 png_charp profile_name = NULL;
450 int compression_type = 0;
451 png_bytep profile_data_raw = NULL;
452 png_uint_32 profile_length = 0;
453
454 if (png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type,
455 (png_bytepp)&profile_data_raw, &profile_length)) {
456
457 if (profile_length == 0) {
458 LOG_ERROR("Empty ICC profile found.");
459 return 0;
460 }
461
462 *nLen = profile_length;
463 *pProfMem = (unsigned char *)malloc(profile_length);
464 if (!(*pProfMem)) {
465 LOG_ERROR("Memory allocation for ICC profile failed.");
466 return 0;
467 }
468
469 memcpy(*pProfMem, profile_data_raw, profile_length);
470 printf("[INFO] ICC Profile extracted: %u bytes\n", profile_length);
471
472 return 1;
473 }
474
475 return 0;
476}
#define LOG_ERROR(msg)
Definition iccPngDump.cpp:113

Referenced by main().

+ Here is the caller graph for this function:

◆ InjectIccProfile()

bool InjectIccProfile ( const std::string &  inputPng,
const std::string &  iccFile,
const std::string &  outputPng 
)

Injects a new ICC profile into a PNG and writes it to disk.

Parameters
inputPngSource PNG path.
iccFileICC profile file to inject.
outputPngDestination PNG path.
Returns
true on success, false otherwise.

Injects a new ICC profile into a PNG image and writes the output.

Parameters
inputPngPath to the source PNG file.
iccFilePath to the ICC file to embed.
outputPngPath to write the modified PNG file.
Returns
true on success, false on failure.
336 {
337 std::ifstream iccIn(iccFile, std::ios::binary);
338 if (!iccIn.is_open()) {
339 safe_exit("Failed to open ICC profile file for reading.");
340 }
341
342 std::vector<unsigned char> iccData((std::istreambuf_iterator<char>(iccIn)),
343 std::istreambuf_iterator<char>());
344
345 FILE* fpIn = fopen(inputPng.c_str(), "rb");
346 if (!fpIn) {
347 safe_exit("Failed to open input PNG file.");
348 }
349
350 FILE* fpOut = fopen(outputPng.c_str(), "wb");
351 if (!fpOut) {
352 fclose(fpIn);
353 safe_exit("Failed to open output PNG file.");
354 }
355
356 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
357 if (!png_ptr) {
358 fclose(fpIn); fclose(fpOut);
359 safe_exit("Failed to create PNG read struct.");
360 }
361
362 png_infop info_ptr = png_create_info_struct(png_ptr);
363 if (!info_ptr) {
364 png_destroy_read_struct(&png_ptr, NULL, NULL);
365 fclose(fpIn); fclose(fpOut);
366 safe_exit("Failed to create PNG info struct.");
367 }
368
369 if (setjmp(png_jmpbuf(png_ptr))) {
370 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
371 fclose(fpIn); fclose(fpOut);
372 safe_exit("LibPNG read error.");
373 }
374
375 png_init_io(png_ptr, fpIn);
376 png_read_info(png_ptr, info_ptr);
377
378 png_structp write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
379 png_infop write_info_ptr = png_create_info_struct(write_ptr);
380 if (!write_ptr || !write_info_ptr) {
381 safe_exit("Failed to create PNG write structures.");
382 }
383
384 if (setjmp(png_jmpbuf(write_ptr))) {
385 safe_exit("LibPNG write error.");
386 }
387
388 png_init_io(write_ptr, fpOut);
389 png_set_compression_level(write_ptr, Z_BEST_COMPRESSION);
390
391// MUST propagate original info to write_info_ptr before setting ICC
392png_set_rows(write_ptr, write_info_ptr, nullptr); // optional
393png_set_IHDR(write_ptr, write_info_ptr,
394 png_get_image_width(png_ptr, info_ptr),
395 png_get_image_height(png_ptr, info_ptr),
396 png_get_bit_depth(png_ptr, info_ptr),
397 png_get_color_type(png_ptr, info_ptr),
398 png_get_interlace_type(png_ptr, info_ptr),
399 png_get_compression_type(png_ptr, info_ptr),
400 png_get_filter_type(png_ptr, info_ptr));
401
402// only now is it safe to attach ICC
403png_set_iCCP(write_ptr, write_info_ptr, "icc", 0, iccData.data(), iccData.size());
404
405// finally write header
406png_write_info(write_ptr, write_info_ptr);
407
408
409 // Re-read the input image data and write to output
410 png_bytepp row_pointers = (png_bytepp)png_malloc(png_ptr,
411 sizeof(png_bytep) * png_get_image_height(png_ptr, info_ptr));
412
413 for (png_uint_32 y = 0; y < png_get_image_height(png_ptr, info_ptr); y++) {
414 row_pointers[y] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
415 }
416
417 png_read_image(png_ptr, row_pointers);
418 png_write_image(write_ptr, row_pointers);
419 png_write_end(write_ptr, NULL);
420
421 // Cleanup
422 for (png_uint_32 y = 0; y < png_get_image_height(png_ptr, info_ptr); y++) {
423 png_free(png_ptr, row_pointers[y]);
424 }
425 png_free(png_ptr, row_pointers);
426
427 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
428 png_destroy_write_struct(&write_ptr, &write_info_ptr);
429 fclose(fpIn);
430 fclose(fpOut);
431 return true;
432}
#define safe_exit(reason)
Definition iccJpegDump.cpp:126

References safe_exit().

Referenced by main().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *  argv[] 
)

Entry point of the iccPngDump program.

This function handles command-line arguments, opens a PNG file, validates its format, and either extracts or injects an ICC profile.

Parameters
argcArgument count.
argvArgument vector.
Returns
0 on success, non-zero on failure.
185 {
186 printf("[INFO] Starting iccPngDump...\n");
187
188 if (argc < 2) {
189 Usage();
190 safe_exit("Missing input file argument.");
191 }
192
193 const char *inputFile = NULL;
194 const char *outputIccFile = NULL;
195 const char *injectIccFile = NULL;
196 const char *outputPngFile = NULL;
197
198 // Simple CLI arg parsing
199 for (int i = 1; i < argc; ++i) {
200 if (strcmp(argv[i], "--write-icc") == 0 && i + 1 < argc) {
201 injectIccFile = argv[++i];
202 } else if (strcmp(argv[i], "--output") == 0 && i + 1 < argc) {
203 outputPngFile = argv[++i];
204 } else if (!inputFile) {
205 inputFile = argv[i];
206 } else if (!outputIccFile) {
207 outputIccFile = argv[i];
208 }
209 }
210
211 if (!inputFile) {
212 Usage();
213 safe_exit("Input PNG file not specified.");
214 }
215
216// --- Injection Mode ---
217if (injectIccFile) {
218 if (!outputPngFile) {
219 safe_exit("Missing --output argument for write mode.");
220 }
221
222 printf("[INFO] Injecting ICC profile '%s' into PNG: '%s'\n", injectIccFile, outputPngFile);
223
224 if (!InjectIccProfile(inputFile, injectIccFile, outputPngFile)) {
225 safe_exit("Failed to inject ICC profile.");
226 }
227
228 printf("[INFO] Injection successful.\n");
229 return 0;
230}
231
232 // --- Extraction Mode ---
233 printf("[INFO] Opening PNG file: %s\n", inputFile);
234 FILE *fp = fopen(inputFile, "rb");
235 if (!fp) {
236 LOG_ERROR("File cannot be opened.");
237 safe_exit("File error.");
238 }
239
240 unsigned char header[8];
241 if (fread(header, 1, 8, fp) != 8 || png_sig_cmp(header, 0, 8)) {
242 LOG_ERROR("Not a valid PNG file.");
243 fclose(fp);
244 safe_exit("Invalid PNG format.");
245 }
246
247 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
248 if (!png_ptr) {
249 fclose(fp);
250 BAIL_OUT("Failed to create PNG read structure.");
251 }
252
253 png_infop info_ptr = png_create_info_struct(png_ptr);
254 if (!info_ptr) {
255 png_destroy_read_struct(&png_ptr, NULL, NULL);
256 fclose(fp);
257 BAIL_OUT("Failed to create PNG info structure.");
258 }
259
260 if (setjmp(png_jmpbuf(png_ptr))) {
261 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
262 fclose(fp);
263 BAIL_OUT("LibPNG error encountered.");
264 }
265
266 png_init_io(png_ptr, fp);
267 png_set_sig_bytes(png_ptr, 8);
268 png_read_info(png_ptr, info_ptr);
269
270 PrintPngInfo(png_ptr, info_ptr);
271
272 unsigned char *pProfMem = NULL;
273 unsigned int nLen = 0;
274 if (ExtractIccProfile(png_ptr, info_ptr, &pProfMem, &nLen)) {
275 PrintIccProfileInfo(pProfMem, nLen, outputIccFile);
276 free(pProfMem);
277 } else {
278 printf("[INFO] No embedded ICC Profile found.\n");
279 }
280
281 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
282 fclose(fp);
283
284 printf("[INFO] iccPngDump completed successfully.\n");
285 return 0;
286}
void Usage()
Definition iccPngDump.cpp:311
int ExtractIccProfile(png_structp png_ptr, png_infop info_ptr, unsigned char **pProfMem, unsigned int *nLen)
Definition iccPngDump.cpp:448
#define BAIL_OUT(msg)
Definition iccPngDump.cpp:114
void PrintIccProfileInfo(const unsigned char *pProfMem, unsigned int nLen, const char *outputFile)
Definition iccPngDump.cpp:553
void PrintPngInfo(png_structp png_ptr, png_infop info_ptr)
Definition iccPngDump.cpp:489
bool InjectIccProfile(const std::string &inputPng, const std::string &iccFile, const std::string &outputPng)
Definition iccPngDump.cpp:334

References ExtractIccProfile(), InjectIccProfile(), PrintIccProfileInfo(), PrintPngInfo(), safe_exit(), and Usage().

+ Here is the call graph for this function:

◆ PrintIccProfileInfo()

void PrintIccProfileInfo ( const unsigned char *  pProfMem,
unsigned int  nLen,
const char *  outputFile 
)

Displays and optionally saves ICC profile information.

Parameters
pProfMemICC profile memory block.
nLenSize of ICC data.
outputFilePath to write ICC (optional).

Parses and displays ICC profile metadata, and optionally saves it to a file.

Parameters
pProfMemPointer to the ICC profile data.
nLenLength of the ICC profile data in bytes.
outputFilePath to the output file for saving the ICC profile (optional).
553 {
554 printf("--------------------> ICC Profile Information <---------------------------\n");
555 printf("Profile Size: %u bytes\n", nLen);
556
557 // Attempt to parse the ICC profile
558 CIccProfile *pProfile = OpenIccProfile(pProfMem, nLen);
559 if (!pProfile) {
560 LOG_ERROR("Failed to parse ICC Profile.");
561 return;
562 }
563
564 // Extract ICC header details
565 icHeader *pHdr = &pProfile->m_Header;
566 CIccInfo Fmt;
567
568 printf(" Color Space: %s\n", Fmt.GetColorSpaceSigName(pHdr->colorSpace));
569 printf(" Colorimetric PCS: %s\n", Fmt.GetColorSpaceSigName(pHdr->pcs));
570 printf(" Profile Version: %d.%d.%d\n",
571 (pHdr->version >> 24) & 0xFF, // Major version
572 (pHdr->version >> 20) & 0x0F, // Minor version
573 (pHdr->version >> 16) & 0x0F); // Sub-minor version
574
575 delete pProfile;
576
577 // If an output file is specified, save the ICC profile
578 if (outputFile) {
579 FILE *outFile = fopen(outputFile, "wb");
580 if (!outFile) {
581 LOG_ERROR("Unable to open output file for writing.");
582 return;
583 }
584 fwrite(pProfMem, 1, nLen, outFile);
585 fclose(outFile);
586 printf("[INFO] ICC Profile saved to: %s\n", outputFile);
587 }
588
589 printf("--------------------------------------------------------------------\n");
590}
icColorSpaceSignature colorSpace
Definition icProfileHeader.h:2048
icUInt32Number version
Definition icProfileHeader.h:2046
icColorSpaceSignature pcs
Definition icProfileHeader.h:2049
Definition icProfileHeader.h:2043
class ICCPROFLIB_API CIccProfile
Definition IccPcc.h:80
CIccProfile * OpenIccProfile(const icChar *szFilename, bool bUseSubProfile)
Definition IccProfile.cpp:3387
Definition IccUtil.h:303
const icChar * GetColorSpaceSigName(icColorSpaceSignature sig)
Definition IccUtil.cpp:1640

References CIccProfile, icHeader::colorSpace, CIccInfo::GetColorSpaceSigName(), OpenIccProfile(), icHeader::pcs, and icHeader::version.

Referenced by main().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PrintPngInfo()

void PrintPngInfo ( png_structp  png_ptr,
png_infop  info_ptr 
)

Prints information about a given PNG file.

Parameters
png_ptrPointer to the PNG structure.
info_ptrPointer to the PNG info structure.

Displays detailed metadata information about a PNG image.

Parameters
png_ptrPointer to the PNG read structure.
info_ptrPointer to the PNG info structure.
489 {
490 // Retrieve PNG metadata
491 int width = png_get_image_width(png_ptr, info_ptr);
492 int height = png_get_image_height(png_ptr, info_ptr);
493 int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
494 int color_type = png_get_color_type(png_ptr, info_ptr);
495 int interlace_type = png_get_interlace_type(png_ptr, info_ptr);
496
497 printf("--------------------> PNG Image Metadata <---------------------------\n");
498 printf("Size: (%d x %d) pixels\n", width, height);
499 printf("Bit Depth: %d\n", bit_depth);
500
501 // Decode color type
502 printf("Color Type: ");
503 switch (color_type) {
504 case PNG_COLOR_TYPE_GRAY:
505 printf("Grayscale\n");
506 break;
507 case PNG_COLOR_TYPE_RGB:
508 printf("RGB (Truecolor)\n");
509 break;
510 case PNG_COLOR_TYPE_PALETTE:
511 printf("Indexed Color (Palette)\n");
512 break;
513 case PNG_COLOR_TYPE_GRAY_ALPHA:
514 printf("Grayscale with Alpha\n");
515 break;
516 case PNG_COLOR_TYPE_RGB_ALPHA:
517 printf("RGBA (Truecolor with Alpha)\n");
518 break;
519 default:
520 printf("Unknown (%d)\n", color_type);
521 break;
522 }
523
524 // Decode interlace type
525 printf("Interlace Type: ");
526 switch (interlace_type) {
527 case PNG_INTERLACE_NONE:
528 printf("None\n");
529 break;
530 case PNG_INTERLACE_ADAM7:
531 printf("Adam7 Interlacing\n");
532 break;
533 default:
534 printf("Unknown (%d)\n", interlace_type);
535 break;
536 }
537
538 printf("--------------------------------------------------------------------\n");
539}

Referenced by main().

+ Here is the caller graph for this function:

◆ safe_exit()

void safe_exit ( const char *  reason)

Safely exits the program with a given reason.

Parameters
reasonThe reason for exiting.

Logs an error message and exits the program safely.

Parameters
reasonA string containing the reason for exiting.
297 {
298 LOG_ERROR(reason);
299 exit(EXIT_FAILURE);
300}

Referenced by InjectIccProfile(), and main().

+ Here is the caller graph for this function:

◆ Usage()

void Usage ( )

Displays usage information for the program.

Displays usage information for the iccPngDump tool.

This function provides details on the correct command-line syntax.

311 {
312 printf("Usage:\n");
313 printf(" iccPngDump <input.png> [output.icc]\n");
314 printf(" - Extracts ICC profile from PNG.\n");
315 printf(" - Saves profile to [output.icc] if specified.\n");
316 printf("\n");
317 printf(" iccPngDump <input.png> --write-icc <profile.icc> --output <output.png>\n");
318 printf(" - Injects specified ICC profile into PNG.\n");
319 printf(" - Outputs modified PNG as <output.png>.\n");
320}