mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
sharp alpha channel
resolve sharp endianness issues
This commit is contained in:
parent
d0c419632e
commit
107b4a8b07
|
@ -60,9 +60,10 @@ class TestImageOpsUsm(PillowTestCase):
|
|||
|
||||
def test_usm_accuracy(self):
|
||||
|
||||
i = snakes._new(ImageOps.unsharp_mask(snakes, 5, 1024, 0))
|
||||
src = snakes.convert('RGB')
|
||||
i = src._new(ImageOps.unsharp_mask(src, 5, 1024, 0))
|
||||
# Image should not be changed because it have only 0 and 255 levels.
|
||||
self.assertEqual(i.tobytes(), snakes.tobytes())
|
||||
self.assertEqual(i.tobytes(), src.tobytes())
|
||||
|
||||
def test_blur_accuracy(self):
|
||||
|
||||
|
|
|
@ -10,13 +10,16 @@
|
|||
#include "Imaging.h"
|
||||
|
||||
|
||||
static inline UINT8 clip(double in)
|
||||
typedef UINT8 pixel[4];
|
||||
|
||||
|
||||
static inline UINT8 clip8(int in)
|
||||
{
|
||||
if (in >= 255.0)
|
||||
return (UINT8) 255;
|
||||
if (in <= 0.0)
|
||||
return (UINT8) 0;
|
||||
return (UINT8) (in + 0.5);
|
||||
if (in >= 255)
|
||||
return 255;
|
||||
if (in <= 0)
|
||||
return 0;
|
||||
return (UINT8) in;
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,109 +28,64 @@ ImagingUnsharpMask(Imaging imOut, Imaging imIn, float radius, int percent,
|
|||
int threshold)
|
||||
{
|
||||
ImagingSectionCookie cookie;
|
||||
|
||||
Imaging result;
|
||||
int channel = 0;
|
||||
int channels = 0;
|
||||
int hasAlpha = 0;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int x, y, diff;
|
||||
|
||||
int *lineIn = NULL;
|
||||
int *lineOut = NULL;
|
||||
pixel *lineIn = NULL;
|
||||
pixel *lineOut = NULL;
|
||||
UINT8 *lineIn8 = NULL;
|
||||
UINT8 *lineOut8 = NULL;
|
||||
|
||||
int diff = 0;
|
||||
|
||||
INT32 newPixel = 0;
|
||||
|
||||
if (strcmp(imIn->mode, "RGB") == 0) {
|
||||
channels = 3;
|
||||
} else if (strcmp(imIn->mode, "RGBA") == 0) {
|
||||
channels = 3;
|
||||
} else if (strcmp(imIn->mode, "RGBX") == 0) {
|
||||
channels = 3;
|
||||
} else if (strcmp(imIn->mode, "CMYK") == 0) {
|
||||
channels = 4;
|
||||
} else if (strcmp(imIn->mode, "L") == 0) {
|
||||
channels = 1;
|
||||
} else
|
||||
return ImagingError_ModeError();
|
||||
|
||||
/* first, do a gaussian blur on the image, putting results in imOut
|
||||
temporarily */
|
||||
/* First, do a gaussian blur on the image, putting results in imOut
|
||||
temporarily. All format checks are in gaussian blur. */
|
||||
result = ImagingGaussianBlur(imOut, imIn, radius, 3);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
/* now, go through each pixel, compare "normal" pixel to blurred
|
||||
pixel. if the difference is more than threshold values, apply
|
||||
/* Now, go through each pixel, compare "normal" pixel to blurred
|
||||
pixel. If the difference is more than threshold values, apply
|
||||
the OPPOSITE correction to the amount of blur, multiplied by
|
||||
percent. */
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
|
||||
if (strcmp(imIn->mode, "RGBX") == 0 || strcmp(imIn->mode, "RGBA") == 0) {
|
||||
hasAlpha = 1;
|
||||
}
|
||||
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
if (channels == 1) {
|
||||
if (imIn->image8)
|
||||
{
|
||||
lineIn8 = imIn->image8[y];
|
||||
lineOut8 = imOut->image8[y];
|
||||
} else {
|
||||
lineIn = imIn->image32[y];
|
||||
lineOut = imOut->image32[y];
|
||||
}
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
newPixel = 0;
|
||||
/* compare in/out pixels, apply sharpening */
|
||||
if (channels == 1) {
|
||||
diff =
|
||||
((UINT8 *) & lineIn8[x])[0] -
|
||||
((UINT8 *) & lineOut8[x])[0];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
/* compare in/out pixels, apply sharpening */
|
||||
diff = lineIn8[x] - lineOut8[x];
|
||||
if (abs(diff) > threshold) {
|
||||
/* add the diff*percent to the original pixel */
|
||||
imOut->image8[y][x] =
|
||||
clip((((UINT8 *) & lineIn8[x])[0]) +
|
||||
(diff * ((float) percent) / 100.0));
|
||||
lineOut8[x] = clip8(lineIn8[x] + diff * percent / 100);
|
||||
} else {
|
||||
/* newPixel is the same as imIn */
|
||||
imOut->image8[y][x] = ((UINT8 *) & lineIn8[x])[0];
|
||||
/* new pixel is the same as imIn */
|
||||
lineOut8[x] = lineIn8[x];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lineIn = (pixel *)imIn->image32[y];
|
||||
lineOut = (pixel *)imOut->image32[y];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
/* compare in/out pixels, apply sharpening */
|
||||
diff = lineIn[x][0] - lineOut[x][0];
|
||||
lineOut[x][0] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][0] + diff * percent / 100) : lineIn[x][0];
|
||||
|
||||
else {
|
||||
for (channel = 0; channel < channels; channel++) {
|
||||
diff = (int) ((((UINT8 *) & lineIn[x])[channel]) -
|
||||
(((UINT8 *) & lineOut[x])[channel]));
|
||||
if (abs(diff) > threshold) {
|
||||
/* add the diff*percent to the original pixel
|
||||
this may not work for little-endian systems, fix it! */
|
||||
newPixel =
|
||||
newPixel |
|
||||
clip((float) (((UINT8 *) & lineIn[x])[channel])
|
||||
+
|
||||
(diff *
|
||||
(((float) percent /
|
||||
100.0)))) << (channel * 8);
|
||||
} else {
|
||||
/* newPixel is the same as imIn
|
||||
this may not work for little-endian systems, fix it! */
|
||||
newPixel =
|
||||
newPixel | ((UINT8 *) & lineIn[x])[channel] <<
|
||||
(channel * 8);
|
||||
}
|
||||
}
|
||||
if (hasAlpha) {
|
||||
/* preserve the alpha channel
|
||||
this may not work for little-endian systems, fix it! */
|
||||
newPixel =
|
||||
newPixel | ((UINT8 *) & lineIn[x])[channel] << 24;
|
||||
}
|
||||
imOut->image32[y][x] = newPixel;
|
||||
diff = lineIn[x][1] - lineOut[x][1];
|
||||
lineOut[x][1] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][1] + diff * percent / 100) : lineIn[x][1];
|
||||
|
||||
diff = lineIn[x][2] - lineOut[x][2];
|
||||
lineOut[x][2] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][2] + diff * percent / 100) : lineIn[x][2];
|
||||
|
||||
diff = lineIn[x][3] - lineOut[x][3];
|
||||
lineOut[x][3] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][3] + diff * percent / 100) : lineIn[x][3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user