diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index f8e257ddc..8dfd90ab3 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -46,8 +46,6 @@ ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataL ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed(0), aperture(0.), shutter(0.) { - - size_t dotpos = fname.find_last_of ('.'); root = nullptr; iptc = nullptr; @@ -72,7 +70,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed( fclose (f); extractInfo (); } - } else if ((dotpos < fname.size() - 3 && !fname.casefold().compare (dotpos, 4, ".jpg")) || (dotpos < fname.size() - 4 && !fname.casefold().compare (dotpos, 5, ".jpeg"))) { + } else if (hasJpegExtension(fname)) { FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { @@ -83,7 +81,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed( iptc = iptc_data_new_from_jpeg_file (ff); fclose (ff); } - } else if ((dotpos < fname.size() - 3 && !fname.casefold().compare (dotpos, 4, ".tif")) || (dotpos < fname.size() - 4 && !fname.casefold().compare (dotpos, 5, ".tiff"))) { + } else if (hasTiffExtension(fname)) { FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index e886dabce..59f7cf541 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -1441,19 +1441,11 @@ void png_flush(png_structp png_ptr) int ImageIO::load (Glib::ustring fname) { - size_t lastdot = fname.find_last_of ('.'); - - if( Glib::ustring::npos == lastdot ) { - return IMIO_FILETYPENOTSUPPORTED; - } - - if (!fname.casefold().compare (lastdot, 4, ".png")) { + if (hasPngExtension(fname)) { return loadPNG (fname); - } else if (!fname.casefold().compare (lastdot, 4, ".jpg") || - !fname.casefold().compare (lastdot, 5, ".jpeg")) { + } else if (hasJpegExtension(fname)) { return loadJPEG (fname); - } else if (!fname.casefold().compare (lastdot, 4, ".tif") || - !fname.casefold().compare (lastdot, 5, ".tiff")) { + } else if (hasTiffExtension(fname)) { return loadTIFF (fname); } else { return IMIO_FILETYPENOTSUPPORTED; @@ -1462,20 +1454,11 @@ int ImageIO::load (Glib::ustring fname) int ImageIO::save (Glib::ustring fname) { - - size_t lastdot = fname.find_last_of ('.'); - - if( Glib::ustring::npos == lastdot ) { - return IMIO_FILETYPENOTSUPPORTED; - } - - if (!fname.casefold().compare (lastdot, 4, ".png")) { + if (hasPngExtension(fname)) { return savePNG (fname); - } else if (!fname.casefold().compare (lastdot, 4, ".jpg") || - !fname.casefold().compare (lastdot, 5, ".jpeg")) { + } else if (hasJpegExtension(fname)) { return saveJPEG (fname); - } else if (!fname.casefold().compare (lastdot, 4, ".tif") || - !fname.casefold().compare (lastdot, 5, ".tiff")) { + } else if (hasTiffExtension(fname)) { return saveTIFF (fname); } else { return IMIO_FILETYPENOTSUPPORTED; diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index 2eda4b512..ac911aaa7 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -74,27 +74,19 @@ void StdImageSource::getSampleFormat (const Glib::ustring &fname, IIOSampleForma sFormat = IIOSF_UNKNOWN; sArrangement = IIOSA_UNKNOWN; - size_t lastdot = fname.find_last_of ('.'); - - if( Glib::ustring::npos == lastdot ) { - return; - } - - if (!fname.casefold().compare (lastdot, 4, ".jpg") || - !fname.casefold().compare (lastdot, 5, ".jpeg")) { + if (hasJpegExtension(fname)) { // For now, png and jpeg files are converted to unsigned short by the loader itself, // but there should be functions that read the sample format first, like the TIFF case below sFormat = IIOSF_UNSIGNED_CHAR; sArrangement = IIOSA_CHUNKY; return; - } else if (!fname.casefold().compare (lastdot, 4, ".png")) { + } else if (hasPngExtension(fname)) { int result = ImageIO::getPNGSampleFormat (fname, sFormat, sArrangement); if (result == IMIO_SUCCESS) { return; } - } else if (!fname.casefold().compare (lastdot, 4, ".tif") || - !fname.casefold().compare (lastdot, 5, ".tiff")) { + } else if (hasTiffExtension(fname)) { int result = ImageIO::getTIFFSampleFormat (fname, sFormat, sArrangement); if (result == IMIO_SUCCESS) { diff --git a/rtengine/utils.cc b/rtengine/utils.cc index b862e290f..f5b3e496b 100644 --- a/rtengine/utils.cc +++ b/rtengine/utils.cc @@ -29,7 +29,7 @@ using namespace std; namespace rtengine { -void poke255_uc(unsigned char* &dest, unsigned char r, unsigned char g, unsigned char b) +void poke255_uc(unsigned char*& dest, unsigned char r, unsigned char g, unsigned char b) { #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ *(dest++) = b; @@ -44,7 +44,7 @@ void poke255_uc(unsigned char* &dest, unsigned char r, unsigned char g, unsigned #endif } -void poke01_d(unsigned char* &dest, double r, double g, double b) +void poke01_d(unsigned char*& dest, double r, double g, double b) { #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ *(dest++) = (unsigned char)(b * 255.); @@ -59,7 +59,7 @@ void poke01_d(unsigned char* &dest, double r, double g, double b) #endif } -void poke01_f(unsigned char* &dest, float r, float g, float b) +void poke01_f(unsigned char*& dest, float r, float g, float b) { #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ *(dest++) = (unsigned char)(b * 255.f); @@ -74,9 +74,8 @@ void poke01_f(unsigned char* &dest, float r, float g, float b) #endif } -void bilinearInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) +void bilinearInterp(const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) { - int ix = 0; for (int i = 0; i < dh; i++) { @@ -132,9 +131,8 @@ void bilinearInterp (const unsigned char* src, int sw, int sh, unsigned char* ds } } -void nearestInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) +void nearestInterp(const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) { - int ix = 0; for (int i = 0; i < dh; i++) { @@ -150,9 +148,8 @@ void nearestInterp (const unsigned char* src, int sw, int sh, unsigned char* dst } } -void rotate (unsigned char* img, int& w, int& h, int deg) +void rotate(unsigned char* img, int& w, int& h, int deg) { - if (deg == 0) { return; } @@ -186,13 +183,12 @@ void rotate (unsigned char* img, int& w, int& h, int deg) rotated[3 * (w * (h - i - 1) + w - j - 1) + 2] = img[ix++]; } - memcpy (img, rotated, 3 * w * h); - delete [] rotated; + memcpy(img, rotated, 3 * w * h); + delete[] rotated; } -void hflip (unsigned char* img, int w, int h) +void hflip(unsigned char* img, int w, int h) { - unsigned char* flipped = new unsigned char[3 * w * h]; int ix = 0; @@ -203,13 +199,12 @@ void hflip (unsigned char* img, int w, int h) flipped[3 * (w * i + w - 1 - j) + 2] = img[ix++]; } - memcpy (img, flipped, 3 * w * h); - delete [] flipped; + memcpy(img, flipped, 3 * w * h); + delete[] flipped; } -void vflip (unsigned char* img, int w, int h) +void vflip(unsigned char* img, int w, int h) { - unsigned char* flipped = new unsigned char[3 * w * h]; int ix = 0; @@ -220,10 +215,34 @@ void vflip (unsigned char* img, int w, int h) flipped[3 * (w * (h - 1 - i) + j) + 2] = img[ix++]; } - memcpy (img, flipped, 3 * w * h); - delete [] flipped; + memcpy(img, flipped, 3 * w * h); + delete[] flipped; +} + +Glib::ustring getFileExtension(const Glib::ustring& filename) +{ + const Glib::ustring::size_type lastdot_pos = filename.find_last_of('.'); + return + lastdot_pos != Glib::ustring::npos + ? filename.substr(lastdot_pos + 1).lowercase() + : Glib::ustring(); +} + +bool hasJpegExtension(const Glib::ustring& filename) +{ + const Glib::ustring extension = getFileExtension(filename); + return extension == "jpg" || extension == "jpeg"; +} + +bool hasTiffExtension(const Glib::ustring& filename) +{ + const Glib::ustring extension = getFileExtension(filename); + return extension == "tif" || extension == "tiff"; +} + +bool hasPngExtension(const Glib::ustring& filename) +{ + return getFileExtension(filename) == "png"; } } - - diff --git a/rtengine/utils.h b/rtengine/utils.h index c46999219..b2c1d16a8 100644 --- a/rtengine/utils.h +++ b/rtengine/utils.h @@ -19,22 +19,23 @@ #pragma once #include +#include namespace rtengine { -// update a point of a Cairo::Surface by accessing the raw data -void poke255_uc(unsigned char* &dest, unsigned char r, unsigned char g, unsigned char b); -// update a point of a Cairo::Surface by accessing the raw data -void poke01_d(unsigned char* &dest, double r, double g, double b); -// update a point of a Cairo::Surface by accessing the raw data -void poke01_f(unsigned char* &dest, float r, float g, float b); +// Update a point of a Cairo::Surface by accessing the raw data +void poke255_uc(unsigned char*& dest, unsigned char r, unsigned char g, unsigned char b); +// Update a point of a Cairo::Surface by accessing the raw data +void poke01_d(unsigned char*& dest, double r, double g, double b); +// Update a point of a Cairo::Surface by accessing the raw data +void poke01_f(unsigned char*& dest, float r, float g, float b); -void bilinearInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); -void nearestInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); -void rotate (unsigned char* img, int& w, int& h, int deg); -void hflip (unsigned char* img, int w, int h); -void vflip (unsigned char* img, int w, int h); +void bilinearInterp(const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); +void nearestInterp(const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); +void rotate(unsigned char* img, int& w, int& h, int deg); +void hflip(unsigned char* img, int w, int h); +void vflip(unsigned char* img, int w, int h); template typename std::underlying_type::type toUnderlying(ENUM value) @@ -42,4 +43,13 @@ typename std::underlying_type::type toUnderlying(ENUM value) return static_cast::type>(value); } +// Return lower case extension without the "." or "" if the given name contains no "." +Glib::ustring getFileExtension(const Glib::ustring& filename); +// Return true if file has .jpeg or .jpg extension (ignoring case) +bool hasJpegExtension(const Glib::ustring& filename); +// Return true if file has .tiff or .tif extension (ignoring case) +bool hasTiffExtension(const Glib::ustring& filename); +// Return true if file has .png extension (ignoring case) +bool hasPngExtension(const Glib::ustring& filename); + } diff --git a/rtgui/profilestore.cc b/rtgui/profilestore.cc index c80bbe388..ddb6782d4 100644 --- a/rtgui/profilestore.cc +++ b/rtgui/profilestore.cc @@ -269,7 +269,6 @@ int ProfileStore::findFolderId(const Glib::ustring &path) */ const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU(Glib::ustring path) { - if (path.empty()) { return nullptr; } @@ -278,12 +277,18 @@ const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU(Glib::ustring path return internalDefaultEntry; } - size_t lastdot = path.find_last_of ('.'); + // consistently apply casefold() to make sure dot position is correct + const Glib::ustring casefolded_path = path.casefold(); + const Glib::ustring::size_type lastdot_pos = casefolded_path.find_last_of('.'); - if (lastdot != Glib::ustring::npos && lastdot <= path.size() - 4 && !path.casefold().compare (lastdot, 4, paramFileExtension)) - // removing the extension + if ( + lastdot_pos != Glib::ustring::npos + && lastdot_pos <= casefolded_path.size() - 4 + && !casefolded_path.compare(lastdot_pos, 4, paramFileExtension)) { - path = path.substr(0, lastdot); + // removing the extension + // now use dot position without casefold() + path = path.substr(0, path.find_last_of('.')); } // dir separator may come from options file and may be \ or /, we convert them to G_DIR_SEPARATOR_S