From 53116cbb1aebd12757f12ef998b96e3b6d3d8275 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sat, 22 Feb 2020 22:12:09 +0100 Subject: [PATCH 01/20] Cache Images for faster parsing subsequent images (or frames in an animation) --- source/core/support/imageutil.cpp | 10 +- source/parser/ImageCache.cpp | 166 +++++++++++++++++++++++ source/parser/ImageCache.h | 79 +++++++++++ source/parser/parser.cpp | 15 +- windows/vs2015/povparser.vcxproj | 2 + windows/vs2015/povparser.vcxproj.filters | 6 + 6 files changed, 272 insertions(+), 6 deletions(-) create mode 100644 source/parser/ImageCache.cpp create mode 100644 source/parser/ImageCache.h diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index ae50e194e..7bf3ffcbd 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1387,10 +1387,14 @@ ImageData *Copy_Image(ImageData *Old) void Destroy_Image(ImageData *image) { - if ((image == nullptr) || (--(image->References) > 0)) - return; + return; + + // Images are now cached - delete image; + // if ((image == nullptr) || (--(image->References) > 0)) + // return; + // + // delete image; } ImageData::~ImageData() diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp new file mode 100644 index 000000000..382e94e34 --- /dev/null +++ b/source/parser/ImageCache.cpp @@ -0,0 +1,166 @@ +//****************************************************************************** +/// +/// @file parser/ImageCache.cpp +/// +/// This module implements a cache for images used in a scene so they only heve +/// to be loaded once during animation rendering or between manual renders +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + + +// C++ variants of C standard header files +#include +#include +#include + +#include +#include + +#ifndef WIN32 +#include // Unix lib for getting last modified file date and time +#endif +#ifdef WIN32 +#define stat _stat // Windows lib for getting last modified file date and time +#endif + + +// POV-Ray header files (base module) +#include "base/base_fwd.h" +#include "base/messenger_fwd.h" +#include "base/povassert.h" +#include "base/stringtypes.h" +#include "base/textstream_fwd.h" +#include "base/textstreambuffer.h" +#include "base/image/image_fwd.h" + +// this must be the last file included +#include "base/povdebug.h" + + +namespace pov_image_cache +{ + using namespace pov_base; + using namespace std; + static inline std::string U16toString(const std::u16string& wstr); + static inline char* StrToChar(const std::string str); + static inline char* U16toChar(const std::u16string& wstr); + + struct ImageCacheEntry final + { + Image* image; + __time64_t lastModified; + }; + + static std::map Cache; // <- The actual cache + + // Gets the last modified time from the filesystem + __time64_t GetLastModifiedTime(const std::string filename) + { + char* cstrFilename = StrToChar(filename); + + struct stat result; + if (stat(cstrFilename, &result) == 0) + { + delete cstrFilename; + return result.st_mtime; + } + delete cstrFilename; + return 0; + } + + // Try to get the image from the cache + Image* GetCachedImage(const UCS2* filename) + { + std::string lookupFilename = U16toString(filename); + + std::map::iterator idx = Cache.find(lookupFilename); + if (idx != Cache.end()) + { + __time64_t lastModified = GetLastModifiedTime(lookupFilename); + if (lastModified == Cache[lookupFilename].lastModified) + return idx->second.image; //Cache[lookupFilename].image; + + // Remove old image from cache and release memory so the newer version can be loaded + delete idx->second.image; + Cache.erase(idx); + } + + return nullptr; + } + + // Store a new image into cache + void StoreImageInCache(const UCS2* filename, Image* image) + { + std::string lookupFilename = U16toString(filename); + __time64_t lastModified = GetLastModifiedTime(lookupFilename); + Cache[lookupFilename] = ImageCacheEntry{ image = image, lastModified = lastModified }; + } + + // May be called frome some menu item, personally, I'd just close PovRay and start a new process (different scenes often share resources in my case) + // Do not allow calling it while parsing or rendering! + void ClearCache() + { + std::map::iterator it = Cache.begin(); + + // Iterate over the map using Iterator till end. + while (it != Cache.end()) + { + delete it->second.image; + Cache.erase(it); + } + } + + static inline std::string U16toString(const std::u16string& wstr) + { + std::string str = ""; + char cstr[3] = "\0"; + mbstate_t mbs; + for (const auto& it : wstr) { + memset(&mbs, 0, sizeof(mbs));//set shift state to the initial state + memmove(cstr, "\0\0\0", 3); + c16rtomb(cstr, it, &mbs); + str.append(std::string(cstr)); + }//for + return str; + } + + static inline char* StrToChar(const std::string str) + { + char* cstring = new char[str.length() + 1]; + strcpy(cstring, str.c_str()); + return cstring; + } + + static inline char* U16toChar(const std::u16string& wstr) + { + return StrToChar(U16toString(wstr)); + } + +} \ No newline at end of file diff --git a/source/parser/ImageCache.h b/source/parser/ImageCache.h new file mode 100644 index 000000000..9f24c5116 --- /dev/null +++ b/source/parser/ImageCache.h @@ -0,0 +1,79 @@ +//****************************************************************************** +/// +/// @file parser/ImageCache.h +/// +/// Declarations related to the Image Cache. +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +#ifndef POVRAY_PARSER_IMAGE_CACHE_H +#define POVRAY_PARSER_IMAGE_CACHE_H + +#include +#include + +#ifndef WIN32 +#include // Unix lib for getting last modified file date and time +#endif +#ifdef WIN32 +#define stat _stat // Windows lib for getting last modified file date and time +#endif + + +// POV-Ray header files (base module) +#include "base/base_fwd.h" +#include "base/messenger_fwd.h" +#include "base/povassert.h" +#include "base/stringtypes.h" +#include "base/textstream_fwd.h" +#include "base/textstreambuffer.h" +#include "base/image/image_fwd.h" + +namespace pov +{ + class Blob_Element; + struct ContainedByShape; + struct GenericSpline; + class ImageData; + class Mesh; + struct PavementPattern; + struct TilingPattern; + struct TrueTypeFont; +} + +namespace pov_image_cache +{ + using namespace pov_base; + + Image* GetCachedImage(const UCS2* filename); + void StoreImageInCache(const UCS2* filename, Image* image); +}; + +#endif // POVRAY_PARSER_IMAGE_CACHE_H \ No newline at end of file diff --git a/source/parser/parser.cpp b/source/parser/parser.cpp index 2473903c4..60031b6d3 100644 --- a/source/parser/parser.cpp +++ b/source/parser/parser.cpp @@ -113,7 +113,7 @@ #include "vm/fnpovfpu.h" // POV-Ray header files (parser module) -// (none at the moment) +#include "parser/ImageCache.h" // this must be the last file included #include "base/povdebug.h" @@ -122,6 +122,7 @@ namespace pov_parser { using namespace pov; +using namespace pov_image_cache; using std::min; using std::max; @@ -9971,8 +9972,12 @@ OStream *Parser::CreateFile(const UCS2String& filename, unsigned int stype, bool //****************************************************************************** -Image *Parser::Read_Image(int filetype, const UCS2 *filename, const ImageReadOptions& options) +Image *Parser::Read_Image(int filetype, const UCS2* filename, const ImageReadOptions& options) { + Image* img = pov_image_cache::GetCachedImage(filename); + if (img != nullptr) + return img; + unsigned int stype; Image::ImageFileType type; UCS2String ign; @@ -10040,7 +10045,11 @@ Image *Parser::Read_Image(int filetype, const UCS2 *filename, const ImageReadOpt if (file == nullptr) throw POV_EXCEPTION(kCannotOpenFileErr, "Cannot find image file."); - return Image::Read(type, file.get(), options); + img = Image::Read(type, file.get(), options); + + pov_image_cache::StoreImageInCache(filename, img); + + return img; } //****************************************************************************** diff --git a/windows/vs2015/povparser.vcxproj b/windows/vs2015/povparser.vcxproj index e90289687..bb5dcfdbd 100644 --- a/windows/vs2015/povparser.vcxproj +++ b/windows/vs2015/povparser.vcxproj @@ -400,6 +400,7 @@ + @@ -424,6 +425,7 @@ + diff --git a/windows/vs2015/povparser.vcxproj.filters b/windows/vs2015/povparser.vcxproj.filters index d050cbe31..1efdb1c0d 100644 --- a/windows/vs2015/povparser.vcxproj.filters +++ b/windows/vs2015/povparser.vcxproj.filters @@ -46,6 +46,9 @@ Parser Headers + + Parser Headers + @@ -93,5 +96,8 @@ Parser Source + + Parser Source + \ No newline at end of file From 783ff84c3a6509e6026c8b058a90f658dd5355d3 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sat, 22 Feb 2020 22:41:33 +0100 Subject: [PATCH 02/20] Remove #include --- source/parser/ImageCache.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index 382e94e34..c86b52f34 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -37,7 +37,6 @@ // C++ variants of C standard header files #include -#include #include #include From 0e4550b72bf0aacff994424bb6ec4aeb2922b914 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sat, 22 Feb 2020 23:10:27 +0100 Subject: [PATCH 03/20] Replaced with --- source/parser/ImageCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index c86b52f34..bc29ab318 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -37,7 +37,7 @@ // C++ variants of C standard header files #include -#include +#include #include #include From b5ef8705f4c37bd7987dbc6622003ff1ce00d967 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sat, 22 Feb 2020 23:36:09 +0100 Subject: [PATCH 04/20] Added #include --- source/parser/ImageCache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index bc29ab318..e9d93fa46 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -38,6 +38,7 @@ // C++ variants of C standard header files #include #include +#include #include #include From 3989f81ec285c43a4ae8e0b3efbaa70a42cf1439 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 00:19:59 +0100 Subject: [PATCH 05/20] Use pov_base::UCS2toSysString instead of own function. --- source/parser/ImageCache.cpp | 42 +++++------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index e9d93fa46..d91012ada 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -37,8 +37,6 @@ // C++ variants of C standard header files #include -#include -#include #include #include @@ -59,6 +57,7 @@ #include "base/textstream_fwd.h" #include "base/textstreambuffer.h" #include "base/image/image_fwd.h" +#include "base/stringutilities.h" // this must be the last file included #include "base/povdebug.h" @@ -68,9 +67,7 @@ namespace pov_image_cache { using namespace pov_base; using namespace std; - static inline std::string U16toString(const std::u16string& wstr); - static inline char* StrToChar(const std::string str); - static inline char* U16toChar(const std::u16string& wstr); + //static inline char* StrToChar(const std::string str); struct ImageCacheEntry final { @@ -83,22 +80,20 @@ namespace pov_image_cache // Gets the last modified time from the filesystem __time64_t GetLastModifiedTime(const std::string filename) { - char* cstrFilename = StrToChar(filename); + const char* cstrFilename = filename.c_str(); struct stat result; if (stat(cstrFilename, &result) == 0) { - delete cstrFilename; return result.st_mtime; } - delete cstrFilename; return 0; } // Try to get the image from the cache Image* GetCachedImage(const UCS2* filename) { - std::string lookupFilename = U16toString(filename); + std::string lookupFilename = pov_base::UCS2toSysString(filename); std::map::iterator idx = Cache.find(lookupFilename); if (idx != Cache.end()) @@ -118,7 +113,7 @@ namespace pov_image_cache // Store a new image into cache void StoreImageInCache(const UCS2* filename, Image* image) { - std::string lookupFilename = U16toString(filename); + std::string lookupFilename = pov_base::UCS2toSysString(filename); __time64_t lastModified = GetLastModifiedTime(lookupFilename); Cache[lookupFilename] = ImageCacheEntry{ image = image, lastModified = lastModified }; } @@ -136,31 +131,4 @@ namespace pov_image_cache Cache.erase(it); } } - - static inline std::string U16toString(const std::u16string& wstr) - { - std::string str = ""; - char cstr[3] = "\0"; - mbstate_t mbs; - for (const auto& it : wstr) { - memset(&mbs, 0, sizeof(mbs));//set shift state to the initial state - memmove(cstr, "\0\0\0", 3); - c16rtomb(cstr, it, &mbs); - str.append(std::string(cstr)); - }//for - return str; - } - - static inline char* StrToChar(const std::string str) - { - char* cstring = new char[str.length() + 1]; - strcpy(cstring, str.c_str()); - return cstring; - } - - static inline char* U16toChar(const std::u16string& wstr) - { - return StrToChar(U16toString(wstr)); - } - } \ No newline at end of file From 63eb73ad666b9e9e6d9a20dbc5c34e4c1de708a0 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 01:27:15 +0100 Subject: [PATCH 06/20] Destroy the Image from ImageUtil (resolve C4150: deletion of pointer to incomplete type) --- source/core/support/imageutil.cpp | 5 +++++ source/core/support/imageutil.h | 1 + source/parser/ImageCache.cpp | 9 ++++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index 7bf3ffcbd..606fc11d2 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1397,6 +1397,11 @@ void Destroy_Image(ImageData *image) // delete image; } +void Remove_Cached_Image(Image* image) { + delete image; +} + + ImageData::~ImageData() { #ifdef POV_VIDCAP_IMPL diff --git a/source/core/support/imageutil.h b/source/core/support/imageutil.h index b4bf41bc2..c86959443 100644 --- a/source/core/support/imageutil.h +++ b/source/core/support/imageutil.h @@ -143,6 +143,7 @@ int map_pos(const Vector3d& EPoint, const ImageData* pImage, DBL *xcoor, DBL *yc ImageData *Copy_Image(ImageData *old); ImageData *Create_Image(void); void Destroy_Image(ImageData *image); +void Remove_Cached_Image(Image* image); /// @} /// diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index d91012ada..fa6bc126a 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -58,6 +58,7 @@ #include "base/textstreambuffer.h" #include "base/image/image_fwd.h" #include "base/stringutilities.h" +#include "core/support/imageutil.h" // this must be the last file included #include "base/povdebug.h" @@ -67,7 +68,7 @@ namespace pov_image_cache { using namespace pov_base; using namespace std; - //static inline char* StrToChar(const std::string str); + using namespace pov; struct ImageCacheEntry final { @@ -103,7 +104,8 @@ namespace pov_image_cache return idx->second.image; //Cache[lookupFilename].image; // Remove old image from cache and release memory so the newer version can be loaded - delete idx->second.image; + //delete idx->second.image; + pov::Remove_Cached_Image(idx->second.image); Cache.erase(idx); } @@ -127,7 +129,8 @@ namespace pov_image_cache // Iterate over the map using Iterator till end. while (it != Cache.end()) { - delete it->second.image; + //delete it->second.image; + pov::Remove_Cached_Image(it->second.image); Cache.erase(it); } } From 4196674a8ae55c4fc045dd038ca9c6f77a4e7b89 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 01:47:05 +0100 Subject: [PATCH 07/20] Replace __time64_t with long --- source/parser/ImageCache.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index fa6bc126a..d48919619 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -73,20 +73,20 @@ namespace pov_image_cache struct ImageCacheEntry final { Image* image; - __time64_t lastModified; + long lastModified; }; static std::map Cache; // <- The actual cache // Gets the last modified time from the filesystem - __time64_t GetLastModifiedTime(const std::string filename) + long GetLastModifiedTime(const std::string filename) { const char* cstrFilename = filename.c_str(); struct stat result; if (stat(cstrFilename, &result) == 0) { - return result.st_mtime; + return (long)result.st_mtime; } return 0; } @@ -99,12 +99,11 @@ namespace pov_image_cache std::map::iterator idx = Cache.find(lookupFilename); if (idx != Cache.end()) { - __time64_t lastModified = GetLastModifiedTime(lookupFilename); + long lastModified = GetLastModifiedTime(lookupFilename); if (lastModified == Cache[lookupFilename].lastModified) return idx->second.image; //Cache[lookupFilename].image; // Remove old image from cache and release memory so the newer version can be loaded - //delete idx->second.image; pov::Remove_Cached_Image(idx->second.image); Cache.erase(idx); } @@ -116,7 +115,7 @@ namespace pov_image_cache void StoreImageInCache(const UCS2* filename, Image* image) { std::string lookupFilename = pov_base::UCS2toSysString(filename); - __time64_t lastModified = GetLastModifiedTime(lookupFilename); + long lastModified = GetLastModifiedTime(lookupFilename); Cache[lookupFilename] = ImageCacheEntry{ image = image, lastModified = lastModified }; } @@ -129,7 +128,6 @@ namespace pov_image_cache // Iterate over the map using Iterator till end. while (it != Cache.end()) { - //delete it->second.image; pov::Remove_Cached_Image(it->second.image); Cache.erase(it); } From f312aa8503caacad9a80e2e7f613ebd7b9a5be09 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 02:14:36 +0100 Subject: [PATCH 08/20] Instead of using a teaspoon (file->readByte()), read in a whole row at once. --- source/base/image/bmp.cpp | 50 ++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/source/base/image/bmp.cpp b/source/base/image/bmp.cpp index c1ecd6dcd..e4677be46 100644 --- a/source/base/image/bmp.cpp +++ b/source/base/image/bmp.cpp @@ -667,24 +667,52 @@ Image *Read (IStream *file, const ImageReadOptions& options) int pad = has_alpha ? 0 : (4 - ((file_width * 3) % 4)) & 0x03 ; unsigned int a = 255 ; // value to use for files that don't have an alpha channel (full opacity) - for (int y = file_height - 1 ; y >= 0 ; y--) + unsigned int pixelWidth = (has_alpha ? 4 : 3); + unsigned int rowLength = file_width * pixelWidth; + + unsigned char* rowBuffer = new unsigned char[rowLength]; + + if (has_alpha) + { + for (int y = file_height - 1; y >= 0; y--) + { + file->read(rowBuffer, rowLength); + if (!file) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); + + for (int x = file_width - 1; x >= 0; x--) + { + int offset = x * pixelWidth; + SetEncodedRGBAValue(image, x, y, gamma, 255, rowBuffer[offset + 2], rowBuffer[offset + 1], rowBuffer[offset], rowBuffer[offset + 3], premul); + } + + if (pad && !Skip(file, pad)) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); + } + } + else { - for (int x = 0 ; x < file_width ; x++) + for (int y = file_height - 1; y >= 0; y--) { - unsigned int b = Read_Safe_Char (*file); - unsigned int g = Read_Safe_Char (*file); - unsigned int r = Read_Safe_Char (*file); - if (has_alpha) - a = Read_Safe_Char (*file); - SetEncodedRGBAValue (image, x, y, gamma, 255, r, g, b, a, premul); + file->read(rowBuffer, rowLength); + if (!file) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); + + for (int x = file_width - 1; x >= 0; x--) + { + int offset = x * pixelWidth; + SetEncodedRGBAValue(image, x, y, gamma, 255, rowBuffer[offset + 2], rowBuffer[offset + 1], rowBuffer[offset], a, premul); + } + + if (pad && !Skip(file, pad)) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); } - if (pad && !Skip (file, pad)) - throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image.") ; } + + delete[] rowBuffer; } return (image) ; - } } From 133d88f388814dc9f1252955956137c6bcddc372 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:08:38 +0100 Subject: [PATCH 09/20] Set the image pointer to null and delete the wrapper, thus preventing the image from being deleted. --- source/core/support/imageutil.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index 606fc11d2..b2aa66279 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1387,14 +1387,12 @@ ImageData *Copy_Image(ImageData *Old) void Destroy_Image(ImageData *image) { - return; - - // Images are now cached + if ((image == nullptr) || (--(image->References) > 0)) + return; + + image->data = nullptr; // prevent it from being deleted, Images are now cached - // if ((image == nullptr) || (--(image->References) > 0)) - // return; - // - // delete image; + delete image; } void Remove_Cached_Image(Image* image) { From 415f2c028ba43829ff7a53e6399c5c5a53206584 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:11:53 +0100 Subject: [PATCH 10/20] Point the image to null to prevent it from being deleted when the wrapper gets deleted. --- source/core/support/imageutil.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index 606fc11d2..3619cfe8f 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1387,14 +1387,11 @@ ImageData *Copy_Image(ImageData *Old) void Destroy_Image(ImageData *image) { - return; - - // Images are now cached - - // if ((image == nullptr) || (--(image->References) > 0)) - // return; - // - // delete image; + if ((image == nullptr) || (--(image->References) > 0)) + return; + + image->data = nullptr; // Prevent the image from being deleted. Images are now cached. + delete image; } void Remove_Cached_Image(Image* image) { From 7fb27ec44f65ef7133f5d767ff5eab7746955b7d Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:46:25 +0100 Subject: [PATCH 11/20] Revert "Point the image to null to prevent it from being deleted when the wrapper gets deleted." This reverts commit 415f2c028ba43829ff7a53e6399c5c5a53206584. --- source/core/support/imageutil.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index 3619cfe8f..606fc11d2 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1387,11 +1387,14 @@ ImageData *Copy_Image(ImageData *Old) void Destroy_Image(ImageData *image) { - if ((image == nullptr) || (--(image->References) > 0)) - return; - - image->data = nullptr; // Prevent the image from being deleted. Images are now cached. - delete image; + return; + + // Images are now cached + + // if ((image == nullptr) || (--(image->References) > 0)) + // return; + // + // delete image; } void Remove_Cached_Image(Image* image) { From 3e6586eea225a0d90a47c30e024b272605d17e88 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:46:30 +0100 Subject: [PATCH 12/20] Revert "Replace __time64_t with long" This reverts commit 4196674a8ae55c4fc045dd038ca9c6f77a4e7b89. --- source/parser/ImageCache.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index d48919619..fa6bc126a 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -73,20 +73,20 @@ namespace pov_image_cache struct ImageCacheEntry final { Image* image; - long lastModified; + __time64_t lastModified; }; static std::map Cache; // <- The actual cache // Gets the last modified time from the filesystem - long GetLastModifiedTime(const std::string filename) + __time64_t GetLastModifiedTime(const std::string filename) { const char* cstrFilename = filename.c_str(); struct stat result; if (stat(cstrFilename, &result) == 0) { - return (long)result.st_mtime; + return result.st_mtime; } return 0; } @@ -99,11 +99,12 @@ namespace pov_image_cache std::map::iterator idx = Cache.find(lookupFilename); if (idx != Cache.end()) { - long lastModified = GetLastModifiedTime(lookupFilename); + __time64_t lastModified = GetLastModifiedTime(lookupFilename); if (lastModified == Cache[lookupFilename].lastModified) return idx->second.image; //Cache[lookupFilename].image; // Remove old image from cache and release memory so the newer version can be loaded + //delete idx->second.image; pov::Remove_Cached_Image(idx->second.image); Cache.erase(idx); } @@ -115,7 +116,7 @@ namespace pov_image_cache void StoreImageInCache(const UCS2* filename, Image* image) { std::string lookupFilename = pov_base::UCS2toSysString(filename); - long lastModified = GetLastModifiedTime(lookupFilename); + __time64_t lastModified = GetLastModifiedTime(lookupFilename); Cache[lookupFilename] = ImageCacheEntry{ image = image, lastModified = lastModified }; } @@ -128,6 +129,7 @@ namespace pov_image_cache // Iterate over the map using Iterator till end. while (it != Cache.end()) { + //delete it->second.image; pov::Remove_Cached_Image(it->second.image); Cache.erase(it); } From 0cb2cd9927f9afb1b8116a111aed83556ca78139 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:46:39 +0100 Subject: [PATCH 13/20] Revert "Destroy the Image from ImageUtil (resolve C4150: deletion of pointer to incomplete type)" This reverts commit 63eb73ad666b9e9e6d9a20dbc5c34e4c1de708a0. --- source/core/support/imageutil.cpp | 5 ----- source/core/support/imageutil.h | 1 - source/parser/ImageCache.cpp | 9 +++------ 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index 606fc11d2..7bf3ffcbd 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1397,11 +1397,6 @@ void Destroy_Image(ImageData *image) // delete image; } -void Remove_Cached_Image(Image* image) { - delete image; -} - - ImageData::~ImageData() { #ifdef POV_VIDCAP_IMPL diff --git a/source/core/support/imageutil.h b/source/core/support/imageutil.h index c86959443..b4bf41bc2 100644 --- a/source/core/support/imageutil.h +++ b/source/core/support/imageutil.h @@ -143,7 +143,6 @@ int map_pos(const Vector3d& EPoint, const ImageData* pImage, DBL *xcoor, DBL *yc ImageData *Copy_Image(ImageData *old); ImageData *Create_Image(void); void Destroy_Image(ImageData *image); -void Remove_Cached_Image(Image* image); /// @} /// diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index fa6bc126a..d91012ada 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -58,7 +58,6 @@ #include "base/textstreambuffer.h" #include "base/image/image_fwd.h" #include "base/stringutilities.h" -#include "core/support/imageutil.h" // this must be the last file included #include "base/povdebug.h" @@ -68,7 +67,7 @@ namespace pov_image_cache { using namespace pov_base; using namespace std; - using namespace pov; + //static inline char* StrToChar(const std::string str); struct ImageCacheEntry final { @@ -104,8 +103,7 @@ namespace pov_image_cache return idx->second.image; //Cache[lookupFilename].image; // Remove old image from cache and release memory so the newer version can be loaded - //delete idx->second.image; - pov::Remove_Cached_Image(idx->second.image); + delete idx->second.image; Cache.erase(idx); } @@ -129,8 +127,7 @@ namespace pov_image_cache // Iterate over the map using Iterator till end. while (it != Cache.end()) { - //delete it->second.image; - pov::Remove_Cached_Image(it->second.image); + delete it->second.image; Cache.erase(it); } } From c5bf02492b4bd5cf2c211fdeb37b5ff9a1baa341 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:46:57 +0100 Subject: [PATCH 14/20] Revert "Use pov_base::UCS2toSysString instead of own function." This reverts commit 3989f81ec285c43a4ae8e0b3efbaa70a42cf1439. --- source/parser/ImageCache.cpp | 42 +++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index d91012ada..e9d93fa46 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -37,6 +37,8 @@ // C++ variants of C standard header files #include +#include +#include #include #include @@ -57,7 +59,6 @@ #include "base/textstream_fwd.h" #include "base/textstreambuffer.h" #include "base/image/image_fwd.h" -#include "base/stringutilities.h" // this must be the last file included #include "base/povdebug.h" @@ -67,7 +68,9 @@ namespace pov_image_cache { using namespace pov_base; using namespace std; - //static inline char* StrToChar(const std::string str); + static inline std::string U16toString(const std::u16string& wstr); + static inline char* StrToChar(const std::string str); + static inline char* U16toChar(const std::u16string& wstr); struct ImageCacheEntry final { @@ -80,20 +83,22 @@ namespace pov_image_cache // Gets the last modified time from the filesystem __time64_t GetLastModifiedTime(const std::string filename) { - const char* cstrFilename = filename.c_str(); + char* cstrFilename = StrToChar(filename); struct stat result; if (stat(cstrFilename, &result) == 0) { + delete cstrFilename; return result.st_mtime; } + delete cstrFilename; return 0; } // Try to get the image from the cache Image* GetCachedImage(const UCS2* filename) { - std::string lookupFilename = pov_base::UCS2toSysString(filename); + std::string lookupFilename = U16toString(filename); std::map::iterator idx = Cache.find(lookupFilename); if (idx != Cache.end()) @@ -113,7 +118,7 @@ namespace pov_image_cache // Store a new image into cache void StoreImageInCache(const UCS2* filename, Image* image) { - std::string lookupFilename = pov_base::UCS2toSysString(filename); + std::string lookupFilename = U16toString(filename); __time64_t lastModified = GetLastModifiedTime(lookupFilename); Cache[lookupFilename] = ImageCacheEntry{ image = image, lastModified = lastModified }; } @@ -131,4 +136,31 @@ namespace pov_image_cache Cache.erase(it); } } + + static inline std::string U16toString(const std::u16string& wstr) + { + std::string str = ""; + char cstr[3] = "\0"; + mbstate_t mbs; + for (const auto& it : wstr) { + memset(&mbs, 0, sizeof(mbs));//set shift state to the initial state + memmove(cstr, "\0\0\0", 3); + c16rtomb(cstr, it, &mbs); + str.append(std::string(cstr)); + }//for + return str; + } + + static inline char* StrToChar(const std::string str) + { + char* cstring = new char[str.length() + 1]; + strcpy(cstring, str.c_str()); + return cstring; + } + + static inline char* U16toChar(const std::u16string& wstr) + { + return StrToChar(U16toString(wstr)); + } + } \ No newline at end of file From b9076971d69e2653c0d00fac9abc7759248e514c Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:47:07 +0100 Subject: [PATCH 15/20] Revert "Added #include " This reverts commit b5ef8705f4c37bd7987dbc6622003ff1ce00d967. --- source/parser/ImageCache.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index e9d93fa46..bc29ab318 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -38,7 +38,6 @@ // C++ variants of C standard header files #include #include -#include #include #include From 957a032e184d858d38e064c5ad0f735aff6ca48e Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:47:16 +0100 Subject: [PATCH 16/20] Revert "Replaced with " This reverts commit 0e4550b72bf0aacff994424bb6ec4aeb2922b914. --- source/parser/ImageCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index bc29ab318..c86b52f34 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -37,7 +37,7 @@ // C++ variants of C standard header files #include -#include +#include #include #include From d00b1b5246fd5ec958011fe27441814d0208b086 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:47:29 +0100 Subject: [PATCH 17/20] Revert "Remove #include " This reverts commit 783ff84c3a6509e6026c8b058a90f658dd5355d3. --- source/parser/ImageCache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp index c86b52f34..382e94e34 100644 --- a/source/parser/ImageCache.cpp +++ b/source/parser/ImageCache.cpp @@ -37,6 +37,7 @@ // C++ variants of C standard header files #include +#include #include #include From bee9f79bf6ba48c9c8bfe245672780596d02dcf0 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Sun, 23 Feb 2020 21:53:22 +0100 Subject: [PATCH 18/20] Revert "Cache Images for faster parsing subsequent images (or frames in an animation)" This reverts commit 53116cbb1aebd12757f12ef998b96e3b6d3d8275. --- source/core/support/imageutil.cpp | 10 +- source/parser/ImageCache.cpp | 166 ----------------------- source/parser/ImageCache.h | 79 ----------- source/parser/parser.cpp | 15 +- windows/vs2015/povparser.vcxproj | 2 - windows/vs2015/povparser.vcxproj.filters | 6 - 6 files changed, 6 insertions(+), 272 deletions(-) delete mode 100644 source/parser/ImageCache.cpp delete mode 100644 source/parser/ImageCache.h diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index 7bf3ffcbd..ae50e194e 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1387,14 +1387,10 @@ ImageData *Copy_Image(ImageData *Old) void Destroy_Image(ImageData *image) { - return; - - // Images are now cached + if ((image == nullptr) || (--(image->References) > 0)) + return; - // if ((image == nullptr) || (--(image->References) > 0)) - // return; - // - // delete image; + delete image; } ImageData::~ImageData() diff --git a/source/parser/ImageCache.cpp b/source/parser/ImageCache.cpp deleted file mode 100644 index 382e94e34..000000000 --- a/source/parser/ImageCache.cpp +++ /dev/null @@ -1,166 +0,0 @@ -//****************************************************************************** -/// -/// @file parser/ImageCache.cpp -/// -/// This module implements a cache for images used in a scene so they only heve -/// to be loaded once during animation rendering or between manual renders -/// -/// @copyright -/// @parblock -/// -/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. -/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. -/// -/// POV-Ray is free software: you can redistribute it and/or modify -/// it under the terms of the GNU Affero General Public License as -/// published by the Free Software Foundation, either version 3 of the -/// License, or (at your option) any later version. -/// -/// POV-Ray is distributed in the hope that it will be useful, -/// but WITHOUT ANY WARRANTY; without even the implied warranty of -/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -/// GNU Affero General Public License for more details. -/// -/// You should have received a copy of the GNU Affero General Public License -/// along with this program. If not, see . -/// -/// ---------------------------------------------------------------------------- -/// -/// POV-Ray is based on the popular DKB raytracer version 2.12. -/// DKBTrace was originally written by David K. Buck. -/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. -/// -/// @endparblock -/// -//****************************************************************************** - - -// C++ variants of C standard header files -#include -#include -#include - -#include -#include - -#ifndef WIN32 -#include // Unix lib for getting last modified file date and time -#endif -#ifdef WIN32 -#define stat _stat // Windows lib for getting last modified file date and time -#endif - - -// POV-Ray header files (base module) -#include "base/base_fwd.h" -#include "base/messenger_fwd.h" -#include "base/povassert.h" -#include "base/stringtypes.h" -#include "base/textstream_fwd.h" -#include "base/textstreambuffer.h" -#include "base/image/image_fwd.h" - -// this must be the last file included -#include "base/povdebug.h" - - -namespace pov_image_cache -{ - using namespace pov_base; - using namespace std; - static inline std::string U16toString(const std::u16string& wstr); - static inline char* StrToChar(const std::string str); - static inline char* U16toChar(const std::u16string& wstr); - - struct ImageCacheEntry final - { - Image* image; - __time64_t lastModified; - }; - - static std::map Cache; // <- The actual cache - - // Gets the last modified time from the filesystem - __time64_t GetLastModifiedTime(const std::string filename) - { - char* cstrFilename = StrToChar(filename); - - struct stat result; - if (stat(cstrFilename, &result) == 0) - { - delete cstrFilename; - return result.st_mtime; - } - delete cstrFilename; - return 0; - } - - // Try to get the image from the cache - Image* GetCachedImage(const UCS2* filename) - { - std::string lookupFilename = U16toString(filename); - - std::map::iterator idx = Cache.find(lookupFilename); - if (idx != Cache.end()) - { - __time64_t lastModified = GetLastModifiedTime(lookupFilename); - if (lastModified == Cache[lookupFilename].lastModified) - return idx->second.image; //Cache[lookupFilename].image; - - // Remove old image from cache and release memory so the newer version can be loaded - delete idx->second.image; - Cache.erase(idx); - } - - return nullptr; - } - - // Store a new image into cache - void StoreImageInCache(const UCS2* filename, Image* image) - { - std::string lookupFilename = U16toString(filename); - __time64_t lastModified = GetLastModifiedTime(lookupFilename); - Cache[lookupFilename] = ImageCacheEntry{ image = image, lastModified = lastModified }; - } - - // May be called frome some menu item, personally, I'd just close PovRay and start a new process (different scenes often share resources in my case) - // Do not allow calling it while parsing or rendering! - void ClearCache() - { - std::map::iterator it = Cache.begin(); - - // Iterate over the map using Iterator till end. - while (it != Cache.end()) - { - delete it->second.image; - Cache.erase(it); - } - } - - static inline std::string U16toString(const std::u16string& wstr) - { - std::string str = ""; - char cstr[3] = "\0"; - mbstate_t mbs; - for (const auto& it : wstr) { - memset(&mbs, 0, sizeof(mbs));//set shift state to the initial state - memmove(cstr, "\0\0\0", 3); - c16rtomb(cstr, it, &mbs); - str.append(std::string(cstr)); - }//for - return str; - } - - static inline char* StrToChar(const std::string str) - { - char* cstring = new char[str.length() + 1]; - strcpy(cstring, str.c_str()); - return cstring; - } - - static inline char* U16toChar(const std::u16string& wstr) - { - return StrToChar(U16toString(wstr)); - } - -} \ No newline at end of file diff --git a/source/parser/ImageCache.h b/source/parser/ImageCache.h deleted file mode 100644 index 9f24c5116..000000000 --- a/source/parser/ImageCache.h +++ /dev/null @@ -1,79 +0,0 @@ -//****************************************************************************** -/// -/// @file parser/ImageCache.h -/// -/// Declarations related to the Image Cache. -/// -/// @copyright -/// @parblock -/// -/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. -/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. -/// -/// POV-Ray is free software: you can redistribute it and/or modify -/// it under the terms of the GNU Affero General Public License as -/// published by the Free Software Foundation, either version 3 of the -/// License, or (at your option) any later version. -/// -/// POV-Ray is distributed in the hope that it will be useful, -/// but WITHOUT ANY WARRANTY; without even the implied warranty of -/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -/// GNU Affero General Public License for more details. -/// -/// You should have received a copy of the GNU Affero General Public License -/// along with this program. If not, see . -/// -/// ---------------------------------------------------------------------------- -/// -/// POV-Ray is based on the popular DKB raytracer version 2.12. -/// DKBTrace was originally written by David K. Buck. -/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. -/// -/// @endparblock -/// -//****************************************************************************** - -#ifndef POVRAY_PARSER_IMAGE_CACHE_H -#define POVRAY_PARSER_IMAGE_CACHE_H - -#include -#include - -#ifndef WIN32 -#include // Unix lib for getting last modified file date and time -#endif -#ifdef WIN32 -#define stat _stat // Windows lib for getting last modified file date and time -#endif - - -// POV-Ray header files (base module) -#include "base/base_fwd.h" -#include "base/messenger_fwd.h" -#include "base/povassert.h" -#include "base/stringtypes.h" -#include "base/textstream_fwd.h" -#include "base/textstreambuffer.h" -#include "base/image/image_fwd.h" - -namespace pov -{ - class Blob_Element; - struct ContainedByShape; - struct GenericSpline; - class ImageData; - class Mesh; - struct PavementPattern; - struct TilingPattern; - struct TrueTypeFont; -} - -namespace pov_image_cache -{ - using namespace pov_base; - - Image* GetCachedImage(const UCS2* filename); - void StoreImageInCache(const UCS2* filename, Image* image); -}; - -#endif // POVRAY_PARSER_IMAGE_CACHE_H \ No newline at end of file diff --git a/source/parser/parser.cpp b/source/parser/parser.cpp index 60031b6d3..2473903c4 100644 --- a/source/parser/parser.cpp +++ b/source/parser/parser.cpp @@ -113,7 +113,7 @@ #include "vm/fnpovfpu.h" // POV-Ray header files (parser module) -#include "parser/ImageCache.h" +// (none at the moment) // this must be the last file included #include "base/povdebug.h" @@ -122,7 +122,6 @@ namespace pov_parser { using namespace pov; -using namespace pov_image_cache; using std::min; using std::max; @@ -9972,12 +9971,8 @@ OStream *Parser::CreateFile(const UCS2String& filename, unsigned int stype, bool //****************************************************************************** -Image *Parser::Read_Image(int filetype, const UCS2* filename, const ImageReadOptions& options) +Image *Parser::Read_Image(int filetype, const UCS2 *filename, const ImageReadOptions& options) { - Image* img = pov_image_cache::GetCachedImage(filename); - if (img != nullptr) - return img; - unsigned int stype; Image::ImageFileType type; UCS2String ign; @@ -10045,11 +10040,7 @@ Image *Parser::Read_Image(int filetype, const UCS2* filename, const ImageReadOpt if (file == nullptr) throw POV_EXCEPTION(kCannotOpenFileErr, "Cannot find image file."); - img = Image::Read(type, file.get(), options); - - pov_image_cache::StoreImageInCache(filename, img); - - return img; + return Image::Read(type, file.get(), options); } //****************************************************************************** diff --git a/windows/vs2015/povparser.vcxproj b/windows/vs2015/povparser.vcxproj index bb5dcfdbd..e90289687 100644 --- a/windows/vs2015/povparser.vcxproj +++ b/windows/vs2015/povparser.vcxproj @@ -400,7 +400,6 @@ - @@ -425,7 +424,6 @@ - diff --git a/windows/vs2015/povparser.vcxproj.filters b/windows/vs2015/povparser.vcxproj.filters index 1efdb1c0d..d050cbe31 100644 --- a/windows/vs2015/povparser.vcxproj.filters +++ b/windows/vs2015/povparser.vcxproj.filters @@ -46,9 +46,6 @@ Parser Headers - - Parser Headers - @@ -96,8 +93,5 @@ Parser Source - - Parser Source - \ No newline at end of file From d691288b2a7dcdb6ae60fd49dacbf5d5449d0f9b Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Mon, 24 Feb 2020 00:40:15 +0100 Subject: [PATCH 19/20] Only the Bitmap changes... --- source/base/image/bmp.cpp | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/source/base/image/bmp.cpp b/source/base/image/bmp.cpp index c1ecd6dcd..c2c4cfaf6 100644 --- a/source/base/image/bmp.cpp +++ b/source/base/image/bmp.cpp @@ -667,24 +667,56 @@ Image *Read (IStream *file, const ImageReadOptions& options) int pad = has_alpha ? 0 : (4 - ((file_width * 3) % 4)) & 0x03 ; unsigned int a = 255 ; // value to use for files that don't have an alpha channel (full opacity) - for (int y = file_height - 1 ; y >= 0 ; y--) + const unsigned int pixelWidth = (has_alpha ? 4 : 3); + const unsigned int rowLength = file_width * pixelWidth; + + unsigned char* rowBuffer = new unsigned char[rowLength]; + + if (has_alpha) { - for (int x = 0 ; x < file_width ; x++) + for (int y = file_height - 1; y >= 0; y--) { - unsigned int b = Read_Safe_Char (*file); - unsigned int g = Read_Safe_Char (*file); - unsigned int r = Read_Safe_Char (*file); - if (has_alpha) - a = Read_Safe_Char (*file); - SetEncodedRGBAValue (image, x, y, gamma, 255, r, g, b, a, premul); + file->read(rowBuffer, rowLength); + if (!file) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); + + int offset = rowLength - pixelWidth; + + for (int x = file_width - 1; x >= 0; x--) + { + SetEncodedRGBAValue(image, x, y, gamma, 255, rowBuffer[offset + 2], rowBuffer[offset + 1], rowBuffer[offset], rowBuffer[offset + 3], premul); + offset -= pixelWidth; + } + + if (pad && !Skip(file, pad)) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); } - if (pad && !Skip (file, pad)) - throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image.") ; } - } + else + { + for (int y = file_height - 1; y >= 0; y--) + { + file->read(rowBuffer, rowLength); + if (!file) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); + + int offset = rowLength - pixelWidth; + + for (int x = file_width - 1; x >= 0; x--) + { + SetEncodedRGBValue(image, x, y, gamma, 255, rowBuffer[offset + 2], rowBuffer[offset + 1], rowBuffer[offset]); + offset -= pixelWidth; + } - return (image) ; + if (pad && !Skip(file, pad)) + throw POV_EXCEPTION(kFileDataErr, "Error reading data from BMP image."); + } + } + + delete[] rowBuffer; + } + return (image); } } From 243e2fbc87024b407326184a9afebef0ddc0b704 Mon Sep 17 00:00:00 2001 From: Louis Somers Date: Mon, 24 Feb 2020 00:58:28 +0100 Subject: [PATCH 20/20] No changes to imageutil.cpp --- source/core/support/imageutil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/support/imageutil.cpp b/source/core/support/imageutil.cpp index c47564be5..ae50e194e 100644 --- a/source/core/support/imageutil.cpp +++ b/source/core/support/imageutil.cpp @@ -1389,7 +1389,7 @@ void Destroy_Image(ImageData *image) { if ((image == nullptr) || (--(image->References) > 0)) return; - + delete image; }