439 lines
9.6 KiB
C
439 lines
9.6 KiB
C
/*
|
|
pov_hf15.c
|
|
==========
|
|
|
|
Un 'height_field' de POVray est une image au format TGA
|
|
qui stocke des altitudes sur 15 bits, avec les poids
|
|
forts dans la composante rouge et les poids faibles dans
|
|
la composante verte. Pour le bleu, je ne sais pas ce
|
|
qu'il en est, donc on va le forcer a 0.
|
|
|
|
2 oct 2001: adding a function for writing a PGM 15 bits file.
|
|
16 oct 2001: the 'read pgm hf' func of Povray seems bogus, so we have
|
|
to wait for POV 3.5 for testing my func :(
|
|
23 oct 2001: all references to 16 bits are supersedes by reference
|
|
to 15 bits. after all, it's better ?
|
|
|
|
-------------------------------------------------
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "../tthimage.h"
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* que faire si l'altitude est negative ? on clampe !-)
|
|
* ... et rappelons qu'il faut sauver en TGA pour que Pov
|
|
* retrouve ses 2^15 valeurs d'altitude.
|
|
*/
|
|
int Image_hf15_plot(Image_Desc *im, int x, int y, int h)
|
|
{
|
|
int r, g;
|
|
|
|
if (h < 0) h = 0; /* On clampe ... */
|
|
if (h > 32767) h = 32767;
|
|
|
|
if ((x<0) || (y<0) || (x>=im->width) || (y>im->height))
|
|
{
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s : %d,%d out of image\n", __func__, x, y);
|
|
#endif
|
|
return OUT_OF_IMAGE;
|
|
}
|
|
|
|
r = (h >> 8) & 0xff; /* les poids forts */
|
|
g = h & 0xff; /* les poids faibles */
|
|
|
|
(im->Rpix[y])[x] = r;
|
|
(im->Gpix[y])[x] = g;
|
|
(im->Bpix[y])[x] = 0; /* valeur 'secure', on pourrait y mettre */
|
|
/* autre chose. voir les sources de pov ? */
|
|
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* recuperer la hauteur stockée dans une image 'hf15'
|
|
* en cas de dépassement, la valeur est silencieusement limitée.
|
|
*/
|
|
int Image_hf15_height(Image_Desc *img, int x, int y)
|
|
{
|
|
register int a, b;
|
|
int h;
|
|
|
|
if ((x<0) || (y<0) || (x>=img->width) || (y>img->height))
|
|
{
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s : %d,%d out of image\n", __func__, x, y);
|
|
#endif
|
|
/* VERY BAD BUG HERE */
|
|
return OUT_OF_IMAGE;
|
|
}
|
|
|
|
/* 28 mars 2007 : optimization for speed -> use direct access
|
|
h = (Image_R_pixel(img, x, y) << 8) + Image_G_pixel(img, x, y);
|
|
*/
|
|
a = (img->Rpix[y])[x];
|
|
b = (img->Gpix[y])[x];
|
|
h = ( a << 8) + b;
|
|
|
|
return h & 0x7fff;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* parameter 'mode' is not used. set it to 0, please.
|
|
*/
|
|
int Image_hf15_hf2gray(Image_Desc *src, Image_Desc *dst, int mode)
|
|
{
|
|
int x, y, h;
|
|
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
h = Image_hf15_height(src, x, y) >> 7;
|
|
Image_plotRGB(dst, x, y, h, h, h);
|
|
}
|
|
}
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/* il y a peut-etre une maniere plus astucieuse de choisr ces
|
|
* coeeficients que de prendre des valeurs arbitraires... */
|
|
#define K_R 65
|
|
#define K_G 42 /* il faut bien le caser, le 42 */
|
|
#define K_B 19
|
|
#define K_TOT (K_R+K_G+K_B)
|
|
|
|
/* parameter 'mode' is not used at this time. please use 0 ! */
|
|
int Image_hf15_rgb2hf(Image_Desc *src, Image_Desc *dst, int mode)
|
|
{
|
|
int x, y, h, hmax, hmin;
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
fprintf(stderr, "RGB -> HF: k_tot = %d\n", K_TOT);
|
|
fprintf(stderr, " max_v = %d\n", K_R*255+K_G*255+K_B*255);
|
|
#endif
|
|
|
|
if (0 != mode)
|
|
{
|
|
fprintf(stderr, "when calling %s, mode must be 0\n", __func__);
|
|
#if FORCE_ABORT
|
|
abort();
|
|
#endif
|
|
}
|
|
|
|
hmax = -9999; hmin = 424242;
|
|
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
h = Image_R_pixel(src, x, y) * K_R +
|
|
Image_G_pixel(src, x, y) * K_G +
|
|
Image_B_pixel(src, x, y) * K_B ;
|
|
|
|
#if DEBUG_LEVEL
|
|
if (h > hmax) hmax = h;
|
|
if (h < hmin) hmin = h;
|
|
#endif
|
|
|
|
Image_hf15_plot(dst, x, y, h);
|
|
}
|
|
}
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, " h min = %d, h max = %d\n", hmin, hmax);
|
|
#endif
|
|
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* Warning: this 15 bit (valid?) pgm file can't be loaded
|
|
* by POVray. I've send a bug report, but get no answer
|
|
* from the POV team....
|
|
* May be we have to wait for the release of v3.5 ?
|
|
*/
|
|
#define VERSION_STRING "PGM hf15 / Janv 2010"
|
|
#define TAILLE_BUFFER 65536
|
|
int Image_hf15_save_PGM(char *nom, Image_Desc *img, char *comment)
|
|
{
|
|
FILE *fp;
|
|
int x, y, h, foo;
|
|
int par_ligne, nbr_overshoot;
|
|
|
|
char buffer[TAILLE_BUFFER];
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s: saving %p as file '%s'\n", __func__, img, nom);
|
|
#endif
|
|
|
|
if ((fp=fopen(nom, "w")) == NULL)
|
|
{
|
|
fprintf(stderr, "ecriture PGM hf15 %s err fopen\n", nom);
|
|
return FILE_CREATE_ERR;
|
|
}
|
|
foo = setvbuf(fp, buffer, _IOFBF, TAILLE_BUFFER);
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s: setvbuf -> %d\n", __func__, foo);
|
|
#endif
|
|
|
|
fprintf(fp, "P2\n%d %d\n32767\n", img->width, img->height);
|
|
fprintf(fp, "#\n# written by libimage v %s, %s\n",
|
|
IMAGE_VERSION_STRING, VERSION_STRING);
|
|
if (comment != NULL)
|
|
fprintf(fp, "# %s\n", comment);
|
|
fputs("#\n", fp);
|
|
|
|
nbr_overshoot = 0;
|
|
par_ligne = 0;
|
|
for (y=0; y<img->height; y++)
|
|
{
|
|
for (x=0; x<img->width; x++)
|
|
{
|
|
h = Image_R_pixel(img, x, y) * 256 +
|
|
Image_G_pixel(img, x, y);
|
|
|
|
if (h > 32767)
|
|
{
|
|
fprintf(stderr, "overshoot at %d,%d -> %d\n",
|
|
x, y, h);
|
|
|
|
if (nbr_overshoot > 42)
|
|
{
|
|
#if FORCE_ABORT
|
|
abort();
|
|
#endif
|
|
}
|
|
nbr_overshoot++;
|
|
h = 32767;
|
|
}
|
|
foo = fprintf(fp, "%d ", h);
|
|
par_ligne += foo;
|
|
if (par_ligne > 65) /* magic value ? */
|
|
{
|
|
fputs("\n", fp);
|
|
par_ligne = 0;
|
|
}
|
|
}
|
|
#if DEBUG_LEVEL > 1
|
|
fprintf(fp, "\n# end of src pixline %d\n", y);
|
|
#endif
|
|
}
|
|
|
|
fputs("\n", fp);
|
|
#if DEBUG_LEVEL > 1
|
|
fprintf(stderr, "Pov hf15 save PGM: %p %s: a re-tester...\n", img, nom);
|
|
#endif
|
|
fclose(fp);
|
|
|
|
if (nbr_overshoot)
|
|
fprintf(stderr, "in %s, on a eu %d overshoots\n",
|
|
__func__, nbr_overshoot);
|
|
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
static struct
|
|
{
|
|
int x, y;
|
|
} deltas[] =
|
|
{ { -1, -1, },
|
|
{ 0, -1, },
|
|
{ 1, -1, },
|
|
{ -1, 0, },
|
|
{ 0, 0, },
|
|
{ 1, 0, },
|
|
{ -1, 1, },
|
|
{ 0, 1, },
|
|
{ 1, 1 }
|
|
};
|
|
|
|
#define PRECISION 42 /* à quoi ça sert ? */
|
|
|
|
int
|
|
Image_hf15_lissage(Image_Desc *s, Image_Desc *d, int coef, int flag)
|
|
{
|
|
int x, y, h, cumul, foo;
|
|
int r, g;
|
|
long temps, nbpix=0L;
|
|
#if DEBUG_LEVEL
|
|
double ttp;
|
|
int under, over;
|
|
#endif
|
|
|
|
if (flag)
|
|
{
|
|
fprintf(stderr, "Warning! Lissage hf15: flag (%d) must be 0\n", flag);
|
|
#if FORCE_ABORT
|
|
abort();
|
|
#endif
|
|
}
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> Lissage hf15 : %p -> %p : coef %d, flag 0x%04x\n",
|
|
s, d, coef, flag);
|
|
#endif
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
Image_start_chrono("lissage hf15", 15);
|
|
#endif
|
|
|
|
/* BIG FIX at night, the 7 january 2010 */
|
|
/* we _must_ clean the border of the target image buffer */
|
|
Image_raz_sides(d);
|
|
|
|
#if DEBUG_LEVEL
|
|
under = over = 0;
|
|
#endif
|
|
|
|
for (y=1; y<s->height-1; y++)
|
|
{
|
|
for (x=1; x<s->width-1; x++)
|
|
{
|
|
cumul = 0;
|
|
for (foo=0; foo<9; foo++)
|
|
{
|
|
/* XXX attention optimisation dangeureuse.
|
|
h = Image_R_pixel(s, x+deltas[foo].x, y+deltas[foo].y) * 256 +
|
|
Image_G_pixel(s, x+deltas[foo].x, y+deltas[foo].y);
|
|
XXX car on utilise un acces 'insecure' a la memoire image */
|
|
h = (s->Rpix[y+deltas[foo].y])[x+deltas[foo].x] * 256;
|
|
h += (s->Gpix[y+deltas[foo].y])[x+deltas[foo].x];
|
|
h &= 0x7fff;
|
|
h *= PRECISION;
|
|
|
|
if (foo==4) cumul += (h*coef);
|
|
else cumul += h;
|
|
}
|
|
|
|
cumul /= ((8+coef)*PRECISION);
|
|
|
|
if (cumul > 32767)
|
|
{
|
|
cumul = 32767;
|
|
#if DEBUG_LEVEL
|
|
over++;
|
|
#endif
|
|
}
|
|
if (cumul < 0)
|
|
{
|
|
cumul = 0;
|
|
#if DEBUG_LEVEL
|
|
under++;
|
|
#endif
|
|
}
|
|
|
|
r = (cumul >> 8) & 0x7f;
|
|
g = cumul & 0xff;
|
|
|
|
(d->Rpix[y])[x] = r;
|
|
(d->Gpix[y])[x] = g;
|
|
(d->Bpix[y])[x] = 0;
|
|
|
|
nbpix++;
|
|
}
|
|
}
|
|
|
|
#if DEBUG_LEVEL
|
|
if (under || over)
|
|
fprintf(stderr, "%s : under=%d over=%d\n", __func__, under, over);
|
|
#endif
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
temps = Image_stop_chrono(NULL, 15);
|
|
ttp = ((double)temps / (double)nbpix)*1000000.0;
|
|
fprintf(stderr, "Lissage hf15: %.4f µs/pixel\n", ttp);
|
|
#endif
|
|
|
|
d->modified = 1;
|
|
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* WARNING! experimental: prototype may change!
|
|
*/
|
|
int
|
|
Image_hf15_calc_minmax(Image_Desc *img, char *txt, int *pmin, int *pmax)
|
|
{
|
|
int x, y, h, minH, maxH;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s ( %p, '%s', %p, %p )\n", __func__, img, txt, pmin, pmax);
|
|
#endif
|
|
|
|
minH = 99999999; maxH = -99999999;
|
|
|
|
for (y=1; y<img->height-1; y++)
|
|
{
|
|
for (x=1; x<img->width-1; x++)
|
|
{
|
|
h = (Image_R_pixel(img, x, y) << 8) +
|
|
Image_G_pixel(img, x, y);
|
|
if (h > maxH) maxH = h;
|
|
if (h < minH) minH = h;
|
|
}
|
|
}
|
|
|
|
if (txt != NULL)
|
|
{
|
|
fprintf(stderr, "* hf15 @ %p * %s : min=%d max=%d\n",
|
|
img, txt, minH, maxH);
|
|
}
|
|
|
|
if (pmin != NULL) *pmin = minH;
|
|
if (pmax != NULL) *pmax = maxH;
|
|
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/* new 6 Nov 2001 */
|
|
/*
|
|
* Need more doc !
|
|
*/
|
|
int
|
|
Image_hf15_mul_add(Image_Desc *src, Image_Desc *dst, int mul, int add)
|
|
{
|
|
int x, y, h;
|
|
|
|
fprintf(stderr, "Pov hf15: mul %d & add %d\n", mul, add);
|
|
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
h = Image_hf15_height(src, x, y);
|
|
h = (h * mul) + add;
|
|
Image_hf15_plot(dst, x, y, h);
|
|
}
|
|
}
|
|
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/* new 6 Nov 2001 */
|
|
int
|
|
Image_hf15_invert(Image_Desc *src, Image_Desc *dst)
|
|
{
|
|
int x, y, h;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s : %p --> %p\n", __func__, src, dst);
|
|
#endif
|
|
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
h = 32768 - Image_hf15_height(src, x, y);
|
|
Image_hf15_plot(dst, x, y, h);
|
|
}
|
|
}
|
|
return FUNC_IS_BETA;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|