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 
00275         for (i=0; i<depth_bits; i++)
00276                 mask |= 1 << i;
00277 
00278         if ((fp = fopen(fname, "wb")) == NULL) {
00279                 edt_msg_printf_perror(
00280                                 DVUFATAL, 
00281                                 "Can't open destination data file '%s' for writing", 
00282                                 fname);
00283                 return -1;
00284         }
00285 
00286         if (Cast_tbl == NULL)
00287                 Cast_tbl = create_cast_tbl(depth_bits, 256);
00288 
00289 
00290         if (Pdv_debug) printf("writing rasterfile header to %s\n", fname);
00291         if (Pdv_debug) printf("x %d y %d addr %p name %s\n", x_size, y_size, addr, fname);
00292         rowsize = x_size ;
00293         if(rowsize & 1)
00294         {
00295                 rowsize++ ;
00296         }
00297         ras.ras_magic = RAS_MAGIC;
00298         ras.ras_width = x_size;
00299         ras.ras_height = y_size;
00300         ras.ras_depth = 8;
00301         ras.ras_length = x_size * y_size;
00302         ras.ras_type = RT_STANDARD;
00303         ras.ras_maptype = RMT_EQUAL_RGB;
00304         ras.ras_maplength = 256 * 3;
00305 
00306         scanline = (u_char *)malloc(x_size * sizeof(short));
00307 
00308         if ((ret = fwrite_sun_long(&ras, sizeof(ras), 1, fp)) != 1)
00309                 goto err_ret;
00310 
00311         for (i = 0; i < 256; i++)
00312                 colors[i] = i;
00313 
00314         if (fwrite(colors, sizeof(colors), 1, fp) != 1)
00315                 goto err_ret;
00316         if (fwrite(colors, sizeof(colors), 1, fp) != 1)
00317                 goto err_ret;
00318         if (fwrite(colors, sizeof(colors), 1, fp) != 1)
00319                 goto err_ret;
00320 
00321 
00322         shortp = (u_short *)addr;
00323         for(i=0; i<y_size ; i++)
00324         {
00325                 for (j=0; j<x_size; j++)
00326                         scanline[j] = Cast_tbl[(*shortp++) & mask];
00327                 if ((ret = fwrite(scanline, rowsize, 1, fp)) != 1)
00328                         goto err_ret;
00329         }
00330         fclose(fp);
00331         free(scanline);
00332         free_cast_tbl();
00333         return 0;
00334 
00335 err_ret:
00336         ret = errno;
00337         fclose(fp);
00338         free(scanline);
00339         free_cast_tbl();
00340         return ret;
00341 }
00342 
00343 int
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 int
00495 dvu_write_image(char *fname, u_char *addr, int x_size, int y_size,int istride)
00496 {
00497     struct rasterfile ras;
00498     u_char          colors[256];
00499     FILE           *fp;
00500     int             i;
00501     int             rowsize ;
00502 
00503     if ((fp = fopen(fname, "wb")) == NULL)
00504     {
00505         edt_msg_printf_perror(
00506                 DVUFATAL, 
00507                 "Can't open destination data file '%s' for writing", 
00508                 fname);
00509         return (-1);
00510     }
00511 
00512     rowsize = x_size ;
00513     if(rowsize & 1)
00514     {
00515         rowsize++ ;
00516     }
00517     ras.ras_magic = RAS_MAGIC;
00518     ras.ras_width = x_size;
00519     ras.ras_height = y_size;
00520     ras.ras_depth = 8;
00521     ras.ras_length = x_size * y_size;
00522     ras.ras_type = RT_STANDARD;
00523     ras.ras_maptype = RMT_EQUAL_RGB;
00524     ras.ras_maplength = 256 * 3;
00525 
00526     fwrite_sun_long(&ras, sizeof(ras), 1, fp);
00527 
00528     for (i = 0; i < 256; i++)
00529         colors[i] = i;
00530     fwrite(colors, sizeof(colors), 1, fp);
00531     fwrite(colors, sizeof(colors), 1, fp);
00532     fwrite(colors, sizeof(colors), 1, fp);
00533 
00534     for(i = 0; i < y_size ; i++)
00535     {
00536         fwrite(addr, rowsize, 1, fp);
00537         addr += istride ;
00538     }
00539     fclose(fp);
00540     return(0) ;
00541 }
00542 
00543 
00556 int
00557 dvu_write_rasfile24(char *fname, u_char *addr, int x_size, int y_size)
00558 {
00559     struct rasterfile ras;
00560     FILE           *fp;
00561     int             rowsize ;
00562     int             ret ;
00563 
00564     if ((fp = fopen(fname, "wb")) == NULL)
00565     {
00566         edt_msg_printf_perror(
00567                 DVUFATAL, 
00568                 "Can't open destination data file '%s' for writing", 
00569                 fname);
00570         return (-1);
00571     }
00572 
00573     rowsize = x_size ;
00574     if(rowsize & 1)
00575     {
00576         rowsize++ ;
00577     }
00578     ras.ras_magic = RAS_MAGIC;
00579     ras.ras_width = x_size;
00580     ras.ras_height = y_size;
00581     ras.ras_depth = 24;
00582     ras.ras_length = x_size * y_size;
00583     ras.ras_type = RT_STANDARD;
00584     ras.ras_maptype = RMT_NONE ;
00585     ras.ras_maplength = 0 ;
00586 
00587     fwrite_sun_long(&ras, sizeof(ras), 1, fp);
00588     if (Pdv_debug)
00589         printf("before write %d %d\n",x_size,y_size*3) ;
00590     ret = (int) fwrite(addr, x_size, y_size*3, fp);
00591     if(Pdv_debug)
00592         printf("done ret %d\n",ret) ;
00593     fclose(fp);
00594     return(0) ;
00595 }
00596 
00625 int
00626 dvu_write_image24(char *fname, u_char *addr, int x_size, int y_size, int istride)
00627 {
00628     struct rasterfile ras;
00629     FILE           *fp;
00630     int              y ;
00631 
00632     if ((fp = fopen(fname, "wb")) == NULL)
00633     {
00634         edt_msg_printf_perror(
00635                 DVUFATAL, 
00636                 "Can't open destination data file '%s' for writing", 
00637                 fname);
00638         return (-1);
00639     }
00640 
00641     ras.ras_magic = RAS_MAGIC;
00642     ras.ras_width = x_size;
00643     ras.ras_height = y_size;
00644     ras.ras_depth = 24;
00645     ras.ras_length = x_size * y_size;
00646     ras.ras_type = RT_STANDARD;
00647     ras.ras_maptype = RMT_NONE ;
00648     ras.ras_maplength = 0 ;
00649 
00650     fwrite_sun_long(&ras, sizeof(ras), 1, fp);
00651     for(y = 0 ; y < y_size ; y++)
00652     {
00653         fwrite(addr, x_size*3, 1, fp);
00654         addr += istride*3 ;
00655     }
00656     fclose(fp);
00657     return(0) ;
00658 }
00659 
00660 
00661 static double wscale ;
00662 static int wmin ;
00663 static int wmax ;
00664 static u_char w2byte[4096] ;
00665 
00666 /* pass word input, byte output, count, and min and max desired range */
00667 int
00668 dvu_wordscale(u_short *words, u_char *bytes, int count, 
00669                           int minbyte, int maxbyte, int doinit) 
00670 {
00671     int i ;
00672     if (doinit)
00673     {
00674         wmin = words[0] ;
00675         wmax = words[0] ;
00676         for(i = 0 ; i < count ; i++)
00677         {
00678             if (words[i] < wmin) wmin = words[i] ;
00679             if (words[i] > wmax) wmax = words[i] ;
00680         }
00681         if (wmax == wmin)
00682         {
00683             if (Pdv_debug)
00684                 printf("wordscale - no range in input image - all words %d\n",wmax) ;
00685             return(-1) ;
00686         }
00687         wscale = (float)(maxbyte - minbyte)/(float)(wmax - wmin) ;
00688 
00689         for(i = 0 ; i < 4096 ; i++)
00690         {
00691             if (i < wmin) w2byte[i] = minbyte ;
00692             else if (i > wmax) w2byte[i] = maxbyte ;
00693             w2byte[i] = (u_char)((float)(i - wmin) * wscale + minbyte) ;
00694         }
00695     }
00696     for(i = 0 ; i < count ; i++)
00697     {
00698         bytes[i] = (u_char)w2byte[words[i]] ;
00699     }
00700     return(0) ;
00701 }
00702 
00703 /* pass word input, byte output, count, and min and max desired range */
00704 int
00705 dvu_winscale(dvu_window *wi, dvu_window *bi, int minbyte, int maxbyte, int doinit) 
00706 {
00707     int y, x ;
00708     int toy, tox ;
00709     u_short tmp ;
00710     int i ;
00711     if (doinit)
00712     {
00713         wmax = wmin = wi->mat16[wi->top][wi->left] ;
00714         for(y = wi->top ; y <= wi->bottom ; y++)
00715         {
00716             for(x = wi->left ; x <= wi->right ; x++)
00717             {
00718                 tmp = wi->mat16[y][x] ;
00719                 if (tmp < wmin) wmin = tmp ;
00720                 if (tmp > wmax) wmax = tmp ;
00721             }
00722         }
00723         if (wmax == wmin)
00724         {
00725             printf("wordscale - no range in input image - all words %d\n",wmax) ;
00726             return(-1) ;
00727         }
00728         wscale = (float)(maxbyte - minbyte)/(float)(wmax - wmin) ;
00729 
00730         for(i = 0 ; i < 4096 ; i++)
00731         {
00732             if (i < wmin) w2byte[i] = minbyte ;
00733             else if (i > wmax) w2byte[i] = maxbyte ;
00734             w2byte[i] = (u_char )((float)(i - wmin) * wscale + minbyte) ;
00735         }
00736     }
00737     toy = bi->top ;
00738     for(y = wi->top ; y <= wi->bottom ; y++)
00739     {
00740         tox = bi->left ;
00741         for(x = wi->left ; x <= wi->right ; x++)
00742         {
00743             bi->mat[toy][tox] = (u_char)w2byte[wi->mat16[y][x]] ;
00744             tox++ ;
00745         }
00746         toy++ ;
00747     }
00748     return(0) ;
00749 }
00750 
00751 static int
00752 init_lookup(int depth)
00753 {
00754     int ncolors = 1 << depth ;
00755     int i ;
00756     if (Pdv_debug) 
00757         printf("init_lookup %d bit %d entries\n", depth,ncolors) ;
00758     if (!hist)
00759     {
00760         hist = (int *)malloc(ncolors * sizeof(int)) ;
00761         if (!hist)
00762         {
00763             printf("can't alloc mem for %d element histogram\n",ncolors) ;
00764             return(-1) ;
00765         }
00766     }
00767     if (depth > 8)
00768     {
00769         if (!slookup)
00770             slookup = (u_short *)malloc(ncolors * sizeof(u_short)) ;
00771         if (!slookup)
00772         {
00773             printf("can't alloc mem for %d element lookup\n",ncolors) ;
00774             return(-1) ;
00775         }
00776         for (i = 0 ; i < ncolors ; i++)
00777         {
00778             slookup[i] = i ;
00779             hist[i] = 0 ;
00780         }
00781     }
00782     else
00783     {
00784         if (!blookup)
00785             blookup = (u_char *)malloc(ncolors * sizeof(u_char)) ;
00786         if (!blookup)
00787         {
00788             printf("can't alloc mem for %d element lookup\n",ncolors) ;
00789             return(-1) ;
00790         }
00791         for (i = 0 ; i < ncolors ; i++)
00792         {
00793             blookup[i] = i ;
00794             hist[i] = 0 ;
00795         }
00796     }
00797     return(0) ;
00798 }
00799 
00800 
00809 int
00810 dvu_histeq(u_char *src, u_char *dst, int size, int depth)
00811 {
00812     int i ;
00813     unsigned long total;
00814     double intermediate ;
00815     int ncolors = 1 << depth ;
00816     int ret ;
00817 
00818     if(Pdv_debug) printf("dvu_histeq %p %p %d %d\n",src,dst,size,depth) ;
00819 
00820     if ((ret = init_lookup(depth))) return(ret) ;
00821 
00822     /* compute histeq curve */
00823     total = 0;
00824     if (depth > 8)
00825     {
00826         u_short *s ;
00827         s = (u_short *)src ;
00828         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00829         for (i = 0 ; i < ncolors ; i++)
00830         {
00831             total += hist[i];
00832             intermediate = total ;
00833             intermediate *= (ncolors - 1) ;
00834             intermediate /= size ;
00835             slookup[i] = (u_short)intermediate ;
00836         }
00837     }
00838     else
00839     {
00840         u_char *s ;
00841         s = (u_char *)src ;
00842         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00843         for (i = 0 ; i < ncolors ; i++)
00844         {
00845             total += hist[i];
00846             blookup[i] = (u_char)((total * (ncolors - 1)) / size) ;
00847         }
00848     }
00849     dvu_lookup(src,dst,size,depth) ;
00850     return(0) ;
00851 }
00852 
00853 
00854 /* the following 4 routines are work in progress */
00855 int
00856 dvu_load_lookup(char *filename,int depth) 
00857 {
00858     FILE *ltab ;
00859     int index, val ;
00860     int ncolors = 1 << depth ;
00861     int ret ;
00862 
00863     if ((ret = init_lookup(depth))) return(ret) ;
00864 
00865     if (Pdv_debug)
00866         printf("loading lookup from %s\n",filename) ;
00867     if (!(ltab = fopen(filename,"r")))
00868     {
00869         printf("can't open %s for lookup table\n",filename) ;
00870         return(-1) ;
00871     }
00872     index = 0 ;
00873     while(index < ncolors && (fscanf(ltab,"%d",&val)))
00874     {
00875         if (depth > 8)
00876             slookup[index++] = val ;
00877         else
00878             blookup[index++] = val ;
00879     }
00880     if (Pdv_debug) printf("read %d values\n",index) ;
00881     fclose(ltab) ;
00882     return(0) ;
00883 }
00884 
00885 int
00886 dvu_save_lookup(char *filename,int depth) 
00887 {
00888     FILE *ltab ;
00889     int ret ;
00890     int i ;
00891     int ncolors = 1 << depth ;
00892     if (Pdv_debug)
00893         printf("saving lookup to %s\n",filename) ;
00894 
00895     if (!blookup && !slookup)
00896         if ((ret = init_lookup(depth))) return(ret) ;
00897 
00898     if (!(ltab = fopen(filename,"wb")))
00899     {
00900         edt_msg_printf_perror(
00901                 DVUFATAL, 
00902                 "Can't open '%s' for lookup table", 
00903                 filename);
00904         return(-1) ;
00905     }
00906     if (Pdv_debug > 1)
00907     {
00908         if (depth > 8)
00909             for(i = 0 ; i < ncolors ; i++) printf(" %d (%d)\n",
00910                     slookup[i],hist[i]) ;
00911         else
00912             for(i = 0 ; i < ncolors ; i++) printf(" %d (%d)\n",
00913                     blookup[i],hist[i]) ;
00914     }
00915     if (depth > 8)
00916         for(i = 0 ; i < ncolors ; i++) fprintf(ltab," %d\n",
00917                 slookup[i]) ;
00918     else
00919         for(i = 0 ; i < ncolors ; i++) fprintf(ltab," %d\n",
00920                 blookup[i]) ;
00921     fclose(ltab) ;
00922     return(0) ;
00923 }
00924 
00925 int
00926 dvu_lookup(u_char *src, u_char *dst, int size, int depth)
00927 {
00928     if (Pdv_debug)
00929         printf("dvu_lookup\n") ;
00930     if (depth > 8)
00931     {
00932         u_short *s ;
00933         u_short *d ;
00934         int i ;
00935         d = (u_short *)dst ;
00936         s = (u_short *)src ;
00937         for (i = 0 ; i < size ; i++)
00938         {
00939             *d++ = slookup[*s++] ;
00940         }
00941     }
00942     else
00943     {
00944         u_char *s ;
00945         u_char *d ;
00946         int i ;
00947         d = (u_char *)dst ;
00948         s = (u_char *)src ;
00949         for (i = 0 ; i < size ; i++)
00950         {
00951             *d++ = blookup[*s++] ;
00952         }
00953     }
00954     if (Pdv_debug)
00955         printf("dvu_lookup done\n") ;
00956 
00957     return(0) ;
00958 }
00959 
00969 int
00970 dvu_exp_histeq(u_char *src, u_char *dst, int size, int depth, int cutoff)
00971 {
00972     int i ;
00973     unsigned long total;
00974     int ncolors = 1 << depth ;
00975     int ret ;
00976     int min, max, distinct ;
00977     float inc ;
00978     float val ;
00979     int ival ;
00980 
00981     if(Pdv_debug) printf("dvu_exp_histeq %p %p %d %d\n",src,dst,size,depth) ;
00982 
00983     if ((ret = init_lookup(depth))) return(ret) ;
00984 
00985     /* compute histeq curve */
00986     total = 0;
00987     if (depth > 8)
00988     {
00989         u_short *s ;
00990         s = (u_short *)src ;
00991         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00992     }
00993     else
00994     {
00995         u_char *s ;
00996         s = (u_char *)src ;
00997         for (i = 0 ; i < size ; i++) hist[*s++]++ ;
00998     }
00999     for(i = 0 ; i < ncolors ; i++)
01000     {
01001         if (hist[i] >= cutoff) 
01002         {
01003             min = i ;
01004             break ;
01005         }
01006     }
01007     for(i = ncolors-1 ; i >= 0; i--)
01008     {
01009         if (hist[i] >= cutoff) 
01010         {
01011             max = i ;
01012             break ;
01013         }
01014     }
01015     distinct = 0 ;
01016     for(i = 0 ; i < ncolors ; i++)
01017     {
01018         if (hist[i] >= cutoff) distinct++ ;
01019     }
01020     if (Pdv_debug)
01021         printf("exp_histeq:min %d max %d distinct %d (with %d pixel cutoff)\n",
01022             min,max,distinct,cutoff) ;
01023     inc = (float)ncolors / (float)distinct ;
01024     val = 0.0 ;
01025     for (i = 0 ; i < ncolors ; i++)
01026     {
01027         ival = (int)(val + 0.5) ;
01028         if (hist[i] >= cutoff) val += inc ;
01029         if (Pdv_debug > 2) printf("%d (%d) %3.2f %d\n",
01030                 i,hist[i],val,ival) ;
01031         if (depth > 8)
01032             slookup[i] = ival ;
01033         else
01034             blookup[i] = ival ;
01035     }
01036 
01037     dvu_lookup(src,dst,size,depth) ;
01038     return(0) ;
01039 }
01040 
01041 void
01042 dvu_free_tables()
01043 {
01044     if (slookup) free(slookup) ;
01045     if (hist) free(hist) ;
01046 }
01047 /*
01048  * setup a window structure with y indexes to start of each row
01049  * to cut down on number of parameters and hopefully make for 
01050  * some more common code
01051  */
01052 dvu_window *
01053 dvu_init_window(u_char *data, int sx, int sy, 
01054                                 int dx, int dy, int xdim, int ydim, int depth)
01055 {
01056     dvu_window *s ;
01057     int y ;
01058     int bytes ;
01059 
01060     s = (dvu_window *) malloc(sizeof(dvu_window)) ;
01061     bytes = (depth + 7) / 8 ;
01062     if (!data) data = (u_char *)malloc(xdim*ydim*bytes) ;
01063 
01064     s->left = sx ;
01065     s->right = sx + dx - 1 ;
01066     s->top = sy ;
01067     s->bottom = sy + dy - 1 ;
01068     s->xdim = xdim ;
01069     s->ydim = ydim ;
01070     s->depth = depth ;
01071     s->data = data ;
01072     s->mat = 0 ;
01073     s->mat16 = 0 ;
01074     s->mat24 = 0 ;
01075     switch(bytes)
01076     {
01077     case 1:
01078         s->mat = (u_char **) calloc(ydim,sizeof(u_char *)) ;
01079         for (y = 0 ; y < ydim ; y++)
01080             s->mat[y] = data + y * xdim  ;
01081         break ;
01082     case 2:
01083         s->mat16 = (u_short **) calloc(ydim,sizeof(u_short *)) ;
01084         for (y = 0 ; y < ydim ; y++)
01085             s->mat16[y] = (u_short *)(data + y * xdim * 2)  ;
01086         break ;
01087     case 3:
01088         s->mat24 = (bgrpoint **) calloc(ydim,sizeof(bgrpoint *)) ;
01089         for (y = 0 ; y < ydim ; y++)
01090             s->mat24[y] = (bgrpoint *)(data + y * xdim * 3)  ;
01091         break ;
01092     }
01093     return(s) ;
01094 }
01095 
01096 /*
01097  * use for reseting sub image in window or changing data
01098  */
01099 dvu_window *
01100 dvu_reset_window(dvu_window *s, u_char *data, int sx, int sy, int dx, int dy)
01101 {
01102     register int y ;
01103     register int stride ;
01104     register int rows ;
01105     register int bytes ;
01106 
01107     s->left = sx ;
01108     s->right = sx + dx - 1 ;
01109     s->top = sy ;
01110     s->bottom = sy + dy - 1 ;
01111     s->data = data ;
01112     rows = s->ydim ;
01113     stride = s->xdim ;
01114     bytes = (s->depth + 7) / 8 ;
01115     switch(bytes)
01116     {
01117     case 1:
01118         for (y = 0 ; y < rows ; y++)
01119             s->mat[y] = data + y * stride  ;
01120         break ;
01121     case 2:
01122         for (y = 0 ; y < rows ; y++)
01123             s->mat16[y] = (u_short *)(data + y * stride * 2)  ;
01124         break ;
01125     case 3:
01126         for (y = 0 ; y < rows ; y++)
01127             s->mat24[y] = (bgrpoint *)(data + y * stride * 3)  ;
01128         break ;
01129     }
01130     return(s) ;
01131 }
01132 
01133 /*
01134  * free struct for window - not data
01135  */
01136 int
01137 dvu_free_window(dvu_window *w)
01138 {
01139     free(w->mat) ;
01140     free(w) ;
01141     return(0) ;
01142 }
01143 
01144 int
01145 ten2one(u_short *wbuf, u_char *bbuf, int count)
01146 {
01147     dvu_word2byte(wbuf, bbuf, count, 10) ;
01148     return(0) ;
01149 }
01150 
01151 int
01152 dvu_word2byte(u_short *wbuf, u_char *bbuf, int count, int depth)
01153 {
01154     register u_short *from, *end;
01155     register u_char *to;
01156         int shift = depth - 8 ;
01157 
01158     from = wbuf;
01159     end = from + count;
01160     to = bbuf;
01161     while (from < end)
01162     {
01163         *to++ = *from++ >> shift;
01164     }
01165     return(0) ;
01166 }
01167 
01168 /*
01169  * dvu_word2byte with args for scanline stride
01170  */
01171 int
01172 dvu_word2byte_with_stride(u_short *wbuf, u_char *bbuf, 
01173                                                   int wstride, int bstride, 
01174                                                   int xsize, int ysize, int depth)
01175 {
01176     register u_short *from, *end;
01177     register u_char *to;
01178     register u_char *next_toptr;
01179     register u_short *next_fromptr;
01180     register u_short *end_fromptr;
01181         int shift = depth - 8 ;
01182 
01183     next_fromptr = wbuf;
01184     next_toptr = bbuf;
01185     end_fromptr = wbuf + (xsize * ysize);
01186     while (next_fromptr < end_fromptr)
01187     {
01188         from = next_fromptr;
01189         to = next_toptr;
01190         end = next_fromptr + xsize;
01191 
01192         while (from < end)
01193             *to++ = *from++ >> shift;
01194 
01195         next_fromptr += wstride;
01196         next_toptr += bstride;
01197     }
01198     return(0) ;
01199 }
01200 
01201 
01202 void
01203 dvu_perror(char *str)
01204 {
01205 #ifdef _NT_
01206         LPVOID lpMsgBuf;
01207 
01208 FormatMessage(
01209     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
01210     NULL,
01211     GetLastError(),
01212     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /*  Default language */
01213     (LPTSTR) &lpMsgBuf,
01214     0,
01215     NULL
01216 );
01217 
01218         fprintf(stderr, "%s: %s\n", str, lpMsgBuf) ;
01219 #else
01220         perror(str) ;
01221 #endif
01222 }
01223 
01224 /*******************************************/
01225 static void putshort(FILE *fp, int i)
01226     
01227 {
01228   int c, c1;
01229 
01230   c = ((unsigned int ) i) & 0xff;  c1 = (((unsigned int) i)>>8) & 0xff;
01231   putc(c, fp);   putc(c1,fp);
01232 }
01233 
01234 
01235 /*******************************************/
01236 static void putint(FILE *fp, int i)
01237    
01238 {
01239   int c, c1, c2, c3;
01240   c  = ((unsigned int ) i)      & 0xff;  
01241   c1 = (((unsigned int) i)>>8)  & 0xff;
01242   c2 = (((unsigned int) i)>>16) & 0xff;
01243   c3 = (((unsigned int) i)>>24) & 0xff;
01244 
01245   putc(c, fp);   putc(c1,fp);  putc(c2,fp);  putc(c3,fp);
01246 }
01247 
01248 
01249 #ifndef _NT_
01250 #define BI_RGB 0L
01251 #endif
01252 
01274 int 
01275 dvu_write_bmp(char *fname, u_char *buffer, int width, int height)
01276 {
01277   int w = width, h = height; /* shortcut names */
01278   FILE *fp ;
01279   int bperlin ;
01280   int nc = 256 ;
01281   int nbits = 8 ;
01282   int   i,j,padw;
01283   u_char *pp;
01284 
01285   fp = fopen(fname,"wb") ;
01286   if (!fp) return(-1) ;
01287   
01288   bperlin = ((w * nbits + 31) / 32) * 4;   /* # bytes written per line */
01289 
01290   putc('B', fp);  putc('M', fp);           /* BMP file magic number */
01291 
01292   /* compute filesize and write it */
01293   i = 14 +                /* size of bitmap file header */
01294       40 +                /* size of bitmap info header */
01295       (nc * 4) +          /* size of colormap */
01296       bperlin * h;        /* size of image data */
01297 
01298   putint(fp, i);
01299   putshort(fp, 0);        /* reserved1 */
01300   putshort(fp, 0);        /* reserved2 */
01301   putint(fp, 14 + 40 + (nc * 4));  /* offset from BOfile to BObitmap */
01302 
01303   putint(fp, 40);         /* biSize: size of bitmap info header */
01304   putint(fp, w);          /* biWidth */
01305   putint(fp, h);          /* biHeight */
01306   putshort(fp, 1);        /* biPlanes:  must be '1' */
01307   putshort(fp, nbits);    /* biBitCount: 1,4,8, or 24 */
01308   putint(fp, BI_RGB);     /* biCompression:  BI_RGB, BI_RLE8 or BI_RLE4 */
01309   putint(fp, bperlin*h);  /* biSizeImage:  size of raw image data */
01310   putint(fp, 75 * 39);    /* biXPelsPerMeter: (75dpi * 39" per meter) */
01311   putint(fp, 75 * 39);    /* biYPelsPerMeter: (75dpi * 39" per meter) */
01312   putint(fp, nc);         /* biClrUsed: # of colors used in cmap */
01313   putint(fp, nc);         /* biClrImportant: same as above */
01314 
01315 
01316   /* write out the colormap */
01317   for (i=0; i<nc; i++) {
01318       putc(i,fp);
01319       putc(i,fp);
01320       putc(i,fp);
01321       putc(0,fp);
01322     }
01323 
01324   /* write out the image */
01325 
01326 
01327   padw = ((w + 3)/4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
01328 
01329   for (i=h-1; i>=0; i--) {
01330     pp = buffer + (i * w);
01331 
01332     for (j=0; j<w; j++) putc(*pp++, fp);
01333     for ( ; j<padw; j++) putc(0, fp);
01334   }
01335 
01336   fclose(fp) ;
01337   return(0) ;
01338 }
01339 
01340 #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
01341 
01342 #ifndef WIN32
01343 
01344 #define DWORD unsigned long
01345 #define LONG long
01346 #define WORD unsigned short
01347 #define BYTE unsigned char
01348 
01349 
01350 typedef struct tagBITMAPFILEHEADER {
01351         WORD    bfType;
01352         DWORD   bfSize;
01353         WORD    bfReserved1;
01354         WORD    bfReserved2;
01355         DWORD   bfOffBits;
01356 } BITMAPFILEHEADER;
01357 
01358 /* structures for defining DIBs */
01359 typedef struct tagBITMAPCOREHEADER {
01360         DWORD   bcSize;                 /* used to get to color table */
01361         WORD    bcWidth;
01362         WORD    bcHeight;
01363         WORD    bcPlanes;
01364         WORD    bcBitCount;
01365 } BITMAPCOREHEADER ;
01366 
01367 
01368 typedef struct tagBITMAPINFOHEADER{
01369         DWORD      biSize;
01370         LONG       biWidth;
01371         LONG       biHeight;
01372         WORD       biPlanes;
01373         WORD       biBitCount;
01374         DWORD      biCompression;
01375         DWORD      biSizeImage;
01376         LONG       biXPelsPerMeter;
01377         LONG       biYPelsPerMeter;
01378         DWORD      biClrUsed;
01379         DWORD      biClrImportant;
01380 } BITMAPINFOHEADER;
01381 
01382 /* constants for the biCompression field */
01383 /* #define BI_RGB        0L */ /* already defined above */
01384 #define BI_RLE8       1L
01385 #define BI_RLE4       2L
01386 #define BI_BITFIELDS  3L
01387 
01388 typedef struct tagRGBQUAD {
01389         BYTE    rgbBlue;
01390         BYTE    rgbGreen;
01391         BYTE    rgbRed;
01392         BYTE    rgbReserved;
01393 } RGBQUAD, *LPRGBQUAD;
01394 
01395 typedef struct tagBITMAPINFO {
01396     BITMAPINFOHEADER    bmiHeader;
01397     RGBQUAD             bmiColors[1];
01398 } BITMAPINFO;
01399 
01400 #else
01401 
01402 #endif
01403 
01423 int
01424 dvu_write_bmp_24(char *fname, u_char *buffer, int width, int height)
01425 
01426 {
01427         int w = width, h = height; /* shortcut names */
01428 
01429         u_char     *bp;
01430 
01431         FILE *f;
01432         DWORD dwDIBSize;
01433         
01434         DWORD dwBmBitsSize;
01435 
01436         int nPadding;
01437         int widthbytes = w * 3;
01438 
01439         int row;
01440 
01441         BITMAPFILEHEADER bmfHdr; /* Header for Bitmap file */
01442 
01443         /* Allocate memory for the header (if necessary) */
01444         BITMAPINFO *pBMI = (BITMAPINFO *)
01445                         malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
01446 
01447   /* Fill in the header info. */
01448         BITMAPINFOHEADER* pBI = (BITMAPINFOHEADER*) pBMI;
01449         pBI->biSize = sizeof(BITMAPINFOHEADER);
01450         pBI->biWidth = w;
01451         pBI->biHeight = h;
01452         pBI->biPlanes = 1;
01453         pBI->biBitCount = 24;
01454         pBI->biCompression = BI_RGB;
01455         pBI->biSizeImage = 0;
01456         pBI->biXPelsPerMeter = 0;
01457         pBI->biYPelsPerMeter = 0;
01458         pBI->biClrUsed = 0;
01459         pBI->biClrImportant = 0;
01460 
01461 
01462         /* Fill Header */
01463         /* Fill in the fields of the file header */
01464 
01465         /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
01466         bmfHdr.bfType = 0x4D42;  /* "BM" */
01467 
01468         /* Calculate the size of the DIB. */
01469         /* First, find size of header plus size of color table.  Since the */
01470         /* first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER contains */
01471         /* the size of the structure, let's use this. Partial Calculation. */
01472 
01473         dwDIBSize = *(unsigned long *)pBMI ;
01474         
01475         dwBmBitsSize = WIDTHBYTES(w * ((DWORD)pBMI->bmiHeader.biBitCount)) * 
01476                 h;
01477 
01478         nPadding = WIDTHBYTES(w * ((DWORD)pBMI->bmiHeader.biBitCount)) -
01479                         w * (3);
01480 
01481         dwDIBSize += dwBmBitsSize;
01482 
01483         /* Now, since we have calculated the correct size, why don't we */
01484         /* fill in the biSizeImage field (this will fix any .BMP files */
01485         /* which have this field incorrect). */
01486         pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
01487                 
01488         /* Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) */
01489         bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
01490         bmfHdr.bfReserved1 = 0;
01491         bmfHdr.bfReserved2 = 0;
01492 
01493         /* Now, calculate the offset the actual bitmap bits will be in */
01494         /* the file -- It's the Bitmap file header plus the DIB header, */
01495         /* plus the size of the color table. */
01496         bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
01497                 pBMI->bmiHeader.biSize;
01498 
01499         /* Open  */
01500         f = fopen(fname, "wb");
01501 
01502 
01503         /* Write Header  */
01504         fwrite(&bmfHdr,1, sizeof(bmfHdr),f);
01505         fwrite(pBMI, 1, pBMI->bmiHeader.biSize,f);
01506         /* Write Data */
01507         
01508         bp = buffer + (h-1) * (w *3);
01509 
01510         for (row = h-1;row >= 0;row--, bp -= widthbytes)
01511         {
01512                 fwrite(bp,1,w * 3,f);
01513                 if (nPadding)
01514                         fwrite(bp,1,nPadding,f);
01515         }
01516 
01517         /* Close File */
01518         fclose(f);
01519 
01520         return 0;
01521 }
01522 
01538 int 
01539 dvu_write_raw(int imagesize, u_char *imagebuf, char *fname)
01540 {
01541         FILE *fd ;
01542         if ((fd = fopen(fname,"wb")) == NULL)
01543         {
01544                 dvu_perror(fname) ;
01545                 return(-1) ;
01546         }
01547         fwrite(imagebuf,imagesize,1,fd) ;
01548         fclose(fd) ;
01549     return(0) ;
01550 }   
01551 
01552 
01553 static u_char *
01554 create_cast_tbl(depth_bits, nents)
01555 int depth_bits, nents;
01556 {
01557     int i;
01558     u_char *tbl;
01559     float mult;
01560     float fmin=0.0;
01561     int ncolors = 1 << depth_bits;
01562 
01563     mult = (float)255.0/(float)ncolors;
01564     if ((tbl = (u_char *)malloc(ncolors * sizeof(char))) == NULL)
01565     {
01566         printf("malloc for cast_tbl failed, size %d\n", ncolors);
01567         exit(0);
01568     }
01569 
01570     for (i=0; i < ncolors; i++)
01571     {
01572         tbl[i] = (int)(fmin + ((mult * (float)i) + 0.5));
01573     }
01574 
01575     if (Pdv_debug)
01576     {
01577         printf("Cast_tbl: depth (bytes) %d nents %d ncolors %d mult %1.2f\n",
01578                                             depth_bits, nents, ncolors, mult);
01579         printf("Cast_tbl %d: %d\n", 0, tbl[0]);
01580         printf("Cast_tbl %d: %d\n", ncolors/2, tbl[ncolors/2]);
01581         printf("Cast_tbl %d: %d\n", ncolors-1, tbl[ncolors-1]);
01582     }
01583 
01584 
01585 
01586 
01587     return tbl;
01588 }    
01589 
01590 static void
01591 free_cast_tbl()
01592 {
01593     free(Cast_tbl);
01594     Cast_tbl = NULL;
01595 }
01596 
01597 /*
01598  * just not trusting byte order stuff, and also need to have char buffers
01599  * for this kind of thing sometimes....
01600  */
01601 void
01602 dvu_long_to_charbuf(unsigned int val, u_char *buf)
01603 {
01604     buf[0] = (u_char) ((val & 0xff000000) >> 24);
01605     buf[1] = (u_char) ((val & 0x00ff0000) >> 16);
01606     buf[2] = (u_char) ((val & 0x0000ff00) >> 8);
01607     buf[3] = (u_char) ((val & 0x000000ff) );
01608 }
01609  /* end weakgroup */
01611 

Generated on Mon Mar 21 14:14:43 2011 by  doxygen 1.4.7