LCOV - code coverage report
Current view: top level - gutils - gimagereadrgb.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 175 0.0 %
Date: 2017-08-04 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : #include "gimage.h"
      28             : #include <string.h>
      29             : 
      30             : struct sgiheader {
      31             :     short magic;                /* Magic (SGI identification) number    */
      32             :     char format;                /* Storage format (RLE=1 or VERBATIM=0) */
      33             :     char bpc;                   /* Bytes per pixel channel (1or2 bytes) */
      34             :     unsigned short dim;         /* Number of dimensions (1,2,3)         */
      35             :     unsigned short width;       /* Width of image in pixels     X-size  */
      36             :     unsigned short height;      /* Height of image in pixels    Y-size  */
      37             :     unsigned short chans;       /* Number of channels (1,3,4)   Z-size  */
      38             :     long pixmin;                /* Minimum pixel value  (darkest)       */
      39             :     long pixmax;                /* Maximum pixel value  (brightest)     */
      40             :     char dummy[4];              /* Ignored                              */
      41             :     char imagename[80];         /* Image name   (0..79chars + '\0')     */
      42             :     long colormap;              /* Colormap ID  (0,1,2,3)               */
      43             :     char pad[404];              /* Ignored      (total=512bytes)        */
      44             : };
      45             : 
      46             : #define SGI_MAGIC       474
      47             : #define VERBATIM        0
      48             : #define RLE             1
      49             : 
      50           0 : static int getlong(FILE *fp, long *value) {
      51             : /* Get Big-Endian long (32bit int) value. Return 0 if okay, -1 if error */
      52             :     int ch1, ch2, ch3, ch4;
      53             : 
      54           0 :     if ( (ch1=fgetc(fp))<0 || (ch2=fgetc(fp))<0 || \
      55           0 :          (ch3=fgetc(fp))<0 || (ch4=fgetc(fp))<0 ) {
      56           0 :         *value=0;
      57           0 :         return( -1 );
      58             :     }
      59           0 :     *value=(long)( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
      60           0 :     return( 0 );
      61             : }
      62             : 
      63           0 : static int getshort(FILE *fp) {
      64             : /* Get Big-Endian short 16bit value. Return value if okay, -1 if error  */
      65             :     int ch1, ch2;
      66             : 
      67           0 :     if ( (ch1=fgetc(fp))<0 || (ch2=fgetc(fp))<0 )
      68           0 :         return( -1 );
      69             : 
      70           0 :     return( (ch1<<8) | ch2 );
      71             : }
      72             : 
      73           0 : static int getsgiheader(struct sgiheader *head,FILE *fp) {
      74             : /* Get Header info. Return 0 if read input file okay, -1 if read error  */
      75           0 :     if ( (head->magic=getshort(fp))<0     || head->magic!=SGI_MAGIC || \
      76           0 :          (head->format=fgetc(fp))<0       || \
      77           0 :          (head->bpc=fgetc(fp))<0  || \
      78           0 :          (head->dim=getshort(fp))==(unsigned short)-1        ||      \
      79           0 :          (head->width=getshort(fp))==(unsigned short)-1      ||      \
      80           0 :          (head->height=getshort(fp))==(unsigned short)-1||      \
      81           0 :          (head->chans=getshort(fp))==(unsigned short)-1      ||      \
      82           0 :          getlong(fp,&head->pixmin)       || \
      83           0 :          getlong(fp,&head->pixmax)       || \
      84           0 :          fread(head->dummy,sizeof(head->dummy),1,fp)<1 || \
      85           0 :          fread(head->imagename,sizeof(head->imagename),1,fp)<1 || \
      86           0 :          getlong(fp,&head->colormap)     || \
      87           0 :          fread(head->pad,sizeof(head->pad),1,fp)<1 )
      88           0 :     return( -1 );
      89             : 
      90             :     /* Check if header information okay (for us to use here ) */
      91           0 :     if ( (head->format!=VERBATIM && head->format!=RLE) || \
      92           0 :          (head->bpc!=1 && head->bpc!=2) || \
      93           0 :          head->dim<1 || head->dim>3 || \
      94           0 :          head->pixmax>65535 || (head->pixmax>255 && head->bpc==1) || \
      95           0 :          (head->chans!=1 && head->chans!=3 && head->chans!=4) || \
      96           0 :          head->pixmax<0 || head->pixmin<0 || head->pixmin>=head->pixmax || \
      97           0 :          head->colormap!=0 )
      98           0 :     return( -1 );
      99             : 
     100           0 :     return( 0 );
     101             : }
     102             : 
     103           0 : static long scalecolor(struct sgiheader *header,long value) {
     104           0 :     return( (value-header->pixmin)*255L/(header->pixmax-header->pixmin) );
     105             : }
     106             : 
     107           0 : static int readlongtab(FILE *fp,unsigned long *tab,long tablen) {
     108             : /* RLE table info, exit=0 if okay, return -1 if error */
     109             :     long i;
     110             : 
     111           0 :     for ( i=0; i<tablen; ++i )
     112           0 :         if ( getlong(fp,(long *)&tab[i]) )
     113           0 :             return( -1 ); /* had a read error */
     114             : 
     115           0 :     return( 0 ); /* read everything okay */
     116             : }
     117             : 
     118           0 : static int find_scanline(FILE *fp,struct sgiheader *header,int cur,
     119             :         unsigned long *starttab,unsigned char **ptrtab) {
     120             : /* Find and expand a scanline. Return 0 if okay, else -ve if error */
     121           0 :     int ch = 0,i,cnt;
     122             :     long val;
     123             :     unsigned char *pt;
     124             : 
     125           0 :     for ( i=0; i<cur; ++i )
     126           0 :         if ( starttab[i]==starttab[cur] ) {
     127           0 :             ptrtab[cur] = ptrtab[i];
     128           0 :             return( 0 );
     129             :         }
     130           0 :     if ( (pt=ptrtab[cur]=(unsigned char *) malloc(header->width))==NULL ) {
     131           0 :         NoMoreMemMessage();
     132           0 :         return( -1 );
     133             :     }
     134           0 :     if ( fseek(fp,starttab[cur],0)!= 0 ) return( -2 );
     135           0 :     while ( header->bpc==1 ) {
     136           0 :         if ( (ch=fgetc(fp))<0 ) return( -2 );
     137           0 :         if ( (cnt=(ch&0x7f))==0 ) return( 0 );
     138           0 :         if ( ch&0x80 ) {
     139           0 :             while ( --cnt>=0 ) {
     140           0 :                 if ( (ch=fgetc(fp))<0 ) return( -2 );
     141           0 :                 *pt++ = scalecolor(header,ch);
     142             :             }
     143             :         } else {
     144           0 :             if ( (ch=fgetc(fp))<0 ) return( -2 );
     145           0 :             ch = scalecolor(header,ch);
     146           0 :             while ( --cnt>=0 )
     147           0 :                 *pt++ = ch;
     148             :         }
     149             :     }
     150           0 :     while ( header->bpc!=1 ) {
     151           0 :         if ( getlong(fp,&val) ) return( -2 );
     152           0 :         if ( (cnt=(ch&0x7f))==0 ) return( 0 );
     153           0 :         if ( ch&0x80 ) {
     154           0 :             while ( --cnt>=0 ) {
     155           0 :                 if ( getlong(fp,&val) ) return( -2 );
     156           0 :                 *pt++ = scalecolor(header,val);
     157             :             }
     158             :         } else {
     159           0 :             if ( getlong(fp,&val) ) return( -2 );
     160           0 :             val = scalecolor(header,val);
     161           0 :             while ( --cnt>=0 )
     162           0 :                 *pt++ = val;
     163             :         }
     164             :     }
     165           0 :     return( -2 );
     166             : }
     167             : 
     168           0 : static void freeptrtab(unsigned char **ptrtab,long tot) {
     169             :     long i,j;
     170             : 
     171           0 :     if ( ptrtab!=NULL )
     172           0 :         for ( i=0; i<tot; ++i )
     173           0 :             if ( ptrtab[i]!=NULL ) {
     174           0 :                 for ( j=i+1; j<tot; ++j )
     175           0 :                     if ( ptrtab[j]==ptrtab[i] )
     176           0 :                         ptrtab[j] = NULL;
     177           0 :                 free(ptrtab[i]);
     178             :             }
     179           0 : }
     180             : 
     181           0 : GImage *GImageReadRgb(char *filename) {
     182             :     FILE *fp;                   /* source file */
     183             :     struct sgiheader header;
     184             :     int i,j,k;
     185             :     unsigned char *pt, *end;
     186           0 :     unsigned char *r=NULL,*g=NULL,*b=NULL,*a=NULL;      /* Colors */
     187           0 :     unsigned long *starttab=NULL /*, *lengthtab=NULL */;
     188           0 :     unsigned char **ptrtab=NULL;
     189           0 :     long tablen=0;
     190             :     unsigned long *ipt, *iend;
     191           0 :     GImage *ret = NULL;
     192             :     struct _GImage *base;
     193             : 
     194           0 :     if ( (fp=fopen(filename,"rb"))==NULL ) {
     195           0 :         fprintf(stderr,"Can't open \"%s\"\n", filename);
     196           0 :         return( NULL );
     197             :     }
     198             : 
     199             :     /* Check, and Get, Header information */
     200           0 :     if ( getsgiheader(&header,fp) )
     201           0 :         goto errorGImageReadRgbFile;
     202             : 
     203             :     /* Create memory to hold image, exit with NULL if not enough memory */
     204           0 :     if ( (ret=GImageCreate(header.dim==3?it_true:it_index,header.width,header.height))==NULL ) {
     205           0 :         fclose(fp);
     206           0 :         return( NULL );
     207             :     }
     208           0 :     base = ret->u.image;
     209             : 
     210           0 :     if ( header.format==RLE ) {
     211             :         /* Working with RLE image data*/
     212             : 
     213             :         /* First, get offset table info */
     214           0 :         tablen = header.height*header.chans;
     215           0 :         if ( (starttab=(unsigned long *)calloc(1,tablen*sizeof(long)))==NULL || \
     216             :            /*(lengthtab=(unsigned long *)calloc(1,tablen*sizeof(long)))==NULL || \ */
     217           0 :              (ptrtab=(unsigned char **)calloc(1,tablen*sizeof(unsigned char *)))==NULL ) {
     218           0 :             NoMoreMemMessage();
     219           0 :             goto errorGImageReadRgbMem;
     220             :         }
     221           0 :         if ( readlongtab(fp,starttab,tablen) )
     222             :             /* || readlongtab(fp,lengthtab,tablen) */
     223           0 :             goto errorGImageReadRgbFile;
     224             : 
     225             :         /* Next, get image data */
     226           0 :         for ( i=0; i<tablen; ++i )
     227           0 :             if ( (k=find_scanline(fp,&header,i,starttab,ptrtab)) ) {
     228           0 :                 if ( k==-1 ) goto errorGImageReadRgbMem; else goto errorGImageReadRgbFile;
     229             :             }
     230             : 
     231             :         /* Then, build image */
     232           0 :         if ( header.chans==1 ) {
     233           0 :             for ( i=0; i<header.height; ++i )
     234           0 :                 memcpy(base->data + (header.height-1-i)*base->bytes_per_line,ptrtab[i],header.width);
     235             :         } else {
     236             :             unsigned long *ipt;
     237           0 :             for ( i=0; i<header.height; ++i ) {
     238           0 :                 ipt = (unsigned long *) (base->data + (header.height-1-i)*base->bytes_per_line);
     239           0 :                 for ( j=0; j<header.width; ++j )
     240           0 :                     *ipt++ = COLOR_CREATE(ptrtab[i][j],
     241             :                             ptrtab[i+header.height][j], ptrtab[i+2*header.height][j]);
     242             :             }
     243             :         }
     244           0 :         freeptrtab(ptrtab,tablen);
     245           0 :         free(ptrtab); free(starttab); /*free(lengthtab);*/
     246             :     } else {
     247             :         /* working with Verbatim image data*/
     248           0 :         if ( header.chans==1 && header.bpc==1 ) {
     249           0 :             for ( i=0; i<header.height; ++i ) {
     250           0 :                 fread(base->data + (header.height-1-i)*base->bytes_per_line,header.width,1,fp);
     251           0 :                 if ( header.pixmax!=255 ) {
     252           0 :                     pt = (unsigned char *) (base->data+(header.height-1-i)*base->bytes_per_line);
     253           0 :                     for ( end=pt+header.width; pt<end; ++pt )
     254           0 :                         *pt = (*pt*255)/header.pixmax;
     255             :                 }
     256             :             }
     257           0 :         } else if ( header.chans==1 ) {
     258           0 :             for ( i=0; i<header.height; ++i ) {
     259           0 :                 pt = (unsigned char *) (base->data + (header.height-1-i)*base->bytes_per_line);
     260           0 :                 for ( end=pt+header.width; pt<end; ) {
     261           0 :                     if ( (k=getshort(fp))<0 ) goto errorGImageReadRgbFile;
     262           0 :                     *pt++ = (k*255L)/header.pixmax;
     263             :                 }
     264             :             }
     265             :         } else {
     266             :             /* import RGB=3 or RGBA=4 Verbatim images */
     267             :             unsigned char *rpt, *gpt, *bpt;
     268           0 :             if ( (r=(unsigned char *) malloc(header.width*sizeof(unsigned char)))==NULL || \
     269           0 :                  (g=(unsigned char *) malloc(header.width*sizeof(unsigned char)))==NULL || \
     270           0 :                  (b=(unsigned char *) malloc(header.width*sizeof(unsigned char)))==NULL || \
     271           0 :                  (header.chans==4 && \
     272           0 :                  (a=(unsigned char *) malloc(header.width*sizeof(unsigned char)))==NULL) ) {
     273           0 :                 NoMoreMemMessage();
     274           0 :                 goto errorGImageReadRgbMem;
     275             :             }
     276           0 :             if ( header.bpc==1 ) {
     277           0 :                 for ( i=0; i<header.height; ++i ) {
     278           0 :                     if ( (fread(r,header.width,1,fp))<1 || \
     279           0 :                          (fread(g,header.width,1,fp))<1 || \
     280           0 :                          (fread(b,header.width,1,fp))<1 || \
     281           0 :                          (header.chans==4 && (fread(a,header.width,1,fp))<1) )
     282             :                         goto errorGImageReadRgbFile;
     283           0 :                 ipt = (unsigned long *) (base->data + (header.height-1-i)*base->bytes_per_line);
     284           0 :                 rpt = r; gpt = g; bpt = b;
     285           0 :                 for ( iend=ipt+header.width; ipt<iend; )
     286           0 :                     *ipt++ = COLOR_CREATE(*rpt++*255L/header.pixmax,
     287             :                             *gpt++*255L/header.pixmax,*bpt++*255L/header.pixmax);
     288             :                 }
     289             :             } else {
     290           0 :             for ( i=0; i<header.height; ++i ) {
     291           0 :                 for ( j=0; j<header.width; ++j ) {
     292           0 :                     if ( (k=getshort(fp))<0 ) goto errorGImageReadRgbFile;
     293           0 :                     r[j] = k*255L/header.pixmax;
     294             :                 }
     295           0 :                 for ( j=0; j<header.width; ++j ) {
     296           0 :                     if ( (k=getshort(fp))<0 ) goto errorGImageReadRgbFile;
     297           0 :                     g[j] = k*255L/header.pixmax;
     298             :                 }
     299           0 :                 for ( j=0; j<header.width; ++j ) {
     300           0 :                     if ( (k=getshort(fp))<0 ) goto errorGImageReadRgbFile;
     301           0 :                     b[j] = k*255L/header.pixmax;
     302             :                 }
     303           0 :                 if ( header.chans==4 ) {
     304           0 :                     fread(a,header.width,1,fp);
     305           0 :                     fread(a,header.width,1,fp);
     306             :                 }
     307           0 :                 ipt = (unsigned long *) (base->data + (header.height-1-i)*base->bytes_per_line);
     308           0 :                 rpt = r; gpt = g; bpt = b;
     309           0 :                 for ( iend=ipt+header.width; ipt<iend; )
     310           0 :                     *ipt++ = COLOR_CREATE(*rpt++,*gpt++,*bpt++);
     311             :             }
     312             :             }
     313           0 :             free(r); free(g); free(b); free(a);
     314             :         }
     315             :     }
     316           0 :     return( ret );
     317             : 
     318             : errorGImageReadRgbFile:
     319           0 :     fprintf(stderr,"Bad input file \"%s\"\n",filename );
     320             : errorGImageReadRgbMem:
     321           0 :     freeptrtab(ptrtab,tablen);
     322           0 :     free(ptrtab); free(starttab); /*free(lengthtab);*/
     323           0 :     free(r); free(g); free(b); free(a);
     324           0 :     GImageDestroy(ret);
     325           0 :     fclose(fp);
     326           0 :     return( NULL );
     327             : }

Generated by: LCOV version 1.10