libtthimage/Lib/scale.c

243 lines
5.7 KiB
C

/*
scale.c
--------------
I think that I have to make an effort in math studies
for future enhancement of this module :)
see also: halfsize.c doublesz.c
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "../tthimage.h"
/*::------------------------------------------------------------------::*/
/*
* do not use in production !-)
*/
int Image_scale_simple(Image_Desc *src, Image_Desc *dst, int k)
{
float coefX, coefY, fx, fy;
int xd, yd, xs, ys;
int r, g, b;
#if DEBUG_LEVEL
fprintf(stderr, "scale simple: %p (%dx%d) -> %p (%dx%d) k:%d \n",
src, src->width, src->height,
dst, dst->width, dst->height, k);
#endif
if (k) {
fprintf(stderr, "in %s, k must be zero, was %d\n", __func__, k);
return BAD_PARAMETER;
}
coefX = (float)dst->width / (float)src->width;
coefY = (float)dst->height / (float)src->height;
#if DEBUG_LEVEL
fprintf(stderr, "coefficients: X %f y %f\n", coefX, coefY);
#endif
/*
* bon, pour les interpolations, il faut que je trouve
* un peu de doc... mais ou ?
*/
for (yd=0; yd<dst->height; yd++) {
for (xd=0; xd<dst->width; xd++) {
fx = (float)xd / coefX;
fy = (float)yd / coefY;
xs = (int)fx;
ys = (int)fy;
Image_getRGB(src, xs, ys, &r, &g, &b);
(dst->Rpix[yd])[xd] = r;
(dst->Gpix[yd])[xd] = g;
(dst->Bpix[yd])[xd] = b;
}
}
return FUNC_IS_ALPHA;
}
/*::------------------------------------------------------------------::*/
/* new 2 nov 2009 - ave StEx */
/*
I've lost all my mathematical concepts so I'm going to make
some approximations\dots
this function is PRIVATE, see 'Image_getpix_bilin' for public interface
2022 September : update in progress.
*/
static int getpix_bilin(Image_Desc *src, double fx, double fy,
int *pr, int *pg, int *pb)
{
double x11, y11, x22, y22;
int xx, yy;
int r11, g11, b11, r12, g12, b12,
r21, g21, b21, r22, g22, b22;
double drh, drw;
double raa, gaa, baa;
double rbb, gbb, bbb;
double rcc, gcc, bcc;
/* before real ops, set RGB to some know values */
*pr = *pg = *pb = 0;
/* build all the nasty values */
x11 = floor(fx); y11 = floor(fy);
x22 = ceil(fx); y22 = ceil(fy);
drw = fx - x11; drh = fy - y11;
xx = (int)x11; yy = (int)y11;
#if DEBUG_LEVEL > 2
printf("X %10.3f %10.3f %10.3f %10.3f %4d\n", fx, x11, x22, drw, xx);
printf("Y %10.3f %10.3f %10.3f %10.3f %4d\n", fy, y11, y22, drh, yy);
#endif
if ( ! Image_xy_inside(src, xx, yy) )
return -1;
if ( ! Image_xy_inside(src, xx+1, yy+1) )
return -2;
r11 = src->Rpix[yy][xx]; g11 = src->Gpix[yy][xx]; b11 = src->Bpix[yy][xx];
r12 = src->Rpix[yy][xx+1]; g12 = src->Gpix[yy][xx+1]; b12 = src->Bpix[yy][xx+1];
r22 = src->Rpix[yy+1][xx+1]; g22 = src->Gpix[yy+1][xx+1]; b22 = src->Bpix[yy+1][xx+1];
r21 = src->Rpix[yy+1][xx]; g21 = src->Gpix[yy+1][xx]; b21 = src->Bpix[yy+1][xx];
/* hum hum... */
raa = (double)r11 * (1.0-drw) + (double)r12 * drw;
gaa = (double)g11 * (1.0-drw) + (double)g12 * drw;
baa = (double)b11 * (1.0-drw) + (double)b12 * drw;
if (raa < 0.0) abort();
if (gaa < 0.0) abort();
if (baa < 0.0) abort();
rbb = (double)r21 * (1.0-drw) + (double)r22 * drw;
gbb = (double)g21 * (1.0-drw) + (double)g22 * drw;
bbb = (double)b21 * (1.0-drw) + (double)b22 * drw;
if (rbb < 0.0) abort();
if (gbb < 0.0) abort();
if (bbb < 0.0) abort();
/* hu ho ? */
rcc = (raa * (1.0-drh)) + (rbb * drh);
gcc = (gaa * (1.0-drh)) + (gbb * drh);
bcc = (baa * (1.0-drh)) + (bbb * drh);
*pr = (int)rcc; *pg = (int)gcc; *pb = (int)bcc;
return -105;
}
/*::------------------------------------------------------------------::*/
int Image_scale_bilinear(Image_Desc *src, Image_Desc *dst, int k)
{
int xd, yd, xs, ys, r, g, b;
double coefX, coefY;
double fxd, fyd, fxs, fys;
#if DEBUG_LEVEL
fprintf(stderr, "scale bilinear: %p (%dx%d) -> %p (%dx%d) k:%d \n",
src, src->width, src->height,
dst, dst->width, dst->height, k);
#endif
if (k) {
fprintf(stderr, "in %s, k must be zero, was %d\n", __func__, k);
return BAD_PARAMETER;
}
coefX = (double)dst->width / (double)src->width;
coefY = (double)dst->height / (double)src->height;
#if DEBUG_LEVEL
fprintf(stderr, "%s : coefs %lf %lf\n", __func__, coefX, coefY);
#endif
for (yd=0; yd<dst->height; yd++) {
fyd = (double)yd;
fys = fyd / coefY;
for (xd=0; xd<dst->width; xd++) {
fxd = (double)xd;
fxs = fxd / coefX;
getpix_bilin(src, fxs, fys, &r, &g, &b);
(dst->Rpix[yd])[xd] = r;
(dst->Gpix[yd])[xd] = g;
(dst->Bpix[yd])[xd] = b;
}
}
return FUNC_IS_BETA;
}
/*::------------------------------------------------------------------::*/
int Image_getpix_bilin(Image_Desc *src, double fx, double fy,
int *pr, int *pg, int *pb)
{
int foo;
foo = getpix_bilin(src, fx, fy, pr, pg, pb);
return foo;
}
/*::------------------------------------------------------------------::*/
/*
* for now, method must be 0 !
*/
Image_Desc * Image_new_scale( Image_Desc *src,
float scaleX, float scaleY,
int methode )
{
float fx, fy;
int nw, nh, foo;
Image_Desc *dst;
#if DEBUG_LEVEL
fprintf(stderr, "%s: image\t%d %d, scale %f %f\n", __func__,
src->width, src->height, scaleX, scaleY);
#endif
if (methode) {
fprintf(stderr, "in %s, methode must be zero, was %d\n", __func__, methode);
return NULL;
}
fx = (float)src->width * scaleX;
fy = (float)src->height * scaleY;
nw = (int)(ceil((double)fx));
nh = (int)(ceil((double)fy));
#if DEBUG_LEVEL
fprintf(stderr, "\t%f %f\n", fx, fy);
fprintf(stderr, "\tnew dims: %d x %d\n", nw, nh);
#endif
if ( (dst = Image_alloc(nw, nh, 3)) == NULL ) {
fprintf(stderr, "%s: no memory\n", __func__);
return NULL;
}
#if DEBUG_LEVEL
fprintf(stderr, "\tnew image @ %p\n", dst);
#endif
foo = Image_scale_simple(src, dst, 0);
if (foo) {
fprintf(stderr, "in %s scale_simple -> %d\n", __func__, foo);
}
return dst;
}
/*::------------------------------------------------------------------::*/