mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 07:57:27 +03:00 
			
		
		
		
	Merge branch 'fix-blur-alpha'
This commit is contained in:
		
						commit
						e3793447fc
					
				
							
								
								
									
										
											BIN
										
									
								
								Tests/images/color_snakes.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/color_snakes.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.3 KiB | 
|  | @ -5,6 +5,7 @@ from PIL import ImageOps | ||||||
| from PIL import ImageFilter | from PIL import ImageFilter | ||||||
| 
 | 
 | ||||||
| im = Image.open("Tests/images/hopper.ppm") | im = Image.open("Tests/images/hopper.ppm") | ||||||
|  | snakes = Image.open("Tests/images/color_snakes.png") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TestImageOpsUsm(PillowTestCase): | class TestImageOpsUsm(PillowTestCase): | ||||||
|  | @ -16,7 +17,7 @@ class TestImageOpsUsm(PillowTestCase): | ||||||
|         self.assertEqual(i.size, (128, 128)) |         self.assertEqual(i.size, (128, 128)) | ||||||
|         # i.save("blur.bmp") |         # i.save("blur.bmp") | ||||||
| 
 | 
 | ||||||
|         i = ImageOps.usm(im, 2.0, 125, 8) |         i = ImageOps.unsharp_mask(im, 2.0, 125, 8) | ||||||
|         self.assertEqual(i.mode, "RGB") |         self.assertEqual(i.mode, "RGB") | ||||||
|         self.assertEqual(i.size, (128, 128)) |         self.assertEqual(i.size, (128, 128)) | ||||||
|         # i.save("usm.bmp") |         # i.save("usm.bmp") | ||||||
|  | @ -33,7 +34,7 @@ class TestImageOpsUsm(PillowTestCase): | ||||||
|         self.assertEqual(i.mode, "RGB") |         self.assertEqual(i.mode, "RGB") | ||||||
|         self.assertEqual(i.size, (128, 128)) |         self.assertEqual(i.size, (128, 128)) | ||||||
| 
 | 
 | ||||||
|     def test_usm(self): |     def test_usm_formats(self): | ||||||
| 
 | 
 | ||||||
|         usm = ImageOps.unsharp_mask |         usm = ImageOps.unsharp_mask | ||||||
|         self.assertRaises(ValueError, lambda: usm(im.convert("1"))) |         self.assertRaises(ValueError, lambda: usm(im.convert("1"))) | ||||||
|  | @ -45,7 +46,7 @@ class TestImageOpsUsm(PillowTestCase): | ||||||
|         usm(im.convert("CMYK")) |         usm(im.convert("CMYK")) | ||||||
|         self.assertRaises(ValueError, lambda: usm(im.convert("YCbCr"))) |         self.assertRaises(ValueError, lambda: usm(im.convert("YCbCr"))) | ||||||
| 
 | 
 | ||||||
|     def test_blur(self): |     def test_blur_formats(self): | ||||||
| 
 | 
 | ||||||
|         blur = ImageOps.gaussian_blur |         blur = ImageOps.gaussian_blur | ||||||
|         self.assertRaises(ValueError, lambda: blur(im.convert("1"))) |         self.assertRaises(ValueError, lambda: blur(im.convert("1"))) | ||||||
|  | @ -57,6 +58,33 @@ class TestImageOpsUsm(PillowTestCase): | ||||||
|         blur(im.convert("CMYK")) |         blur(im.convert("CMYK")) | ||||||
|         self.assertRaises(ValueError, lambda: blur(im.convert("YCbCr"))) |         self.assertRaises(ValueError, lambda: blur(im.convert("YCbCr"))) | ||||||
| 
 | 
 | ||||||
|  |     def test_usm_accuracy(self): | ||||||
|  | 
 | ||||||
|  |         i = snakes._new(ImageOps.unsharp_mask(snakes, 5, 1024, 0)) | ||||||
|  |         # Image should not be changed because it have only 0 and 255 levels. | ||||||
|  |         self.assertEqual(i.tobytes(), snakes.tobytes()) | ||||||
|  | 
 | ||||||
|  |     def test_blur_accuracy(self): | ||||||
|  | 
 | ||||||
|  |         i = snakes._new(ImageOps.gaussian_blur(snakes, 1)) | ||||||
|  |         # Alpha channel must match whole. | ||||||
|  |         self.assertEqual(i.split()[3], snakes.split()[3]) | ||||||
|  |         # These pixels surrounded with pixels with 255 intensity. | ||||||
|  |         # They must be 255. | ||||||
|  |         for x, y, c in [(1, 0, 1), (2, 0, 1), (7, 8, 1), (8, 8, 1), (2, 9, 1), | ||||||
|  |                         (7, 3, 0), (8, 3, 0), (5, 8, 0), (5, 9, 0), (1, 3, 0), | ||||||
|  |                         (4, 3, 2), (4, 2, 2)]: | ||||||
|  |             self.assertEqual(i.im.getpixel((x, y))[c], 255) | ||||||
|  |         # Fuzzy match. | ||||||
|  |         gp = lambda x, y: i.im.getpixel((x, y)) | ||||||
|  |         self.assertTrue(211 <= gp(7, 4)[0] <= 213) | ||||||
|  |         self.assertTrue(211 <= gp(7, 5)[2] <= 213) | ||||||
|  |         self.assertTrue(211 <= gp(7, 6)[2] <= 213) | ||||||
|  |         self.assertTrue(211 <= gp(7, 7)[1] <= 213) | ||||||
|  |         self.assertTrue(211 <= gp(8, 4)[0] <= 213) | ||||||
|  |         self.assertTrue(211 <= gp(8, 5)[2] <= 213) | ||||||
|  |         self.assertTrue(211 <= gp(8, 6)[2] <= 213) | ||||||
|  |         self.assertTrue(211 <= gp(8, 7)[1] <= 213) | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|  |  | ||||||
|  | @ -48,10 +48,10 @@ | ||||||
| static inline UINT8 clip(double in) | static inline UINT8 clip(double in) | ||||||
| { | { | ||||||
|     if (in >= 255.0) |     if (in >= 255.0) | ||||||
| 	return (UINT8) 255; |         return (UINT8) 255; | ||||||
|     if (in <= 0.0) |     if (in <= 0.0) | ||||||
| 	return (UINT8) 0; |         return (UINT8) 0; | ||||||
|     return (UINT8) in; |     return (UINT8) (in + 0.5); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static Imaging | static Imaging | ||||||
|  | @ -79,6 +79,7 @@ gblur(Imaging im, Imaging imOut, float floatRadius, int channels, int padding) | ||||||
| 
 | 
 | ||||||
|     int radius = 0; |     int radius = 0; | ||||||
|     float remainder = 0.0; |     float remainder = 0.0; | ||||||
|  |     int hasAlpha = 0; | ||||||
| 
 | 
 | ||||||
|     int i; |     int i; | ||||||
| 
 | 
 | ||||||
|  | @ -108,31 +109,31 @@ gblur(Imaging im, Imaging imOut, float floatRadius, int channels, int padding) | ||||||
|     maskData = malloc(radius * sizeof(float)); |     maskData = malloc(radius * sizeof(float)); | ||||||
|     /* FIXME: error checking */ |     /* FIXME: error checking */ | ||||||
|     for (x = 0; x < radius; x++) { |     for (x = 0; x < radius; x++) { | ||||||
| 	z = ((float) (x + 2) / ((float) radius)); |         z = ((float) (x + 2) / ((float) radius)); | ||||||
| 	dev = 0.5 + (((float) (radius * radius)) * 0.001); |         dev = 0.5 + (((float) (radius * radius)) * 0.001); | ||||||
| 	/* you can adjust this factor to change the shape/center-weighting
 |         /* you can adjust this factor to change the shape/center-weighting
 | ||||||
| 	   of the gaussian */ |            of the gaussian */ | ||||||
| 	maskData[x] = (float) pow((1.0 / sqrt(2.0 * 3.14159265359 * dev)), |         maskData[x] = (float) pow((1.0 / sqrt(2.0 * 3.14159265359 * dev)), | ||||||
| 				  ((-(z - 1.0) * -(x - 1.0)) / |                                   ((-(z - 1.0) * -(x - 1.0)) / | ||||||
| 				   (2.0 * dev))); |                                    (2.0 * dev))); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* if there's any remainder, multiply the first/last values in
 |     /* if there's any remainder, multiply the first/last values in
 | ||||||
|        MaskData it.  this allows us to support float radius values. */ |        MaskData it.  this allows us to support float radius values. */ | ||||||
|     if (remainder > 0.0) { |     if (remainder > 0.0) { | ||||||
| 	maskData[0] *= remainder; |         maskData[0] *= remainder; | ||||||
| 	maskData[radius - 1] *= remainder; |         maskData[radius - 1] *= remainder; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (x = 0; x < radius; x++) { |     for (x = 0; x < radius; x++) { | ||||||
| 	/* this is done separately now due to the correction for float
 |         /* this is done separately now due to the correction for float
 | ||||||
| 	   radius values above */ |            radius values above */ | ||||||
| 	sum += maskData[x]; |         sum += maskData[x]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < radius; i++) { |     for (i = 0; i < radius; i++) { | ||||||
| 	maskData[i] *= (1.0 / sum); |         maskData[i] *= (1.0 / sum); | ||||||
| 	/* printf("%f\n", maskData[i]); */ |         /* printf("%f\n", maskData[i]); */ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* create a temporary memory buffer for the data for the first pass
 |     /* create a temporary memory buffer for the data for the first pass
 | ||||||
|  | @ -140,9 +141,9 @@ gblur(Imaging im, Imaging imOut, float floatRadius, int channels, int padding) | ||||||
| 
 | 
 | ||||||
|     /* don't bother about alpha/padding */ |     /* don't bother about alpha/padding */ | ||||||
|     buffer = calloc((size_t) (im->xsize * im->ysize * channels), |     buffer = calloc((size_t) (im->xsize * im->ysize * channels), | ||||||
| 		    sizeof(float)); |                     sizeof(float)); | ||||||
|     if (buffer == NULL) |     if (buffer == NULL) | ||||||
| 	return ImagingError_MemoryError(); |         return ImagingError_MemoryError(); | ||||||
| 
 | 
 | ||||||
|     /* be nice to other threads while you go off to lala land */ |     /* be nice to other threads while you go off to lala land */ | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
|  | @ -153,94 +154,98 @@ gblur(Imaging im, Imaging imOut, float floatRadius, int channels, int padding) | ||||||
| 
 | 
 | ||||||
|     /* perform a blur on each line, and place in the temporary storage buffer */ |     /* perform a blur on each line, and place in the temporary storage buffer */ | ||||||
|     for (y = 0; y < im->ysize; y++) { |     for (y = 0; y < im->ysize; y++) { | ||||||
| 	if (channels == 1 && im->image8 != NULL) { |         if (channels == 1 && im->image8 != NULL) { | ||||||
| 	    line8 = (UINT8 *) im->image8[y]; |             line8 = (UINT8 *) im->image8[y]; | ||||||
| 	} else { |         } else { | ||||||
| 	    line = im->image32[y]; |             line = im->image32[y]; | ||||||
| 	} |         } | ||||||
| 	for (x = 0; x < im->xsize; x++) { |         for (x = 0; x < im->xsize; x++) { | ||||||
| 	    newPixel[0] = newPixel[1] = newPixel[2] = newPixel[3] = 0; |             newPixel[0] = newPixel[1] = newPixel[2] = newPixel[3] = 0; | ||||||
| 	    /* for each neighbor pixel, factor in its value/weighting to the
 |             /* for each neighbor pixel, factor in its value/weighting to the
 | ||||||
| 	       current pixel */ |                current pixel */ | ||||||
| 	    for (pix = 0; pix < radius; pix++) { |             for (pix = 0; pix < radius; pix++) { | ||||||
| 		/* figure the offset of this neighbor pixel */ |                 /* figure the offset of this neighbor pixel */ | ||||||
| 		offset = |                 offset = | ||||||
| 		    (int) ((-((float) radius / 2.0) + (float) pix) + 0.5); |                     (int) ((-((float) radius / 2.0) + (float) pix) + 0.5); | ||||||
| 		if (x + offset < 0) |                 if (x + offset < 0) | ||||||
| 		    offset = -x; |                     offset = -x; | ||||||
| 		else if (x + offset >= im->xsize) |                 else if (x + offset >= im->xsize) | ||||||
| 		    offset = im->xsize - x - 1; |                     offset = im->xsize - x - 1; | ||||||
| 
 | 
 | ||||||
| 		/* add (neighbor pixel value * maskData[pix]) to the current
 |                 /* add (neighbor pixel value * maskData[pix]) to the current
 | ||||||
| 		   pixel value */ |                    pixel value */ | ||||||
| 		if (channels == 1) { |                 if (channels == 1) { | ||||||
| 		    buffer[(y * im->xsize) + x] += |                     buffer[(y * im->xsize) + x] += | ||||||
| 			((float) ((UINT8 *) & line8[x + offset])[0]) * |                         ((float) ((UINT8 *) & line8[x + offset])[0]) * | ||||||
| 			(maskData[pix]); |                         (maskData[pix]); | ||||||
| 		} else { |                 } else { | ||||||
| 		    for (channel = 0; channel < channels; channel++) { |                     for (channel = 0; channel < channels; channel++) { | ||||||
| 			buffer[(y * im->xsize * channels) + |                         buffer[(y * im->xsize * channels) + | ||||||
| 			       (x * channels) + channel] += |                                (x * channels) + channel] += | ||||||
| 			    ((float) ((UINT8 *) & line[x + offset]) |                             ((float) ((UINT8 *) & line[x + offset]) | ||||||
| 			     [channel]) * (maskData[pix]); |                              [channel]) * (maskData[pix]); | ||||||
| 		    } |                     } | ||||||
| 		} |                 } | ||||||
| 	    } |             } | ||||||
| 	} |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (strcmp(im->mode, "RGBX") == 0 || strcmp(im->mode, "RGBA") == 0) { | ||||||
|  |         hasAlpha = 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* perform a blur on each column in the buffer, and place in the
 |     /* perform a blur on each column in the buffer, and place in the
 | ||||||
|        output image */ |        output image */ | ||||||
|     for (x = 0; x < im->xsize; x++) { |     for (x = 0; x < im->xsize; x++) { | ||||||
| 	for (y = 0; y < im->ysize; y++) { |         for (y = 0; y < im->ysize; y++) { | ||||||
| 	    newPixel[0] = newPixel[1] = newPixel[2] = newPixel[3] = 0; |             newPixel[0] = newPixel[1] = newPixel[2] = newPixel[3] = 0; | ||||||
| 	    /* for each neighbor pixel, factor in its value/weighting to the
 |             /* for each neighbor pixel, factor in its value/weighting to the
 | ||||||
| 	       current pixel */ |                current pixel */ | ||||||
| 	    for (pix = 0; pix < radius; pix++) { |             for (pix = 0; pix < radius; pix++) { | ||||||
| 		/* figure the offset of this neighbor pixel */ |                 /* figure the offset of this neighbor pixel */ | ||||||
| 		offset = |                 offset = | ||||||
| 		    (int) (-((float) radius / 2.0) + (float) pix + 0.5); |                     (int) (-((float) radius / 2.0) + (float) pix + 0.5); | ||||||
| 		if (y + offset < 0) |                 if (y + offset < 0) | ||||||
| 		    offset = -y; |                     offset = -y; | ||||||
| 		else if (y + offset >= im->ysize) |                 else if (y + offset >= im->ysize) | ||||||
| 		    offset = im->ysize - y - 1; |                     offset = im->ysize - y - 1; | ||||||
| 		/* add (neighbor pixel value * maskData[pix]) to the current
 |  | ||||||
| 		   pixel value */ |  | ||||||
| 		for (channel = 0; channel < channels; channel++) { |  | ||||||
| 		    newPixel[channel] += |  | ||||||
| 			(buffer |  | ||||||
| 			 [((y + offset) * im->xsize * channels) + |  | ||||||
| 			  (x * channels) + channel]) * (maskData[pix]); |  | ||||||
| 		} |  | ||||||
| 	    } |  | ||||||
| 	    /* if the image is RGBX or RGBA, copy the 4th channel data to
 |  | ||||||
| 	       newPixel, so it gets put in imOut */ |  | ||||||
| 	    if (strcmp(im->mode, "RGBX") == 0 |  | ||||||
| 		|| strcmp(im->mode, "RGBA") == 0) { |  | ||||||
| 	      newPixel[3] = (float) ((UINT8 *) & line[x + offset])[3]; |  | ||||||
| 	    } |  | ||||||
| 
 | 
 | ||||||
| 	    /* pack the channels into an INT32 so we can put them back in
 |                 /* add (neighbor pixel value * maskData[pix]) to the current
 | ||||||
| 	       the PIL image */ |                    pixel value */ | ||||||
| 	    newPixelFinals = 0; |                 for (channel = 0; channel < channels; channel++) { | ||||||
| 	    if (channels == 1) { |                     newPixel[channel] += | ||||||
| 		newPixelFinals = clip(newPixel[0]); |                         (buffer | ||||||
| 	    } else { |                          [((y + offset) * im->xsize * channels) + | ||||||
| 		/* for RGB, the fourth channel isn't used anyways, so just
 |                           (x * channels) + channel]) * (maskData[pix]); | ||||||
| 		   pack a 0 in there, this saves checking the mode for each |                 } | ||||||
| 		   pixel. */ |             } | ||||||
| 		/* this doesn't work on little-endian machines... fix it! */ |             /* if the image is RGBX or RGBA, copy the 4th channel data to
 | ||||||
| 		newPixelFinals = |                newPixel, so it gets put in imOut */ | ||||||
| 		    clip(newPixel[0]) | clip(newPixel[1]) << 8 | |             if (hasAlpha) { | ||||||
| 		    clip(newPixel[2]) << 16 | clip(newPixel[3]) << 24; |                 newPixel[3] = (float) ((UINT8 *) & im->image32[y][x])[3]; | ||||||
| 	    } |             } | ||||||
| 	    /* set the resulting pixel in imOut */ | 
 | ||||||
| 	    if (channels == 1) { |             /* pack the channels into an INT32 so we can put them back in
 | ||||||
| 		imOut->image8[y][x] = (UINT8) newPixelFinals; |                the PIL image */ | ||||||
| 	    } else { |             newPixelFinals = 0; | ||||||
| 		imOut->image32[y][x] = newPixelFinals; |             if (channels == 1) { | ||||||
| 	    } |                 newPixelFinals = clip(newPixel[0]); | ||||||
| 	} |             } else { | ||||||
|  |                 /* for RGB, the fourth channel isn't used anyways, so just
 | ||||||
|  |                    pack a 0 in there, this saves checking the mode for each | ||||||
|  |                    pixel. */ | ||||||
|  |                 /* this doesn't work on little-endian machines... fix it! */ | ||||||
|  |                 newPixelFinals = | ||||||
|  |                     clip(newPixel[0]) | clip(newPixel[1]) << 8 | | ||||||
|  |                     clip(newPixel[2]) << 16 | clip(newPixel[3]) << 24; | ||||||
|  |             } | ||||||
|  |             /* set the resulting pixel in imOut */ | ||||||
|  |             if (channels == 1) { | ||||||
|  |                 imOut->image8[y][x] = (UINT8) newPixelFinals; | ||||||
|  |             } else { | ||||||
|  |                 imOut->image32[y][x] = newPixelFinals; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* free the buffer */ |     /* free the buffer */ | ||||||
|  | @ -258,29 +263,29 @@ Imaging ImagingGaussianBlur(Imaging im, Imaging imOut, float radius) | ||||||
|     int padding = 0; |     int padding = 0; | ||||||
| 
 | 
 | ||||||
|     if (strcmp(im->mode, "RGB") == 0) { |     if (strcmp(im->mode, "RGB") == 0) { | ||||||
| 	channels = 3; |         channels = 3; | ||||||
| 	padding = 1; |         padding = 1; | ||||||
|     } else if (strcmp(im->mode, "RGBA") == 0) { |     } else if (strcmp(im->mode, "RGBA") == 0) { | ||||||
| 	channels = 3; |         channels = 3; | ||||||
| 	padding = 1; |         padding = 1; | ||||||
|     } else if (strcmp(im->mode, "RGBX") == 0) { |     } else if (strcmp(im->mode, "RGBX") == 0) { | ||||||
| 	channels = 3; |         channels = 3; | ||||||
| 	padding = 1; |         padding = 1; | ||||||
|     } else if (strcmp(im->mode, "CMYK") == 0) { |     } else if (strcmp(im->mode, "CMYK") == 0) { | ||||||
| 	channels = 4; |         channels = 4; | ||||||
| 	padding = 0; |         padding = 0; | ||||||
|     } else if (strcmp(im->mode, "L") == 0) { |     } else if (strcmp(im->mode, "L") == 0) { | ||||||
| 	channels = 1; |         channels = 1; | ||||||
| 	padding = 0; |         padding = 0; | ||||||
|     } else |     } else | ||||||
| 	return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
| 
 | 
 | ||||||
|     return gblur(im, imOut, radius, channels, padding); |     return gblur(im, imOut, radius, channels, padding); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Imaging | Imaging | ||||||
| ImagingUnsharpMask(Imaging im, Imaging imOut, float radius, int percent, | ImagingUnsharpMask(Imaging im, Imaging imOut, float radius, int percent, | ||||||
| 		   int threshold) |                    int threshold) | ||||||
| { | { | ||||||
|     ImagingSectionCookie cookie; |     ImagingSectionCookie cookie; | ||||||
| 
 | 
 | ||||||
|  | @ -288,6 +293,7 @@ ImagingUnsharpMask(Imaging im, Imaging imOut, float radius, int percent, | ||||||
|     int channel = 0; |     int channel = 0; | ||||||
|     int channels = 0; |     int channels = 0; | ||||||
|     int padding = 0; |     int padding = 0; | ||||||
|  |     int hasAlpha = 0; | ||||||
| 
 | 
 | ||||||
|     int x = 0; |     int x = 0; | ||||||
|     int y = 0; |     int y = 0; | ||||||
|  | @ -302,28 +308,28 @@ ImagingUnsharpMask(Imaging im, Imaging imOut, float radius, int percent, | ||||||
|     INT32 newPixel = 0; |     INT32 newPixel = 0; | ||||||
| 
 | 
 | ||||||
|     if (strcmp(im->mode, "RGB") == 0) { |     if (strcmp(im->mode, "RGB") == 0) { | ||||||
| 	channels = 3; |         channels = 3; | ||||||
| 	padding = 1; |         padding = 1; | ||||||
|     } else if (strcmp(im->mode, "RGBA") == 0) { |     } else if (strcmp(im->mode, "RGBA") == 0) { | ||||||
| 	channels = 3; |         channels = 3; | ||||||
| 	padding = 1; |         padding = 1; | ||||||
|     } else if (strcmp(im->mode, "RGBX") == 0) { |     } else if (strcmp(im->mode, "RGBX") == 0) { | ||||||
| 	channels = 3; |         channels = 3; | ||||||
| 	padding = 1; |         padding = 1; | ||||||
|     } else if (strcmp(im->mode, "CMYK") == 0) { |     } else if (strcmp(im->mode, "CMYK") == 0) { | ||||||
| 	channels = 4; |         channels = 4; | ||||||
| 	padding = 0; |         padding = 0; | ||||||
|     } else if (strcmp(im->mode, "L") == 0) { |     } else if (strcmp(im->mode, "L") == 0) { | ||||||
| 	channels = 1; |         channels = 1; | ||||||
| 	padding = 0; |         padding = 0; | ||||||
|     } else |     } else | ||||||
| 	return ImagingError_ModeError(); |         return ImagingError_ModeError(); | ||||||
| 
 | 
 | ||||||
|     /* first, do a gaussian blur on the image, putting results in imOut
 |     /* first, do a gaussian blur on the image, putting results in imOut
 | ||||||
|        temporarily */ |        temporarily */ | ||||||
|     result = gblur(im, imOut, radius, channels, padding); |     result = gblur(im, imOut, radius, channels, padding); | ||||||
|     if (!result) |     if (!result) | ||||||
| 	return NULL; |         return NULL; | ||||||
| 
 | 
 | ||||||
|     /* now, go through each pixel, compare "normal" pixel to blurred
 |     /* now, go through each pixel, compare "normal" pixel to blurred
 | ||||||
|        pixel.  if the difference is more than threshold values, apply |        pixel.  if the difference is more than threshold values, apply | ||||||
|  | @ -332,64 +338,67 @@ ImagingUnsharpMask(Imaging im, Imaging imOut, float radius, int percent, | ||||||
| 
 | 
 | ||||||
|     ImagingSectionEnter(&cookie); |     ImagingSectionEnter(&cookie); | ||||||
| 
 | 
 | ||||||
|     for (y = 0; y < im->ysize; y++) { |     if (strcmp(im->mode, "RGBX") == 0 || strcmp(im->mode, "RGBA") == 0) { | ||||||
| 	if (channels == 1) { |         hasAlpha = 1; | ||||||
| 	    lineIn8 = im->image8[y]; |     } | ||||||
| 	    lineOut8 = imOut->image8[y]; |  | ||||||
| 	} else { |  | ||||||
| 	    lineIn = im->image32[y]; |  | ||||||
| 	    lineOut = imOut->image32[y]; |  | ||||||
| 	} |  | ||||||
| 	for (x = 0; x < im->xsize; x++) { |  | ||||||
| 	    newPixel = 0; |  | ||||||
| 	    /* compare in/out pixels, apply sharpening */ |  | ||||||
| 	    if (channels == 1) { |  | ||||||
| 		diff = |  | ||||||
| 		    ((UINT8 *) & lineIn8[x])[0] - |  | ||||||
| 		    ((UINT8 *) & lineOut8[x])[0]; |  | ||||||
| 		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)); |  | ||||||
| 		} else { |  | ||||||
| 		    /* newPixel is the same as imIn */ |  | ||||||
| 		    imOut->image8[y][x] = ((UINT8 *) & lineIn8[x])[0]; |  | ||||||
| 		} |  | ||||||
| 	    } |  | ||||||
| 
 | 
 | ||||||
| 	    else { |     for (y = 0; y < im->ysize; y++) { | ||||||
| 		for (channel = 0; channel < channels; channel++) { |         if (channels == 1) { | ||||||
| 		    diff = (int) ((((UINT8 *) & lineIn[x])[channel]) - |             lineIn8 = im->image8[y]; | ||||||
| 				  (((UINT8 *) & lineOut[x])[channel])); |             lineOut8 = imOut->image8[y]; | ||||||
| 		    if (abs(diff) > threshold) { |         } else { | ||||||
| 			/* add the diff*percent to the original pixel
 |             lineIn = im->image32[y]; | ||||||
| 			   this may not work for little-endian systems, fix it! */ |             lineOut = imOut->image32[y]; | ||||||
| 			newPixel = |         } | ||||||
| 			    newPixel | |         for (x = 0; x < im->xsize; x++) { | ||||||
| 			    clip((float) (((UINT8 *) & lineIn[x])[channel]) |             newPixel = 0; | ||||||
| 				 + |             /* compare in/out pixels, apply sharpening */ | ||||||
| 				 (diff * |             if (channels == 1) { | ||||||
| 				  (((float) percent / |                 diff = | ||||||
| 				    100.0)))) << (channel * 8); |                     ((UINT8 *) & lineIn8[x])[0] - | ||||||
| 		    } else { |                     ((UINT8 *) & lineOut8[x])[0]; | ||||||
| 			/* newPixel is the same as imIn
 |                 if (abs(diff) > threshold) { | ||||||
| 			   this may not work for little-endian systems, fix it! */ |                     /* add the diff*percent to the original pixel */ | ||||||
| 			newPixel = |                     imOut->image8[y][x] = | ||||||
| 			    newPixel | ((UINT8 *) & lineIn[x])[channel] << |                         clip((((UINT8 *) & lineIn8[x])[0]) + | ||||||
| 			    (channel * 8); |                              (diff * ((float) percent) / 100.0)); | ||||||
| 		    } |                 } else { | ||||||
| 		} |                     /* newPixel is the same as imIn */ | ||||||
| 		if (strcmp(im->mode, "RGBX") == 0 |                     imOut->image8[y][x] = ((UINT8 *) & lineIn8[x])[0]; | ||||||
| 		    || strcmp(im->mode, "RGBA") == 0) { |                 } | ||||||
| 		    /* preserve the alpha channel
 |             } | ||||||
| 		       this may not work for little-endian systems, fix it! */ | 
 | ||||||
| 		    newPixel = |             else { | ||||||
| 			newPixel | ((UINT8 *) & lineIn[x])[channel] << 24; |                 for (channel = 0; channel < channels; channel++) { | ||||||
| 		} |                     diff = (int) ((((UINT8 *) & lineIn[x])[channel]) - | ||||||
| 		imOut->image32[y][x] = newPixel; |                                   (((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; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ImagingSectionLeave(&cookie); |     ImagingSectionLeave(&cookie); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user