@@ -5795,21 +5795,52 @@ namespace cimg_library {
57955795 **/
57965796 inline cimg_int64 fsize(std::FILE *const file) {
57975797 if (!file) return (cimg_int64)-1;
5798- const cimg_long pos = std::ftell(file);
5799- cimg::fseek(file,0,SEEK_END);
5800- const cimg_int64 siz = (cimg_int64)std::ftell(file);
5801- cimg::fseek(file,pos,SEEK_SET);
5798+
5799+ #if cimg_OS==1 // Optimized for POSIX Environements (Linux, macOS, BSD, etc.)
5800+ const int fd = fileno(file);
5801+ struct stat st;
5802+ if (fd>=0 && !fstat(fd,&st)) return (cimg_int64)st.st_size;
5803+ #elif cimg_OS==2 // Optimized for Windows Environements (MSVC, MinGW)
5804+ const int fd = _fileno(file);
5805+ struct _stati64 st;
5806+ if (fd>=0 && !_fstati64(fd,&st)) return (cimg_int64)st.st_size;
5807+ #endif
5808+
5809+ // Fallback, used for non-POSIX systems or if fstat failed (pipes or sockets).
5810+ const cimg_long pos = cimg::ftell(file);
5811+ cimg::fseek(file, 0, SEEK_END);
5812+ const cimg_int64 siz = (cimg_int64)cimg::ftell(file);
5813+ cimg::fseek(file, pos, SEEK_SET);
58025814 return siz;
58035815 }
58045816
5817+ //! Get file size from filename.
58055818 inline cimg_int64 fsize(const char *const filename) {
5806- std::FILE *const file = cimg::std_fopen(filename,"rb");
5819+ if (!filename || !*filename) return (cimg_int64)-1;
5820+
5821+ #if cimg_OS==1 // Optimized for POSIX Environements (Linux, macOS, BSD, etc.)
5822+ struct stat st;
5823+ if (!stat(filename,&st)) return (cimg_int64)st.st_size;
5824+ #elif cimg_OS==2 // Optimized for Windows Environements (MSVC, MinGW)
5825+ // Convert UTF-8 path to wchar_t.
5826+ int len = MultiByteToWideChar(CP_UTF8,0,filename,-1,0,0);
5827+ if (len>0) {
5828+ CImg<wchar_t> wfilename((unsigned int)len);
5829+ if (MultiByteToWideChar(CP_UTF8,0,filename,-1,wfilename,len)) {
5830+ struct _stati64 st;
5831+ if (!_wstati64(wfilename,&st)) return (cimg_int64)st.st_size;
5832+ }
5833+ }
5834+ #endif
5835+
5836+ // Fallback.
5837+ std::FILE *const file = cimg::fopen(filename, "rb");
5838+ if (!file) return (cimg_int64)-1;
58075839 const cimg_int64 siz = fsize(file);
58085840 cimg::fclose(file);
58095841 return siz;
58105842 }
58115843
5812-
58135844 // Thread-safe version of std::localtime().
58145845 inline struct tm* localtime(const time_t *const time_ptr, struct tm *const result) {
58155846#if cimg_OS==2
@@ -65308,7 +65339,7 @@ namespace cimg_library {
6530865339 (Ts2 && !cimg::strcasecmp(Ts2,str_pixeltype)) || \
6530965340 (Ts3 && !cimg::strcasecmp(Ts3,str_pixeltype)))) { \
6531065341 for (unsigned int l = 0; l<=nn1; ++l) { \
65311- j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0;
65342+ j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; \
6531265343 W = H = D = C = 0; \
6531365344 if (cimg_sscanf(tmp._data,"%d %d %d %d",&W,&H,&D,&C)!=4) \
6531465345 throw CImgIOException(_cimglist_instance \
0 commit comments