L mode support

This commit is contained in:
Alexander 2019-12-01 19:57:15 +03:00
parent a241f1ed8e
commit 008c1c88e2
2 changed files with 184 additions and 12 deletions

View File

@ -79,12 +79,17 @@ class TestImageReduce(PillowTestCase):
last_row = im.resize((area_size[0], 1), Image.BOX, last_row_box) last_row = im.resize((area_size[0], 1), Image.BOX, last_row_box)
reference.paste(last_row, (0, area_size[1])) reference.paste(last_row, (0, area_size[1]))
if area_size[0] < reduced.size[0]: if area_size[0] < reduced.size[0] and area_size[1] < reduced.size[1]:
last_pixel_box = (area_box[2], area_box[3], im.size[0], im.size[1]) last_pixel_box = (area_box[2], area_box[3], im.size[0], im.size[1])
last_pixel = im.resize((1, 1), Image.BOX, last_pixel_box) last_pixel = im.resize((1, 1), Image.BOX, last_pixel_box)
reference.paste(last_pixel, area_size) reference.paste(last_pixel, area_size)
self.assert_compare_images(reduced, reference, average_diff, max_diff) try:
self.assert_compare_images(reduced, reference, average_diff, max_diff)
except Exception:
reduced.save("_out.{}.{}x{}.reduced.png".format(im.mode, *factor))
reference.save("_out.{}.{}x{}.reference.png".format(im.mode, *factor))
raise
def assert_compare_images(self, a, b, max_average_diff, max_diff=255): def assert_compare_images(self, a, b, max_average_diff, max_diff=255):
self.assertEqual( self.assertEqual(
@ -114,6 +119,11 @@ class TestImageReduce(PillowTestCase):
.format(last_diff, max_diff, band), .format(last_diff, max_diff, band),
) )
def test_mode_L(self):
im = self.get_image("L")
for factor in self.remarkable_factors:
self.compare_reduce_with_reference(im, factor)
def test_mode_LA(self): def test_mode_LA(self):
im = self.get_image("LA") im = self.get_image("LA")
for factor in self.remarkable_factors: for factor in self.remarkable_factors:
@ -124,6 +134,11 @@ class TestImageReduce(PillowTestCase):
for factor in self.remarkable_factors: for factor in self.remarkable_factors:
self.compare_reduce_with_reference(im, factor) self.compare_reduce_with_reference(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)
def test_mode_RGB(self): def test_mode_RGB(self):
im = self.get_image("RGB") im = self.get_image("RGB")
for factor in self.remarkable_factors: for factor in self.remarkable_factors:
@ -139,6 +154,11 @@ class TestImageReduce(PillowTestCase):
for factor in self.remarkable_factors: for factor in self.remarkable_factors:
self.compare_reduce_with_reference(im, factor) self.compare_reduce_with_reference(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)
def test_mode_CMYK(self): def test_mode_CMYK(self):
im = self.get_image("CMYK") im = self.get_image("CMYK")
for factor in self.remarkable_factors: for factor in self.remarkable_factors:

View File

@ -24,7 +24,36 @@ ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
UINT32 amend = yscale * xscale / 2; UINT32 amend = yscale * xscale / 2;
if (imIn->image8) { if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss = amend;
for (yy = y*yscale; yy < y*yscale + 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;
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;
ss += line[xx + 0] + line[xx + 1];
}
if (xscale & 0x01) {
xx = x*xscale + xi;
ss += line[xx + 0];
}
}
imOut->image8[y][x] = (ss * multiplier) >> 24;
}
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
@ -183,7 +212,21 @@ ImagingReduce1xN(Imaging imOut, Imaging imIn, int yscale)
UINT32 amend = yscale * xscale / 2; UINT32 amend = yscale * xscale / 2;
if (imIn->image8) { if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss = amend;
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
UINT8 *line0 = (UINT8 *)imIn->image8[yy];
UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
ss += line0[x + 0] + line1[x + 0];
}
if (yscale & 0x01) {
UINT8 *line = (UINT8 *)imIn->image8[yy];
ss += line[x + 0];
}
imOut->image8[y][x] = (ss * multiplier) >> 24;
}
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
@ -279,7 +322,21 @@ ImagingReduceNx1(Imaging imOut, Imaging imIn, int xscale)
UINT32 amend = yscale * xscale / 2; UINT32 amend = yscale * xscale / 2;
if (imIn->image8) { if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss = amend;
UINT8 *line = (UINT8 *)imIn->image8[y];
for (xi = 0; xi < xscale - 1; xi += 2) {
xx = x*xscale + xi;
ss += line[xx + 0] + line[xx + 1];
}
if (xscale & 0x01) {
xx = x*xscale + xi;
ss += line[xx + 0];
}
imOut->image8[y][x] = (ss * multiplier) >> 24;
}
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
@ -373,7 +430,16 @@ ImagingReduce2x2(Imaging imOut, Imaging imIn)
UINT32 amend = yscale * xscale / 2; UINT32 amend = yscale * xscale / 2;
if (imIn->image8) { if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image8[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image8[y*yscale + 1];
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss;
ss = line0[x*xscale + 0] + line0[x*xscale + 1] +
line1[x*xscale + 0] + line1[x*xscale + 1];
imOut->image8[y][x] = (ss + amend) >> 2;
}
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
@ -444,7 +510,18 @@ ImagingReduce3x3(Imaging imOut, Imaging imIn)
UINT32 amend = yscale * xscale / 2; UINT32 amend = yscale * xscale / 2;
if (imIn->image8) { if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image8[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image8[y*yscale + 1];
UINT8 *line2 = (UINT8 *)imIn->image8[y*yscale + 2];
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss;
ss = line0[x*xscale + 0] + line0[x*xscale + 1] + line0[x*xscale + 2] +
line1[x*xscale + 0] + line1[x*xscale + 1] + line1[x*xscale + 2] +
line2[x*xscale + 0] + line2[x*xscale + 1] + line2[x*xscale + 2];
imOut->image8[y][x] = ((ss + amend) * multiplier) >> 24;
}
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
@ -527,7 +604,20 @@ ImagingReduce4x4(Imaging imOut, Imaging imIn)
UINT32 amend = yscale * xscale / 2; UINT32 amend = yscale * xscale / 2;
if (imIn->image8) { if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image8[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image8[y*yscale + 1];
UINT8 *line2 = (UINT8 *)imIn->image8[y*yscale + 2];
UINT8 *line3 = (UINT8 *)imIn->image8[y*yscale + 3];
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss;
ss = line0[x*xscale + 0] + line0[x*xscale + 1] + line0[x*xscale + 2] + line0[x*xscale + 3] +
line1[x*xscale + 0] + line1[x*xscale + 1] + line1[x*xscale + 2] + line1[x*xscale + 3] +
line2[x*xscale + 0] + line2[x*xscale + 1] + line2[x*xscale + 2] + line2[x*xscale + 3] +
line3[x*xscale + 0] + line3[x*xscale + 1] + line3[x*xscale + 2] + line3[x*xscale + 3];
imOut->image8[y][x] = (ss + amend) >> 4;
}
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
@ -619,7 +709,22 @@ ImagingReduce5x5(Imaging imOut, Imaging imIn)
UINT32 amend = yscale * xscale / 2; UINT32 amend = yscale * xscale / 2;
if (imIn->image8) { if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image8[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image8[y*yscale + 1];
UINT8 *line2 = (UINT8 *)imIn->image8[y*yscale + 2];
UINT8 *line3 = (UINT8 *)imIn->image8[y*yscale + 3];
UINT8 *line4 = (UINT8 *)imIn->image8[y*yscale + 4];
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss;
ss = line0[x*xscale + 0] + line0[x*xscale + 1] + line0[x*xscale + 2] + line0[x*xscale + 3] + line0[x*xscale + 4] +
line1[x*xscale + 0] + line1[x*xscale + 1] + line1[x*xscale + 2] + line1[x*xscale + 3] + line1[x*xscale + 4] +
line2[x*xscale + 0] + line2[x*xscale + 1] + line2[x*xscale + 2] + line2[x*xscale + 3] + line2[x*xscale + 4] +
line3[x*xscale + 0] + line3[x*xscale + 1] + line3[x*xscale + 2] + line3[x*xscale + 3] + line3[x*xscale + 4] +
line4[x*xscale + 0] + line4[x*xscale + 1] + line4[x*xscale + 2] + line4[x*xscale + 3] + line4[x*xscale + 4];
imOut->image8[y][x] = ((ss + amend) * multiplier) >> 24;
}
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
@ -720,7 +825,54 @@ ImagingReduceCorners(Imaging imOut, Imaging imIn, int xscale, int yscale)
int x, y, xx, yy; int x, y, xx, yy;
if (imIn->image8) { if (imIn->image8) {
if (imIn->xsize % xscale) {
int scale = (imIn->xsize % xscale) * yscale;
UINT32 multiplier = division_UINT32(scale, 8);
UINT32 amend = scale / 2;
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT32 ss = amend;
x = imIn->xsize / xscale;
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
UINT8 *line = (UINT8 *)imIn->image8[yy];
for (xx = x*xscale; xx < imIn->xsize; xx++) {
ss += line[xx + 0];
}
}
imOut->image8[y][x] = (ss * multiplier) >> 24;
}
}
if (imIn->ysize % yscale) {
int scale = xscale * (imIn->ysize % yscale);
UINT32 multiplier = division_UINT32(scale, 8);
UINT32 amend = scale / 2;
y = imIn->ysize / yscale;
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss = amend;
for (yy = y*yscale; yy < imIn->ysize; yy++) {
UINT8 *line = (UINT8 *)imIn->image8[yy];
for (xx = x*xscale; xx < x*xscale + 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);
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++) {
UINT8 *line = (UINT8 *)imIn->image8[yy];
for (xx = x*xscale; xx < imIn->xsize; xx++) {
ss += line[xx + 0];
}
}
imOut->image8[y][x] = (ss * multiplier) >> 24;
}
} else { } else {
switch(imIn->type) { switch(imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8: