/* resize.cpp
*
*/
#include <stdio.h>
#include <math.h>
#include "image.h"
void resize_gray(IMAGE *in, IMAGE *out);
void resize_rgb(IMAGE *in, IMAGE *out);
int main(int argc, char *argv[])
{
int magx, magy;
IMAGE *in, *out;
char *infile,*outfile;
if (argc<3) {
printf("usage: resize infile outfile [magx] [magy]\n");
printf("Image size expanded using bilinear interpolation.\n");
return -1;
}
infile=argv[1];
outfile=argv[2];
if (argc>3) sscanf(argv[3],"%d",&magx);
else magx = 1;
if (argc>4) sscanf(argv[4],"%d",&magy);
else magy=magx;
printf("input image: %s\n",infile);
in = open_image(infile);
if (!in) {
printf("error opening image file\n");
return -1;
}
printf("image size: %d x %d\n",in->hlen,in->vlen);
printf("pixel magnification: %d x %d\n\n",magx,magy);
if (magx<=1 && magy<=1) {
printf("no enlargement necessary\n");
return -1;
}
printf("output image: %s\n",outfile);
out = make_image(outfile,in->hlen*magx,in->vlen*magy,in->type);
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) resize_rgb(in,out);
else resize_gray(in,out);
return 0;
}
inline float linint(double x, double x1, float fx1, float fx2)
{
return (float)((fx2-fx1)*(x-x1)+fx1);
}
/*****
*
C
C RESIZE USES BI-LINEAR INTERPOLATION TO CHANGE THE PICTURE ON
C WORKFILE WFIN TO A DIFFERENT SIZE PICTURE ON WFOUT. OUTPIX IS THE
C NUMBER OF PIXELS/LINE ON THE NEW PICTURE, AND OUTLIN IS THE NUMBER
C OF LINES
C
******/
void resize_gray(IMAGE *in, IMAGE *out)
{
int i, j, ipntr;
int x0, y0, x1;
double fpix, flin, lp, ps, pp;
pixel *buf, *buf1, *buf2, *buf3;
float *fbuf1, *fbuf2, *fbuf3;
float t1, t2;
buf1 = make_buffer(in);
buf2 = make_buffer(in);
buf3 = make_buffer(out);
/* compute incremental factors */
fpix = (double) (in->hlen-1)/ (double) (out->hlen-1);
flin = (double) (in->vlen-1) / (double) (out->vlen-1);
ps=0.0;
lp=0.0;
/* get window */
get_line(in,0,buf1,PIX_FLOAT);
get_line(in,1,buf2,PIX_FLOAT);
ipntr=1;
for (j=0; j<out->vlen; j++) {
if (lp>ipntr) {
buf= buf1; buf1 = buf2; buf2 = buf;
ipntr++;
get_line(in,ipntr,buf2,PIX_FLOAT);
}
/* interpolate */
pp = ps;
fbuf1 = (float *) buf1;
fbuf2 = (float *) buf2;
fbuf3 = (float *) buf3;
for (i=0; i<out->hlen; i++, pp += fpix) {
x0 = (int) floor(pp);
y0 = (int) floor(lp);
x1 = x0+1;
if (pp==x0) fbuf3[i] = linint(lp,y0,fbuf1[x0],fbuf2[x0]);
else if (pp==x1) fbuf3[i] = linint(lp,y0,fbuf1[x1],fbuf2[x1]);
else {
t1 = linint(pp,x0,fbuf1[x0],fbuf1[x1]);
t2 = linint(pp,x0,fbuf2[x0],fbuf2[x1]);
fbuf3[i] = linint(lp,y0,t1,t2);
}
}
/* write line to output file */
put_line(out,j,buf3,PIX_FLOAT);
lp += flin;
}
free_buffer(buf3);
free_buffer(buf2);
free_buffer(buf1);
}
struct rgb_color {
float red, green, blue;
void set(pixel val);
pixel rgb();
void interp(double x, double x1, rgb_color &c1, rgb_color &c2);
};
void rgb_color::set(pixel val)
{
red = GetRValue(val);
green = GetGValue(val);
blue = GetBValue(val);
}
inline pixel rgb_color::rgb()
{
return RGB((int)red,(int)green,(int)blue);
}
void rgb_color::interp(double x, double x1, rgb_color &c1, rgb_color &c2)
{
float dx = (float)(x-x1);
red = (c2.red-c1.red)*dx + c1.red;
green = (c2.green-c1.green)*dx + c1.green;
blue = (c2,blue-c1.blue)*dx + c1.blue;
}
void resize_rgb(IMAGE *in, IMAGE *out)
{
int i, j, ipntr;
int x0, y0, x1;
double fpix, flin, lp, ps, pp;
pixel *inpbuf, *outbuf;
rgb_color val, t1, t2;
rgb_color *buf, *buf1, *buf2;
inpbuf = make_buffer(in);
outbuf = make_buffer(in);
buf1 = new rgb_color[in->hlen];
buf2 = new rgb_color[in->hlen];
/* compute incremental factors */
fpix = (double) (in->hlen-1)/ (double) (out->hlen-1);
flin = (double) (in->vlen-1) / (double) (out->vlen-1);
ps=0.0;
lp=0.0;
/* get window */
get_line(in,0,inpbuf,PIX_RGB);
for (i=0; i<in->hlen; i++) buf1[i].set(inpbuf[i]);
get_line(in,1,inpbuf,PIX_RGB);
for (i=0; i<in->hlen; i++) buf2[i].set(inpbuf[i]);
ipntr=1;
for (j=0; j<out->vlen; j++) {
if (lp>ipntr) {
buf= buf1; buf1 = buf2; buf2 = buf;
ipntr++;
get_line(in,ipntr,inpbuf,PIX_RGB);
for (i=0; i<in->hlen; i++) buf2[i].set(inpbuf[i]);
}
/* interpolate */
pp = ps;
for (i=0; i<out->hlen; i++, pp += fpix) {
x0 = (int) floor(pp);
y0 = (int) floor(lp);
x1 = x0+1;
if (pp==x0) val.interp(lp,y0,buf1[x0],buf2[x0]);
else if (pp==x1) val.interp(lp,y0,buf1[x1],buf2[x1]);
else {
t1.interp(pp,x0,buf1[x0],buf1[x1]);
t2.interp(pp,x0,buf2[x0],buf2[x1]);
val.interp(lp,y0,t1,t2);
}
outbuf[i] = val.rgb();
}
/* write line to output file */
put_line(out,j,outbuf,PIX_RGB);
lp += flin;
}
free_buffer(outbuf);
free_buffer(inpbuf);
delete [] buf1;
delete [] buf2;
}