enhanced multiple image sorting

improved image memory allocation
This commit is contained in:
Thomas Jentzsch 2022-08-18 16:31:54 +02:00
parent fea886d4b6
commit 34618aab46
4 changed files with 28 additions and 20 deletions

View File

@ -49,13 +49,13 @@ void JPGLibrary::loadImage(const string& filename, FBSurface& surface,
in.seekg(0);
// Create space for the entire file
if(size > myFileBuffer.size())
myFileBuffer.resize(size);
if(size > myFileBuffer.capacity())
myFileBuffer.reserve(size * 1.5);
if(!in.read(myFileBuffer.data(), size))
loadImageERROR("Image data reading failed");
loadImageERROR("JPG image data reading failed");
if(njDecode(myFileBuffer.data(), static_cast<int>(size)))
loadImageERROR("Error decoding the input file");
loadImageERROR("Error decoding the JPG image");
// Read the entire image in one go
myReadInfo.buffer = njGetImage();

View File

@ -49,18 +49,18 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi
std::ifstream in(filename, std::ios_base::binary);
if(!in.is_open())
loadImageERROR("No snapshot found");
loadImageERROR("No image found");
// Create the PNG loading context structure
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
png_user_error, png_user_warn);
if(png_ptr == nullptr)
loadImageERROR("Couldn't allocate memory for PNG file");
loadImageERROR("Couldn't allocate memory for PNG image");
// Allocate/initialize the memory for image information. REQUIRED.
info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == nullptr)
loadImageERROR("Couldn't create image information for PNG file");
loadImageERROR("Couldn't create image information for PNG image");
// Set up the input control
png_set_read_fn(png_ptr, &in, png_read_data);
@ -97,7 +97,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi
// Create/initialize storage area for the current image
if(!allocateStorage(iwidth, iheight))
loadImageERROR("Not enough memory to read PNG file");
loadImageERROR("Not enough memory to read PNG image");
// The PNG read function expects an array of rows, not a single 1-D array
for(uInt32 irow = 0, offset = 0; irow < ReadInfo.height; ++irow, offset += ReadInfo.pitch)
@ -385,12 +385,12 @@ bool PNGLibrary::allocateStorage(png_uint_32 w, png_uint_32 h)
{
// Create space for the entire image (3 bytes per pixel in RGB format)
const size_t req_buffer_size = w * h * 3;
if(req_buffer_size > ReadInfo.buffer.size())
ReadInfo.buffer.resize(req_buffer_size);
if(req_buffer_size > ReadInfo.buffer.capacity())
ReadInfo.buffer.reserve(req_buffer_size * 1.5);
const size_t req_row_size = h;
if(req_row_size > ReadInfo.row_pointers.size())
ReadInfo.row_pointers.resize(req_row_size);
if(req_row_size > ReadInfo.row_pointers.capacity())
ReadInfo.row_pointers.reserve(req_row_size * 1.5);
ReadInfo.width = w;
ReadInfo.height = h;

View File

@ -90,6 +90,7 @@ void RomImageWidget::reloadProperties(const FSNode& node)
void RomImageWidget::parseProperties(const FSNode& node, bool full)
{
uInt64 startTime = TimerManager::getTicks() / 1000;
if(myNavSurface == nullptr)
{
// Create navigation surface
@ -154,7 +155,8 @@ void RomImageWidget::parseProperties(const FSNode& node, bool full)
// Try to find all snapshots by property and ROM file name
myImageList.clear();
getImageList(myProperties.get(PropType::Cart_Name), node.getNameWithExt());
getImageList(myProperties.get(PropType::Cart_Name), node.getNameWithExt(),
oldFileName);
// The first file found before must not be the first file now, if files by
// property *and* ROM name are found (TODO: fix that!)
@ -191,13 +193,14 @@ bool RomImageWidget::changeImage(int direction)
#ifdef IMAGE_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RomImageWidget::getImageList(const string& propName, const string& romName)
bool RomImageWidget::getImageList(const string& propName, const string& romName,
const string& oldFileName)
{
const std::regex symbols{R"([-[\]{}()*+?.,\^$|#])"}; // \s
const string rgxPropName = std::regex_replace(propName, symbols, R"(\$&)");
const string rgxRomName = std::regex_replace(romName, symbols, R"(\$&)");
// Look for <name.png|jpg> or <name_#.png|jpg> (# is a number)
const std::regex rgx("^(" + rgxPropName + "|" + rgxRomName + ")(_\\d+){0,1}\\.(png|jpg)$");
const std::regex rgx("^(" + rgxPropName + "|" + rgxRomName + ")(_\\d+)?\\.(png|jpg)$");
FSNode::NameFilter filter = ([&](const FSNode& node)
{
@ -212,14 +215,17 @@ bool RomImageWidget::getImageList(const string& propName, const string& romName)
// Sort again, not considering extensions, else <filename.png|jpg> would be at
// the end of the list
std::sort(myImageList.begin(), myImageList.end(),
[](const FSNode& node1, const FSNode& node2)
[oldFileName](const FSNode& node1, const FSNode& node2)
{
int compare = BSPF::compareIgnoreCase(node1.getNameWithExt(), node2.getNameWithExt());
return
compare < 0 ||
// PNGs first!
(compare == 0 &&
node1.getName().substr(node1.getName().find_last_of('.') + 1) >
node2.getName().substr(node2.getName().find_last_of('.') + 1)); // PNGs first!
node2.getName().substr(node2.getName().find_last_of('.') + 1)) ||
// Make sure that first image found in initial load is first image now too
node1.getName() == oldFileName;
}
);
return myImageList.size() > 0;
@ -348,7 +354,7 @@ void RomImageWidget::drawWidget(bool hilite)
FBSurface& s = dialog().surface();
const int yoff = myImageHeight;
s.fillRect(_x+1, _y+1, _w-2, _h-2, _bgcolor);
s.fillRect(_x, _y + 1, _w, _h - 1, _bgcolor);
s.frameRect(_x, _y, _w, myImageHeight, kColor);
if(!myHaveProperties)

View File

@ -35,7 +35,8 @@ class RomImageWidget : public Widget
return font.getFontHeight() * 9 / 8;
}
void setProperties(const FSNode& node, const Properties properties, bool full = true);
void setProperties(const FSNode& node, const Properties properties,
bool full = true);
void clearProperties();
void reloadProperties(const FSNode& node);
bool changeImage(int direction = 1);
@ -52,7 +53,8 @@ class RomImageWidget : public Widget
private:
void parseProperties(const FSNode& node, bool full = true);
#ifdef IMAGE_SUPPORT
bool getImageList(const string& propName, const string& romName);
bool getImageList(const string& propName, const string& romName,
const string& oldFileName);
bool tryImageFormats(string& fileName);
bool loadImage(const string& fileName);
bool loadPng(const string& fileName);