diff --git a/pdfio-content.c b/pdfio-content.c index 355bb58..6c54e0d 100644 --- a/pdfio-content.c +++ b/pdfio-content.c @@ -121,11 +121,38 @@ static unsigned png_crc_table[256] = // CRC-32 table for PNG files // -// 'pdfioArrayCreateCalibratedColorFromMatrix()' - Create a calibrated color space array using a CIE XYZ transform matrix. +// 'pdfioArrayCreateColorFromICCObj()' - Create an ICC-based color space array. +// + +pdfio_array_t * // O - Color array +pdfioArrayCreateColorFromICCObj( + pdfio_file_t *pdf, // I - PDF file + pdfio_obj_t *icc_object) // I - ICC profile object +{ + pdfio_array_t *icc_color; // Color array + + + // Range check input... + if (!pdf || !icc_object) + return (NULL); + + // Create the array with two values - a name and an object reference... + if ((icc_color = pdfioArrayCreate(pdf)) == NULL) + return (NULL); + + pdfioArrayAppendName(icc_color, "ICCBased"); + pdfioArrayAppendObj(icc_color, icc_object); + + return (icc_color); +} + + +// +// 'pdfioArrayCreateColorFromMatrix()' - Create a calibrated color space array using a CIE XYZ transform matrix. // pdfio_array_t * // O - Color space array -pdfioArrayCreateCalibratedColorFromMatrix( +pdfioArrayCreateColorFromMatrix( pdfio_file_t *pdf, // I - PDF file size_t num_colors, // I - Number of colors (1 or 3) double gamma, // I - Gamma value @@ -207,11 +234,41 @@ pdfioArrayCreateCalibratedColorFromMatrix( // -// 'pdfioArrayCreateCalibratedColorFromPrimaries()' - Create a calibrated color sapce array using CIE xy primary chromacities. +// 'pdfioArrayCreateColorFromPalette()' - Create an indexed color space array. +// + +pdfio_array_t * // O - Color array +pdfioArrayCreateColorFromPalette( + pdfio_file_t *pdf, // I - PDF file + size_t num_colors, // I - Number of colors + const unsigned char *colors) // I - RGB values for colors +{ + pdfio_array_t *indexed_color; // Color array + + + // Range check input... + if (!pdf || num_colors < 1 || !colors) + return (NULL); + + // Create the array with four values... + if ((indexed_color = pdfioArrayCreate(pdf)) == NULL) + return (NULL); + + pdfioArrayAppendName(indexed_color, "Indexed"); + pdfioArrayAppendName(indexed_color, "DeviceRGB"); + pdfioArrayAppendNumber(indexed_color, num_colors - 1); + pdfioArrayAppendBinary(indexed_color, colors, num_colors * 3); + + return (indexed_color); +} + + +// +// 'pdfioArrayCreateColorFromPrimaries()' - Create a calibrated color sapce array using CIE xy primary chromacities. // pdfio_array_t * // O - Color space array -pdfioArrayCreateCalibratedColorFromPrimaries( +pdfioArrayCreateColorFromPrimaries( pdfio_file_t *pdf, // I - PDF file size_t num_colors, // I - Number of colors (1 or 3) double gamma, // I - Gama value @@ -274,64 +331,7 @@ pdfioArrayCreateCalibratedColorFromPrimaries( PDFIO_DEBUG("pdfioFileCreateCalibratedColorFromPrimaries: matrix=[%g %g %g %g %g %g %g %g %g]\n", matrix[0][0], matrix[1][0], matrix[2][0], matrix[0][1], matrix[1][1], matrix[2][2], matrix[0][2], matrix[1][2], matrix[2][1]); // Now that we have the white point and matrix, use those to make the color array... - return (pdfioArrayCreateCalibratedColorFromMatrix(pdf, num_colors, gamma, matrix, white_point)); -} - - -// -// 'pdfioArrayCreateICCBasedColor()' - Create an ICC-based color space array. -// - -pdfio_array_t * // O - Color array -pdfioArrayCreateICCBasedColor( - pdfio_file_t *pdf, // I - PDF file - pdfio_obj_t *icc_object) // I - ICC profile object -{ - pdfio_array_t *icc_color; // Color array - - - // Range check input... - if (!pdf || !icc_object) - return (NULL); - - // Create the array with two values - a name and an object reference... - if ((icc_color = pdfioArrayCreate(pdf)) == NULL) - return (NULL); - - pdfioArrayAppendName(icc_color, "ICCBased"); - pdfioArrayAppendObj(icc_color, icc_object); - - return (icc_color); -} - - -// -// 'pdfioArrayCreateIndexedColor()' - Create an indexed color space array. -// - -pdfio_array_t * // O - Color array -pdfioArrayCreateIndexedColor( - pdfio_file_t *pdf, // I - PDF file - size_t num_colors, // I - Number of colors - const unsigned char *colors) // I - RGB values for colors -{ - pdfio_array_t *indexed_color; // Color array - - - // Range check input... - if (!pdf || num_colors < 1 || !colors) - return (NULL); - - // Create the array with four values... - if ((indexed_color = pdfioArrayCreate(pdf)) == NULL) - return (NULL); - - pdfioArrayAppendName(indexed_color, "Indexed"); - pdfioArrayAppendName(indexed_color, "DeviceRGB"); - pdfioArrayAppendNumber(indexed_color, num_colors - 1); - pdfioArrayAppendBinary(indexed_color, colors, num_colors * 3); - - return (indexed_color); + return (pdfioArrayCreateColorFromMatrix(pdf, num_colors, gamma, matrix, white_point)); } @@ -1177,18 +1177,82 @@ pdfioFileCreateFontObj( // -// 'pdfioFileCreateICCProfileObj()' - Add an ICC profile object to a PDF file. +// 'pdfioFileCreateICCObj()' - Add an ICC profile object to a PDF file. // pdfio_obj_t * // O - Object -pdfioFileCreateICCProfileObj( +pdfioFileCreateICCObj( pdfio_file_t *pdf, // I - PDF file - const char *filename) // I - Filename + const char *filename, // I - Filename + size_t num_colors) // I - Number of color components (1, 3, or 4) { - (void)pdf; - (void)filename; + pdfio_dict_t *dict; // ICC profile dictionary + pdfio_obj_t *obj; // ICC profile object + pdfio_stream_t *st; // ICC profile stream + int fd; // File + unsigned char buffer[16384]; // Read buffer + ssize_t bytes; // Bytes read - return (NULL); + + // Range check input... + if (!pdf) + return (NULL); + + if (!filename) + { + _pdfioFileError(pdf, "No ICC profile filename specified."); + return (NULL); + } + + if ((fd = open(filename, O_RDONLY | O_BINARY)) < 0) + { + _pdfioFileError(pdf, "Unable to open ICC profile '%s': %s", filename, strerror(errno)); + return (NULL); + } + + if (num_colors != 1 && num_colors != 3 && num_colors != 4) + { + _pdfioFileError(pdf, "Unsupported number of colors (%lu) for ICC profile.", (unsigned long)num_colors); + close(fd); + return (NULL); + } + + // Create the ICC profile object... + if ((dict = pdfioDictCreate(pdf)) == NULL) + { + close(fd); + return (NULL); + } + + pdfioDictSetNumber(dict, "N", num_colors); + pdfioDictSetName(dict, "Filter", "FlateDecode"); + + if ((obj = pdfioFileCreateObj(pdf, dict)) == NULL) + { + close(fd); + return (NULL); + } + + if ((st = pdfioObjCreateStream(obj, PDFIO_FILTER_FLATE)) == NULL) + { + close(fd); + return (NULL); + } + + while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) + { + if (!pdfioStreamWrite(st, buffer, (size_t)bytes)) + { + close(fd); + pdfioStreamClose(st); + return (NULL); + } + } + + close(fd); + pdfioStreamClose(st); + + return (obj); } @@ -1603,7 +1667,7 @@ copy_jpeg(pdfio_dict_t *dict, // I - Dictionary pdfioDictSetNumber(dict, "Width", width); pdfioDictSetNumber(dict, "Height", height); pdfioDictSetNumber(dict, "BitsPerComponent", 8); - pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateCalibratedColorFromMatrix(dict->pdf, num_colors, pdfioSRGBGamma, pdfioSRGBMatrix, pdfioSRGBWhitePoint)); + pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateColorFromMatrix(dict->pdf, num_colors, pdfioSRGBGamma, pdfioSRGBMatrix, pdfioSRGBWhitePoint)); pdfioDictSetName(dict, "Filter", "DCTDecode"); obj = pdfioFileCreateObj(dict->pdf, dict); @@ -1686,9 +1750,9 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary PDFIO_DEBUG("copy_png: Adding %s ColorSpace value.\n", color_type == _PDFIO_PNG_TYPE_GRAY ? "CalGray" : "CalRGB"); if (wx != 0.0) - pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateCalibratedColorFromPrimaries(dict->pdf, color_type == _PDFIO_PNG_TYPE_GRAY ? 1 : 3, gamma, wx, wy, rx, ry, bx, by, gx, gy)); + pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateColorFromPrimaries(dict->pdf, color_type == _PDFIO_PNG_TYPE_GRAY ? 1 : 3, gamma, wx, wy, rx, ry, bx, by, gx, gy)); else - pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateCalibratedColorFromMatrix(dict->pdf, color_type == _PDFIO_PNG_TYPE_GRAY ? 1 : 3, gamma, pdfioSRGBMatrix, pdfioSRGBWhitePoint)); + pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateColorFromMatrix(dict->pdf, color_type == _PDFIO_PNG_TYPE_GRAY ? 1 : 3, gamma, pdfioSRGBMatrix, pdfioSRGBWhitePoint)); } obj = pdfioFileCreateObj(dict->pdf, dict); @@ -1800,7 +1864,7 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary PDFIO_DEBUG("copy_png: Adding Indexed ColorSpace value.\n"); - pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateIndexedColor(dict->pdf, length / 3, buffer)); + pdfioDictSetArray(dict, "ColorSpace", pdfioArrayCreateColorFromPalette(dict->pdf, length / 3, buffer)); break; case _PDFIO_PNG_CHUNK_cHRM : // Cromacities and white point diff --git a/pdfio-content.h b/pdfio-content.h index 30365fb..8365e28 100644 --- a/pdfio-content.h +++ b/pdfio-content.h @@ -84,10 +84,10 @@ extern const double pdfioSRGBWhitePoint[3] PDFIO_PUBLIC; // // Color array functions... -extern pdfio_array_t *pdfioArrayCreateCalibratedColorFromMatrix(pdfio_file_t *pdf, size_t num_colors, double gamma, const double matrix[3][3], const double white_point[3]) PDFIO_PUBLIC; -extern pdfio_array_t *pdfioArrayCreateCalibratedColorFromPrimaries(pdfio_file_t *pdf, size_t num_colors, double gamma, double wx, double wy, double rx, double ry, double gx, double gy, double bx, double by) PDFIO_PUBLIC; -extern pdfio_array_t *pdfioArrayCreateICCBasedColor(pdfio_file_t *pdf, pdfio_obj_t *icc_object) PDFIO_PUBLIC; -extern pdfio_array_t *pdfioArrayCreateIndexedColor(pdfio_file_t *pdf, size_t num_colors, const unsigned char *colors) PDFIO_PUBLIC; +extern pdfio_array_t *pdfioArrayCreateColorFromICCObj(pdfio_file_t *pdf, pdfio_obj_t *icc_object) PDFIO_PUBLIC; +extern pdfio_array_t *pdfioArrayCreateColorFromMatrix(pdfio_file_t *pdf, size_t num_colors, double gamma, const double matrix[3][3], const double white_point[3]) PDFIO_PUBLIC; +extern pdfio_array_t *pdfioArrayCreateColorFromPalette(pdfio_file_t *pdf, size_t num_colors, const unsigned char *colors) PDFIO_PUBLIC; +extern pdfio_array_t *pdfioArrayCreateColorFromPrimaries(pdfio_file_t *pdf, size_t num_colors, double gamma, double wx, double wy, double rx, double ry, double gx, double gy, double bx, double by) PDFIO_PUBLIC; // PDF content drawing functions... extern bool pdfioContentClip(pdfio_stream_t *st, bool even_odd) PDFIO_PUBLIC; @@ -146,7 +146,7 @@ extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, size_t num_fragme // Resource helpers... extern pdfio_obj_t *pdfioFileCreateBaseFontObj(pdfio_file_t *pdf, const char *name) PDFIO_PUBLIC; extern pdfio_obj_t *pdfioFileCreateFontObj(pdfio_file_t *pdf, const char *filename, bool unicode) PDFIO_PUBLIC; -extern pdfio_obj_t *pdfioFileCreateICCProfileObj(pdfio_file_t *pdf, const char *filename) PDFIO_PUBLIC; +extern pdfio_obj_t *pdfioFileCreateICCObj(pdfio_file_t *pdf, const char *filename, size_t num_colors) PDFIO_PUBLIC; extern pdfio_obj_t *pdfioFileCreateImageObj(pdfio_file_t *pdf, const char *filename, bool interpolate) PDFIO_PUBLIC; // Image object helpers... diff --git a/testpdfio.c b/testpdfio.c index 680f2c1..5bde633 100644 --- a/testpdfio.c +++ b/testpdfio.c @@ -725,7 +725,13 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page contents stream pdfio_array_t *cs; // Color space array + pdfio_obj_t *prophoto; // ProPhotoRGB ICC profile object + fputs("pdfioFileCreateICCObj(ProPhotoRGB): ", stdout); + if ((prophoto = pdfioFileCreateICCObj(pdf, "testfiles/iso22028-2-romm-rgb.icc", 3)) != NULL) + puts("PASS"); + else + return (1); fputs("pdfioDictCreate: ", stdout); if ((dict = pdfioDictCreate(pdf)) != NULL) @@ -733,8 +739,8 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else return (1); - fputs("pdfioArrayCreateCalibratedColorFromMatrix(AdobeRGB): ", stdout); - if ((cs = pdfioArrayCreateCalibratedColorFromMatrix(pdf, 3, pdfioAdobeRGBGamma, pdfioAdobeRGBMatrix, pdfioAdobeRGBWhitePoint)) != NULL) + fputs("pdfioArrayCreateColorFromMatrix(AdobeRGB): ", stdout); + if ((cs = pdfioArrayCreateColorFromMatrix(pdf, 3, pdfioAdobeRGBGamma, pdfioAdobeRGBMatrix, pdfioAdobeRGBWhitePoint)) != NULL) puts("PASS"); else return (1); @@ -745,8 +751,8 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else return (1); - fputs("pdfioArrayCreateCalibratedColorFromMatrix(DisplayP3): ", stdout); - if ((cs = pdfioArrayCreateCalibratedColorFromMatrix(pdf, 3, pdfioDisplayP3Gamma, pdfioDisplayP3Matrix, pdfioDisplayP3WhitePoint)) != NULL) + fputs("pdfioArrayCreateColorFromMatrix(DisplayP3): ", stdout); + if ((cs = pdfioArrayCreateColorFromMatrix(pdf, 3, pdfioDisplayP3Gamma, pdfioDisplayP3Matrix, pdfioDisplayP3WhitePoint)) != NULL) puts("PASS"); else return (1); @@ -757,8 +763,20 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else return (1); - fputs("pdfioArrayCreateCalibratedColorFromMatrix(sRGB): ", stdout); - if ((cs = pdfioArrayCreateCalibratedColorFromMatrix(pdf, 3, pdfioSRGBGamma, pdfioSRGBMatrix, pdfioSRGBWhitePoint)) != NULL) + fputs("pdfioArrayCreateColorFromICCObj(ProPhotoRGB): ", stdout); + if ((cs = pdfioArrayCreateColorFromICCObj(pdf, prophoto)) != NULL) + puts("PASS"); + else + return (1); + + fputs("pdfioPageDictAddColorSpace(ProPhotoRGB): ", stdout); + if (pdfioPageDictAddColorSpace(dict, "ProPhotoRGB", cs)) + puts("PASS"); + else + return (1); + + fputs("pdfioArrayCreateColorFromMatrix(sRGB): ", stdout); + if ((cs = pdfioArrayCreateColorFromMatrix(pdf, 3, pdfioSRGBGamma, pdfioSRGBMatrix, pdfioSRGBWhitePoint)) != NULL) puts("PASS"); else return (1); @@ -830,8 +848,8 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else goto error; - fputs("pdfioContentTextMoveTo(82, 360): ", stdout); - if (pdfioContentTextMoveTo(st, 82, 360)) + fputs("pdfioContentTextMoveTo(82, 234): ", stdout); + if (pdfioContentTextMoveTo(st, 82, 234)) puts("PASS"); else goto error; @@ -872,6 +890,18 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else goto error; + fputs("pdfioContentTextShow(\"ProPhotoRGB\"): ", stdout); + if (pdfioContentTextShow(st, "ProPhotoRGB")) + puts("PASS"); + else + goto error; + + fputs("pdfioContentTextMoveTo(-234, 252): ", stdout); + if (pdfioContentTextMoveTo(st, -234, 252)) + puts("PASS"); + else + goto error; + fputs("pdfioContentTextShow(\"DeviceCMYK\"): ", stdout); if (pdfioContentTextShow(st, "DeviceCMYK")) puts("PASS"); @@ -896,8 +926,8 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else goto error; - fputs("pdfioContentMatrixTranslate(82, 162): ", stdout); - if (pdfioContentMatrixTranslate(st, 82, 162)) + fputs("pdfioContentMatrixTranslate(82, 36): ", stdout); + if (pdfioContentMatrixTranslate(st, 82, 36)) puts("PASS"); else goto error; @@ -923,8 +953,8 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else goto error; - fputs("pdfioContentMatrixTranslate(316, 162): ", stdout); - if (pdfioContentMatrixTranslate(st, 316, 162)) + fputs("pdfioContentMatrixTranslate(316, 36): ", stdout); + if (pdfioContentMatrixTranslate(st, 316, 36)) puts("PASS"); else goto error; @@ -950,8 +980,8 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else goto error; - fputs("pdfioContentMatrixTranslate(82, 414): ", stdout); - if (pdfioContentMatrixTranslate(st, 82, 414)) + fputs("pdfioContentMatrixTranslate(82, 288): ", stdout); + if (pdfioContentMatrixTranslate(st, 82, 288)) puts("PASS"); else goto error; @@ -971,8 +1001,35 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file else goto error; - fputs("pdfioContentMatrixTranslate(316, 414): ", stdout); - if (pdfioContentMatrixTranslate(st, 316, 414)) + fputs("pdfioContentSetFillColorSpace(ProPhotoRGB): ", stdout); + if (pdfioContentSetFillColorSpace(st, "ProPhotoRGB")) + puts("PASS"); + else + goto error; + + fputs("pdfioContentMatrixTranslate(316, 288): ", stdout); + if (pdfioContentMatrixTranslate(st, 316, 288)) + puts("PASS"); + else + goto error; + + if (write_color_patch(st, false)) + goto error; + + fputs("pdfioContentRestore(): ", stdout); + if (pdfioContentRestore(st)) + puts("PASS"); + else + goto error; + + fputs("pdfioContentSave(): ", stdout); + if (pdfioContentSave(st)) + puts("PASS"); + else + goto error; + + fputs("pdfioContentMatrixTranslate(82, 540): ", stdout); + if (pdfioContentMatrixTranslate(st, 82, 540)) puts("PASS"); else goto error;