Pillow/src/libImaging/Reduce.c

1402 lines
68 KiB
C
Raw Normal View History

2019-11-24 04:13:48 +03:00
#include "Imaging.h"
#include <math.h>
#define ROUND_UP(f) ((int) ((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F))
2019-11-25 04:20:31 +03:00
UINT32
division_UINT32(int divider, int result_bits)
{
UINT32 max_dividend = (1 << result_bits) * divider;
float max_int = (1 << 30) * 4.0;
return (UINT32) (max_int / max_dividend);
}
2019-11-25 23:34:52 +03:00
void
ImagingReduceNxN(Imaging imOut, Imaging imIn, int xscale, int yscale)
{
/* The most general implementation for any xscale and yscale
*/
int x, y, xx, yy, xi;
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
UINT32 amend = yscale * xscale / 2;
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
}
}
2019-11-25 23:34:52 +03:00
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss3 = amend;
for (yy = y*yscale; yy < y*yscale + 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;
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;
ss0 += line[xx*4 + 0] + line[xx*4 + 4];
ss3 += line[xx*4 + 3] + line[xx*4 + 7];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
if (xscale & 0x01) {
xx = x*xscale + xi;
ss0 += line[xx*4 + 0];
ss3 += line[xx*4 + 3];
2019-11-25 23:34:52 +03:00
}
}
2019-12-01 22:28:16 +03:00
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, 0,
0, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend;
for (yy = y*yscale; yy < y*yscale + 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;
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] +
line1[xx*4 + 1] + line1[xx*4 + 5];
ss2 += line0[xx*4 + 2] + line0[xx*4 + 6] +
line1[xx*4 + 2] + line1[xx*4 + 6];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
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];
2019-11-25 23:34:52 +03:00
}
}
2019-12-01 22:28:16 +03:00
if (yscale & 0x01) {
UINT8 *line = (UINT8 *)imIn->image[yy];
for (xi = 0; xi < xscale - 1; xi += 2) {
xx = x*xscale + xi;
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];
}
}
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
for (yy = y*yscale; yy < y*yscale + 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;
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] +
line1[xx*4 + 1] + line1[xx*4 + 5];
ss2 += line0[xx*4 + 2] + line0[xx*4 + 6] +
line1[xx*4 + 2] + line1[xx*4 + 6];
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];
ss1 += line0[xx*4 + 1] + line1[xx*4 + 1];
ss2 += line0[xx*4 + 2] + line1[xx*4 + 2];
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;
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];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
if (xscale & 0x01) {
xx = x*xscale + xi;
ss0 += line[xx*4 + 0];
ss1 += line[xx*4 + 1];
ss2 += line[xx*4 + 2];
ss3 += line[xx*4 + 3];
2019-11-25 23:34:52 +03:00
}
}
2019-12-01 22:28:16 +03:00
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-25 23:34:52 +03:00
}
}
}
}
}
void
ImagingReduce1xN(Imaging imOut, Imaging imIn, int yscale)
{
/* Optimized implementation for xscale = 1.
*/
int x, y, yy;
int xscale = 1;
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
UINT32 amend = yscale * xscale / 2;
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
}
}
2019-11-25 23:34:52 +03:00
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss3 = amend;
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
UINT8 *line0 = (UINT8 *)imIn->image[yy];
UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
ss0 += line0[x*4 + 0] + line1[x*4 + 0];
ss3 += line0[x*4 + 3] + line1[x*4 + 3];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
if (yscale & 0x01) {
UINT8 *line = (UINT8 *)imIn->image[yy];
ss0 += line[x*4 + 0];
ss3 += line[x*4 + 3];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, 0,
0, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend;
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
UINT8 *line0 = (UINT8 *)imIn->image[yy];
UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
ss0 += line0[x*4 + 0] + line1[x*4 + 0];
ss1 += line0[x*4 + 1] + line1[x*4 + 1];
ss2 += line0[x*4 + 2] + line1[x*4 + 2];
}
if (yscale & 0x01) {
UINT8 *line = (UINT8 *)imIn->image[yy];
ss0 += line[x*4 + 0];
ss1 += line[x*4 + 1];
ss2 += line[x*4 + 2];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
UINT8 *line0 = (UINT8 *)imIn->image[yy];
UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
ss0 += line0[x*4 + 0] + line1[x*4 + 0];
ss1 += line0[x*4 + 1] + line1[x*4 + 1];
ss2 += line0[x*4 + 2] + line1[x*4 + 2];
ss3 += line0[x*4 + 3] + line1[x*4 + 3];
}
if (yscale & 0x01) {
UINT8 *line = (UINT8 *)imIn->image[yy];
ss0 += line[x*4 + 0];
ss1 += line[x*4 + 1];
ss2 += line[x*4 + 2];
ss3 += line[x*4 + 3];
}
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-25 23:34:52 +03:00
}
}
}
}
}
void
ImagingReduceNx1(Imaging imOut, Imaging imIn, int xscale)
{
/* Optimized implementation for yscale = 1.
*/
int x, y, xx, xi;
int yscale = 1;
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
UINT32 amend = yscale * xscale / 2;
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
}
}
2019-11-25 23:34:52 +03:00
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line = (UINT8 *)imIn->image[y];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss3 = amend;
for (xi = 0; xi < xscale - 1; xi += 2) {
xx = x*xscale + xi;
ss0 += line[xx*4 + 0] + line[xx*4 + 4];
ss3 += line[xx*4 + 3] + line[xx*4 + 7];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
if (xscale & 0x01) {
xx = x*xscale + xi;
ss0 += line[xx*4 + 0];
ss3 += line[xx*4 + 3];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, 0,
0, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend;
for (xi = 0; xi < xscale - 1; xi += 2) {
xx = x*xscale + xi;
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];
2019-11-25 23:34:52 +03:00
}
2019-12-01 22:28:16 +03:00
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
for (xi = 0; xi < xscale - 1; xi += 2) {
xx = x*xscale + xi;
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];
ss3 += line[xx*4 + 3];
}
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-25 23:34:52 +03:00
}
}
}
}
}
void
ImagingReduce2x1(Imaging imOut, Imaging imIn)
{
/* Optimized implementation for xscale = 2 and yscale = 1.
*/
int xscale = 2, yscale = 1;
int x, y;
UINT32 ss0, ss1, ss2, ss3;
UINT32 amend = yscale * xscale / 2;
if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image8[y*yscale + 0];
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss;
ss = line0[x*xscale + 0] + line0[x*xscale + 1];
imOut->image8[y][x] = (ss + amend) >> 1;
}
}
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7];
v = MAKE_UINT32((ss0 + amend) >> 1, 0,
0, (ss3 + amend) >> 1);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6];
v = MAKE_UINT32((ss0 + amend) >> 1, (ss1 + amend) >> 1,
(ss2 + amend) >> 1, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7];
v = MAKE_UINT32((ss0 + amend) >> 1, (ss1 + amend) >> 1,
(ss2 + amend) >> 1, (ss3 + amend) >> 1);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
}
}
}
}
void
ImagingReduce1x2(Imaging imOut, Imaging imIn)
{
/* Optimized implementation for xscale = 1 and yscale = 2.
*/
int xscale = 1, yscale = 2;
int x, y;
UINT32 ss0, ss1, ss2, ss3;
UINT32 amend = yscale * xscale / 2;
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] +
line1[x*xscale + 0];
imOut->image8[y][x] = (ss + amend) >> 1;
}
}
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image[y*yscale + 1];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] +
line1[x*xscale*4 + 0];
ss3 = line0[x*xscale*4 + 3] +
line1[x*xscale*4 + 3];
v = MAKE_UINT32((ss0 + amend) >> 1, 0,
0, (ss3 + amend) >> 1);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] +
line1[x*xscale*4 + 0];
ss1 = line0[x*xscale*4 + 1] +
line1[x*xscale*4 + 1];
ss2 = line0[x*xscale*4 + 2] +
line1[x*xscale*4 + 2];
v = MAKE_UINT32((ss0 + amend) >> 1, (ss1 + amend) >> 1,
(ss2 + amend) >> 1, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] +
line1[x*xscale*4 + 0];
ss1 = line0[x*xscale*4 + 1] +
line1[x*xscale*4 + 1];
ss2 = line0[x*xscale*4 + 2] +
line1[x*xscale*4 + 2];
ss3 = line0[x*xscale*4 + 3] +
line1[x*xscale*4 + 3];
v = MAKE_UINT32((ss0 + amend) >> 1, (ss1 + amend) >> 1,
(ss2 + amend) >> 1, (ss3 + amend) >> 1);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
}
}
}
}
2019-11-24 17:40:05 +03:00
void
ImagingReduce2x2(Imaging imOut, Imaging imIn)
{
2019-11-26 03:36:58 +03:00
/* Optimized implementation for xscale = 2 and yscale = 2.
2019-11-25 23:34:52 +03:00
*/
2019-11-25 05:16:03 +03:00
int xscale = 2, yscale = 2;
2019-11-24 17:40:05 +03:00
int x, y;
2019-11-25 05:16:03 +03:00
UINT32 ss0, ss1, ss2, ss3;
UINT32 amend = yscale * xscale / 2;
2019-11-24 17:40:05 +03:00
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
}
}
2019-11-24 17:40:05 +03:00
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image[y*yscale + 1];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7];
v = MAKE_UINT32((ss0 + amend) >> 2, 0,
0, (ss3 + amend) >> 2);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6];
v = MAKE_UINT32((ss0 + amend) >> 2, (ss1 + amend) >> 2,
(ss2 + amend) >> 2, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7];
v = MAKE_UINT32((ss0 + amend) >> 2, (ss1 + amend) >> 2,
(ss2 + amend) >> 2, (ss3 + amend) >> 2);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-25 05:16:03 +03:00
}
}
}
}
}
void
ImagingReduce3x1(Imaging imOut, Imaging imIn)
{
/* Optimized implementation for xscale = 3 and yscale = 1.
*/
int xscale = 3, yscale = 1;
int x, y;
UINT32 ss0, ss1, ss2, ss3;
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
UINT32 amend = yscale * xscale / 2;
if (imIn->image8) {
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image8[y*yscale + 0];
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 ss;
ss = line0[x*xscale + 0] + line0[x*xscale + 1] + line0[x*xscale + 2];
imOut->image8[y][x] = ((ss + amend) * multiplier) >> 24;
}
}
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, 0,
0, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
}
}
}
}
void
ImagingReduce1x3(Imaging imOut, Imaging imIn)
{
/* Optimized implementation for xscale = 3 and yscale = 3.
*/
int xscale = 1, yscale = 3;
int x, y;
UINT32 ss0, ss1, ss2, ss3;
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
UINT32 amend = yscale * xscale / 2;
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] +
line1[x*xscale + 0] +
line2[x*xscale + 0];
imOut->image8[y][x] = ((ss + amend) * multiplier) >> 24;
}
}
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image[y*yscale + 1];
UINT8 *line2 = (UINT8 *)imIn->image[y*yscale + 2];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] +
line1[x*xscale*4 + 0] +
line2[x*xscale*4 + 0];
ss3 = line0[x*xscale*4 + 3] +
line1[x*xscale*4 + 3] +
line2[x*xscale*4 + 3];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, 0,
0, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] +
line1[x*xscale*4 + 0] +
line2[x*xscale*4 + 0];
ss1 = line0[x*xscale*4 + 1] +
line1[x*xscale*4 + 1] +
line2[x*xscale*4 + 1];
ss2 = line0[x*xscale*4 + 2] +
line1[x*xscale*4 + 2] +
line2[x*xscale*4 + 2];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] +
line1[x*xscale*4 + 0] +
line2[x*xscale*4 + 0];
ss1 = line0[x*xscale*4 + 1] +
line1[x*xscale*4 + 1] +
line2[x*xscale*4 + 1];
ss2 = line0[x*xscale*4 + 2] +
line1[x*xscale*4 + 2] +
line2[x*xscale*4 + 2];
ss3 = line0[x*xscale*4 + 3] +
line1[x*xscale*4 + 3] +
line2[x*xscale*4 + 3];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
}
}
}
}
2019-11-25 05:16:03 +03:00
void
ImagingReduce3x3(Imaging imOut, Imaging imIn)
{
2019-11-26 03:36:58 +03:00
/* Optimized implementation for xscale = 3 and yscale = 3.
2019-11-25 23:34:52 +03:00
*/
2019-11-25 05:16:03 +03:00
int xscale = 3, yscale = 3;
int x, y;
UINT32 ss0, ss1, ss2, ss3;
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
UINT32 amend = yscale * xscale / 2;
2019-11-24 17:40:05 +03:00
2019-11-25 05:16:03 +03:00
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
}
}
2019-11-25 05:16:03 +03:00
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image[y*yscale + 1];
UINT8 *line2 = (UINT8 *)imIn->image[y*yscale + 2];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7] + line1[x*xscale*4 + 11] +
line2[x*xscale*4 + 3] + line2[x*xscale*4 + 7] + line2[x*xscale*4 + 11];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, 0,
0, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5] + line1[x*xscale*4 + 9] +
line2[x*xscale*4 + 1] + line2[x*xscale*4 + 5] + line2[x*xscale*4 + 9];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6] + line1[x*xscale*4 + 10] +
line2[x*xscale*4 + 2] + line2[x*xscale*4 + 6] + line2[x*xscale*4 + 10];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5] + line1[x*xscale*4 + 9] +
line2[x*xscale*4 + 1] + line2[x*xscale*4 + 5] + line2[x*xscale*4 + 9];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6] + line1[x*xscale*4 + 10] +
line2[x*xscale*4 + 2] + line2[x*xscale*4 + 6] + line2[x*xscale*4 + 10];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7] + line1[x*xscale*4 + 11] +
line2[x*xscale*4 + 3] + line2[x*xscale*4 + 7] + line2[x*xscale*4 + 11];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-25 05:16:03 +03:00
}
}
}
}
}
2019-11-24 17:40:05 +03:00
2019-11-25 05:16:03 +03:00
void
ImagingReduce4x4(Imaging imOut, Imaging imIn)
{
2019-11-26 03:36:58 +03:00
/* Optimized implementation for xscale = 4 and yscale = 4.
2019-11-25 23:34:52 +03:00
*/
2019-11-25 05:16:03 +03:00
int xscale = 4, yscale = 4;
int x, y;
UINT32 ss0, ss1, ss2, ss3;
UINT32 amend = yscale * xscale / 2;
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
}
}
2019-11-25 05:16:03 +03:00
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image[y*yscale + 1];
UINT8 *line2 = (UINT8 *)imIn->image[y*yscale + 2];
UINT8 *line3 = (UINT8 *)imIn->image[y*yscale + 3];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] + line0[x*xscale*4 + 12] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] + line1[x*xscale*4 + 12] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8] + line2[x*xscale*4 + 12] +
line3[x*xscale*4 + 0] + line3[x*xscale*4 + 4] + line3[x*xscale*4 + 8] + line3[x*xscale*4 + 12];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11] + line0[x*xscale*4 + 15] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7] + line1[x*xscale*4 + 11] + line1[x*xscale*4 + 15] +
line2[x*xscale*4 + 3] + line2[x*xscale*4 + 7] + line2[x*xscale*4 + 11] + line2[x*xscale*4 + 15] +
line3[x*xscale*4 + 3] + line3[x*xscale*4 + 7] + line3[x*xscale*4 + 11] + line3[x*xscale*4 + 15];
v = MAKE_UINT32((ss0 + amend) >> 4, 0,
0, (ss3 + amend) >> 4);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] + line0[x*xscale*4 + 12] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] + line1[x*xscale*4 + 12] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8] + line2[x*xscale*4 + 12] +
line3[x*xscale*4 + 0] + line3[x*xscale*4 + 4] + line3[x*xscale*4 + 8] + line3[x*xscale*4 + 12];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9] + line0[x*xscale*4 + 13] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5] + line1[x*xscale*4 + 9] + line1[x*xscale*4 + 13] +
line2[x*xscale*4 + 1] + line2[x*xscale*4 + 5] + line2[x*xscale*4 + 9] + line2[x*xscale*4 + 13] +
line3[x*xscale*4 + 1] + line3[x*xscale*4 + 5] + line3[x*xscale*4 + 9] + line3[x*xscale*4 + 13];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10] + line0[x*xscale*4 + 14] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6] + line1[x*xscale*4 + 10] + line1[x*xscale*4 + 14] +
line2[x*xscale*4 + 2] + line2[x*xscale*4 + 6] + line2[x*xscale*4 + 10] + line2[x*xscale*4 + 14] +
line3[x*xscale*4 + 2] + line3[x*xscale*4 + 6] + line3[x*xscale*4 + 10] + line3[x*xscale*4 + 14];
v = MAKE_UINT32((ss0 + amend) >> 4, (ss1 + amend) >> 4,
(ss2 + amend) >> 4, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] + line0[x*xscale*4 + 12] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] + line1[x*xscale*4 + 12] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8] + line2[x*xscale*4 + 12] +
line3[x*xscale*4 + 0] + line3[x*xscale*4 + 4] + line3[x*xscale*4 + 8] + line3[x*xscale*4 + 12];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9] + line0[x*xscale*4 + 13] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5] + line1[x*xscale*4 + 9] + line1[x*xscale*4 + 13] +
line2[x*xscale*4 + 1] + line2[x*xscale*4 + 5] + line2[x*xscale*4 + 9] + line2[x*xscale*4 + 13] +
line3[x*xscale*4 + 1] + line3[x*xscale*4 + 5] + line3[x*xscale*4 + 9] + line3[x*xscale*4 + 13];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10] + line0[x*xscale*4 + 14] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6] + line1[x*xscale*4 + 10] + line1[x*xscale*4 + 14] +
line2[x*xscale*4 + 2] + line2[x*xscale*4 + 6] + line2[x*xscale*4 + 10] + line2[x*xscale*4 + 14] +
line3[x*xscale*4 + 2] + line3[x*xscale*4 + 6] + line3[x*xscale*4 + 10] + line3[x*xscale*4 + 14];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11] + line0[x*xscale*4 + 15] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7] + line1[x*xscale*4 + 11] + line1[x*xscale*4 + 15] +
line2[x*xscale*4 + 3] + line2[x*xscale*4 + 7] + line2[x*xscale*4 + 11] + line2[x*xscale*4 + 15] +
line3[x*xscale*4 + 3] + line3[x*xscale*4 + 7] + line3[x*xscale*4 + 11] + line3[x*xscale*4 + 15];
v = MAKE_UINT32((ss0 + amend) >> 4, (ss1 + amend) >> 4,
(ss2 + amend) >> 4, (ss3 + amend) >> 4);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-25 05:16:03 +03:00
}
}
}
}
}
2019-11-25 23:34:52 +03:00
2019-11-25 05:16:03 +03:00
void
ImagingReduce5x5(Imaging imOut, Imaging imIn)
{
2019-11-25 23:34:52 +03:00
/* Fast special case for xscale = 5 and yscale = 5.
*/
2019-11-25 05:16:03 +03:00
int xscale = 5, yscale = 5;
int x, y;
UINT32 ss0, ss1, ss2, ss3;
UINT32 multiplier = division_UINT32(yscale * xscale, 8);
UINT32 amend = yscale * xscale / 2;
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
}
}
2019-11-25 05:16:03 +03:00
} else {
2019-12-01 22:28:16 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
UINT8 *line0 = (UINT8 *)imIn->image[y*yscale + 0];
UINT8 *line1 = (UINT8 *)imIn->image[y*yscale + 1];
UINT8 *line2 = (UINT8 *)imIn->image[y*yscale + 2];
UINT8 *line3 = (UINT8 *)imIn->image[y*yscale + 3];
UINT8 *line4 = (UINT8 *)imIn->image[y*yscale + 4];
if (imIn->bands == 2) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] + line0[x*xscale*4 + 12] + line0[x*xscale*4 + 16] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] + line1[x*xscale*4 + 12] + line1[x*xscale*4 + 16] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8] + line2[x*xscale*4 + 12] + line2[x*xscale*4 + 16] +
line3[x*xscale*4 + 0] + line3[x*xscale*4 + 4] + line3[x*xscale*4 + 8] + line3[x*xscale*4 + 12] + line3[x*xscale*4 + 16] +
line4[x*xscale*4 + 0] + line4[x*xscale*4 + 4] + line4[x*xscale*4 + 8] + line4[x*xscale*4 + 12] + line4[x*xscale*4 + 16];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11] + line0[x*xscale*4 + 15] + line0[x*xscale*4 + 19] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7] + line1[x*xscale*4 + 11] + line1[x*xscale*4 + 15] + line1[x*xscale*4 + 19] +
line2[x*xscale*4 + 3] + line2[x*xscale*4 + 7] + line2[x*xscale*4 + 11] + line2[x*xscale*4 + 15] + line2[x*xscale*4 + 19] +
line3[x*xscale*4 + 3] + line3[x*xscale*4 + 7] + line3[x*xscale*4 + 11] + line3[x*xscale*4 + 15] + line3[x*xscale*4 + 19] +
line4[x*xscale*4 + 3] + line4[x*xscale*4 + 7] + line4[x*xscale*4 + 11] + line4[x*xscale*4 + 15] + line4[x*xscale*4 + 19];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, 0,
0, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else if (imIn->bands == 3) {
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] + line0[x*xscale*4 + 12] + line0[x*xscale*4 + 16] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] + line1[x*xscale*4 + 12] + line1[x*xscale*4 + 16] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8] + line2[x*xscale*4 + 12] + line2[x*xscale*4 + 16] +
line3[x*xscale*4 + 0] + line3[x*xscale*4 + 4] + line3[x*xscale*4 + 8] + line3[x*xscale*4 + 12] + line3[x*xscale*4 + 16] +
line4[x*xscale*4 + 0] + line4[x*xscale*4 + 4] + line4[x*xscale*4 + 8] + line4[x*xscale*4 + 12] + line4[x*xscale*4 + 16];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9] + line0[x*xscale*4 + 13] + line0[x*xscale*4 + 17] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5] + line1[x*xscale*4 + 9] + line1[x*xscale*4 + 13] + line1[x*xscale*4 + 17] +
line2[x*xscale*4 + 1] + line2[x*xscale*4 + 5] + line2[x*xscale*4 + 9] + line2[x*xscale*4 + 13] + line2[x*xscale*4 + 17] +
line3[x*xscale*4 + 1] + line3[x*xscale*4 + 5] + line3[x*xscale*4 + 9] + line3[x*xscale*4 + 13] + line3[x*xscale*4 + 17] +
line4[x*xscale*4 + 1] + line4[x*xscale*4 + 5] + line4[x*xscale*4 + 9] + line4[x*xscale*4 + 13] + line4[x*xscale*4 + 17];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10] + line0[x*xscale*4 + 14] + line0[x*xscale*4 + 18] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6] + line1[x*xscale*4 + 10] + line1[x*xscale*4 + 14] + line1[x*xscale*4 + 18] +
line2[x*xscale*4 + 2] + line2[x*xscale*4 + 6] + line2[x*xscale*4 + 10] + line2[x*xscale*4 + 14] + line2[x*xscale*4 + 18] +
line3[x*xscale*4 + 2] + line3[x*xscale*4 + 6] + line3[x*xscale*4 + 10] + line3[x*xscale*4 + 14] + line3[x*xscale*4 + 18] +
line4[x*xscale*4 + 2] + line4[x*xscale*4 + 6] + line4[x*xscale*4 + 10] + line4[x*xscale*4 + 14] + line4[x*xscale*4 + 18];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, 0);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
} else { // bands == 4
for (x = 0; x < imIn->xsize / xscale; x++) {
UINT32 v;
ss0 = line0[x*xscale*4 + 0] + line0[x*xscale*4 + 4] + line0[x*xscale*4 + 8] + line0[x*xscale*4 + 12] + line0[x*xscale*4 + 16] +
line1[x*xscale*4 + 0] + line1[x*xscale*4 + 4] + line1[x*xscale*4 + 8] + line1[x*xscale*4 + 12] + line1[x*xscale*4 + 16] +
line2[x*xscale*4 + 0] + line2[x*xscale*4 + 4] + line2[x*xscale*4 + 8] + line2[x*xscale*4 + 12] + line2[x*xscale*4 + 16] +
line3[x*xscale*4 + 0] + line3[x*xscale*4 + 4] + line3[x*xscale*4 + 8] + line3[x*xscale*4 + 12] + line3[x*xscale*4 + 16] +
line4[x*xscale*4 + 0] + line4[x*xscale*4 + 4] + line4[x*xscale*4 + 8] + line4[x*xscale*4 + 12] + line4[x*xscale*4 + 16];
ss1 = line0[x*xscale*4 + 1] + line0[x*xscale*4 + 5] + line0[x*xscale*4 + 9] + line0[x*xscale*4 + 13] + line0[x*xscale*4 + 17] +
line1[x*xscale*4 + 1] + line1[x*xscale*4 + 5] + line1[x*xscale*4 + 9] + line1[x*xscale*4 + 13] + line1[x*xscale*4 + 17] +
line2[x*xscale*4 + 1] + line2[x*xscale*4 + 5] + line2[x*xscale*4 + 9] + line2[x*xscale*4 + 13] + line2[x*xscale*4 + 17] +
line3[x*xscale*4 + 1] + line3[x*xscale*4 + 5] + line3[x*xscale*4 + 9] + line3[x*xscale*4 + 13] + line3[x*xscale*4 + 17] +
line4[x*xscale*4 + 1] + line4[x*xscale*4 + 5] + line4[x*xscale*4 + 9] + line4[x*xscale*4 + 13] + line4[x*xscale*4 + 17];
ss2 = line0[x*xscale*4 + 2] + line0[x*xscale*4 + 6] + line0[x*xscale*4 + 10] + line0[x*xscale*4 + 14] + line0[x*xscale*4 + 18] +
line1[x*xscale*4 + 2] + line1[x*xscale*4 + 6] + line1[x*xscale*4 + 10] + line1[x*xscale*4 + 14] + line1[x*xscale*4 + 18] +
line2[x*xscale*4 + 2] + line2[x*xscale*4 + 6] + line2[x*xscale*4 + 10] + line2[x*xscale*4 + 14] + line2[x*xscale*4 + 18] +
line3[x*xscale*4 + 2] + line3[x*xscale*4 + 6] + line3[x*xscale*4 + 10] + line3[x*xscale*4 + 14] + line3[x*xscale*4 + 18] +
line4[x*xscale*4 + 2] + line4[x*xscale*4 + 6] + line4[x*xscale*4 + 10] + line4[x*xscale*4 + 14] + line4[x*xscale*4 + 18];
ss3 = line0[x*xscale*4 + 3] + line0[x*xscale*4 + 7] + line0[x*xscale*4 + 11] + line0[x*xscale*4 + 15] + line0[x*xscale*4 + 19] +
line1[x*xscale*4 + 3] + line1[x*xscale*4 + 7] + line1[x*xscale*4 + 11] + line1[x*xscale*4 + 15] + line1[x*xscale*4 + 19] +
line2[x*xscale*4 + 3] + line2[x*xscale*4 + 7] + line2[x*xscale*4 + 11] + line2[x*xscale*4 + 15] + line2[x*xscale*4 + 19] +
line3[x*xscale*4 + 3] + line3[x*xscale*4 + 7] + line3[x*xscale*4 + 11] + line3[x*xscale*4 + 15] + line3[x*xscale*4 + 19] +
line4[x*xscale*4 + 3] + line4[x*xscale*4 + 7] + line4[x*xscale*4 + 11] + line4[x*xscale*4 + 15] + line4[x*xscale*4 + 19];
v = MAKE_UINT32(
((ss0 + amend) * multiplier) >> 24, ((ss1 + amend) * multiplier) >> 24,
((ss2 + amend) * multiplier) >> 24, ((ss3 + amend) * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-25 05:16:03 +03:00
}
}
}
}
}
2019-11-25 23:34:52 +03:00
2019-11-25 05:16:03 +03:00
void
2019-11-25 23:34:52 +03:00
ImagingReduceCorners(Imaging imOut, Imaging imIn, int xscale, int yscale)
2019-11-25 05:16:03 +03:00
{
2019-11-26 02:45:13 +03:00
/* Fill the last row and the last column for any xscale and yscale.
*/
2019-11-25 23:34:52 +03:00
int x, y, xx, yy;
2019-11-25 05:16:03 +03:00
if (imIn->image8) {
2019-12-01 19:57:15 +03:00
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;
2019-11-25 05:16:03 +03:00
2019-12-01 19:57:15 +03:00
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;
}
2019-11-25 05:16:03 +03:00
} else {
2019-12-01 22:28:16 +03:00
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 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
x = imIn->xsize / xscale;
2019-11-25 04:20:31 +03:00
2019-12-01 22:28:16 +03:00
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
UINT8 *line = (UINT8 *)imIn->image[yy];
for (xx = x*xscale; xx < imIn->xsize; xx++) {
ss0 += line[xx*4 + 0];
ss1 += line[xx*4 + 1];
ss2 += line[xx*4 + 2];
ss3 += line[xx*4 + 3];
2019-11-26 02:45:13 +03:00
}
}
2019-12-01 22:28:16 +03:00
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
2019-11-26 02:45:13 +03:00
}
2019-12-01 22:28:16 +03:00
}
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++) {
2019-11-26 02:45:13 +03:00
UINT32 v;
UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
for (yy = y*yscale; yy < imIn->ysize; yy++) {
UINT8 *line = (UINT8 *)imIn->image[yy];
2019-12-01 22:28:16 +03:00
for (xx = x*xscale; xx < x*xscale + xscale; xx++) {
2019-11-26 02:45:13 +03:00
ss0 += line[xx*4 + 0];
ss1 += line[xx*4 + 1];
ss2 += line[xx*4 + 2];
ss3 += line[xx*4 + 3];
}
}
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
2019-12-01 22:28:16 +03:00
}
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 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++) {
UINT8 *line = (UINT8 *)imIn->image[yy];
for (xx = x*xscale; xx < imIn->xsize; xx++) {
ss0 += line[xx*4 + 0];
ss1 += line[xx*4 + 1];
ss2 += line[xx*4 + 2];
ss3 += line[xx*4 + 3];
}
}
v = MAKE_UINT32(
(ss0 * multiplier) >> 24, (ss1 * multiplier) >> 24,
(ss2 * multiplier) >> 24, (ss3 * multiplier) >> 24);
memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
}
}
}
2019-11-24 17:40:05 +03:00
2019-12-01 22:28:16 +03:00
void
ImagingReduceNxN_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
{
/* The most general implementation for any xscale and yscale
*/
int x, y, xx, yy, xi;
double multiplier = 1.0 / (yscale * xscale);
switch(imIn->type) {
case IMAGING_TYPE_INT32:
2019-12-01 22:52:43 +03:00
for (y = 0; y < imIn->ysize / yscale; y++) {
for (x = 0; x < imIn->xsize / xscale; x++) {
double ss = 0;
for (yy = y*yscale; yy < y*yscale + 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;
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;
ss += line[xx + 0] + line[xx + 1];
}
if (xscale & 0x01) {
xx = x*xscale + xi;
ss += line[xx + 0];
}
}
IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
}
}
2019-12-01 22:28:16 +03:00
break;
case IMAGING_TYPE_FLOAT32:
for (y = 0; y < imIn->ysize / yscale; y++) {
for (x = 0; x < imIn->xsize / xscale; x++) {
double ss = 0;
for (yy = y*yscale; yy < y*yscale + yscale - 1; yy += 2) {
2019-12-01 22:52:43 +03:00
FLOAT32 *line0 = (FLOAT32 *)imIn->image32[yy];
FLOAT32 *line1 = (FLOAT32 *)imIn->image32[yy + 1];
2019-12-01 22:28:16 +03:00
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) {
2019-12-01 22:52:43 +03:00
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
2019-12-01 22:28:16 +03:00
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];
}
}
IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
}
}
break;
}
}
void
ImagingReduceCorners_32bpc(Imaging imOut, Imaging imIn, int xscale, int yscale)
{
/* Fill the last row and the last column for any xscale and yscale.
*/
int x, y, xx, yy;
switch(imIn->type) {
case IMAGING_TYPE_INT32:
2019-12-01 22:52:43 +03:00
if (imIn->xsize % xscale) {
double multiplier = 1.0 / ((imIn->xsize % xscale) * yscale);
for (y = 0; y < imIn->ysize / yscale; y++) {
double ss = 0;
x = imIn->xsize / xscale;
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
INT32 *line = (INT32 *)imIn->image32[yy];
for (xx = x*xscale; xx < imIn->xsize; 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++) {
double ss = 0;
for (yy = y*yscale; yy < imIn->ysize; yy++) {
INT32 *line = (INT32 *)imIn->image32[yy];
for (xx = x*xscale; xx < x*xscale + 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));
double ss = 0;
x = imIn->xsize / xscale;
y = imIn->ysize / yscale;
for (yy = y*yscale; yy < imIn->ysize; yy++) {
INT32 *line = (INT32 *)imIn->image32[yy];
for (xx = x*xscale; xx < imIn->xsize; xx++) {
ss += line[xx + 0];
}
}
IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
}
2019-12-01 22:28:16 +03:00
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++) {
double ss = 0;
x = imIn->xsize / xscale;
for (yy = y*yscale; yy < y*yscale + yscale; yy++) {
2019-12-01 22:52:43 +03:00
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
2019-12-01 22:28:16 +03:00
for (xx = x*xscale; xx < imIn->xsize; xx++) {
ss += line[xx + 0];
}
}
IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
}
2019-11-24 17:40:05 +03:00
}
2019-12-01 22:28:16 +03:00
if (imIn->ysize % yscale) {
double multiplier = 1.0 / (xscale * (imIn->ysize % yscale));
y = imIn->ysize / yscale;
for (x = 0; x < imIn->xsize / xscale; x++) {
double ss = 0;
for (yy = y*yscale; yy < imIn->ysize; yy++) {
2019-12-01 22:52:43 +03:00
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
2019-12-01 22:28:16 +03:00
for (xx = x*xscale; xx < x*xscale + 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));
double ss = 0;
x = imIn->xsize / xscale;
y = imIn->ysize / yscale;
for (yy = y*yscale; yy < imIn->ysize; yy++) {
2019-12-01 22:52:43 +03:00
FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
2019-12-01 22:28:16 +03:00
for (xx = x*xscale; xx < imIn->xsize; xx++) {
ss += line[xx + 0];
}
}
IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
}
break;
2019-11-24 17:40:05 +03:00
}
}
2019-11-24 04:13:48 +03:00
Imaging
ImagingReduce(Imaging imIn, int xscale, int yscale)
{
2019-11-25 23:34:52 +03:00
ImagingSectionCookie cookie;
2019-11-24 04:13:48 +03:00
Imaging imOut = NULL;
2019-12-01 20:34:05 +03:00
if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0)
return (Imaging) ImagingError_ModeError();
if (imIn->type == IMAGING_TYPE_SPECIAL)
return (Imaging) ImagingError_ModeError();
2019-11-24 17:40:05 +03:00
imOut = ImagingNewDirty(imIn->mode,
(imIn->xsize + xscale - 1) / xscale,
(imIn->ysize + yscale - 1) / yscale);
2019-11-25 04:20:31 +03:00
if ( ! imOut) {
return NULL;
}
2019-11-24 17:40:05 +03:00
2019-11-25 23:34:52 +03:00
ImagingSectionEnter(&cookie);
2019-12-01 22:28:16 +03:00
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);
}
2019-11-25 23:34:52 +03:00
} else {
2019-12-01 22:28:16 +03:00
ImagingReduceNxN(imOut, imIn, xscale, yscale);
2019-11-25 23:34:52 +03:00
}
2019-11-24 17:40:05 +03:00
2019-12-01 22:28:16 +03:00
ImagingReduceCorners(imOut, imIn, xscale, yscale);
break;
case IMAGING_TYPE_INT32:
case IMAGING_TYPE_FLOAT32:
ImagingReduceNxN_32bpc(imOut, imIn, xscale, yscale);
ImagingReduceCorners_32bpc(imOut, imIn, xscale, yscale);
break;
}
2019-11-24 04:13:48 +03:00
2019-11-25 23:34:52 +03:00
ImagingSectionLeave(&cookie);
2019-11-24 04:13:48 +03:00
return imOut;
}