Merge branch 'dev' into tiff32float
This commit is contained in:
@@ -303,6 +303,11 @@ int ImageIO::loadPNG (Glib::ustring fname)
|
||||
return IMIO_HEADERERROR;
|
||||
}
|
||||
|
||||
// silence the warning about "invalid" sRGB profiles -- see #4260
|
||||
#if defined(PNG_SKIP_sRGB_CHECK_PROFILE) && defined(PNG_SET_OPTION_SUPPORTED)
|
||||
png_set_option(png, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON);
|
||||
#endif
|
||||
|
||||
png_infop info = png_create_info_struct (png);
|
||||
png_infop end_info = png_create_info_struct (png);
|
||||
|
||||
@@ -351,6 +356,22 @@ int ImageIO::loadPNG (Glib::ustring fname)
|
||||
png_set_strip_alpha(png);
|
||||
}
|
||||
|
||||
// reading the embedded ICC profile if any
|
||||
if (png_get_valid(png, info, PNG_INFO_iCCP)) {
|
||||
png_charp name;
|
||||
int compression_type;
|
||||
#if PNG_LIBPNG_VER < 10500
|
||||
png_charp profdata;
|
||||
#else
|
||||
png_bytep profdata;
|
||||
#endif
|
||||
png_uint_32 proflen;
|
||||
png_get_iCCP(png, info, &name, &compression_type, &profdata, &proflen);
|
||||
embProfile = cmsOpenProfileFromMem(profdata, proflen);
|
||||
loadedProfileData = new char[proflen];
|
||||
memcpy(loadedProfileData, profdata, proflen);
|
||||
}
|
||||
|
||||
//setting gamma
|
||||
double gamma;
|
||||
|
||||
@@ -900,6 +921,77 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s
|
||||
return IMIO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Taken from Darktable -- src/imageio/format/png.c
|
||||
//
|
||||
/* Write EXIF data to PNG file.
|
||||
* Code copied from DigiKam's libs/dimg/loaders/pngloader.cpp.
|
||||
* The EXIF embedding is defined by ImageMagicK.
|
||||
* It is documented in the ExifTool page:
|
||||
* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html
|
||||
*
|
||||
* ..and in turn copied from ufraw. thanks to udi and colleagues
|
||||
* for making useful code much more readable and discoverable ;)
|
||||
*/
|
||||
|
||||
void PNGwriteRawProfile(png_struct *ping, png_info *ping_info, const char *profile_type, guint8 *profile_data, png_uint_32 length)
|
||||
{
|
||||
png_textp text;
|
||||
long i;
|
||||
guint8 *sp;
|
||||
png_charp dp;
|
||||
png_uint_32 allocated_length, description_length;
|
||||
|
||||
const guint8 hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
text = static_cast<png_textp>(png_malloc(ping, sizeof(png_text)));
|
||||
description_length = strlen(profile_type);
|
||||
allocated_length = length * 2 + (length >> 5) + 20 + description_length;
|
||||
|
||||
text[0].text = static_cast<png_charp>(png_malloc(ping, allocated_length));
|
||||
text[0].key = static_cast<png_charp>(png_malloc(ping, 80));
|
||||
text[0].key[0] = '\0';
|
||||
|
||||
g_strlcat(text[0].key, "Raw profile type ", 80);
|
||||
g_strlcat(text[0].key, profile_type, 80);
|
||||
|
||||
sp = profile_data;
|
||||
dp = text[0].text;
|
||||
*dp++ = '\n';
|
||||
|
||||
g_strlcpy(dp, profile_type, allocated_length);
|
||||
|
||||
dp += description_length;
|
||||
*dp++ = '\n';
|
||||
*dp = '\0';
|
||||
|
||||
g_snprintf(dp, allocated_length - strlen(text[0].text), "%8lu ", static_cast<unsigned long int>(length));
|
||||
|
||||
dp += 8;
|
||||
|
||||
for(i = 0; i < long(length); i++)
|
||||
{
|
||||
if(i % 36 == 0) *dp++ = '\n';
|
||||
|
||||
*(dp++) = hex[((*sp >> 4) & 0x0f)];
|
||||
*(dp++) = hex[((*sp++) & 0x0f)];
|
||||
}
|
||||
|
||||
*dp++ = '\n';
|
||||
*dp = '\0';
|
||||
text[0].text_length = (dp - text[0].text);
|
||||
text[0].compression = -1;
|
||||
|
||||
if(text[0].text_length <= allocated_length) png_set_text(ping, ping_info, text, 1);
|
||||
|
||||
png_free(ping, text[0].text);
|
||||
png_free(ping, text[0].key);
|
||||
png_free(ping, text);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int ImageIO::savePNG (Glib::ustring fname, volatile int bps)
|
||||
{
|
||||
if (getWidth() < 1 || getHeight() < 1) {
|
||||
@@ -924,6 +1016,11 @@ int ImageIO::savePNG (Glib::ustring fname, volatile int bps)
|
||||
return IMIO_HEADERERROR;
|
||||
}
|
||||
|
||||
// silence the warning about "invalid" sRGB profiles -- see #4260
|
||||
#if defined(PNG_SKIP_sRGB_CHECK_PROFILE) && defined(PNG_SET_OPTION_SUPPORTED)
|
||||
png_set_option(png, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON);
|
||||
#endif
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
|
||||
if (!info) {
|
||||
@@ -954,6 +1051,38 @@ int ImageIO::savePNG (Glib::ustring fname, volatile int bps)
|
||||
png_set_IHDR(png, info, width, height, bps, PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
if (profileData) {
|
||||
#if PNG_LIBPNG_VER < 10500
|
||||
png_charp profdata = reinterpret_cast<png_charp>(profileData);
|
||||
#else
|
||||
png_bytep profdata = reinterpret_cast<png_bytep>(profileData);
|
||||
#endif
|
||||
png_set_iCCP(png, info, const_cast<png_charp>("icc"), 0, profdata, profileLength);
|
||||
}
|
||||
|
||||
{
|
||||
// buffer for the exif and iptc
|
||||
unsigned int bufferSize;
|
||||
unsigned char* buffer = nullptr; // buffer will be allocated in createTIFFHeader
|
||||
unsigned char* iptcdata = nullptr;
|
||||
unsigned int iptclen = 0;
|
||||
|
||||
if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen) && iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
iptcdata = nullptr;
|
||||
}
|
||||
|
||||
int size = rtexif::ExifManager::createPNGMarker(exifRoot, exifChange, width, height, bps, (char*)iptcdata, iptclen, buffer, bufferSize);
|
||||
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
if (buffer && size) {
|
||||
PNGwriteRawProfile(png, info, "exif", buffer, size);
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int rowlen = width * 3 * bps / 8;
|
||||
unsigned char *row = new unsigned char [rowlen];
|
||||
|
Reference in New Issue
Block a user