From 9db35f3d7a51e19ba63d30ba5021da15bd2d2fce Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 9 May 2016 11:42:51 +0530 Subject: [PATCH] Improve quality by only performing partial reductions until the end --- src/calibre/utils/imageops/quantize.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/calibre/utils/imageops/quantize.cpp b/src/calibre/utils/imageops/quantize.cpp index 8f041f5010..06d1b14b0d 100644 --- a/src/calibre/utils/imageops/quantize.cpp +++ b/src/calibre/utils/imageops/quantize.cpp @@ -312,6 +312,8 @@ QImage quantize(const QImage &image, unsigned int maximum_colors, bool dither) { Node root = Node(); QVector color_table = QVector(MAX_COLORS); const QRgb* line = NULL; + // Increasing this number improves quality but also increases running time and memory consumption + static const size_t MAX_LEAVES = 2000; root.check_compiler(); @@ -322,10 +324,8 @@ QImage quantize(const QImage &image, unsigned int maximum_colors, bool dither) { // by iterating over the color table rather than the pixels if (img.format() != QImage::Format_RGB32) img = img.convertToFormat(QImage::Format_RGB32); if (img.isNull()) throw std::bad_alloc(); - // There can be at-most 8*(maximum_colors + 1) nodes, since we reduce the - // tree after each color is added Use an extra eight node just in case - // there is an off-by-one error somewhere :) - Pool node_pool((2 + maximum_colors) * 8); + // There can be no more than MAX_LEAVES * 8 nodes. Add 1 in case there is an off by 1 error somewhere. + Pool node_pool((MAX_LEAVES + 1) * 8); depth = (size_t)log2(maximum_colors); depth = MAX(2, MIN(depth, MAX_DEPTH)); @@ -335,12 +335,13 @@ QImage quantize(const QImage &image, unsigned int maximum_colors, bool dither) { for (c = 0; c < iwidth; c++) { const QRgb pixel = *(line + c); root.add_color(qRed(pixel), qGreen(pixel), qBlue(pixel), depth, 0, &leaf_count, reducible_nodes, node_pool); - while (leaf_count > maximum_colors) + while (leaf_count > MAX_LEAVES) root.reduce(depth, &leaf_count, reducible_nodes, node_pool); } } + while (leaf_count > maximum_colors) + root.reduce(depth, &leaf_count, reducible_nodes, node_pool); - if (leaf_count > maximum_colors) throw std::out_of_range("Leaf count > max colors, something bad happened"); color_table.resize(leaf_count); root.set_palette_colors(color_table.data(), &index, dither); ans.setColorTable(color_table);