libdvu.c

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

Generated on 19 Jun 2015 by  doxygen 1.4.7