Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions src/PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2428,14 +2428,7 @@ def resize(
(box[3] - reduce_box[1]) / factor_y,
)

if self.size[1] > self.size[0] * 100 and size[1] < self.size[1]:
im = self.im.resize(
(self.size[0], size[1]), resample, (0, box[1], self.size[0], box[3])
)
im = im.resize(size, resample, (box[0], 0, box[2], size[1]))
else:
im = self.im.resize(size, resample, box)
return self._new(im)
return self._new(self.im.resize(size, resample, box))

def reduce(
self,
Expand Down
133 changes: 82 additions & 51 deletions src/libImaging/Resample.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,82 +717,113 @@ ImagingResampleInner(
Imaging imTemp = NULL;
Imaging imOut = NULL;

int i, need_horizontal, need_vertical;
int i, second_pass, need_horizontal, need_vertical, error = 0;
int ybox_first, ybox_last;
int ksize_horiz, ksize_vert;
int ksize_horiz = 0, ksize_vert = 0;
int *bounds_horiz, *bounds_vert;
double *kk_horiz, *kk_vert;

need_horizontal = xsize != imIn->xsize || box[0] || box[2] != xsize;
need_vertical = ysize != imIn->ysize || box[1] || box[3] != ysize;

ksize_vert = precompute_coeffs(
imIn->ysize, box[1], box[3], ysize, filterp, &bounds_vert, &kk_vert
);
if (!ksize_vert) {
return NULL;
}
// If height is being scaled down, but not width,
// then run the vertical pass first, to make the horizontal pass faster
int horizontal_first = !(xsize >= (box[2] - box[0]) && ysize < (box[3] - box[1]));

// First used row in the source image
ybox_first = bounds_vert[0];
// Last used row in the source image
ybox_last = bounds_vert[ysize * 2 - 2] + bounds_vert[ysize * 2 - 1];

/* two-pass resize, horizontal pass */
if ((need_horizontal && horizontal_first) || need_vertical) {
ksize_vert = precompute_coeffs(
imIn->ysize, box[1], box[3], ysize, filterp, &bounds_vert, &kk_vert
);
if (!ksize_vert) {
return NULL;
}
}
if (need_horizontal) {
if (horizontal_first) {
// First used row in the source image
ybox_first = bounds_vert[0];
// Last used row in the source image
ybox_last = bounds_vert[ysize * 2 - 2] + bounds_vert[ysize * 2 - 1];

// Shift bounds for vertical pass
for (i = 0; i < ysize; i++) {
bounds_vert[i * 2] -= ybox_first;
}
}

ksize_horiz = precompute_coeffs(
imIn->xsize, box[0], box[2], xsize, filterp, &bounds_horiz, &kk_horiz
);
if (!ksize_horiz) {
free(bounds_vert);
free(kk_vert);
return NULL;
error = 1;
goto end;
}
}

// Shift bounds for vertical pass
for (i = 0; i < ysize; i++) {
bounds_vert[i * 2] -= ybox_first;
#define PASS(function, w, h, offset, ksize, bounds, kk) \
second_pass = imTemp != NULL; \
imTemp = ImagingNewDirty(imIn->mode, w, h); \
if (!imTemp) { \
error = 1; \
goto end; \
} \
function(imTemp, imIn, offset, ksize, bounds, kk); \
if (second_pass) { \
ImagingDelete(imIn); \
} \
imIn = imTemp;

if (horizontal_first) {
if (need_horizontal) {
PASS(
ResampleHorizontal,
xsize,
ybox_last - ybox_first,
ybox_first,
ksize_horiz,
bounds_horiz,
kk_horiz
);
}

imTemp = ImagingNewDirty(imIn->mode, xsize, ybox_last - ybox_first);
if (imTemp) {
ResampleHorizontal(
imTemp, imIn, ybox_first, ksize_horiz, bounds_horiz, kk_horiz
if (need_vertical) {
PASS(ResampleVertical, xsize, ysize, 0, ksize_vert, bounds_vert, kk_vert);
}
} else {
if (need_vertical) {
PASS(
ResampleVertical,
imIn->xsize,
ysize,
0,
ksize_vert,
bounds_vert,
kk_vert
);
}
free(bounds_horiz);
free(kk_horiz);
if (!imTemp) {
free(bounds_vert);
free(kk_vert);
return NULL;
if (need_horizontal) {
PASS(
ResampleHorizontal, xsize, ysize, 0, ksize_horiz, bounds_horiz, kk_horiz
);
}
imOut = imIn = imTemp;
}

/* vertical pass */
if (need_vertical) {
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, ysize);
if (imOut) {
/* imIn can be the original image or horizontally resampled one */
ResampleVertical(imOut, imIn, 0, ksize_vert, bounds_vert, kk_vert);
}
/* it's safe to call ImagingDelete with empty value
if previous step was not performed. */
ImagingDelete(imTemp);
free(bounds_vert);
free(kk_vert);
if (!imOut) {
return NULL;
}
} else {
// Free in any case
end:
if (ksize_horiz) {
free(bounds_horiz);
free(kk_horiz);
}
if (ksize_vert) {
free(bounds_vert);
free(kk_vert);
}
if (error) {
return NULL;
}

/* none of the previous steps are performed, copying */
if (!imOut) {
if (imTemp) {
imOut = imTemp;
} else {
// none of the previous steps are performed, copying
imOut = ImagingCopy(imIn);
}

Expand Down
Loading