diff --git a/src/calibre/utils/imageops/imageops.cpp b/src/calibre/utils/imageops/imageops.cpp index 95c13cc5d0..299b7ff875 100644 --- a/src/calibre/utils/imageops/imageops.cpp +++ b/src/calibre/utils/imageops/imageops.cpp @@ -38,18 +38,20 @@ unsigned int read_border_row(const QImage &img, const unsigned int width, const return ans; } +#define ENSURE32(img) \ + if (img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32) { \ + img = img.convertToFormat(img.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32); \ + if (img.isNull()) { PyErr_NoMemory(); return NULL; } \ + } \ + QImage* remove_borders(const QImage &image, double fuzz) { int *buf = NULL; QImage* ans = NULL, img = image, timg; QTransform transpose; - transpose.rotate(90); unsigned int width = img.width(), height = img.height(); unsigned int top_border = 0, bottom_border = 0, left_border = 0, right_border = 0; - if (img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32) { - img = img.convertToFormat(img.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32); - if (img.isNull()) { PyErr_NoMemory(); return NULL; } - } + ENSURE32(img) buf = new int[3*(MAX(width, height)+1)]; fuzz /= 255; @@ -57,6 +59,7 @@ QImage* remove_borders(const QImage &image, double fuzz) { if (top_border >= height - 1) goto end; bottom_border = read_border_row(img, width, height, buf, fuzz, false); if (bottom_border >= height - 1) goto end; + transpose.rotate(90); timg = img.transformed(transpose); if (timg.isNull()) { PyErr_NoMemory(); goto end; } left_border = read_border_row(timg, height, width, buf, fuzz, true); @@ -74,3 +77,20 @@ end: if (!PyErr_Occurred()) ans = new QImage(img); return ans; } + +QImage* grayscale(const QImage &image) { + QImage img = image, *ans = NULL; + QRgb *row = NULL, *pixel = NULL; + int r = 0, gray = 0, width = img.width(), height = img.height(); + + ENSURE32(img); + for (r = 0; r < height; r++) { + row = reinterpret_cast(img.scanLine(r)); + for (pixel = row; pixel < row + width; pixel++) { + gray = qGray(*pixel); + *pixel = QColor(gray, gray, gray).rgba(); + } + } + if (!PyErr_Occurred()) ans = new QImage(img); + return ans; +} diff --git a/src/calibre/utils/imageops/imageops.h b/src/calibre/utils/imageops/imageops.h index c7ca6dab10..1f70459c4d 100644 --- a/src/calibre/utils/imageops/imageops.h +++ b/src/calibre/utils/imageops/imageops.h @@ -11,4 +11,5 @@ #include QImage* remove_borders(const QImage &image, double fuzz); +QImage* grayscale(const QImage &image); diff --git a/src/calibre/utils/imageops/imageops.sip b/src/calibre/utils/imageops/imageops.sip index 273fb0b8c7..ee93b77082 100644 --- a/src/calibre/utils/imageops/imageops.sip +++ b/src/calibre/utils/imageops/imageops.sip @@ -16,3 +16,11 @@ QImage* remove_borders(const QImage &image, double fuzz); if (sipRes == NULL) return NULL; } catch (std::bad_alloc) { PyErr_NoMemory(); return NULL; } %End + +QImage* grayscale(const QImage &image); +%MethodCode + try { + sipRes = grayscale(*a0); + if (sipRes == NULL) return NULL; + } catch (std::bad_alloc) { PyErr_NoMemory(); return NULL; } +%End diff --git a/src/calibre/utils/img.py b/src/calibre/utils/img.py index 5b9b079ce8..64b478254f 100644 --- a/src/calibre/utils/img.py +++ b/src/calibre/utils/img.py @@ -120,6 +120,13 @@ def add_borders_to_image(img_data, left=0, top=0, right=0, bottom=0, img = add_borders(img, left=left, top=top, right=right, bottom=bottom, border_color=border_color) return image_to_data(img, fmt=fmt) +def to_grayscale(img): + if hasattr(QImage, 'Format_Grayscale8'): + return img.convertToFormat(QImage.Format_Grayscale8) + if imageops is not None: + return imageops.grayscale(img) + return img + def save_cover_data_to(data, path=None, bgcolor='#ffffff', resize_to=None, compression_quality=90, minify_to=None, grayscale=False): ''' Saves image in data to path, in the format specified by the path @@ -155,9 +162,9 @@ def save_cover_data_to(data, path=None, bgcolor='#ffffff', resize_to=None, compr changed = True img = blend_image(img, bgcolor) if grayscale: - changed = True if not img.allGray(): - img = img.convertToFormat(QImage.Format_Grayscale8) + changed = True + img = to_grayscale(img) if path is None: return image_to_data(img, compression_quality, fmt) if changed else data with lopen(path, 'wb') as f: