libdvu.c

00001 /*
00002  * libdvu.c
00003  *
00004  * EDT digital video device support utility defines and routines
00005  *
00006  * Copyright (C) 1998 EDT, Inc.
00007  */
00008 
00014 #include "edtinc.h"
00015 #include "errno.h"
00016 #include "libdvu.h"
00017 
00018 /* shorthand debug level */
00019 #define DVUFATAL PDVLIB_MSG_FATAL
00020 
00021 #ifndef _rasterfile_h
00022 /* from 4.1.x rasterfile.h */
00023 struct rasterfile
00024 {
00025     int             ras_magic;  /* magic number */
00026     int             ras_width;  /* width (pixels) of image */
00027     int             ras_height; /* height (pixels) of image */
00028     int             ras_depth;  /* depth (1, 8, or 24 bits) of pixel */
00029     int             ras_length; /* length (bytes) of image */
00030     int             ras_type;   /* type of file; see RT_* below */
00031     int             ras_maptype;/* type of colormap; see RMT_* below */
00032     int             ras_maplength;      /* length (bytes) of following map */
00033     /* color map follows for ras_maplength bytes, followed by image */
00034 };
00035 
00036 #define RAS_MAGIC       0x59a66a95
00037 #define RT_STANDARD     1       /* Raw pixrect image in 68000 byte order */
00038 #define RMT_EQUAL_RGB   1       /* red[ras_maplength/3],green[],blue[] */
00039 #define RMT_NONE        0
00040 #endif
00041 
00042 static u_short  *slookup = NULL ;
00043 static u_char   *blookup = NULL ;
00044 static int      *hist = NULL ;
00045 
00046 static void
00047 free_cast_tbl();
00048 
00049 extern int Pdv_debug;
00050 
00051 static u_char *Cast_tbl = NULL;
00052 static u_char *create_cast_tbl();
00053 
00054 static int write_sun_long (int l, FILE *fp)
00055 {
00056     char c;
00057 
00058     c = ((l >> 24) & 0xff);
00059     if (putc (c, fp) == EOF) return (EOF);
00060     c = ((l >> 16) & 0xff);
00061     if (putc (c, fp) == EOF) return (EOF);
00062     c = ((l >> 8) & 0xff);
00063     if (putc (c, fp) == EOF) return (EOF);
00064     c = (l & 0xff);
00065     if (putc (c, fp) == EOF) return (EOF);
00066     return (0);
00067 }
00068 
00087 static int i_am_big_endian()
00088 {
00089     static int   magic                  = 0x33221100;
00090     static const char *is_big_endian    = (const char *) &magic;
00091 
00092     return *is_big_endian != 0;
00093 }
00094 
00109 static void change_endian(long *lp, int n)
00110 {
00111     int          bytes  = 4 * n;
00112     char        *cp     = (char *) lp;
00113     int          i;
00114 
00115     for (i = 0; i < bytes; i += 4) {
00116         char tmp;
00117 
00118         tmp = cp[0]; 
00119         cp[0] = cp[3]; 
00120         cp[3] = tmp;
00121 
00122         tmp = cp[1]; 
00123         cp[1] = cp[2]; 
00124         cp[2] = tmp;
00125     }
00126 }
00127 
00141 static int fwrite_sun_long(const void *buf, int size, int count, FILE *fp)
00142 {
00143     const long  *ibuf           = (const long *) buf;
00144     int          numlongs       = size * count / 4;
00145     int          i;
00146     
00147     for (i = 0; i < numlongs; i++)
00148         write_sun_long(ibuf[i], fp);
00149 
00150     return count;
00151 }
00152 
00165 static int fread_sun_long(void *buf, int size, int count, FILE *fp)
00166 {
00167     int numlongs        = size * count / 4;
00168     size_t numread              = fread(buf, size, count, fp);
00169 
00170     /* convert to native endianness if this isn't a big endian machine */
00171     if (!i_am_big_endian()) 
00172         change_endian((long *) buf, numlongs);
00173 
00174     return numread;
00175 }
00176 
00189 int
00190 dvu_write_rasfile(char *fname, u_char *addr, int x_size, int y_size)
00191 {
00192     struct rasterfile ras;
00193     u_char          colors[256];
00194     FILE           *fp;
00195     int             i;
00196     int             rowsize ;
00197 
00198     if ((fp = fopen(fname, "wb")) == NULL)
00199     {
00200         edt_msg_printf_perror(
00201                 DVUFATAL, 
00202                 "Can't open destination data file '%s' for writing", 
00203                 fname);
00204         return -1;
00205     }
00206 
00207     rowsize = x_size ;
00208     if(rowsize & 1)
00209     {
00210         rowsize++ ;
00211     }
00212     ras.ras_magic = RAS_MAGIC;
00213     ras.ras_width = x_size;
00214     ras.ras_height = y_size;
00215     ras.ras_depth = 8;
00216     ras.ras_length = x_size * y_size;
00217     ras.ras_type = RT_STANDARD;
00218     ras.ras_maptype = RMT_EQUAL_RGB;
00219     ras.ras_maplength = 256 * 3;
00220 
00221     write_sun_long(ras.ras_magic, fp) ;
00222     write_sun_long(ras.ras_width, fp) ;
00223     write_sun_long(ras.ras_height, fp) ;
00224     write_sun_long(ras.ras_depth, fp) ;
00225     write_sun_long(ras.ras_length, fp) ;
00226     write_sun_long(ras.ras_type, fp) ;
00227     write_sun_long(ras.ras_maptype, fp) ;
00228     write_sun_long(ras.ras_maplength, fp) ;
00229 
00230 
00231     for (i = 0; i < 256; i++)
00232         colors[i] = i;
00233     fwrite(colors, sizeof(colors), 1, fp);
00234     fwrite(colors, sizeof(colors), 1, fp);
00235     fwrite(colors, sizeof(colors), 1, fp);
00236 
00237     if (Pdv_debug) printf("before write %d %d\n",x_size,y_size*3) ;
00238     for(i = 0; i < y_size ; i++)
00239     {
00240         fwrite(addr, rowsize, 1, fp);
00241         addr += x_size ;
00242     }
00243     fclose(fp);
00244     return(0) ;
00245 }
00246 
00261 int
00262 dvu_write_rasfile16(char *fname, u_char *addr, int x_size, int y_size, int depth_bits)
00263         
00264 {
00265         struct rasterfile ras;
00266         u_char          colors[256];
00267         u_char     *scanline;
00268         u_short    *shortp;
00269         FILE           *fp;
00270         int             i, j;
00271         int                 rowsize ;
00272         int                 ret;
00273         int                 mask = 0;
00274         int                 depth_bytes = ((int)depth_bits + 7) / 8;
00275 
00276         for (i=0; i<depth_bits; i++)
00277                 mask |= 1 << i;
00278 
00279         if ((fp = fopen(fname, "wb")) == NULL) {
00280                 edt_msg_printf_perror(
00281                                 DVUFATAL, 
00282                                 "Can't open destination data file '%s' for writing", 
00283                                 fname);
00284                 return -1;
00285         }
00286 
00287         if (Cast_tbl == NULL)
00288                 Cast_tbl = create_cast_tbl(depth_bits, 256);
00289 
00290 
00291         if (Pdv_debug) printf("writing rasterfile header to %s\n", fname);
00292         if (Pdv_debug) printf("x %d y %d addr %p name %s\n", x_size, y_size, addr, fname);
00293         rowsize = x_size ;
00294         if(rowsize & 1)
00295         {
00296                 rowsize++ ;
00297         }
00298         ras.ras_magic = RAS_MAGIC;
00299         ras.ras_width = x_size;
00300         ras.ras_height = y_size;
00301         ras.ras_depth = 8;
00302         ras.ras_length = x_size * y_size;
00303         ras.ras_type = RT_STANDARD;
00304         ras.ras_maptype = RMT_EQUAL_RGB;
00305         ras.ras_maplength = 256 * 3;
00306 
00307         scanline = (u_char *)malloc(x_size * sizeof(short));
00308 
00309         if ((ret = fwrite_sun_long(&ras, sizeof(ras), 1, fp)) != 1)
00310                 goto err_ret;
00311 
00312         for (i = 0; i < 256; i++)
00313                 colors[i] = i;
00314 
00315         if (fwrite(colors, sizeof(colors), 1, fp) != 1)
00316                 goto err_ret;
00317         if (fwrite(colors, sizeof(colors), 1, fp) != 1)
00318                 goto err_ret;
00319         if (fwrite(colors, sizeof(colors), 1, fp) != 1)
00320                 goto err_ret;
00321 
00322 
00323         shortp = (u_short *)addr;
00324         for(i=0; i<y_size ; i++)
00325         {
00326                 for (j=0; j<x_size; j++)
00327                         scanline[j] = Cast_tbl[(*shortp++) & mask];
00328                 if ((ret = fwrite(scanline, rowsize, 1, fp)) != 1)
00329                         goto err_ret;
00330         }
00331         fclose(fp);
00332         free(scanline);
00333         free_cast_tbl();
00334         return 0;
00335 
00336 err_ret:
00337         ret = errno;
00338         fclose(fp);
00339         free(scanline);
00340         free_cast_tbl();
00341         return ret;
00342 }
00343 
00344 dvu_write_window(char *fname, dvu_window *w)
00345 {
00346     struct rasterfile ras;
00347     u_char          colors[256];
00348     FILE           *fp;
00349     int             i;
00350     int             rowsize ;
00351     int             x_size ;
00352     int             y_size ;
00353     int             bytes ;
00354     dvu_window      *tmpi = 0 ;
00355 
00356     if ((fp = fopen(fname, "wb")) == NULL)
00357     {
00358         edt_msg_printf_perror(
00359                 DVUFATAL, 
00360                 "Can't open destination data file '%s' for writing", 
00361                 fname);
00362     }
00363     bytes = (w->depth + 7) / 8 ;
00364     x_size = w->right - w->left + 1 ;
00365     y_size = w->bottom - w->top + 1 ;
00366 
00367     if (bytes == 3)
00368     {
00369         if (Pdv_debug)
00370             printf("dvu_write_window does not yet support 24 bit images\n") ;
00371         return(-1) ;
00372     }
00373     if (bytes == 2)
00374     {
00375         tmpi = (dvu_window *)
00376             dvu_init_window(NULL, 0, 0, x_size, y_size, x_size, y_size, 8) ;
00377 
00378         dvu_winscale(w, tmpi, 0, 255, 1)  ;
00379         w = tmpi ;
00380     }
00381     rowsize = x_size ;
00382     if(rowsize & 1)
00383     {
00384         rowsize++ ;
00385     }
00386     ras.ras_magic = RAS_MAGIC;
00387     ras.ras_width = x_size;
00388     ras.ras_height = y_size;
00389     ras.ras_depth = 8;
00390     ras.ras_length = x_size * y_size;
00391     ras.ras_type = RT_STANDARD;
00392     ras.ras_maptype = RMT_EQUAL_RGB;
00393     ras.ras_maplength = 256 * 3;
00394 
00395     fwrite_sun_long(&ras, sizeof(ras), 1, fp);
00396 
00397     for (i = 0; i < 256; i++)
00398         colors[i] = i;
00399     fwrite(colors, sizeof(colors), 1, fp);
00400     fwrite(colors, sizeof(colors), 1, fp);
00401     fwrite(colors, sizeof(colors), 1, fp);
00402 
00403     if (Pdv_debug) printf("before write %d %d\n",x_size,y_size*3) ;
00404     for(i = 0; i < y_size ; i++)
00405     {
00406         fwrite(&w->mat[i + w->top][w->left], rowsize, 1, fp);
00407     }
00408     fclose(fp);
00409     if (tmpi)
00410     {
00411         dvu_free_window(tmpi) ;
00412         free(tmpi->data) ;
00413     }
00414     return(0) ;
00415 }
00416 
00417 dvu_window * 
00418 dvu_read_window(char *fname)
00419 {
00420     struct rasterfile ras;
00421     FILE           *fp;
00422     int             i;
00423     int             rowsize ;
00424     int             x_size ;
00425     int             y_size ;
00426     int             depth ;
00427     int             bytes ;
00428     dvu_window      *s ;
00429 
00430     if ((fp = fopen(fname, "r")) == NULL)
00431     {
00432         edt_msg_printf_perror(
00433                 DVUFATAL, 
00434                 "Can't open source window file '%s' for reading", 
00435                 fname);
00436         return(0) ;
00437     }
00438 
00439     fread_sun_long(&ras, sizeof(ras), 1, fp);
00440     if (ras.ras_magic != RAS_MAGIC)
00441     {
00442         edt_msg(
00443                 DVUFATAL,
00444                 "%s not a sun raster file - exiting\n", fname);
00445         return(0) ;
00446     }
00447 
00448     x_size = ras.ras_width ;
00449     y_size = ras.ras_height ;
00450     depth = ras.ras_depth ;
00451     bytes = (depth + 7) / 8 ;
00452 
00453     rowsize = x_size * bytes ;
00454     if(rowsize & 1)
00455     {
00456         rowsize++ ;
00457     }
00458 
00459     fseek(fp, ras.ras_maplength, 1) ;
00460 
00461     s = (dvu_window *) dvu_init_window(NULL, 0, 0, x_size, y_size, rowsize, y_size, depth) ;
00462 
00463     for(i = 0; i < y_size ; i++)
00464     {
00465         fread(s->mat[i], rowsize, 1, fp) ;
00466     }
00467     fclose(fp);
00468     return(s) ;
00469 }
00470 
00494 dvu_write_image(char *fname, u_char *addr, int x_size, int y_size,int istride)
00495 {
00496     struct rasterfile ras;
00497     u_char          colors[256];
00498     FILE           *fp;
00499     int             i;
00500     int             rowsize ;
00501 
00502     if ((fp = fopen(fname, "wb")) == NULL)
00503     {
00504         edt_msg_printf_perror(
00505                 DVUFATAL, 
00506                 "Can't open destination data file '%s' for writing", 
00507                 fname);
00508         return (-1);
00509     }
00510 
00511     rowsize = x_size ;
00512     if(rowsize & 1)
00513     {
00514         rowsize++ ;
00515     }
00516     ras.ras_magic = RAS_MAGIC;
00517     ras.ras_width = x_size;
00518     ras.ras_height = y_size;
00519     ras.ras_depth = 8;
00520     ras.ras_length = x_size * y_size;
00521     ras.ras_type = RT_STANDARD;
00522     ras.ras_maptype = RMT_EQUAL_RGB;
00523     ras.ras_maplength = 256 * 3;
00524 
00525     fwrite_sun_long(&ras, sizeof(ras), 1, fp);
00526 
00527     for (i = 0; i < 256; i++)
00528         colors[i] = i;
00529     fwrite(colors, sizeof(colors), 1, fp);
00530     fwrite(colors, sizeof(colors), 1, fp);
00531     fwrite(colors, sizeof(colors), 1, fp);
00532 
00533     for(i = 0; i < y_size ; i++)
00534     {
00535         fwrite(addr, rowsize, 1, fp);
00536         addr += istride ;
00537     }
00538     fclose(fp);
00539     return(0) ;
00540 }
00541 
00542 
00555 dvu_write_rasfile24(char *fname, u_char *addr, int x_size, int y_size)
00556 {
00557     struct rasterfile ras;
00558     FILE           *fp;
00559     int             rowsize ;
00560     int             ret ;
00561 
00562     if ((fp = fopen(fname, "wb")) == NULL)
00563     {
00564         edt_msg_printf_perror(
00565                 DVUFATAL, 
00566                 "Can't open destination data file '%s' for writing", 
00567                 fname);
00568         return (-1);
00569     }
00570 
00571     rowsize = x_size ;
00572     if(rowsize & 1)
00573     {
00574         rowsize++ ;
00575     }
00576     ras.ras_magic = RAS_MAGIC;
00577     ras.ras_width = x_size;
00578     ras.ras_height = y_size;
00579     ras.ras_depth = 24;
00580     ras.ras_length = x_size * y_size;
00581     ras.ras_type = RT_STANDARD;
00582     ras.ras_maptype = RMT_NONE ;
00583     ras.ras_maplength = 0 ;
00584 
00585     fwrite_sun_long(&ras, sizeof(ras), 1, fp);
00586     if (Pdv_debug)
00587         printf("before write %d %d\n",x_size,y_size*3) ;
00588     ret = (int) fwrite(addr, x_size, y_size*3, fp);
00589     if(Pdv_debug)
00590         printf("done ret %d\n",ret) ;
00591     fclose(fp);
00592     return(0) ;
00593 }
00594 
00623 dvu_write_image24(char *fname, u_char *addr, int x_size, int y_size, int istride)
00624 {
00625     struct rasterfile ras;
00626     FILE           *fp;
00627     int              y ;
00628 
00629     if ((fp = fopen(fname, "wb")) == NULL)
00630     {
00631         edt_msg_printf_perror(
00632                 DVUFATAL, 
00633                 "Can't open destination data file '%s' for writing", 
00634                 fname);
00635         return (-1);
00636     }
00637 
00638     ras.ras_magic = RAS_MAGIC;
00639     ras.ras_width = x_size;
00640     ras.ras_height = y_size;
00641     ras.ras_depth = 24;
00642     ras.ras_length = x_size * y_size;
00643     ras.ras_type = RT_STANDARD;
00644     ras.ras_maptype = RMT_NONE ;
00645     ras.ras_maplength = 0 ;
00646 
00647     fwrite_sun_long(&ras, sizeof(ras), 1, fp);
00648     for(y = 0 ; y < y_size ; y++)
00649     {
00650         fwrite(addr, x_size*3, 1, fp);
00651         addr += istride*3 ;
00652     }
00653     fclose(fp);
00654     return(0) ;
00655 }
00656 
00657 
00658 static double wscale ;
00659 static int wmin ;
00660 static int wmax ;
00661 static u_char w2byte[4096] ;
00662 
00663 /* pass word input, byte output, count, and min and max desired range */
00664 dvu_wordscale(u_short *words, u_char *bytes, int count, 
00665                           int minbyte, int maxbyte, int doinit) 
00666 {
00667     static int did_init = 0 ;
00668     int i ;
00669     if (doinit)
00670     {
00671         wmin = words[0] ;
00672         wmax = words[0] ;
00673         for(i = 0 ; i < count ; i++)
00674         {
00675             if (words[i] < wmin) wmin = words[i] ;
00676             if (words[i] > wmax) wmax = words[i] ;
00677         }
00678         if (wmax == wmin)
00679         {
00680             if (Pdv_debug)
00681                 printf("wordscale - no range in input image - all words %d\n",wmax) ;
00682             return(-1) ;
00683         }
00684         wscale = (float)(maxbyte - minbyte)/(float)(wmax - wmin) ;
00685 
00686         for(i = 0 ; i < 4096 ; i++)
00687         {
00688             if (i < wmin) w2byte[i] = minbyte ;
00689             else if (i > wmax) w2byte[i] = maxbyte ;
00690             w2byte[i] = (u_char)((float)(i - wmin) * wscale + minbyte) ;
00691         }
00692     }
00693     for(i = 0 ; i < count ; i++)
00694     {
00695         bytes[i] = (u_char)w2byte[words[i]] ;
00696     }
00697     return(0) ;
00698 }
00699 
00700 /* pass word input, byte output, count, and min and max desired range */
00701 dvu_winscale(dvu_window *wi, dvu_window *bi, int minbyte, int maxbyte, int doinit) 
00702 {
00703     static int did_init = 0 ;
00704     int y, x ;
00705     int toy, tox ;
00706     u_short tmp ;
00707     int i ;
00708     if (doinit)
00709     {
00710         wmax = wmin = wi->mat16[wi->top][wi->left] ;
00711         for(y = wi->top ; y <= wi->bottom ; y++)
00712         {
00713             for(x = wi->left ; x <= wi->right ; x++)
00714             {
00715                 tmp = wi->mat16[y][x] ;
00716                 if (tmp < wmin) wmin = tmp ;
00717                 if (tmp > wmax) wmax = tmp ;
00718             }
00719         }
00720         if (wmax == wmin)
00721         {
00722             printf("wordscale - no range in input image - all words %d\n",wmax) ;
00723             return(-1) ;
00724         }
00725         wscale = (float)(maxbyte - minbyte)/(float)(wmax - wmin) ;
00726 
00727         for(i = 0 ; i < 4096 ; i++)
00728         {
00729             if (i < wmin) w2byte[i] = minbyte ;
00730             else if (i > wmax) w2byte[i] = maxbyte ;
00731             w2byte[i] = (u_char )((float)(i - wmin) * wscale + minbyte) ;
00732         }
00733     }
00734     toy = bi->top ;
00735     for(y = wi->top ; y <= wi->bottom ; y++)
00736     {
00737         tox = bi->left ;
00738         for(x = wi->left ; x <= wi->right ; x++)
00739         {
00740             bi->mat[toy][tox] = (u_char)w2byte[wi->mat16[y][x]] ;
00741             tox++ ;
00742         }
00743         toy++ ;
00744     }
00745     return(0) ;
00746 }
00747 
00748 static int
00749 init_lookup(int depth)
00750 {
00751     int ncolors = 1 << depth ;
00752     int i ;
00753     if (Pdv_debug) 
00754         printf("init_lookup %d bit %d entries\n", depth,ncolors) ;
00755     if (!hist)
00756     {
00757         hist = (int *)malloc(ncolors * sizeof(int)) ;
00758         if (!hist)
00759         {
00760             printf("can't alloc mem for %d element histogram\n",ncolors) ;
00761             return(-1) ;
00762         }
00763     }
00764     if (depth > 8)
00765     {
00766         if (!slookup)
00767             slookup = (u_short *)malloc(ncolors * sizeof(u_short)) ;
00768         if (!slookup)
00769         {
00770             printf("can't alloc mem for %d element lookup\n",ncolors) ;
00771             return(-1) ;
00772         }
00773         for (i = 0 ; i < ncolors ; i++)
00774         {
00775             slookup[i] = i ;
00776             hist[i] = 0 ;
00777         }
00778     }
00779     else
00780     {
00781         if (!blookup)
00782             blookup = (u_char *)malloc(ncolors * sizeof(u_char)) ;
00783         if (!blookup)
00784         {
00785             printf("can't alloc mem for %d element lookup\n",ncolors) ;
00786             return(-1) ;
00787         }
00788         for (i = 0 ; i < ncolors ; i++)
00789         {
00790             blookup[i] = i ;
00791             hist[i] = 0 ;
00792         }
00793     }
00794     return(0) ;
00795 }
00796 
00797 
00806 dvu_histeq(u_char *src, u_char *dst, int size, int depth)
00807 {
00808     int i ;
00809     unsigned long total;
00810     double intermediate ;
00811     int ncolors = 1 << depth ;
00812     int ret ;
00813 
00814     if(Pdv_debug) printf("dvu_histeq %p %p %d %d\n",src,dst,size,depth) ;
00815 
00816     if (ret = init_lookup(depth)) return(ret) ;
00817 
00818     /* compute histeq curve */
00819     total = 0;
00820     if (depth > 8)
00821     {
00822         u_short *s ;
00823         s = (u_short *)src ;
00824         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00825         for (i = 0 ; i < ncolors ; i++)
00826         {
00827             total += hist[i];
00828             intermediate = total ;
00829             intermediate *= (ncolors - 1) ;
00830             intermediate /= size ;
00831             slookup[i] = (u_short)intermediate ;
00832         }
00833     }
00834     else
00835     {
00836         u_char *s ;
00837         s = (u_char *)src ;
00838         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00839         for (i = 0 ; i < ncolors ; i++)
00840         {
00841             total += hist[i];
00842             blookup[i] = (u_char)((total * (ncolors - 1)) / size) ;
00843         }
00844     }
00845     dvu_lookup(src,dst,size,depth) ;
00846     return(0) ;
00847 }
00848 
00849 
00850 /* the following 4 routines are work in progress */
00851 dvu_load_lookup(char *filename,int depth) 
00852 {
00853     FILE *ltab ;
00854     int index, val ;
00855     int ncolors = 1 << depth ;
00856     int ret ;
00857 
00858     if (ret = init_lookup(depth)) return(ret) ;
00859 
00860     if (Pdv_debug)
00861         printf("loading lookup from %s\n",filename) ;
00862     if (!(ltab = fopen(filename,"r")))
00863     {
00864         printf("can't open %s for lookup table\n",filename) ;
00865         return(-1) ;
00866     }
00867     index = 0 ;
00868     while(index < ncolors && (fscanf(ltab,"%ld",&val)))
00869     {
00870         if (depth > 8)
00871             slookup[index++] = val ;
00872         else
00873             blookup[index++] = val ;
00874     }
00875     if (Pdv_debug) printf("read %d values\n",index) ;
00876     fclose(ltab) ;
00877     return(0) ;
00878 }
00879 
00880 dvu_save_lookup(char *filename,int depth) 
00881 {
00882     FILE *ltab ;
00883     int ret ;
00884     int i ;
00885     int ncolors = 1 << depth ;
00886     if (Pdv_debug)
00887         printf("saving lookup to %s\n",filename) ;
00888 
00889     if (!blookup && !slookup)
00890         if (ret = init_lookup(depth)) return(ret) ;
00891 
00892     if (!(ltab = fopen(filename,"wb")))
00893     {
00894         edt_msg_printf_perror(
00895                 DVUFATAL, 
00896                 "Can't open '%s' for lookup table", 
00897                 filename);
00898         return(-1) ;
00899     }
00900     if (Pdv_debug > 1)
00901     {
00902         if (depth > 8)
00903             for(i = 0 ; i < ncolors ; i++) printf(" %d (%d)\n",
00904                     slookup[i],hist[i]) ;
00905         else
00906             for(i = 0 ; i < ncolors ; i++) printf(" %d (%d)\n",
00907                     blookup[i],hist[i]) ;
00908     }
00909     if (depth > 8)
00910         for(i = 0 ; i < ncolors ; i++) fprintf(ltab," %d\n",
00911                 slookup[i]) ;
00912     else
00913         for(i = 0 ; i < ncolors ; i++) fprintf(ltab," %d\n",
00914                 blookup[i]) ;
00915     fclose(ltab) ;
00916     return(0) ;
00917 }
00918 
00919 dvu_lookup(u_char *src, u_char *dst, int size, int depth)
00920 {
00921     if (Pdv_debug)
00922         printf("dvu_lookup\n") ;
00923     if (depth > 8)
00924     {
00925         u_short *s ;
00926         u_short *d ;
00927         int i ;
00928         d = (u_short *)dst ;
00929         s = (u_short *)src ;
00930         for (i = 0 ; i < size ; i++)
00931         {
00932             *d++ = slookup[*s++] ;
00933         }
00934     }
00935     else
00936     {
00937         u_char *s ;
00938         u_char *d ;
00939         int i ;
00940         d = (u_char *)dst ;
00941         s = (u_char *)src ;
00942         for (i = 0 ; i < size ; i++)
00943         {
00944             *d++ = blookup[*s++] ;
00945         }
00946     }
00947     if (Pdv_debug)
00948         printf("dvu_lookup done\n") ;
00949 
00950     return(0) ;
00951 }
00952 
00962 dvu_exp_histeq(u_char *src, u_char *dst, int size, int depth, int cutoff)
00963 {
00964     int i ;
00965     unsigned long total;
00966     int ncolors = 1 << depth ;
00967     int ret ;
00968     int min, max, distinct ;
00969     float inc ;
00970     float val ;
00971     int ival ;
00972 
00973     if(Pdv_debug) printf("dvu_exp_histeq %p %p %d %d\n",src,dst,size,depth) ;
00974 
00975     if (ret = init_lookup(depth)) return(ret) ;
00976 
00977     /* compute histeq curve */
00978     total = 0;
00979     if (depth > 8)
00980     {
00981         u_short *s ;
00982         s = (u_short *)src ;
00983         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00984     }
00985     else
00986     {
00987         u_char *s ;
00988         s = (u_char *)src ;
00989         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00990     }
00991     for(i = 0 ; i < ncolors ; i++)
00992     {
00993         if (hist[i] >= cutoff) 
00994         {
00995             min = i ;
00996             break ;
00997         }
00998     }
00999     for(i = ncolors-1 ; i >= 0; i--)
01000     {
01001         if (hist[i] >= cutoff) 
01002         {
01003             max = i ;
01004             break ;
01005         }
01006     }
01007     distinct = 0 ;
01008     for(i = 0 ; i < ncolors ; i++)
01009     {
01010         if (hist[i] >= cutoff) distinct++ ;
01011     }
01012     if (Pdv_debug)
01013         printf("exp_histeq:min %d max %d distinct %d (with %d pixel cutoff)\n",
01014             min,max,distinct,cutoff) ;
01015     inc = (float)ncolors / (float)distinct ;
01016     val = 0.0 ;
01017     for (i = 0 ; i < ncolors ; i++)
01018     {
01019         ival = (int)(val + 0.5) ;
01020         if (hist[i] >= cutoff) val += inc ;
01021         if (Pdv_debug > 2) printf("%d (%d) %3.2f %d\n",
01022                 i,hist[i],val,ival) ;
01023         if (depth > 8)
01024             slookup[i] = ival ;
01025         else
01026             blookup[i] = ival ;
01027     }
01028 
01029     dvu_lookup(src,dst,size,depth) ;
01030     return(0) ;
01031 }
01032 
01033 void
01034 dvu_free_tables()
01035 {
01036     if (slookup) free(slookup) ;
01037     if (hist) free(hist) ;
01038 }
01039 /*
01040  * setup a window structure with y indexes to start of each row
01041  * to cut down on number of parameters and hopefully make for 
01042  * some more common code
01043  */
01044 dvu_window *
01045 dvu_init_window(u_char *data, int sx, int sy, 
01046                                 int dx, int dy, int xdim, int ydim, int depth)
01047 {
01048     dvu_window *s ;
01049     int y ;
01050     int bytes ;
01051 
01052     s = (dvu_window *) malloc(sizeof(dvu_window)) ;
01053     bytes = (depth + 7) / 8 ;
01054     if (!data) data = (u_char *)malloc(xdim*ydim*bytes) ;
01055 
01056     s->left = sx ;
01057     s->right = sx + dx - 1 ;
01058     s->top = sy ;
01059     s->bottom = sy + dy - 1 ;
01060     s->xdim = xdim ;
01061     s->ydim = ydim ;
01062     s->depth = depth ;
01063     s->data = data ;
01064     s->mat = 0 ;
01065     s->mat16 = 0 ;
01066     s->mat24 = 0 ;
01067     switch(bytes)
01068     {
01069     case 1:
01070         s->mat = (u_char **) calloc(ydim,sizeof(u_char *)) ;
01071         for (y = 0 ; y < ydim ; y++)
01072             s->mat[y] = data + y * xdim  ;
01073         break ;
01074     case 2:
01075         s->mat16 = (u_short **) calloc(ydim,sizeof(u_short *)) ;
01076         for (y = 0 ; y < ydim ; y++)
01077             s->mat16[y] = (u_short *)(data + y * xdim * 2)  ;
01078         break ;
01079     case 3:
01080         s->mat24 = (bgrpoint **) calloc(ydim,sizeof(bgrpoint *)) ;
01081         for (y = 0 ; y < ydim ; y++)
01082             s->mat24[y] = (bgrpoint *)(data + y * xdim * 3)  ;
01083         break ;
01084     }
01085     return(s) ;
01086 }
01087 
01088 /*
01089  * use for reseting sub image in window or changing data
01090  */
01091 dvu_window *
01092 dvu_reset_window(dvu_window *s, u_char *data, int sx, int sy, int dx, int dy)
01093 {
01094     register int y ;
01095     register int stride ;
01096     register int rows ;
01097     register int bytes ;
01098 
01099     s->left = sx ;
01100     s->right = sx + dx - 1 ;
01101     s->top = sy ;
01102     s->bottom = sy + dy - 1 ;
01103     s->data = data ;
01104     rows = s->ydim ;
01105     stride = s->xdim ;
01106     bytes = (s->depth + 7) / 8 ;
01107     switch(bytes)
01108     {
01109     case 1:
01110         for (y = 0 ; y < rows ; y++)
01111             s->mat[y] = data + y * stride  ;
01112         break ;
01113     case 2:
01114         for (y = 0 ; y < rows ; y++)
01115             s->mat16[y] = (u_short *)(data + y * stride * 2)  ;
01116         break ;
01117     case 3:
01118         for (y = 0 ; y < rows ; y++)
01119             s->mat24[y] = (bgrpoint *)(data + y * stride * 3)  ;
01120         break ;
01121     }
01122     return(s) ;
01123 }
01124 
01125 /*
01126  * free struct for window - not data
01127  */
01128 dvu_free_window(dvu_window *w)
01129 {
01130     free(w->mat) ;
01131     free(w) ;
01132     return(0) ;
01133 }
01134 
01135 ten2one(u_short *wbuf, u_char *bbuf, int count)
01136 {
01137     dvu_word2byte(wbuf, bbuf, count, 10) ;
01138     return(0) ;
01139 }
01140 
01141 dvu_word2byte(u_short *wbuf, u_char *bbuf, int count, int depth)
01142 {
01143     register u_short *from, *end;
01144     register u_char *to;
01145         int shift = depth - 8 ;
01146 
01147     from = wbuf;
01148     end = from + count;
01149     to = bbuf;
01150     while (from < end)
01151     {
01152         *to++ = *from++ >> shift;
01153     }
01154     return(0) ;
01155 }
01156 
01157 /*
01158  * dvu_word2byte with args for scanline stride
01159  */
01160 dvu_word2byte_with_stride(u_short *wbuf, u_char *bbuf, 
01161                                                   int wstride, int bstride, 
01162                                                   int xsize, int ysize, int depth)
01163 {
01164     register u_short *from, *end;
01165     register u_char *to;
01166     register u_char *next_toptr;
01167     register u_short *next_fromptr;
01168     register u_short *end_fromptr;
01169         int shift = depth - 8 ;
01170 
01171     next_fromptr = wbuf;
01172     next_toptr = bbuf;
01173     end_fromptr = wbuf + (xsize * ysize);
01174     while (next_fromptr < end_fromptr)
01175     {
01176         from = next_fromptr;
01177         to = next_toptr;
01178         end = next_fromptr + xsize;
01179 
01180         while (from < end)
01181             *to++ = *from++ >> shift;
01182 
01183         next_fromptr += wstride;
01184         next_toptr += bstride;
01185     }
01186     return(0) ;
01187 }
01188 
01189 
01190 void
01191 dvu_perror(char *str)
01192 {
01193 #ifdef _NT_
01194         LPVOID lpMsgBuf;
01195 
01196 FormatMessage(
01197     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
01198     NULL,
01199     GetLastError(),
01200     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /*  Default language */
01201     (LPTSTR) &lpMsgBuf,
01202     0,
01203     NULL
01204 );
01205 
01206         fprintf(stderr, "%s: %s\n", str, lpMsgBuf) ;
01207 #else
01208         perror(str) ;
01209 #endif
01210 }
01211 
01212 /*******************************************/
01213 static void putshort(FILE *fp, int i)
01214     
01215 {
01216   int c, c1;
01217 
01218   c = ((unsigned int ) i) & 0xff;  c1 = (((unsigned int) i)>>8) & 0xff;
01219   putc(c, fp);   putc(c1,fp);
01220 }
01221 
01222 
01223 /*******************************************/
01224 static void putint(FILE *fp, int i)
01225    
01226 {
01227   int c, c1, c2, c3;
01228   c  = ((unsigned int ) i)      & 0xff;  
01229   c1 = (((unsigned int) i)>>8)  & 0xff;
01230   c2 = (((unsigned int) i)>>16) & 0xff;
01231   c3 = (((unsigned int) i)>>24) & 0xff;
01232 
01233   putc(c, fp);   putc(c1,fp);  putc(c2,fp);  putc(c3,fp);
01234 }
01235 
01236 
01237 #ifndef _NT_
01238 #define BI_RGB 0L
01239 #endif
01240 
01262 int 
01263 dvu_write_bmp(char *fname, u_char *buffer, int width, int height)
01264 {
01265   int w = width, h = height; /* shortcut names */
01266   FILE *fp ;
01267   int bperlin ;
01268   int nc = 256 ;
01269   int nbits = 8 ;
01270   int   i,j,padw;
01271   u_char *pp;
01272 
01273   fp = fopen(fname,"wb") ;
01274   if (!fp) return(-1) ;
01275   
01276   bperlin = ((w * nbits + 31) / 32) * 4;   /* # bytes written per line */
01277 
01278   putc('B', fp);  putc('M', fp);           /* BMP file magic number */
01279 
01280   /* compute filesize and write it */
01281   i = 14 +                /* size of bitmap file header */
01282       40 +                /* size of bitmap info header */
01283       (nc * 4) +          /* size of colormap */
01284       bperlin * h;        /* size of image data */
01285 
01286   putint(fp, i);
01287   putshort(fp, 0);        /* reserved1 */
01288   putshort(fp, 0);        /* reserved2 */
01289   putint(fp, 14 + 40 + (nc * 4));  /* offset from BOfile to BObitmap */
01290 
01291   putint(fp, 40);         /* biSize: size of bitmap info header */
01292   putint(fp, w);          /* biWidth */
01293   putint(fp, h);          /* biHeight */
01294   putshort(fp, 1);        /* biPlanes:  must be '1' */
01295   putshort(fp, nbits);    /* biBitCount: 1,4,8, or 24 */
01296   putint(fp, BI_RGB);     /* biCompression:  BI_RGB, BI_RLE8 or BI_RLE4 */
01297   putint(fp, bperlin*h);  /* biSizeImage:  size of raw image data */
01298   putint(fp, 75 * 39);    /* biXPelsPerMeter: (75dpi * 39" per meter) */
01299   putint(fp, 75 * 39);    /* biYPelsPerMeter: (75dpi * 39" per meter) */
01300   putint(fp, nc);         /* biClrUsed: # of colors used in cmap */
01301   putint(fp, nc);         /* biClrImportant: same as above */
01302 
01303 
01304   /* write out the colormap */
01305   for (i=0; i<nc; i++) {
01306       putc(i,fp);
01307       putc(i,fp);
01308       putc(i,fp);
01309       putc(0,fp);
01310     }
01311 
01312   /* write out the image */
01313 
01314 
01315   padw = ((w + 3)/4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
01316 
01317   for (i=h-1; i>=0; i--) {
01318     pp = buffer + (i * w);
01319 
01320     for (j=0; j<w; j++) putc(*pp++, fp);
01321     for ( ; j<padw; j++) putc(0, fp);
01322   }
01323 
01324   fclose(fp) ;
01325   return(0) ;
01326 }
01327 
01328 #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
01329 
01330 #ifndef WIN32
01331 
01332 #define DWORD unsigned long
01333 #define LONG long
01334 #define WORD unsigned short
01335 #define BYTE unsigned char
01336 
01337 
01338 typedef struct tagBITMAPFILEHEADER {
01339         WORD    bfType;
01340         DWORD   bfSize;
01341         WORD    bfReserved1;
01342         WORD    bfReserved2;
01343         DWORD   bfOffBits;
01344 } BITMAPFILEHEADER;
01345 
01346 /* structures for defining DIBs */
01347 typedef struct tagBITMAPCOREHEADER {
01348         DWORD   bcSize;                 /* used to get to color table */
01349         WORD    bcWidth;
01350         WORD    bcHeight;
01351         WORD    bcPlanes;
01352         WORD    bcBitCount;
01353 } BITMAPCOREHEADER ;
01354 
01355 
01356 typedef struct tagBITMAPINFOHEADER{
01357         DWORD      biSize;
01358         LONG       biWidth;
01359         LONG       biHeight;
01360         WORD       biPlanes;
01361         WORD       biBitCount;
01362         DWORD      biCompression;
01363         DWORD      biSizeImage;
01364         LONG       biXPelsPerMeter;
01365         LONG       biYPelsPerMeter;
01366         DWORD      biClrUsed;
01367         DWORD      biClrImportant;
01368 } BITMAPINFOHEADER;
01369 
01370 /* constants for the biCompression field */
01371 /* #define BI_RGB        0L */ /* already defined above */
01372 #define BI_RLE8       1L
01373 #define BI_RLE4       2L
01374 #define BI_BITFIELDS  3L
01375 
01376 typedef struct tagRGBQUAD {
01377         BYTE    rgbBlue;
01378         BYTE    rgbGreen;
01379         BYTE    rgbRed;
01380         BYTE    rgbReserved;
01381 } RGBQUAD, *LPRGBQUAD;
01382 
01383 typedef struct tagBITMAPINFO {
01384     BITMAPINFOHEADER    bmiHeader;
01385     RGBQUAD             bmiColors[1];
01386 } BITMAPINFO;
01387 
01388 #else
01389 
01390 #endif
01391 
01411 int
01412 dvu_write_bmp_24(char *fname, u_char *buffer, int width, int height)
01413 
01414 {
01415         int w = width, h = height; /* shortcut names */
01416 
01417         u_char     *bp;
01418 
01419         FILE *f;
01420         DWORD dwDIBSize;
01421         
01422         DWORD dwBmBitsSize;
01423 
01424         int nPadding;
01425         int widthbytes = w * 3;
01426 
01427         int row;
01428 
01429         BITMAPFILEHEADER bmfHdr; /* Header for Bitmap file */
01430 
01431         /* Allocate memory for the header (if necessary) */
01432         BITMAPINFO *pBMI = (BITMAPINFO *)
01433                         malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
01434 
01435   /* Fill in the header info. */
01436         BITMAPINFOHEADER* pBI = (BITMAPINFOHEADER*) pBMI;
01437         pBI->biSize = sizeof(BITMAPINFOHEADER);
01438         pBI->biWidth = w;
01439         pBI->biHeight = h;
01440         pBI->biPlanes = 1;
01441         pBI->biBitCount = 24;
01442         pBI->biCompression = BI_RGB;
01443         pBI->biSizeImage = 0;
01444         pBI->biXPelsPerMeter = 0;
01445         pBI->biYPelsPerMeter = 0;
01446         pBI->biClrUsed = 0;
01447         pBI->biClrImportant = 0;
01448 
01449 
01450         /* Fill Header */
01451         /* Fill in the fields of the file header */
01452 
01453         /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
01454         bmfHdr.bfType = 0x4D42;  /* "BM" */
01455 
01456         /* Calculate the size of the DIB. */
01457         /* First, find size of header plus size of color table.  Since the */
01458         /* first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER contains */
01459         /* the size of the structure, let's use this. Partial Calculation. */
01460 
01461         dwDIBSize = *(unsigned long *)pBMI ;
01462         
01463         dwBmBitsSize = WIDTHBYTES(w * ((DWORD)pBMI->bmiHeader.biBitCount)) * 
01464                 h;
01465 
01466         nPadding = WIDTHBYTES(w * ((DWORD)pBMI->bmiHeader.biBitCount)) -
01467                         w * (3);
01468 
01469         dwDIBSize += dwBmBitsSize;
01470 
01471         /* Now, since we have calculated the correct size, why don't we */
01472         /* fill in the biSizeImage field (this will fix any .BMP files */
01473         /* which have this field incorrect). */
01474         pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
01475                 
01476         /* Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) */
01477         bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
01478         bmfHdr.bfReserved1 = 0;
01479         bmfHdr.bfReserved2 = 0;
01480 
01481         /* Now, calculate the offset the actual bitmap bits will be in */
01482         /* the file -- It's the Bitmap file header plus the DIB header, */
01483         /* plus the size of the color table. */
01484         bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
01485                 pBMI->bmiHeader.biSize;
01486 
01487         /* Open  */
01488         f = fopen(fname, "wb");
01489 
01490 
01491         /* Write Header  */
01492         fwrite(&bmfHdr,1, sizeof(bmfHdr),f);
01493         fwrite(pBMI, 1, pBMI->bmiHeader.biSize,f);
01494         /* Write Data */
01495         
01496         bp = buffer + (h-1) * (w *3);
01497 
01498         for (row = h-1;row >= 0;row--, bp -= widthbytes)
01499         {
01500                 fwrite(bp,1,w * 3,f);
01501                 if (nPadding)
01502                         fwrite(bp,1,nPadding,f);
01503         }
01504 
01505         /* Close File */
01506         fclose(f);
01507 
01508         return 0;
01509 }
01510 
01526 int 
01527 dvu_write_raw(int imagesize, u_char *imagebuf, char *fname)
01528 {
01529         FILE *fd ;
01530         if ((fd = fopen(fname,"wb")) == NULL)
01531         {
01532                 dvu_perror(fname) ;
01533                 return(-1) ;
01534         }
01535         fwrite(imagebuf,imagesize,1,fd) ;
01536         fclose(fd) ;
01537     return(0) ;
01538 }   
01539 
01540 
01541 static u_char *
01542 create_cast_tbl(depth_bits, nents)
01543 int depth_bits, nents;
01544 {
01545     int i;
01546     u_char *tbl;
01547     float mult;
01548     float fmin=0.0;
01549     int ncolors = 1 << depth_bits;
01550 
01551     mult = (float)255.0/(float)ncolors;
01552     if ((tbl = (u_char *)malloc(ncolors * sizeof(char))) == NULL)
01553     {
01554         printf("malloc for cast_tbl failed, size %d\n", ncolors);
01555         exit(0);
01556     }
01557 
01558     for (i=0; i < ncolors; i++)
01559     {
01560         tbl[i] = (int)(fmin + ((mult * (float)i) + 0.5));
01561     }
01562 
01563     if (Pdv_debug)
01564     {
01565         printf("Cast_tbl: depth (bytes) %d nents %d ncolors %d mult %1.2f\n",
01566                                             depth_bits, nents, ncolors, mult);
01567         printf("Cast_tbl %d: %d\n", 0, tbl[0]);
01568         printf("Cast_tbl %d: %d\n", ncolors/2, tbl[ncolors/2]);
01569         printf("Cast_tbl %d: %d\n", ncolors-1, tbl[ncolors-1]);
01570     }
01571 
01572 
01573 
01574 
01575     return tbl;
01576 }    
01577 
01578 static void
01579 free_cast_tbl()
01580 {
01581     free(Cast_tbl);
01582     Cast_tbl = NULL;
01583 }
01584 
01585 /*
01586  * just not trusting byte order stuff, and also need to have char buffers
01587  * for this kind of thing sometimes....
01588  */
01589 void
01590 dvu_long_to_charbuf(unsigned int val, u_char *buf)
01591 {
01592     buf[0] = (u_char) ((val & 0xff000000) >> 24);
01593     buf[1] = (u_char) ((val & 0x00ff0000) >> 16);
01594     buf[2] = (u_char) ((val & 0x0000ff00) >> 8);
01595     buf[3] = (u_char) ((val & 0x000000ff) );
01596 }
01597  /* end weakgroup */
01599 

Generated on Mon May 12 16:38:54 2008 by  doxygen 1.5.1