Move Image size check to PaintEngine

master
Unknown 2018-06-09 06:12:10 +02:00
parent cbe326a798
commit 78c2c107db
4 changed files with 32 additions and 17 deletions

View File

@ -14,6 +14,8 @@ public:
Giant // 15px bold?
};
virtual ~PaintEngine() = default;
/* Checks if the requested imagesize can handled by the Paintengine. Prints warnings to out. Returns true if there are no trouble*/
virtual bool checkImageSize(int w, int h, std::ostream &out) = 0;
virtual bool create(int w, int h) = 0;
virtual void fill(const Color &color) = 0;
virtual void drawText(int x, int y, Font font, const std::string &text, const Color &color) = 0;

View File

@ -3,6 +3,7 @@
#include <sstream>
#include <cstring>
#include <stdexcept>
#include <limits>
#include <gdfontmb.h>
#include <gdfontl.h>
@ -26,6 +27,32 @@ PaintEngine_libgd::~PaintEngine_libgd()
clean();
}
bool PaintEngine_libgd::checkImageSize(int w, int h, std::ostream &out)
{
constexpr int int_max = std::numeric_limits<int>::max();
constexpr bool is32bit = (sizeof(void *) == 4);
// Estimated approximate maximum was determined by trial and error...
// (24100x24100 succeeded; 24200x24200 failed)
constexpr long long estimated_max_pixels_32bit = 24100L * 24100L;
// Print some useful messages in cases where it may not be possible to generate the image...
long long pixels = w*h;
// Study the libgd code to known why the maximum is the following:
long long max_pixels = int_max - int_max % h;
if (pixels > max_pixels) {
out << "WARNING: Image will have " << pixels << " pixels; the PNG graphics library will refuse to handle more than approximately " << int_max << std::endl;
out << " (If map generation fails, consider using --scalefactor to reduce the image size by a factor 2)" << std::endl;
return false;
}
else if (is32bit && pixels > estimated_max_pixels_32bit) {
out << "WARNING: Image will have " << pixels << " pixels; The maximum achievable on a 32-bit system is approximately " << estimated_max_pixels_32bit << std::endl;
out << " (If map generation fails, consider using --scalefactor to reduce the image size by a factor 2 or 4)" << std::endl;
return false;
}
return true;
}
bool PaintEngine_libgd::create(int w, int h)
{
width = w;

View File

@ -9,6 +9,7 @@ class PaintEngine_libgd :
public:
PaintEngine_libgd();
~PaintEngine_libgd() override;
bool checkImageSize(int w, int h, std::ostream & out) override;
bool create(int w, int h) override;
void fill(const Color &color) override;
void drawText(int x, int y, Font font, const std::string &text, const Color &color) override;

View File

@ -1200,23 +1200,6 @@ void TileGenerator::computeMapParameters(const std::string &input)
m_pictWidth += m_tileBorderXCount * m_tileBorderSize;
m_pictHeight /= m_scaleFactor;
m_pictHeight += m_tileBorderYCount * m_tileBorderSize;
// Print some useful messages in cases where it may not be possible to generate the image...
long long pixels = static_cast<long long>(m_pictWidth + borderLeft() + borderRight()) * (m_pictHeight + borderTop() + borderBottom());
// Study the libgd code to known why the maximum is the following:
long long max_pixels = INT_MAX - INT_MAX % m_pictHeight;
if (pixels > max_pixels) {
cerr << "WARNING: Image will have " << pixels << " pixels; the PNG graphics library will refuse to handle more than approximately " << INT_MAX << std::endl;
cerr << " (If map generation fails, consider using --scalefactor to reduce the image size by a factor 2)" << std::endl;
}
// Estimated approximate maximum was determined by trial and error...
// (24100x24100 succeeded; 24200x24200 failed)
#define ESTIMATED_MAX_PIXELS_32BIT (24100*24100L)
else if (sizeof(void *) == 4 && pixels > ESTIMATED_MAX_PIXELS_32BIT) {
cerr << "WARNING: Image will have " << pixels << " pixels; The maximum achievable on a 32-bit system is approximately " << ESTIMATED_MAX_PIXELS_32BIT << std::endl;
cerr << " (If map generation fails, consider using --scalefactor to reduce the image size by a factor 2 or 4)" << std::endl;
}
#undef ESTIMATED_MAX_PIXELS_32BIT
}
@ -1226,6 +1209,8 @@ void TileGenerator::createImage()
int totalPictWidth = m_pictWidth + borderLeft() + borderRight();
paintEngine = new PaintEngine_libgd();
paintEngine->checkImageSize(totalPictWidth, totalPictHeight, std::cerr);
if (!paintEngine->create(totalPictWidth, totalPictHeight)) {
ostringstream oss;
oss << "Failed to allocate " << totalPictWidth << "x" << totalPictHeight << " image";