mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 01:04:29 +03:00
add box parameter
This commit is contained in:
parent
cc30b1e55a
commit
778b5f9fed
|
@ -18,7 +18,7 @@ class TestImageReduce(PillowTestCase):
|
|||
cls.gradients_image = Image.open("Tests/images/radial_gradients.png")
|
||||
cls.gradients_image.load()
|
||||
|
||||
def test_args(self):
|
||||
def test_args_factor(self):
|
||||
im = Image.new("L", (10, 10))
|
||||
|
||||
self.assertEqual((4, 4), im.reduce(3).size)
|
||||
|
@ -62,6 +62,12 @@ class TestImageReduce(PillowTestCase):
|
|||
assert len(mode_info.bands) == 1
|
||||
return self.gradients_image.convert(mode)
|
||||
|
||||
def compare_reduce_with_box(self, im, factor):
|
||||
box = (11, 13, 146, 164)
|
||||
reduced = im.reduce(factor, box=box)
|
||||
reference = im.crop(box).reduce(factor)
|
||||
self.assertEqual(reduced, reference)
|
||||
|
||||
def compare_reduce_with_reference(self, im, factor, average_diff=0.4, max_diff=1):
|
||||
"""Image.reduce() should look very similar to Image.resize(BOX).
|
||||
|
||||
|
@ -136,6 +142,7 @@ class TestImageReduce(PillowTestCase):
|
|||
im = self.get_image("L")
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
||||
def test_mode_LA(self):
|
||||
im = self.get_image("LA")
|
||||
|
@ -146,16 +153,19 @@ class TestImageReduce(PillowTestCase):
|
|||
im.putalpha(Image.new('L', im.size, 255))
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
||||
def test_mode_La(self):
|
||||
im = self.get_image("La")
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
||||
def test_mode_RGB(self):
|
||||
im = self.get_image("RGB")
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
||||
def test_mode_RGBA(self):
|
||||
im = self.get_image("RGBA")
|
||||
|
@ -166,18 +176,22 @@ class TestImageReduce(PillowTestCase):
|
|||
im.putalpha(Image.new('L', im.size, 255))
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
||||
def test_mode_RGBa(self):
|
||||
im = self.get_image("RGBa")
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
||||
def test_mode_I(self):
|
||||
im = self.get_image("I")
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
||||
def test_mode_F(self):
|
||||
im = self.get_image("F")
|
||||
for factor in self.remarkable_factors:
|
||||
self.compare_reduce_with_reference(im, factor, 0, 0)
|
||||
self.compare_reduce_with_box(im, factor)
|
||||
|
|
|
@ -1887,7 +1887,7 @@ class Image(object):
|
|||
|
||||
return self._new(self.im.resize(size, resample, box))
|
||||
|
||||
def reduce(self, factor):
|
||||
def reduce(self, factor, box=None):
|
||||
"""
|
||||
Returns reduced in `factor` times copy of the image.
|
||||
If the size of the image is not dividable by the `factor`,
|
||||
|
@ -1895,21 +1895,30 @@ class Image(object):
|
|||
|
||||
:param factor: A greater than 0 integer or tuple of two integers
|
||||
for width and height separately.
|
||||
:param box: An optional 4-tuple of ints giving the region
|
||||
of the source image which should be reduced.
|
||||
The values should be within (0, 0, width, height) rectangle.
|
||||
If omitted or None, the entire source is used.
|
||||
"""
|
||||
if not isinstance(factor, (list, tuple)):
|
||||
factor = (factor, factor)
|
||||
|
||||
if factor == (1, 1):
|
||||
if box is None:
|
||||
box = (0, 0) + self.size
|
||||
else:
|
||||
box = tuple(box)
|
||||
|
||||
if factor == (1, 1) and box == (0, 0) + self.size:
|
||||
return self.copy()
|
||||
|
||||
if self.mode in ["LA", "RGBA"]:
|
||||
im = self.convert(self.mode[:-1] + "a")
|
||||
im = im.reduce(factor)
|
||||
im = im.reduce(factor, box)
|
||||
return im.convert(self.mode)
|
||||
|
||||
self.load()
|
||||
|
||||
return self._new(self.im.reduce(factor))
|
||||
return self._new(self.im.reduce(factor, box))
|
||||
|
||||
def rotate(
|
||||
self,
|
||||
|
|
|
@ -1836,20 +1836,39 @@ _reduce(ImagingObject* self, PyObject* args)
|
|||
Imaging imOut;
|
||||
|
||||
int xscale, yscale;
|
||||
int box[4] = {0, 0, 0, 0};
|
||||
|
||||
imIn = self->image;
|
||||
box[2] = imIn->xsize;
|
||||
box[3] = imIn->ysize;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "(ii)", &xscale, &yscale))
|
||||
if (!PyArg_ParseTuple(args, "(ii)|(iiii)", &xscale, &yscale,
|
||||
&box[0], &box[1], &box[2], &box[3]))
|
||||
return NULL;
|
||||
|
||||
if (xscale < 1 || yscale < 1) {
|
||||
return ImagingError_ValueError("scale must be > 0");
|
||||
}
|
||||
|
||||
if (box[0] < 0 || box[1] < 0) {
|
||||
return ImagingError_ValueError("box offset can't be negative");
|
||||
}
|
||||
|
||||
if (box[2] > imIn->xsize || box[3] > imIn->ysize) {
|
||||
return ImagingError_ValueError("box can't exceed original image size");
|
||||
}
|
||||
|
||||
if (box[2] < box[0] || box[3] < box[1]) {
|
||||
return ImagingError_ValueError("box can't be empty");
|
||||
}
|
||||
|
||||
if (xscale == 1 && yscale == 1) {
|
||||
imOut = ImagingCopy(imIn);
|
||||
imOut = ImagingCrop(imIn, box[0], box[1], box[2], box[3]);
|
||||
} else {
|
||||
imOut = ImagingReduce(imIn, xscale, yscale);
|
||||
// Change box format: (left, top, width, height)
|
||||
box[2] -= box[0];
|
||||
box[3] -= box[1];
|
||||
imOut = ImagingReduce(imIn, xscale, yscale, box);
|
||||
}
|
||||
|
||||
return PyImagingNew(imOut);
|
||||
|
|
|
@ -313,7 +313,7 @@ extern Imaging ImagingRotate270(Imaging imOut, Imaging imIn);
|
|||
extern Imaging ImagingTranspose(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingTransverse(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]);
|
||||
extern Imaging ImagingReduce(Imaging imIn, int xscale, int yscale);
|
||||
extern Imaging ImagingReduce(Imaging imIn, int xscale, int yscale, int box[4]);
|
||||
extern Imaging ImagingTransform(
|
||||
Imaging imOut, Imaging imIn, int method, int x0, int y0, int x1, int y1,
|
||||
double *a, int filter, int fill);
|
||||
|
|
|
@ -15,39 +15,37 @@ division_UINT32(int divider, int result_bits)
|
|||
|
||||
|
||||
void
|
||||
ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
||||
ImagingReduceNxN(Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale)
|
||||
{
|
||||
/* The most general implementation for any xscale and yscale
|
||||
*/
|
||||
int x, y, xx, yy, xi;
|
||||
int x, y, xx, yy;
|
||||
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
|
||||
UINT32 amend = yscale * xscale / 2;
|
||||
|
||||
if (imIn->image8) {
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
UINT32 ss = amend;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
|
||||
for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
|
||||
UINT8 *line0 = (UINT8 *)imIn->image8[yy];
|
||||
UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss += line0[xx + 0] + line0[xx + 1] +
|
||||
line1[xx + 0] + line1[xx + 1];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss += line0[xx + 0] + line1[xx + 0];
|
||||
}
|
||||
}
|
||||
if (yscale & 0x01) {
|
||||
UINT8 *line = (UINT8 *)imIn->image8[yy];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss += line[xx + 0] + line[xx + 1];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
|
@ -55,36 +53,34 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
if (imIn->bands == 2) {
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
UINT32 v;
|
||||
UINT32 ss0 = amend, ss3 = amend;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
|
||||
for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
|
||||
UINT8 *line0 = (UINT8 *)imIn->image[yy];
|
||||
UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss0 += line0[xx*4 + 0] + line0[xx*4 + 4] +
|
||||
line1[xx*4 + 0] + line1[xx*4 + 4];
|
||||
ss3 += line0[xx*4 + 3] + line0[xx*4 + 7] +
|
||||
line1[xx*4 + 3] + line1[xx*4 + 7];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss0 += line0[xx*4 + 0] + line1[xx*4 + 0];
|
||||
ss3 += line0[xx*4 + 3] + line1[xx*4 + 3];
|
||||
}
|
||||
}
|
||||
if (yscale & 0x01) {
|
||||
UINT8 *line = (UINT8 *)imIn->image[yy];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss0 += line[xx*4 + 0] + line[xx*4 + 4];
|
||||
ss3 += line[xx*4 + 3] + line[xx*4 + 7];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss0 += line[xx*4 + 0];
|
||||
ss3 += line[xx*4 + 3];
|
||||
}
|
||||
|
@ -95,14 +91,14 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
} else if (imIn->bands == 3) {
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
UINT32 v;
|
||||
UINT32 ss0 = amend, ss1 = amend, ss2 = amend;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
|
||||
for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
|
||||
UINT8 *line0 = (UINT8 *)imIn->image[yy];
|
||||
UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss0 += line0[xx*4 + 0] + line0[xx*4 + 4] +
|
||||
line1[xx*4 + 0] + line1[xx*4 + 4];
|
||||
ss1 += line0[xx*4 + 1] + line0[xx*4 + 5] +
|
||||
|
@ -111,7 +107,6 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
line1[xx*4 + 2] + line1[xx*4 + 6];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss0 += line0[xx*4 + 0] + line1[xx*4 + 0];
|
||||
ss1 += line0[xx*4 + 1] + line1[xx*4 + 1];
|
||||
ss2 += line0[xx*4 + 2] + line1[xx*4 + 2];
|
||||
|
@ -119,14 +114,12 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
}
|
||||
if (yscale & 0x01) {
|
||||
UINT8 *line = (UINT8 *)imIn->image[yy];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss0 += line[xx*4 + 0] + line[xx*4 + 4];
|
||||
ss1 += line[xx*4 + 1] + line[xx*4 + 5];
|
||||
ss2 += line[xx*4 + 2] + line[xx*4 + 6];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss0 += line[xx*4 + 0];
|
||||
ss1 += line[xx*4 + 1];
|
||||
ss2 += line[xx*4 + 2];
|
||||
|
@ -138,14 +131,14 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
} else { // bands == 4
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
UINT32 v;
|
||||
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
|
||||
for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
|
||||
UINT8 *line0 = (UINT8 *)imIn->image[yy];
|
||||
UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss0 += line0[xx*4 + 0] + line0[xx*4 + 4] +
|
||||
line1[xx*4 + 0] + line1[xx*4 + 4];
|
||||
ss1 += line0[xx*4 + 1] + line0[xx*4 + 5] +
|
||||
|
@ -156,7 +149,6 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
line1[xx*4 + 3] + line1[xx*4 + 7];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss0 += line0[xx*4 + 0] + line1[xx*4 + 0];
|
||||
ss1 += line0[xx*4 + 1] + line1[xx*4 + 1];
|
||||
ss2 += line0[xx*4 + 2] + line1[xx*4 + 2];
|
||||
|
@ -165,15 +157,13 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
}
|
||||
if (yscale & 0x01) {
|
||||
UINT8 *line = (UINT8 *)imIn->image[yy];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss0 += line[xx*4 + 0] + line[xx*4 + 4];
|
||||
ss1 += line[xx*4 + 1] + line[xx*4 + 5];
|
||||
ss2 += line[xx*4 + 2] + line[xx*4 + 6];
|
||||
ss3 += line[xx*4 + 3] + line[xx*4 + 7];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss0 += line[xx*4 + 0];
|
||||
ss1 += line[xx*4 + 1];
|
||||
ss2 += line[xx*4 + 2];
|
||||
|
@ -1025,74 +1015,77 @@ ImagingReduce5x5(Imaging imOut, Imaging imIn)
|
|||
|
||||
|
||||
void
|
||||
ImagingReduceCorners(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
||||
ImagingReduceCorners(Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale)
|
||||
{
|
||||
/* Fill the last row and the last column for any xscale and yscale.
|
||||
*/
|
||||
int x, y, xx, yy;
|
||||
|
||||
if (imIn->image8) {
|
||||
if (imIn->xsize % xscale) {
|
||||
int scale = (imIn->xsize % xscale) * yscale;
|
||||
if (box[2] % xscale) {
|
||||
int scale = (box[2] % xscale) * yscale;
|
||||
UINT32 multiplier = division_UINT32(scale, 8);
|
||||
UINT32 amend = scale / 2;
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
UINT32 ss = amend;
|
||||
x = imIn->xsize / xscale;
|
||||
x = box[2] / xscale;
|
||||
|
||||
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
|
||||
for (yy = yy_from; yy < yy_from + yscale; yy++) {
|
||||
UINT8 *line = (UINT8 *)imIn->image8[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
imOut->image8[y][x] = (ss * multiplier) >> 24;
|
||||
}
|
||||
}
|
||||
if (imIn->ysize % yscale) {
|
||||
int scale = xscale * (imIn->ysize % yscale);
|
||||
if (box[3] % yscale) {
|
||||
int scale = xscale * (box[3] % yscale);
|
||||
UINT32 multiplier = division_UINT32(scale, 8);
|
||||
UINT32 amend = scale / 2;
|
||||
y = imIn->ysize / yscale;
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
y = box[3] / yscale;
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
UINT32 ss = amend;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
UINT8 *line = (UINT8 *)imIn->image8[yy];
|
||||
for (xx = x*xscale; xx < x*xscale + xscale; xx++) {
|
||||
for (xx = xx_from; xx < xx_from + xscale; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
imOut->image8[y][x] = (ss * multiplier) >> 24;
|
||||
}
|
||||
}
|
||||
if (imIn->xsize % xscale && imIn->ysize % yscale) {
|
||||
int scale = (imIn->xsize % xscale) * (imIn->ysize % yscale);
|
||||
if (box[2] % xscale && box[3] % yscale) {
|
||||
int scale = (box[2] % xscale) * (box[3] % yscale);
|
||||
UINT32 multiplier = division_UINT32(scale, 8);
|
||||
UINT32 amend = scale / 2;
|
||||
UINT32 ss = amend;
|
||||
x = imIn->xsize / xscale;
|
||||
y = imIn->ysize / yscale;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
x = box[2] / xscale;
|
||||
y = box[3] / yscale;
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
UINT8 *line = (UINT8 *)imIn->image8[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
imOut->image8[y][x] = (ss * multiplier) >> 24;
|
||||
}
|
||||
} else {
|
||||
if (imIn->xsize % xscale) {
|
||||
int scale = (imIn->xsize % xscale) * yscale;
|
||||
if (box[2] % xscale) {
|
||||
int scale = (box[2] % xscale) * yscale;
|
||||
UINT32 multiplier = division_UINT32(scale, 8);
|
||||
UINT32 amend = scale / 2;
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
UINT32 v;
|
||||
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
|
||||
x = imIn->xsize / xscale;
|
||||
x = box[2] / xscale;
|
||||
|
||||
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
|
||||
for (yy = yy_from; yy < yy_from + yscale; yy++) {
|
||||
UINT8 *line = (UINT8 *)imIn->image[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss0 += line[xx*4 + 0];
|
||||
ss1 += line[xx*4 + 1];
|
||||
ss2 += line[xx*4 + 2];
|
||||
|
@ -1105,17 +1098,18 @@ ImagingReduceCorners(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
}
|
||||
if (imIn->ysize % yscale) {
|
||||
int scale = xscale * (imIn->ysize % yscale);
|
||||
if (box[3] % yscale) {
|
||||
int scale = xscale * (box[3] % yscale);
|
||||
UINT32 multiplier = division_UINT32(scale, 8);
|
||||
UINT32 amend = scale / 2;
|
||||
y = imIn->ysize / yscale;
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
y = box[3] / yscale;
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
UINT32 v;
|
||||
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
UINT8 *line = (UINT8 *)imIn->image[yy];
|
||||
for (xx = x*xscale; xx < x*xscale + xscale; xx++) {
|
||||
for (xx = xx_from; xx < xx_from + xscale; xx++) {
|
||||
ss0 += line[xx*4 + 0];
|
||||
ss1 += line[xx*4 + 1];
|
||||
ss2 += line[xx*4 + 2];
|
||||
|
@ -1128,17 +1122,17 @@ ImagingReduceCorners(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
}
|
||||
if (imIn->xsize % xscale && imIn->ysize % yscale) {
|
||||
int scale = (imIn->xsize % xscale) * (imIn->ysize % yscale);
|
||||
if (box[2] % xscale && box[3] % yscale) {
|
||||
int scale = (box[2] % xscale) * (box[3] % yscale);
|
||||
UINT32 multiplier = division_UINT32(scale, 8);
|
||||
UINT32 amend = scale / 2;
|
||||
UINT32 v;
|
||||
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
|
||||
x = imIn->xsize / xscale;
|
||||
y = imIn->ysize / yscale;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
x = box[2] / xscale;
|
||||
y = box[3] / yscale;
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
UINT8 *line = (UINT8 *)imIn->image[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss0 += line[xx*4 + 0];
|
||||
ss1 += line[xx*4 + 1];
|
||||
ss2 += line[xx*4 + 2];
|
||||
|
@ -1155,39 +1149,37 @@ ImagingReduceCorners(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
|
||||
|
||||
void
|
||||
ImagingReduceNxN_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
||||
ImagingReduceNxN_32bpc(Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale)
|
||||
{
|
||||
/* The most general implementation for any xscale and yscale
|
||||
*/
|
||||
int x, y, xx, yy, xi;
|
||||
int x, y, xx, yy;
|
||||
double multiplier = 1.0 / (yscale * xscale);
|
||||
|
||||
switch(imIn->type) {
|
||||
case IMAGING_TYPE_INT32:
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
double ss = 0;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
|
||||
for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
|
||||
INT32 *line0 = (INT32 *)imIn->image32[yy];
|
||||
INT32 *line1 = (INT32 *)imIn->image32[yy + 1];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss += line0[xx + 0] + line0[xx + 1] +
|
||||
line1[xx + 0] + line1[xx + 1];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss += line0[xx + 0] + line1[xx + 0];
|
||||
}
|
||||
}
|
||||
if (yscale & 0x01) {
|
||||
INT32 *line = (INT32 *)imIn->image32[yy];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss += line[xx + 0] + line[xx + 1];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
|
@ -1197,30 +1189,28 @@ ImagingReduceNxN_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
break;
|
||||
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
double ss = 0;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
|
||||
for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
|
||||
FLOAT32 *line0 = (FLOAT32 *)imIn->image32[yy];
|
||||
FLOAT32 *line1 = (FLOAT32 *)imIn->image32[yy + 1];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss += line0[xx + 0] + line0[xx + 1] +
|
||||
line1[xx + 0] + line1[xx + 1];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss += line0[xx + 0] + line1[xx + 0];
|
||||
}
|
||||
}
|
||||
if (yscale & 0x01) {
|
||||
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
|
||||
for (xi = 0; xi < xscale - 1; xi += 2) {
|
||||
xx = x*xscale + xi;
|
||||
for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
|
||||
ss += line[xx + 0] + line[xx + 1];
|
||||
}
|
||||
if (xscale & 0x01) {
|
||||
xx = x*xscale + xi;
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
|
@ -1233,7 +1223,7 @@ ImagingReduceNxN_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
|
||||
|
||||
void
|
||||
ImagingReduceCorners_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
||||
ImagingReduceCorners_32bpc(Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale)
|
||||
{
|
||||
/* Fill the last row and the last column for any xscale and yscale.
|
||||
*/
|
||||
|
@ -1241,42 +1231,44 @@ ImagingReduceCorners_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
|
||||
switch(imIn->type) {
|
||||
case IMAGING_TYPE_INT32:
|
||||
if (imIn->xsize % xscale) {
|
||||
double multiplier = 1.0 / ((imIn->xsize % xscale) * yscale);
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
if (box[2] % xscale) {
|
||||
double multiplier = 1.0 / ((box[2] % xscale) * yscale);
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
double ss = 0;
|
||||
x = imIn->xsize / xscale;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
|
||||
x = box[2] / xscale;
|
||||
for (yy = yy_from; yy < yy_from + yscale; yy++) {
|
||||
INT32 *line = (INT32 *)imIn->image32[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
|
||||
}
|
||||
}
|
||||
if (imIn->ysize % yscale) {
|
||||
double multiplier = 1.0 / (xscale * (imIn->ysize % yscale));
|
||||
y = imIn->ysize / yscale;
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
if (box[3] % yscale) {
|
||||
double multiplier = 1.0 / (xscale * (box[3] % yscale));
|
||||
y = box[3] / yscale;
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
double ss = 0;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
INT32 *line = (INT32 *)imIn->image32[yy];
|
||||
for (xx = x*xscale; xx < x*xscale + xscale; xx++) {
|
||||
for (xx = xx_from; xx < xx_from + xscale; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
|
||||
}
|
||||
}
|
||||
if (imIn->xsize % xscale && imIn->ysize % yscale) {
|
||||
double multiplier = 1.0 / ((imIn->xsize % xscale) * (imIn->ysize % yscale));
|
||||
if (box[2] % xscale && box[3] % yscale) {
|
||||
double multiplier = 1.0 / ((box[2] % xscale) * (box[3] % yscale));
|
||||
double ss = 0;
|
||||
x = imIn->xsize / xscale;
|
||||
y = imIn->ysize / yscale;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
x = box[2] / xscale;
|
||||
y = box[3] / yscale;
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
INT32 *line = (INT32 *)imIn->image32[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
|
@ -1285,42 +1277,44 @@ ImagingReduceCorners_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
break;
|
||||
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
if (imIn->xsize % xscale) {
|
||||
double multiplier = 1.0 / ((imIn->xsize % xscale) * yscale);
|
||||
for (y = 0; y < imIn->ysize / yscale; y++) {
|
||||
if (box[2] % xscale) {
|
||||
double multiplier = 1.0 / ((box[2] % xscale) * yscale);
|
||||
for (y = 0; y < box[3] / yscale; y++) {
|
||||
int yy_from = box[1] + y*yscale;
|
||||
double ss = 0;
|
||||
x = imIn->xsize / xscale;
|
||||
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
|
||||
x = box[2] / xscale;
|
||||
for (yy = yy_from; yy < yy_from + yscale; yy++) {
|
||||
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
|
||||
}
|
||||
}
|
||||
if (imIn->ysize % yscale) {
|
||||
double multiplier = 1.0 / (xscale * (imIn->ysize % yscale));
|
||||
y = imIn->ysize / yscale;
|
||||
for (x = 0; x < imIn->xsize / xscale; x++) {
|
||||
if (box[3] % yscale) {
|
||||
double multiplier = 1.0 / (xscale * (box[3] % yscale));
|
||||
y = box[3] / yscale;
|
||||
for (x = 0; x < box[2] / xscale; x++) {
|
||||
int xx_from = box[0] + x*xscale;
|
||||
double ss = 0;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
|
||||
for (xx = x*xscale; xx < x*xscale + xscale; xx++) {
|
||||
for (xx = xx_from; xx < xx_from + xscale; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
|
||||
}
|
||||
}
|
||||
if (imIn->xsize % xscale && imIn->ysize % yscale) {
|
||||
double multiplier = 1.0 / ((imIn->xsize % xscale) * (imIn->ysize % yscale));
|
||||
if (box[2] % xscale && box[3] % yscale) {
|
||||
double multiplier = 1.0 / ((box[2] % xscale) * (box[3] % yscale));
|
||||
double ss = 0;
|
||||
x = imIn->xsize / xscale;
|
||||
y = imIn->ysize / yscale;
|
||||
for (yy = y*yscale; yy < imIn->ysize; yy++) {
|
||||
x = box[2] / xscale;
|
||||
y = box[3] / yscale;
|
||||
for (yy = box[1] + y*yscale; yy < box[1] + box[3]; yy++) {
|
||||
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
|
||||
for (xx = x*xscale; xx < imIn->xsize; xx++) {
|
||||
for (xx = box[0] + x*xscale; xx < box[0] + box[2]; xx++) {
|
||||
ss += line[xx + 0];
|
||||
}
|
||||
}
|
||||
|
@ -1332,7 +1326,7 @@ ImagingReduceCorners_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
|
|||
|
||||
|
||||
Imaging
|
||||
ImagingReduce(Imaging imIn, int xscale, int yscale)
|
||||
ImagingReduce(Imaging imIn, int xscale, int yscale, int box[4])
|
||||
{
|
||||
ImagingSectionCookie cookie;
|
||||
Imaging imOut = NULL;
|
||||
|
@ -1344,8 +1338,8 @@ ImagingReduce(Imaging imIn, int xscale, int yscale)
|
|||
return (Imaging) ImagingError_ModeError();
|
||||
|
||||
imOut = ImagingNewDirty(imIn->mode,
|
||||
(imIn->xsize + xscale - 1) / xscale,
|
||||
(imIn->ysize + yscale - 1) / yscale);
|
||||
(box[2] + xscale - 1) / xscale,
|
||||
(box[3] + yscale - 1) / yscale);
|
||||
if ( ! imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1354,44 +1348,44 @@ ImagingReduce(Imaging imIn, int xscale, int yscale)
|
|||
|
||||
switch(imIn->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
if (xscale == 1) {
|
||||
if (yscale == 2) {
|
||||
ImagingReduce1x2(imOut, imIn);
|
||||
} else if (yscale == 3) {
|
||||
ImagingReduce1x3(imOut, imIn);
|
||||
} else {
|
||||
ImagingReduce1xN(imOut, imIn, yscale);
|
||||
}
|
||||
} else if (yscale == 1) {
|
||||
if (xscale == 2) {
|
||||
ImagingReduce2x1(imOut, imIn);
|
||||
} else if (xscale == 3) {
|
||||
ImagingReduce3x1(imOut, imIn);
|
||||
} else {
|
||||
ImagingReduceNx1(imOut, imIn, xscale);
|
||||
}
|
||||
} else if (xscale == yscale && xscale <= 5) {
|
||||
if (xscale == 2) {
|
||||
ImagingReduce2x2(imOut, imIn);
|
||||
} else if (xscale == 3) {
|
||||
ImagingReduce3x3(imOut, imIn);
|
||||
} else if (xscale == 4) {
|
||||
ImagingReduce4x4(imOut, imIn);
|
||||
} else {
|
||||
ImagingReduce5x5(imOut, imIn);
|
||||
}
|
||||
} else {
|
||||
ImagingReduceNxN(imOut, imIn, xscale, yscale);
|
||||
}
|
||||
// if (xscale == 1) {
|
||||
// if (yscale == 2) {
|
||||
// ImagingReduce1x2(imOut, imIn);
|
||||
// } else if (yscale == 3) {
|
||||
// ImagingReduce1x3(imOut, imIn);
|
||||
// } else {
|
||||
// ImagingReduce1xN(imOut, imIn, yscale);
|
||||
// }
|
||||
// } else if (yscale == 1) {
|
||||
// if (xscale == 2) {
|
||||
// ImagingReduce2x1(imOut, imIn);
|
||||
// } else if (xscale == 3) {
|
||||
// ImagingReduce3x1(imOut, imIn);
|
||||
// } else {
|
||||
// ImagingReduceNx1(imOut, imIn, xscale);
|
||||
// }
|
||||
// } else if (xscale == yscale && xscale <= 5) {
|
||||
// if (xscale == 2) {
|
||||
// ImagingReduce2x2(imOut, imIn);
|
||||
// } else if (xscale == 3) {
|
||||
// ImagingReduce3x3(imOut, imIn);
|
||||
// } else if (xscale == 4) {
|
||||
// ImagingReduce4x4(imOut, imIn);
|
||||
// } else {
|
||||
// ImagingReduce5x5(imOut, imIn);
|
||||
// }
|
||||
// } else {
|
||||
ImagingReduceNxN(imOut, imIn, box, xscale, yscale);
|
||||
// }
|
||||
|
||||
ImagingReduceCorners(imOut, imIn, xscale, yscale);
|
||||
ImagingReduceCorners(imOut, imIn, box, xscale, yscale);
|
||||
break;
|
||||
|
||||
case IMAGING_TYPE_INT32:
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
ImagingReduceNxN_32bpc(imOut, imIn, xscale, yscale);
|
||||
ImagingReduceNxN_32bpc(imOut, imIn, box, xscale, yscale);
|
||||
|
||||
ImagingReduceCorners_32bpc(imOut, imIn, xscale, yscale);
|
||||
ImagingReduceCorners_32bpc(imOut, imIn, box, xscale, yscale);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user