/* 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 #include #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; yheight; y++) { for (x=0; xwidth; 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; yheight; y++) { for (x=0; xwidth; 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; yheight; y++) { for (x=0; xwidth; 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; yheight-1; y++) { for (x=1; xwidth-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; yheight-1; y++) { for (x=1; xwidth-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; yheight; y++) { for (x=0; xwidth; 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; yheight; y++) { for (x=0; xwidth; x++) { h = 32768 - Image_hf15_height(src, x, y); Image_hf15_plot(dst, x, y, h); } } return FUNC_IS_BETA; } /*::------------------------------------------------------------------::*/