/*** reduce.cpp
*
* reduce image size by pixel averaging.
*
***/
#include <stdio.h>
#include <stdlib.h>
#include "image.h"
#include "errmsg.h"
void reduce_gray(IMAGE *in, IMAGE *out, int magx, int magy);
void reduce_rgb(IMAGE *in, IMAGE *out, int magx, int magy);
int main(int argc, char *argv[])
{
int magx, magy;
IMAGE *in, *out;
char *infile,*outfile;
if (argc<4) {
printf("usage: reduce infile outfile magx [magy]\n");
return -1;
}
infile=argv[1];
outfile=argv[2];
sscanf(argv[3],"%d",&magx);
if (argc>4) sscanf(argv[4],"%d",&magy);
else magy=magx;
in = open_image(infile);
if (!in) return -1;
printf("input image: %s\n",infile);
printf("image size: %d x %d\n",in->hlen,in->vlen);
printf("reduction factors: %d x %d\n\n",magx,magy);
if (magx<1 || magy < 1) {
printf("illegal reduction factors\n");
return -1;
}
if (magx == 1 && magy == 1) {
printf("no reduction required\n");
return -1;
}
out = make_image(outfile,in->hlen/magx,in->vlen/magy,in->type);
printf("output image: %s\n",outfile);
if (!out) {
printf("error creating output file\n");
return -1;
}
printf("image size: %d x %d\n",out->hlen,out->vlen);
if (in->type == PIX_RGB) reduce_rgb(in, out, magx, magy);
else reduce_gray(in,out,magx,magy);
return 0;
}
void reduce_gray(IMAGE *in, IMAGE *out, int magx, int magy)
{
pixel *buf1, *buf2;
float *inbuf, *outbuf, sum, magxy;
int i, j, kx, ky, nx, ny;
magxy = (float) magx * (float) magy;
buf1 = make_buffer(in);
buf2 = make_buffer(in);
inbuf = (float *) buf1;
outbuf = (float *) buf2;
for (j=ny=0; j<out->vlen; j++) {
// sum over rows
get_line(in,ny,buf2,PIX_FLOAT);
ny++;
for (ky=1; ky<magy; ky++, ny++) {
get_line(in,ny,buf1,PIX_FLOAT);
for (i=0; i<in->hlen; i++) {
outbuf[i] += inbuf[i];
}
}
for (i=nx=0; i<out->hlen; i++) {
// sum over columns
sum = outbuf[nx];
nx++;
for (kx=1; kx<magx; kx++, nx++) {
sum += outbuf[nx];
}
outbuf[i] = sum/magxy;
}
put_line(out,j,buf2,PIX_FLOAT);
}
free_buffer(buf1);
free_buffer(buf2);
}
void reduce_rgb(IMAGE *in, IMAGE *out, int magx, int magy)
{
pixel *buf, val;
double *red, *grn, *blu;
double redtot, grntot, blutot, magxy;
int i, j, kx, ky, nx, ny;
magxy = (float) magx * (float) magy;
buf = make_buffer(in);
red = new double[in->hlen];
grn = new double[in->hlen];
blu = new double[in->hlen];
if (!red || !grn || !blu) errmsg("alloc error in reduce_rgb");
for (j=ny=0; j<out->vlen; j++) {
// sum over rows
get_line(in,ny,buf,PIX_RGB);
for (i=0; i<in->hlen; i++) {
val = buf[i];
red[i] = GetRValue(val);
grn[i] = GetGValue(val);
blu[i] = GetBValue(val);
}
ny++;
for (ky=1; ky<magy; ky++, ny++) {
get_line(in,ny,buf,PIX_RGB);
for (i=0; i<in->hlen; i++) {
val = buf[i];
red[i] += GetRValue(val);
grn[i] += GetGValue(val);
blu[i] += GetBValue(val);
}
}
for (i=nx=0; i<out->hlen; i++) {
// sum over columns
redtot = red[nx];
grntot = grn[nx];
blutot = blu[nx];
nx++;
for (kx=1; kx<magx; kx++, nx++) {
redtot += red[nx];
grntot += grn[nx];
blutot += blu[nx];
}
redtot /= magxy;
grntot /= magxy;
blutot /= magxy;
buf[i] = RGB((int)redtot,(int)grntot,(int)blutot);
}
put_line(out,j,buf,PIX_RGB);
}
free_buffer(buf);
delete [] red;
delete [] grn;
delete [] blu;
}