mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement despeckle()
This commit is contained in:
parent
9efc0f2d5a
commit
072239c3eb
@ -477,3 +477,102 @@ QImage gaussian_blur(const QImage &image, const float radius, const float sigma)
|
||||
return(buffer);
|
||||
}
|
||||
// }}}
|
||||
|
||||
// despeckle() {{{
|
||||
|
||||
inline void hull(const int x_offset, const int y_offset, const int w, const int h, unsigned char *f, unsigned char *g, const int polarity) {
|
||||
int x, y, v;
|
||||
unsigned char *p, *q, *r, *s;
|
||||
p = f+(w+2); q = g+(w+2);
|
||||
r = p+(y_offset*(w+2)+x_offset);
|
||||
for(y=0; y < h; ++y, ++p, ++q, ++r){
|
||||
++p; ++q; ++r;
|
||||
if(polarity > 0){
|
||||
for(x=w; x > 0; --x, ++p, ++q, ++r){
|
||||
v = (*p);
|
||||
if((int)*r >= (v+2)) v += 1;
|
||||
*q = (unsigned char)v;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(x=w; x > 0; --x, ++p, ++q, ++r){
|
||||
v = (*p);
|
||||
if((int)*r <= (v-2)) v -= 1;
|
||||
*q = (unsigned char)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
p = f+(w+2); q = g+(w+2);
|
||||
r = q+(y_offset*(w+2)+x_offset); s = q-(y_offset*(w+2)+x_offset);
|
||||
for(y=0; y < h; ++y, ++p, ++q, ++r, ++s){
|
||||
++p; ++q; ++r; ++s;
|
||||
if(polarity > 0){
|
||||
for(x=w; x > 0; --x, ++p, ++q, ++r, ++s){
|
||||
v = (*q);
|
||||
if(((int)*s >= (v+2)) && ((int)*r > v)) v+=1;
|
||||
*p = (unsigned char)v;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(x=w; x > 0; --x, ++p, ++q, ++r, ++s){
|
||||
v = (int)(*q);
|
||||
if (((int)*s <= (v-2)) && ((int)*r < v)) v -= 1;
|
||||
*p = (unsigned char)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DESPECKLE_CHANNEL(c, e) \
|
||||
(void)memset(pixels, 0, length); \
|
||||
j = w+2; \
|
||||
for(y=0; y < h; ++y, ++j){ \
|
||||
src = reinterpret_cast<const QRgb *>(img.constScanLine(y)); \
|
||||
++j; \
|
||||
for(x=w-1; x >= 0; --x, ++src, ++j) \
|
||||
pixels[j] = c(*src); \
|
||||
} \
|
||||
(void)memset(buffer, 0, length); \
|
||||
for(i=0; i < 4; ++i){ \
|
||||
hull(X[i], Y[i], w, h, pixels, buffer, 1); \
|
||||
hull(-X[i], -Y[i], w, h, pixels, buffer, 1); \
|
||||
hull(-X[i], -Y[i], w, h, pixels, buffer, -1); \
|
||||
hull(X[i], Y[i], w, h, pixels, buffer, -1); \
|
||||
} \
|
||||
j = w+2; \
|
||||
for(y=0; y < h; ++y, ++j){ \
|
||||
dest = reinterpret_cast<QRgb *>(img.scanLine(y)); \
|
||||
++j; \
|
||||
for(x=w-1; x >= 0; --x, ++dest, ++j) \
|
||||
*dest = e; \
|
||||
}
|
||||
|
||||
QImage despeckle(const QImage &image) {
|
||||
int length, x, y, j, i;
|
||||
QRgb *dest;
|
||||
const QRgb *src;
|
||||
QImage img(image);
|
||||
unsigned char *buffer, *pixels;
|
||||
int w = img.width();
|
||||
int h = img.height();
|
||||
|
||||
static const int
|
||||
X[4]= {0, 1, 1,-1},
|
||||
Y[4]= {1, 0, 1, 1};
|
||||
|
||||
ENSURE32(img);
|
||||
length = (img.width()+2)*(img.height()+2);
|
||||
pixels = new unsigned char[length];
|
||||
buffer = new unsigned char[length];
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
DESPECKLE_CHANNEL(qRed, qRgba(pixels[j], qGreen(*dest), qBlue(*dest), qAlpha(*dest)))
|
||||
DESPECKLE_CHANNEL(qGreen, qRgba(qRed(*dest), pixels[j], qBlue(*dest), qAlpha(*dest)))
|
||||
DESPECKLE_CHANNEL(qBlue, qRgba(qRed(*dest), qGreen(*dest), pixels[j], qAlpha(*dest)))
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
delete[] pixels;
|
||||
delete[] buffer;
|
||||
return(img);
|
||||
}
|
||||
// }}}
|
||||
|
@ -14,4 +14,5 @@ QImage remove_borders(const QImage &image, double fuzz);
|
||||
QImage grayscale(const QImage &image);
|
||||
QImage gaussian_sharpen(const QImage &img, const float radius, const float sigma, const bool high_quality=true);
|
||||
QImage gaussian_blur(const QImage &img, const float radius, const float sigma);
|
||||
QImage despeckle(const QImage &image);
|
||||
|
||||
|
@ -43,3 +43,10 @@ QImage gaussian_blur(const QImage &img, const float radius, const float sigma);
|
||||
sipRes = new QImage(gaussian_blur(*a0, a1, a2));
|
||||
IMAGEOPS_SUFFIX
|
||||
%End
|
||||
|
||||
QImage despeckle(const QImage &image);
|
||||
%MethodCode
|
||||
IMAGEOPS_PREFIX
|
||||
sipRes = new QImage(despeckle(*a0));
|
||||
IMAGEOPS_SUFFIX
|
||||
%End
|
||||
|
@ -227,6 +227,11 @@ def gaussian_blur(img, radius=-1, sigma=3):
|
||||
raise RuntimeError(imageops_err)
|
||||
return imageops.gaussian_blur(image_from_data(img), max(0, radius), sigma)
|
||||
|
||||
def despeckle(img):
|
||||
if imageops is None:
|
||||
raise RuntimeError(imageops_err)
|
||||
return imageops.despeckle(image_from_data(img))
|
||||
|
||||
def run_optimizer(file_path, cmd, as_filter=False, input_data=None):
|
||||
file_path = os.path.abspath(file_path)
|
||||
cwd = os.path.dirname(file_path)
|
||||
|
Loading…
x
Reference in New Issue
Block a user