From 8e7b519b8d3ce5e13ee3c57e01a272b2598ddecb Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 24 May 2019 20:06:51 +0200 Subject: [PATCH] Inline the grayscaling pass in ordered_dither Saving one QImage pixel-loop dance in the process... --- src/calibre/utils/imageops/ordered_dither.cpp | 10 ++++++++-- src/calibre/utils/img.py | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/calibre/utils/imageops/ordered_dither.cpp b/src/calibre/utils/imageops/ordered_dither.cpp index 2fe3d29828..577fe1c181 100644 --- a/src/calibre/utils/imageops/ordered_dither.cpp +++ b/src/calibre/utils/imageops/ordered_dither.cpp @@ -109,13 +109,19 @@ QImage ordered_dither(const QImage &image) { // {{{ if (img.isNull()) throw std::bad_alloc(); } + const bool is_gray = img.isGrayscale(); + for (y = 0; y < height; y++) { const QRgb *src_row = reinterpret_cast(img.constScanLine(y)); uint8_t *dst_row = dst.scanLine(y); for (x = 0; x < width; x++) { const QRgb pixel = *(src_row + x); - // We're running behind grayscale_image, so R = G = B - gray = qRed(pixel); + if (is_gray) { + // Grayscale and RGB32, so R = G = B + gray = qRed(pixel); + } else { + gray = qGray(pixel); + } dithered = dither_o8x8(x, y, gray); *(dst_row + x) = dithered; // ... or palette.indexOf(dithered); for Indexed8 } diff --git a/src/calibre/utils/img.py b/src/calibre/utils/img.py index 376d04d344..a929b09866 100644 --- a/src/calibre/utils/img.py +++ b/src/calibre/utils/img.py @@ -227,7 +227,7 @@ def save_cover_data_to(data, path=None, bgcolor='#ffffff', resize_to=None, compr if img.hasAlphaChannel(): changed = True img = blend_image(img, bgcolor) - if grayscale: + if grayscale and not eink: if not img.allGray(): changed = True img = grayscale_image(img) @@ -464,13 +464,13 @@ def eink_dither_image(img): ''' Dither the source image down to the eInk palette of 16 shades of grey, using ImageMagick's OrderedDither algorithm. - NOTE: Expects input as a grayscale image in RGB32 pixel format (as returned by grayscale_image). - Running blend_image if the image has an alpha channel, - or grayscale_image if it's not already grayscaled is the caller's responsibility. + NOTE: No need to call grayscale_image first, as this will inline a grayscaling pass if need be. Returns a QImage in Grayscale8 pixel format. ''' img = image_from_data(img) + if img.hasAlphaChannel(): + img = blend_image(img) return imageops.ordered_dither(img) # }}}