Merge branch 'dev' into tiff32float

This commit is contained in:
Hombre
2018-01-01 15:24:00 +01:00
99 changed files with 4532 additions and 3026 deletions

View File

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