Fix grayscaling of images not working on Qt < 5.5

This commit is contained in:
Kovid Goyal 2016-05-05 20:17:38 +05:30
parent a3193f3845
commit ea82680617
4 changed files with 43 additions and 7 deletions

View File

@ -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<QRgb*>(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;
}

View File

@ -11,4 +11,5 @@
#include <Python.h>
QImage* remove_borders(const QImage &image, double fuzz);
QImage* grayscale(const QImage &image);

View File

@ -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

View File

@ -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: