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);
|
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 grayscale(const QImage &image);
|
||||||
QImage gaussian_sharpen(const QImage &img, const float radius, const float sigma, const bool high_quality=true);
|
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 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));
|
sipRes = new QImage(gaussian_blur(*a0, a1, a2));
|
||||||
IMAGEOPS_SUFFIX
|
IMAGEOPS_SUFFIX
|
||||||
%End
|
%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)
|
raise RuntimeError(imageops_err)
|
||||||
return imageops.gaussian_blur(image_from_data(img), max(0, radius), sigma)
|
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):
|
def run_optimizer(file_path, cmd, as_filter=False, input_data=None):
|
||||||
file_path = os.path.abspath(file_path)
|
file_path = os.path.abspath(file_path)
|
||||||
cwd = os.path.dirname(file_path)
|
cwd = os.path.dirname(file_path)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user