diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index d562b6fd09b..5fd8a6f6c3f 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -903,14 +903,23 @@ def check_image( im.load() check_image(im, 10, 10, pixel) - im1 = im.copy() - check_image(im1, 10, 10, pixel) - - im2 = im.crop((2, 2, 7, 7)) - check_image(im2, 5, 5, pixel) - - im3 = im.transpose(Image.Transpose.FLIP_LEFT_RIGHT) - check_image(im3, 10, 10, pixel) + copy = im.copy() + check_image(copy, 10, 10, pixel) + + cropped = im.crop((2, 2, 8, 7)) + check_image(cropped, 6, 5, pixel) + + for method, [w, h] in { + Image.Transpose.FLIP_LEFT_RIGHT: (6, 5), + Image.Transpose.FLIP_TOP_BOTTOM: (6, 5), + Image.Transpose.ROTATE_90: (5, 6), + Image.Transpose.ROTATE_180: (6, 5), + Image.Transpose.ROTATE_270: (5, 6), + Image.Transpose.TRANSPOSE: (5, 6), + Image.Transpose.TRANSVERSE: (5, 6), + }.items(): + transposed = cropped.transpose(method) + check_image(transposed, w, h, pixel) @pytest.mark.skipif(not is_win32(), reason="Windows only") diff --git a/src/libImaging/Geometry.c b/src/libImaging/Geometry.c index a74fba7cfd0..1cb64c63349 100644 --- a/src/libImaging/Geometry.c +++ b/src/libImaging/Geometry.c @@ -19,7 +19,8 @@ ImagingFlipLeftRight(Imaging imOut, Imaging imIn) { ImagingSectionCookie cookie; int x, y, xr; - if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { + if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0 || + imIn->pixelsize != imOut->pixelsize) { return (Imaging)ImagingError_ModeError(); } if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { @@ -47,7 +48,8 @@ ImagingFlipTopBottom(Imaging imOut, Imaging imIn) { ImagingSectionCookie cookie; int y, yr; - if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { + if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0 || + imIn->pixelsize != imOut->pixelsize) { return (Imaging)ImagingError_ModeError(); } if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { @@ -74,7 +76,8 @@ ImagingRotate90(Imaging imOut, Imaging imIn) { int x, y, xx, yy, xr, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { + if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0 || + imIn->pixelsize != imOut->pixelsize) { return (Imaging)ImagingError_ModeError(); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { @@ -83,48 +86,38 @@ ImagingRotate90(Imaging imOut, Imaging imIn) { ImagingCopyPalette(imOut, imIn); -#define ROTATE_90(INT, image) \ - for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { \ - for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { \ - yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; \ - xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; \ - for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { \ - for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { \ - yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize \ - ? yy + ROTATE_SMALL_CHUNK \ - : imIn->ysize; \ - xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize \ - ? xx + ROTATE_SMALL_CHUNK \ - : imIn->xsize; \ - for (yyy = yy; yyy < yyysize; yyy++) { \ - INT *in = (INT *)imIn->image[yyy]; \ - xr = imIn->xsize - 1 - xx; \ - for (xxx = xx; xxx < xxxsize; xxx++, xr--) { \ - INT *out = (INT *)imOut->image[xr]; \ - out[yyy] = in[xxx]; \ - } \ - } \ - } \ - } \ - } \ - } - ImagingSectionEnter(&cookie); - if (imIn->image8) { - if (strncmp(imIn->mode, "I;16", 4) == 0) { - ROTATE_90(UINT16, image8); - } else { - ROTATE_90(UINT8, image8); + for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { + for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { + yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; + xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; + for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { + for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { + yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize + ? yy + ROTATE_SMALL_CHUNK + : imIn->ysize; + xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize + ? xx + ROTATE_SMALL_CHUNK + : imIn->xsize; + for (yyy = yy; yyy < yyysize; yyy++) { + char *in = imIn->image[yyy]; + xr = imIn->xsize - 1 - xx; + for (xxx = xx; xxx < xxxsize; xxx++, xr--) { + char *out = imOut->image[xr]; + memcpy( + out + yyy * imIn->pixelsize, + in + xxx * imIn->pixelsize, + imIn->pixelsize); + } + } + } + } } - } else { - ROTATE_90(INT32, image32); } ImagingSectionLeave(&cookie); -#undef ROTATE_90 - return imOut; } @@ -134,7 +127,8 @@ ImagingTranspose(Imaging imOut, Imaging imIn) { int x, y, xx, yy, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { + if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0 || + imIn->pixelsize != imOut->pixelsize) { return (Imaging)ImagingError_ModeError(); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { @@ -143,47 +137,37 @@ ImagingTranspose(Imaging imOut, Imaging imIn) { ImagingCopyPalette(imOut, imIn); -#define TRANSPOSE(INT, image) \ - for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { \ - for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { \ - yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; \ - xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; \ - for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { \ - for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { \ - yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize \ - ? yy + ROTATE_SMALL_CHUNK \ - : imIn->ysize; \ - xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize \ - ? xx + ROTATE_SMALL_CHUNK \ - : imIn->xsize; \ - for (yyy = yy; yyy < yyysize; yyy++) { \ - INT *in = (INT *)imIn->image[yyy]; \ - for (xxx = xx; xxx < xxxsize; xxx++) { \ - INT *out = (INT *)imOut->image[xxx]; \ - out[yyy] = in[xxx]; \ - } \ - } \ - } \ - } \ - } \ - } - ImagingSectionEnter(&cookie); - if (imIn->image8) { - if (strncmp(imIn->mode, "I;16", 4) == 0) { - TRANSPOSE(UINT16, image8); - } else { - TRANSPOSE(UINT8, image8); + for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { + for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { + yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; + xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; + for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { + for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { + yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize + ? yy + ROTATE_SMALL_CHUNK + : imIn->ysize; + xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize + ? xx + ROTATE_SMALL_CHUNK + : imIn->xsize; + for (yyy = yy; yyy < yyysize; yyy++) { + char *in = imIn->image[yyy]; + for (xxx = xx; xxx < xxxsize; xxx++) { + char *out = imOut->image[xxx]; + memcpy( + out + yyy * imIn->pixelsize, + in + xxx * imIn->pixelsize, + imIn->pixelsize); + } + } + } + } } - } else { - TRANSPOSE(INT32, image32); } ImagingSectionLeave(&cookie); -#undef TRANSPOSE - return imOut; } @@ -193,7 +177,8 @@ ImagingTransverse(Imaging imOut, Imaging imIn) { int x, y, xr, yr, xx, yy, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { + if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0 || + imIn->pixelsize != imOut->pixelsize) { return (Imaging)ImagingError_ModeError(); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { @@ -202,49 +187,39 @@ ImagingTransverse(Imaging imOut, Imaging imIn) { ImagingCopyPalette(imOut, imIn); -#define TRANSVERSE(INT, image) \ - for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { \ - for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { \ - yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; \ - xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; \ - for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { \ - for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { \ - yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize \ - ? yy + ROTATE_SMALL_CHUNK \ - : imIn->ysize; \ - xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize \ - ? xx + ROTATE_SMALL_CHUNK \ - : imIn->xsize; \ - yr = imIn->ysize - 1 - yy; \ - for (yyy = yy; yyy < yyysize; yyy++, yr--) { \ - INT *in = (INT *)imIn->image[yyy]; \ - xr = imIn->xsize - 1 - xx; \ - for (xxx = xx; xxx < xxxsize; xxx++, xr--) { \ - INT *out = (INT *)imOut->image[xr]; \ - out[yr] = in[xxx]; \ - } \ - } \ - } \ - } \ - } \ - } - ImagingSectionEnter(&cookie); - if (imIn->image8) { - if (strncmp(imIn->mode, "I;16", 4) == 0) { - TRANSVERSE(UINT16, image8); - } else { - TRANSVERSE(UINT8, image8); + for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { + for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { + yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; + xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; + for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { + for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { + yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize + ? yy + ROTATE_SMALL_CHUNK + : imIn->ysize; + xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize + ? xx + ROTATE_SMALL_CHUNK + : imIn->xsize; + yr = imIn->ysize - 1 - yy; + for (yyy = yy; yyy < yyysize; yyy++, yr--) { + char *in = imIn->image[yyy]; + xr = imIn->xsize - 1 - xx; + for (xxx = xx; xxx < xxxsize; xxx++, xr--) { + char *out = imOut->image[xr]; + memcpy( + out + yr * imIn->pixelsize, + in + xxx * imIn->pixelsize, + imIn->pixelsize); + } + } + } + } } - } else { - TRANSVERSE(INT32, image32); } ImagingSectionLeave(&cookie); -#undef TRANSVERSE - return imOut; } @@ -253,7 +228,8 @@ ImagingRotate180(Imaging imOut, Imaging imIn) { ImagingSectionCookie cookie; int x, y, xr, yr; - if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { + if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0 || + imIn->pixelsize != imOut->pixelsize) { return (Imaging)ImagingError_ModeError(); } if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { @@ -262,33 +238,20 @@ ImagingRotate180(Imaging imOut, Imaging imIn) { ImagingCopyPalette(imOut, imIn); -#define ROTATE_180(INT, image) \ - for (y = 0; y < imIn->ysize; y++, yr--) { \ - INT *in = (INT *)imIn->image[y]; \ - INT *out = (INT *)imOut->image[yr]; \ - xr = imIn->xsize - 1; \ - for (x = 0; x < imIn->xsize; x++, xr--) { \ - out[xr] = in[x]; \ - } \ - } - ImagingSectionEnter(&cookie); yr = imIn->ysize - 1; - if (imIn->image8) { - if (strncmp(imIn->mode, "I;16", 4) == 0) { - ROTATE_180(UINT16, image8) - } else { - ROTATE_180(UINT8, image8) + for (y = 0; y < imIn->ysize; y++, yr--) { + char *in = imIn->image[y]; + char *out = imOut->image[yr]; + xr = imIn->linesize - imIn->pixelsize; + for (x = 0; x < imIn->linesize; x += imIn->pixelsize, xr -= imIn->pixelsize) { + memcpy(out + xr, in + x, imIn->pixelsize); } - } else { - ROTATE_180(INT32, image32) } ImagingSectionLeave(&cookie); -#undef ROTATE_180 - return imOut; } @@ -298,7 +261,8 @@ ImagingRotate270(Imaging imOut, Imaging imIn) { int x, y, xx, yy, yr, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) { + if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0 || + imIn->pixelsize != imOut->pixelsize) { return (Imaging)ImagingError_ModeError(); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { @@ -307,48 +271,38 @@ ImagingRotate270(Imaging imOut, Imaging imIn) { ImagingCopyPalette(imOut, imIn); -#define ROTATE_270(INT, image) \ - for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { \ - for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { \ - yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; \ - xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; \ - for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { \ - for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { \ - yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize \ - ? yy + ROTATE_SMALL_CHUNK \ - : imIn->ysize; \ - xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize \ - ? xx + ROTATE_SMALL_CHUNK \ - : imIn->xsize; \ - yr = imIn->ysize - 1 - yy; \ - for (yyy = yy; yyy < yyysize; yyy++, yr--) { \ - INT *in = (INT *)imIn->image[yyy]; \ - for (xxx = xx; xxx < xxxsize; xxx++) { \ - INT *out = (INT *)imOut->image[xxx]; \ - out[yr] = in[xxx]; \ - } \ - } \ - } \ - } \ - } \ - } - ImagingSectionEnter(&cookie); - if (imIn->image8) { - if (strncmp(imIn->mode, "I;16", 4) == 0) { - ROTATE_270(UINT16, image8); - } else { - ROTATE_270(UINT8, image8); + for (y = 0; y < imIn->ysize; y += ROTATE_CHUNK) { + for (x = 0; x < imIn->xsize; x += ROTATE_CHUNK) { + yysize = y + ROTATE_CHUNK < imIn->ysize ? y + ROTATE_CHUNK : imIn->ysize; + xxsize = x + ROTATE_CHUNK < imIn->xsize ? x + ROTATE_CHUNK : imIn->xsize; + for (yy = y; yy < yysize; yy += ROTATE_SMALL_CHUNK) { + for (xx = x; xx < xxsize; xx += ROTATE_SMALL_CHUNK) { + yyysize = yy + ROTATE_SMALL_CHUNK < imIn->ysize + ? yy + ROTATE_SMALL_CHUNK + : imIn->ysize; + xxxsize = xx + ROTATE_SMALL_CHUNK < imIn->xsize + ? xx + ROTATE_SMALL_CHUNK + : imIn->xsize; + yr = imIn->ysize - 1 - yy; + for (yyy = yy; yyy < yyysize; yyy++, yr--) { + char *in = imIn->image[yyy]; + for (xxx = xx; xxx < xxxsize; xxx++) { + char *out = imOut->image[xxx]; + memcpy( + out + yr * imIn->pixelsize, + in + xxx * imIn->pixelsize, + imIn->pixelsize); + } + } + } + } } - } else { - ROTATE_270(INT32, image32); } ImagingSectionLeave(&cookie); -#undef ROTATE_270 - return imOut; }