243 lines
5.7 KiB
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;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|