ICC profile support (Issue #3)

This commit is contained in:
Michael R Sweet 2021-06-10 12:40:06 -04:00
parent 6aab99d4b3
commit 5533408c09
No known key found for this signature in database
GPG Key ID: BE67C75EC81F3244
3 changed files with 214 additions and 93 deletions

View File

@ -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

View File

@ -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...

View File

@ -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;