Merge branch 'tiff32float' into dev

This commit is contained in:
Hombre
2018-01-08 21:47:14 +01:00
21 changed files with 485 additions and 409 deletions

View File

@@ -330,50 +330,50 @@ Image16::tofloat()
return imgfloat;
}
// Parallized transformation; create transform with cmsFLAGS_NOCACHE!
void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy)
{
// LittleCMS cannot parallelize planar Lab float images
// so build temporary buffers to allow multi processor execution
#ifdef _OPENMP
#pragma omp parallel
#endif
{
AlignedBuffer<float> bufferLab(width * 3);
AlignedBuffer<unsigned short> bufferRGB(width * 3);
// // Parallized transformation; create transform with cmsFLAGS_NOCACHE!
// void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy)
// {
// // LittleCMS cannot parallelize planar Lab float images
// // so build temporary buffers to allow multi processor execution
// #ifdef _OPENMP
// #pragma omp parallel
// #endif
// {
// AlignedBuffer<float> bufferLab(width * 3);
// AlignedBuffer<unsigned short> bufferRGB(width * 3);
#ifdef _OPENMP
#pragma omp for schedule(static)
#endif
// #ifdef _OPENMP
// #pragma omp for schedule(static)
// #endif
for (int y = cy; y < cy + height; y++)
{
unsigned short *pRGB, *pR, *pG, *pB;
float *pLab, *pL, *pa, *pb;
// for (int y = cy; y < cy + height; y++)
// {
// unsigned short *pRGB, *pR, *pG, *pB;
// float *pLab, *pL, *pa, *pb;
pLab= bufferLab.data;
pL = labImage.L[y] + cx;
pa = labImage.a[y] + cx;
pb = labImage.b[y] + cx;
// pLab= bufferLab.data;
// pL = labImage.L[y] + cx;
// pa = labImage.a[y] + cx;
// pb = labImage.b[y] + cx;
for (int x = 0; x < width; x++) {
*(pLab++) = *(pL++) / 327.68f;
*(pLab++) = *(pa++) / 327.68f;
*(pLab++) = *(pb++) / 327.68f;
}
// for (int x = 0; x < width; x++) {
// *(pLab++) = *(pL++) / 327.68f;
// *(pLab++) = *(pa++) / 327.68f;
// *(pLab++) = *(pb++) / 327.68f;
// }
cmsDoTransform (hTransform, bufferLab.data, bufferRGB.data, width);
// cmsDoTransform (hTransform, bufferLab.data, bufferRGB.data, width);
pRGB = bufferRGB.data;
pR = r(y - cy);
pG = g(y - cy);
pB = b(y - cy);
// pRGB = bufferRGB.data;
// pR = r(y - cy);
// pG = g(y - cy);
// pB = b(y - cy);
for (int x = 0; x < width; x++) {
*(pR++) = *(pRGB++);
*(pG++) = *(pRGB++);
*(pB++) = *(pRGB++);
}
} // End of parallelization
}
}
// for (int x = 0; x < width; x++) {
// *(pR++) = *(pRGB++);
// *(pG++) = *(pRGB++);
// *(pB++) = *(pRGB++);
// }
// } // End of parallelization
// }
// }

View File

@@ -96,7 +96,7 @@ public:
delete this;
}
void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy);
/* void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy); */
};
}

View File

@@ -154,11 +154,25 @@ void Imagefloat::getScanline (int row, unsigned char* buffer, int bps)
int ix = 0;
float* sbuffer = (float*) buffer;
// agriggio -- assume the image is normalized to [0, 65535]
for (int i = 0; i < width; i++) {
sbuffer[ix++] = r(row, i) / 65535.f;
sbuffer[ix++] = g(row, i) / 65535.f;
sbuffer[ix++] = b(row, i) / 65535.f;
}
} else if (bps == 16) {
unsigned short *sbuffer = (unsigned short *)buffer;
for (int i = 0, ix = 0; i < width; i++) {
sbuffer[ix++] = r(row, i);
sbuffer[ix++] = g(row, i);
sbuffer[ix++] = b(row, i);
}
} else if (bps == 8) {
for (int i = 0, ix = 0; i < width; i++) {
buffer[ix++] = rtengine::uint16ToUint8Rounded(r(row, i));
buffer[ix++] = rtengine::uint16ToUint8Rounded(g(row, i));
buffer[ix++] = rtengine::uint16ToUint8Rounded(b(row, i));
}
}
}
@@ -516,3 +530,51 @@ void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform)
} // End of parallelization
}
}
// Parallized transformation; create transform with cmsFLAGS_NOCACHE!
void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy)
{
// LittleCMS cannot parallelize planar Lab float images
// so build temporary buffers to allow multi processor execution
#ifdef _OPENMP
#pragma omp parallel
#endif
{
AlignedBuffer<float> bufferLab(width * 3);
AlignedBuffer<float> bufferRGB(width * 3);
#ifdef _OPENMP
#pragma omp for schedule(static)
#endif
for (int y = cy; y < cy + height; y++)
{
float *pRGB, *pR, *pG, *pB;
float *pLab, *pL, *pa, *pb;
pLab= bufferLab.data;
pL = labImage.L[y] + cx;
pa = labImage.a[y] + cx;
pb = labImage.b[y] + cx;
for (int x = 0; x < width; x++) {
*(pLab++) = *(pL++) / 327.68f;
*(pLab++) = *(pa++) / 327.68f;
*(pLab++) = *(pb++) / 327.68f;
}
cmsDoTransform (hTransform, bufferLab.data, bufferRGB.data, width);
pRGB = bufferRGB.data;
pR = r(y - cy);
pG = g(y - cy);
pB = b(y - cy);
for (int x = 0; x < width; x++) {
*(pR++) = *(pRGB++);
*(pG++) = *(pRGB++);
*(pB++) = *(pRGB++);
}
} // End of parallelization
}
}

View File

@@ -106,6 +106,7 @@ public:
void calcCroppedHistogram(const ProcParams &params, float scale, LUTu & hist);
void ExecCMSTransform(cmsHTRANSFORM hTransform);
void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy);
};
}

View File

@@ -75,15 +75,6 @@ FILE* g_fopen_withBinaryAndLock(const Glib::ustring& fname)
return f;
}
Glib::ustring to_utf8 (const std::string& str)
{
try {
return Glib::locale_to_utf8 (str);
} catch (Glib::Error&) {
return Glib::convert_with_fallback (str, "UTF-8", "ISO-8859-1", "?");
}
}
}
Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."};
@@ -136,13 +127,19 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr
iptc = iptc_data_new ();
const unsigned char utf8Esc[] = {0x1B, '%', 'G'};
IptcDataSet * ds = iptc_dataset_new ();
iptc_dataset_set_tag (ds, IPTC_RECORD_OBJECT_ENV, IPTC_TAG_CHARACTER_SET);
iptc_dataset_set_data (ds, utf8Esc, 3, IPTC_DONT_VALIDATE);
iptc_data_add_dataset (iptc, ds);
iptc_dataset_unref (ds);
for (rtengine::procparams::IPTCPairs::const_iterator i = iptcc.begin(); i != iptcc.end(); ++i) {
if (i->first == "Keywords" && !(i->second.empty())) {
for (unsigned int j = 0; j < i->second.size(); j++) {
IptcDataSet * ds = iptc_dataset_new ();
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS);
std::string loc = to_utf8(i->second.at(j));
iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast<size_t>(64), loc.size()), IPTC_DONT_VALIDATE);
iptc_dataset_set_data (ds, (unsigned char*)i->second.at(j).c_str(), min(static_cast<size_t>(64), i->second.at(j).bytes()), IPTC_DONT_VALIDATE);
iptc_data_add_dataset (iptc, ds);
iptc_dataset_unref (ds);
}
@@ -152,8 +149,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr
for (unsigned int j = 0; j < i->second.size(); j++) {
IptcDataSet * ds = iptc_dataset_new ();
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY);
std::string loc = to_utf8(i->second.at(j));
iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast<size_t>(32), loc.size()), IPTC_DONT_VALIDATE);
iptc_dataset_set_data (ds, (unsigned char*)i->second.at(j).c_str(), min(static_cast<size_t>(32), i->second.at(j).bytes()), IPTC_DONT_VALIDATE);
iptc_data_add_dataset (iptc, ds);
iptc_dataset_unref (ds);
}
@@ -165,8 +161,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr
if (i->first == strTags[j].field && !(i->second.empty())) {
IptcDataSet * ds = iptc_dataset_new ();
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, strTags[j].tag);
std::string loc = to_utf8(i->second.at(0));
iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(strTags[j].size, loc.size()), IPTC_DONT_VALIDATE);
iptc_dataset_set_data (ds, (unsigned char*)i->second.at(0).c_str(), min(strTags[j].size, i->second.at(0).bytes()), IPTC_DONT_VALIDATE);
iptc_data_add_dataset (iptc, ds);
iptc_dataset_unref (ds);
}
@@ -1250,13 +1245,13 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp)
int bytes = 0;
if (!error && (bytes = iptc_jpeg_ps3_save_iptc (nullptr, 0, iptcdata, size, buffer, 65532)) < 0) {
if (iptcdata) {
iptc_data_free_buf (iptc, iptcdata);
}
error = true;
}
if (iptcdata) {
iptc_data_free_buf (iptc, iptcdata);
}
if (!error) {
jpeg_write_marker(&cinfo, JPEG_APP0 + 13, buffer, bytes);
}
@@ -1341,189 +1336,198 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed)
int lineWidth = width * 3 * bps / 8;
unsigned char* linebuffer = new unsigned char[lineWidth];
// TODO the following needs to be looked into - do we really need two ways to write a Tiff file ?
if (exifRoot && uncompressed) {
FILE *file = g_fopen_withBinaryAndLock (fname);
// little hack to get libTiff to use proper byte order (see TIFFClienOpen()):
const char *mode = !exifRoot ? "w" : (exifRoot->getOrder() == rtexif::INTEL ? "wl" : "wb");
#ifdef WIN32
FILE *file = g_fopen_withBinaryAndLock (fname);
int fileno = _fileno(file);
int osfileno = _get_osfhandle(fileno);
TIFF* out = TIFFFdOpen (osfileno, fname.c_str(), mode);
#else
TIFF* out = TIFFOpen(fname.c_str(), mode);
int fileno = TIFFFileno (out);
#endif
if (!file) {
delete [] linebuffer;
return IMIO_CANNOTWRITEFILE;
if (!out) {
delete [] linebuffer;
return IMIO_CANNOTWRITEFILE;
}
if (pl) {
pl->setProgressStr ("PROGRESSBAR_SAVETIFF");
pl->setProgress (0.0);
}
if (exifRoot) {
rtexif::TagDirectory* cl = (const_cast<rtexif::TagDirectory*> (exifRoot))->clone (nullptr);
// ------------------ remove some unknown top level tags which produce warnings when opening a tiff (might be useless) -----------------
rtexif::Tag *removeTag = cl->getTag (0x9003);
if (removeTag) {
removeTag->setKeep (false);
}
if (pl) {
pl->setProgressStr ("PROGRESSBAR_SAVETIFF");
pl->setProgress (0.0);
removeTag = cl->getTag (0x9211);
if (removeTag) {
removeTag->setKeep (false);
}
// 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;
// ------------------ Apply list of change -----------------
if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen) && iptcdata) {
for (auto currExifChange : exifChange) {
cl->applyChange (currExifChange.first, currExifChange.second);
}
rtexif::Tag *tag = cl->getTag (TIFFTAG_EXIFIFD);
if (tag && tag->isDirectory()) {
rtexif::TagDirectory *exif = tag->getDirectory();
if (exif) {
int exif_size = exif->calculateSize();
unsigned char *buffer = new unsigned char[exif_size + 8];
// TIFFOpen writes out the header and sets file pointer at position 8
exif->write (8, buffer);
write (fileno, buffer + 8, exif_size);
delete [] buffer;
// let libtiff know that scanlines or any other following stuff should go
// at a different offset:
TIFFSetWriteOffset (out, exif_size + 8);
TIFFSetField (out, TIFFTAG_EXIFIFD, 8);
}
}
//TODO Even though we are saving EXIF IFD - MakerNote still comes out screwed.
if ((tag = cl->getTag (TIFFTAG_MODEL)) != nullptr) {
TIFFSetField (out, TIFFTAG_MODEL, tag->getValue());
}
if ((tag = cl->getTag (TIFFTAG_MAKE)) != nullptr) {
TIFFSetField (out, TIFFTAG_MAKE, tag->getValue());
}
if ((tag = cl->getTag (TIFFTAG_DATETIME)) != nullptr) {
TIFFSetField (out, TIFFTAG_DATETIME, tag->getValue());
}
if ((tag = cl->getTag (TIFFTAG_ARTIST)) != nullptr) {
TIFFSetField (out, TIFFTAG_ARTIST, tag->getValue());
}
if ((tag = cl->getTag (TIFFTAG_COPYRIGHT)) != nullptr) {
TIFFSetField (out, TIFFTAG_COPYRIGHT, tag->getValue());
}
delete cl;
}
unsigned char* iptcdata = nullptr;
unsigned int iptclen = 0;
if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen)) {
if (iptcdata) {
iptc_data_free_buf (iptc, iptcdata);
iptcdata = nullptr;
}
}
int size = rtexif::ExifManager::createTIFFHeader (exifRoot, exifChange, width, height, bps, profileData, profileLength, (char*)iptcdata, iptclen, buffer, bufferSize);
if (iptcdata) {
iptc_data_free_buf (iptc, iptcdata);
if (iptcdata) {
rtexif::Tag* iptcTag = new rtexif::Tag (nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData"));
iptcTag->initLongArray((char*)iptcdata, iptclen);
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::MOTOROLA;
#else
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::INTEL;
#endif
if (needsReverse) {
unsigned char *ptr = iptcTag->getValue();
for (int a = 0; a < iptcTag->getCount(); ++a) {
unsigned char cc;
cc = ptr[3];
ptr[3] = ptr[0];
ptr[0] = cc;
cc = ptr[2];
ptr[2] = ptr[1];
ptr[1] = cc;
ptr += 4;
}
}
TIFFSetField (out, TIFFTAG_RICHTIFFIPTC, iptcTag->getCount(), (long*)iptcTag->getValue());
iptc_data_free_buf (iptc, iptcdata);
}
// The maximum lenght is strangely not the same than for the JPEG file...
// Which maximum length is the good one ?
if (size > 0 && size <= static_cast<int>(bufferSize)) {
fwrite (buffer, size, 1, file);
}
TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " RTVERSION);
TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField (out, TIFFTAG_IMAGELENGTH, height);
TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 3);
TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, height);
TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, bps);
TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_DEFLATE);
TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, bps == 32 ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT);
if (!uncompressed) {
TIFFSetField (out, TIFFTAG_PREDICTOR, bps == 32 ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL);
}
if (profileData) {
TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData);
}
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
bool needsReverse = bps == 16 && exifRoot->getOrder() == rtexif::MOTOROLA;
bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::MOTOROLA;
#else
bool needsReverse = bps == 16 && exifRoot->getOrder() == rtexif::INTEL;
bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::INTEL;
#endif
for (int i = 0; i < height; i++) {
getScanline (i, linebuffer, bps);
for (int row = 0; row < height; row++) {
getScanline (row, linebuffer, bps);
if (needsReverse)
if (needsReverse) {
if (bps == 16) {
for (int i = 0; i < lineWidth; i += 2) {
char c = linebuffer[i];
linebuffer[i] = linebuffer[i + 1];
linebuffer[i + 1] = c;
}
fwrite (linebuffer, lineWidth, 1, file);
if (pl && !(i % 100)) {
pl->setProgress ((double)(i + 1) / height);
} else {
for (int i = 0; i < lineWidth; i += 4) {
std::swap(linebuffer[i], linebuffer[i+3]);
std::swap(linebuffer[i+1], linebuffer[i+2]);
}
}
}
if(buffer) {
delete [] buffer;
}
if (ferror(file)) {
writeOk = false;
}
fclose (file);
} else {
// little hack to get libTiff to use proper byte order (see TIFFClienOpen()):
const char *mode = !exifRoot ? "w" : (exifRoot->getOrder() == rtexif::INTEL ? "wl" : "wb");
#ifdef WIN32
FILE *file = g_fopen_withBinaryAndLock (fname);
int fileno = _fileno(file);
int osfileno = _get_osfhandle(fileno);
TIFF* out = TIFFFdOpen (osfileno, fname.c_str(), mode);
#else
TIFF* out = TIFFOpen(fname.c_str(), mode);
int fileno = TIFFFileno (out);
#endif
if (!out) {
if (TIFFWriteScanline (out, linebuffer, row, 0) < 0) {
TIFFClose (out);
delete [] linebuffer;
return IMIO_CANNOTWRITEFILE;
}
if (pl) {
pl->setProgressStr ("PROGRESSBAR_SAVETIFF");
pl->setProgress (0.0);
if (pl && !(row % 100)) {
pl->setProgress ((double)(row + 1) / height);
}
if (exifRoot) {
rtexif::Tag *tag = exifRoot->getTag (TIFFTAG_EXIFIFD);
if (tag && tag->isDirectory()) {
rtexif::TagDirectory *exif = tag->getDirectory();
if (exif) {
int exif_size = exif->calculateSize();
unsigned char *buffer = new unsigned char[exif_size + 8];
// TIFFOpen writes out the header and sets file pointer at position 8
exif->write (8, buffer);
write (fileno, buffer + 8, exif_size);
delete [] buffer;
// let libtiff know that scanlines or any other following stuff should go
// at a different offset:
TIFFSetWriteOffset (out, exif_size + 8);
TIFFSetField (out, TIFFTAG_EXIFIFD, 8);
}
}
//TODO Even though we are saving EXIF IFD - MakerNote still comes out screwed.
if ((tag = exifRoot->getTag (TIFFTAG_MODEL)) != nullptr) {
TIFFSetField (out, TIFFTAG_MODEL, tag->getValue());
}
if ((tag = exifRoot->getTag (TIFFTAG_MAKE)) != nullptr) {
TIFFSetField (out, TIFFTAG_MAKE, tag->getValue());
}
if ((tag = exifRoot->getTag (TIFFTAG_DATETIME)) != nullptr) {
TIFFSetField (out, TIFFTAG_DATETIME, tag->getValue());
}
if ((tag = exifRoot->getTag (TIFFTAG_ARTIST)) != nullptr) {
TIFFSetField (out, TIFFTAG_ARTIST, tag->getValue());
}
if ((tag = exifRoot->getTag (TIFFTAG_COPYRIGHT)) != nullptr) {
TIFFSetField (out, TIFFTAG_COPYRIGHT, tag->getValue());
}
}
TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " RTVERSION);
TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField (out, TIFFTAG_IMAGELENGTH, height);
TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 3);
TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, height);
TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, bps);
TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_DEFLATE);
if (!uncompressed) {
TIFFSetField (out, TIFFTAG_PREDICTOR, PREDICTOR_NONE);
}
if (profileData) {
TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData);
}
for (int row = 0; row < height; row++) {
getScanline (row, linebuffer, bps);
if (TIFFWriteScanline (out, linebuffer, row, 0) < 0) {
TIFFClose (out);
delete [] linebuffer;
return IMIO_CANNOTWRITEFILE;
}
if (pl && !(row % 100)) {
pl->setProgress ((double)(row + 1) / height);
}
}
if (TIFFFlush(out) != 1) {
writeOk = false;
}
TIFFClose (out);
#ifdef WIN32
fclose (file);
#endif
}
if (TIFFFlush(out) != 1) {
writeOk = false;
}
TIFFClose (out);
#ifdef WIN32
fclose (file);
#endif
delete [] linebuffer;
if (pl) {

View File

@@ -1274,21 +1274,18 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool
}
}
Image16* im16 = im->to16();
delete im;
int imw, imh;
double tmpScale = ipf.resizeScale (&params, fW, fH, imw, imh);
if (tmpScale != 1.0) {
Image16* tempImage = new Image16 (imw, imh);
ipf.resize (im16, tempImage, tmpScale);
delete im16;
im16 = tempImage;
Imagefloat* tempImage = new Imagefloat (imw, imh);
ipf.resize (im, tempImage, tmpScale);
delete im;
im = tempImage;
}
im16->saveTIFF (fname, 16, true);
delete im16;
im->saveTIFF (fname, 16, true);
delete im;
if (plistener) {
plistener->setProgressState (false);

View File

@@ -239,9 +239,9 @@ public:
void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage);
float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh);
void lab2monitorRgb (LabImage* lab, Image8* image);
void resize (Image16* src, Image16* dst, float dScale);
void resize (Imagefloat* src, Imagefloat* dst, float dScale);
void Lanczos (const LabImage* src, LabImage* dst, float scale);
void Lanczos (const Image16* src, Image16* dst, float scale);
void Lanczos (const Imagefloat* src, Imagefloat* dst, float scale);
void deconvsharpening (float** luminance, float** buffer, int W, int H, const SharpeningParams &sharpenParam);
void MLsharpen (LabImage* lab);// Manuel's clarity / sharpening
@@ -349,7 +349,7 @@ public:
void localContrast(LabImage *lab);
Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm);
Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga = nullptr);
Imagefloat* lab2rgbOut (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga = nullptr);
// CieImage *ciec;
bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr);

View File

@@ -262,7 +262,7 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
* If a custom gamma profile can be created, divide by 327.68, convert to xyz and apply the custom gamma transform
* otherwise divide by 327.68, convert to xyz and apply the sRGB transform, before converting with gamma2curve
*/
Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga)
Imagefloat* ImProcFunctions::lab2rgbOut (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga)
{
if (cx < 0) {
@@ -281,7 +281,7 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
ch = lab->H - cy;
}
Image16* image = new Image16 (cw, ch);
Imagefloat* image = new Imagefloat (cw, ch);
cmsHPROFILE oprof = nullptr;
if (ga) {
@@ -300,11 +300,12 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
}
lcmsMutex->lock ();
cmsHPROFILE iprof = cmsCreateLab4Profile(nullptr);
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, oprof, TYPE_RGB_16, icm.outputIntent, flags);
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, oprof, TYPE_RGB_FLT, icm.outputIntent, flags);
lcmsMutex->unlock ();
image->ExecCMSTransform(hTransform, *lab, cx, cy);
cmsDeleteTransform(hTransform);
image->normalizeFloatTo65535();
} else {
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
@@ -329,9 +330,9 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
Color::xyz2srgb(x_, y_, z_, R, G, B);
image->r(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(R)];
image->g(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(G)];
image->b(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(B)];
image->r(i - cy, j - cx) = Color::gamma2curve[CLIP(R)];
image->g(i - cy, j - cx) = Color::gamma2curve[CLIP(G)];
image->b(i - cy, j - cx) = Color::gamma2curve[CLIP(B)];
}
}
}

View File

@@ -46,7 +46,7 @@ static inline float Lanc (float x, float a)
}
}
void ImProcFunctions::Lanczos (const Image16* src, Image16* dst, float scale)
void ImProcFunctions::Lanczos (const Imagefloat* src, Imagefloat* dst, float scale)
{
const float delta = 1.0f / scale;
@@ -159,9 +159,9 @@ void ImProcFunctions::Lanczos (const Image16* src, Image16* dst, float scale)
b += wh[k] * lb[jj];
}
dst->r (i, j) = CLIP (static_cast<int> (r));
dst->g (i, j) = CLIP (static_cast<int> (g));
dst->b (i, j) = CLIP (static_cast<int> (b));
dst->r (i, j) = CLIP (r);//static_cast<int> (r));
dst->g (i, j) = CLIP (g);//static_cast<int> (g));
dst->b (i, j) = CLIP (b);//static_cast<int> (b));
}
}
@@ -396,7 +396,7 @@ float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, in
return (float)dScale;
}
void ImProcFunctions::resize (Image16* src, Image16* dst, float dScale)
void ImProcFunctions::resize (Imagefloat* src, Imagefloat* dst, float dScale)
{
#ifdef PROFILE
time_t t1 = clock();

View File

@@ -534,7 +534,7 @@ public:
* @param errorCode is the error code if an error occured (e.g. the input image could not be loaded etc.)
* @param pl is an optional ProgressListener if you want to keep track of the progress
* @return the resulting image, with the output profile applied, exif and iptc data set. You have to save it or you can access the pixel data directly. */
IImage16* processImage (ProcessingJob* job, int& errorCode, ProgressListener* pl = nullptr, bool flush = false);
IImagefloat* processImage (ProcessingJob* job, int& errorCode, ProgressListener* pl = nullptr, bool flush = false);
/** This class is used to control the batch processing. The class implementing this interface will be called when the full processing of an
* image is ready and the next job to process is needed. */
@@ -545,7 +545,7 @@ public:
* there is no jobs left.
* @param img is the result of the last ProcessingJob
* @return the next ProcessingJob to process */
virtual ProcessingJob* imageReady (IImage16* img) = 0;
virtual ProcessingJob* imageReady (IImagefloat* img) = 0;
virtual void error (Glib::ustring message) = 0;
};
/** This function performs all the image processinf steps corresponding to the given ProcessingJob. It runs in the background, thus it returns immediately,

View File

@@ -65,7 +65,7 @@ public:
{
}
Image16 *operator()()
Imagefloat *operator()()
{
if (!job->fast) {
return normal_pipeline();
@@ -75,7 +75,7 @@ public:
}
private:
Image16 *normal_pipeline()
Imagefloat *normal_pipeline()
{
if (!stage_init()) {
return nullptr;
@@ -86,7 +86,7 @@ private:
return stage_finish();
}
Image16 *fast_pipeline()
Imagefloat *fast_pipeline()
{
if (!job->pparams.resize.enabled) {
return normal_pipeline();
@@ -832,7 +832,7 @@ private:
}
}
Image16 *stage_finish()
Imagefloat *stage_finish()
{
procparams::ProcParams& params = job->pparams;
//ImProcFunctions ipf (&params, true);
@@ -1228,7 +1228,7 @@ private:
}
}
Image16* readyImg = nullptr;
Imagefloat* readyImg = nullptr;
cmsHPROFILE jprof = nullptr;
bool customGamma = false;
bool useLCMS = false;
@@ -1238,7 +1238,7 @@ private:
GammaValues ga;
// if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, &ga);
readyImg = ipf.lab2rgbOut (labView, cx, cy, cw, ch, params.icm, &ga);
customGamma = true;
//or selected Free gamma
@@ -1252,7 +1252,7 @@ private:
// if Default gamma mode: we use the profile selected in the "Output profile" combobox;
// gamma come from the selected profile, otherwise it comes from "Free gamma" tool
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm);
readyImg = ipf.lab2rgbOut (labView, cx, cy, cw, ch, params.icm);
if (settings->verbose) {
printf ("Output profile_: \"%s\"\n", params.icm.output.c_str());
@@ -1282,7 +1282,7 @@ private:
}
if (tmpScale != 1.0 && params.resize.method == "Nearest") { // resize rgb data (gamma applied)
Image16* tempImage = new Image16 (imw, imh);
Imagefloat* tempImage = new Imagefloat (imw, imh);
ipf.resize (readyImg, tempImage, tmpScale);
delete readyImg;
readyImg = tempImage;
@@ -1568,7 +1568,7 @@ private:
} // namespace
IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl, bool flush)
IImagefloat* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl, bool flush)
{
ImageProcessor proc (pjob, errorCode, pl, flush);
return proc();
@@ -1581,7 +1581,7 @@ void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl)
while (currentJob) {
int errorCode;
IImage16* img = processImage (currentJob, errorCode, bpl, true);
IImagefloat* img = processImage (currentJob, errorCode, bpl, true);
if (errorCode) {
bpl->error (M ("MAIN_MSG_CANNOTLOAD"));