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

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /* 2013jan30..feb5, additional fixes and error checks done, Jose Da Silva */
       3             : /*
       4             :  * Redistribution and use in source and binary forms, with or without
       5             :  * modification, are permitted provided that the following conditions are met:
       6             : 
       7             :  * Redistributions of source code must retain the above copyright notice, this
       8             :  * list of conditions and the following disclaimer.
       9             : 
      10             :  * Redistributions in binary form must reproduce the above copyright notice,
      11             :  * this list of conditions and the following disclaimer in the documentation
      12             :  * and/or other materials provided with the distribution.
      13             : 
      14             :  * The name of the author may not be used to endorse or promote products
      15             :  * derived from this software without specific prior written permission.
      16             : 
      17             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      18             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      19             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      20             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      22             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      23             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      24             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      25             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      26             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             :  */
      28             : #include "gimage.h"
      29             : 
      30             : typedef struct _SunRaster {
      31             :   long MagicNumber;     /* Magic (identification) number */
      32             :   long Width;           /* Width of image in pixels */
      33             :   long Height;          /* Height of image in pixels */
      34             :   long Depth;           /* Number of bits per pixel */
      35             :   long Length;          /* Size of image data in bytes */
      36             :   long Type;            /* Type of raster file */
      37             :   long ColorMapType;    /* Type of color map */
      38             :   long ColorMapLength;  /* Size of the color map in bytes */
      39             : } SUNRASTER;
      40             : 
      41             : #define SUN_RAS_MAGIC   0x59a66a95
      42             : #define LITTLE_ENDIAN_MAGIC     0x956aa659      /* if we read this value, must byte swap */
      43             : 
      44             : enum types { TypeOld, TypeStandard, TypeByteEncoded, TypeRGB, TypeTIFF, TypeIFF };
      45             : enum cluts { ClutNone, ClutRGB, ClutRaw };
      46             : 
      47           0 : static int getlong(FILE *fp, long *value) {
      48             : /* Get Big-Endian long (32bit int) value. Return 0 if okay, -1 if error */
      49             :     int ch1, ch2, ch3, ch4;
      50             : 
      51           0 :     if ( (ch1=fgetc(fp))<0 || (ch2=fgetc(fp))<0 || \
      52           0 :          (ch3=fgetc(fp))<0 || (ch4=fgetc(fp))<0 ) {
      53           0 :         *value=0;
      54           0 :         return( -1 );
      55             :     }
      56           0 :     *value=(long)( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
      57           0 :     return( 0 );
      58             : }
      59             : 
      60           0 : static int getrasheader(SUNRASTER *head, FILE *fp) {
      61             : /* Get Header info. Return 0 if read input file okay, -1 if read error  */
      62           0 :     if ( getlong(fp,&head->MagicNumber)   || \
      63           0 :          (head->MagicNumber!=SUN_RAS_MAGIC && head->MagicNumber!=LITTLE_ENDIAN_MAGIC) || \
      64           0 :          getlong(fp,&head->Width)         || \
      65           0 :          getlong(fp,&head->Height)        || \
      66           0 :          getlong(fp,&head->Depth)         || \
      67           0 :          getlong(fp,&head->Length)        || \
      68           0 :          getlong(fp,&head->Type)  || \
      69           0 :          getlong(fp,&head->ColorMapType) || \
      70           0 :          getlong(fp,&head->ColorMapLength) )
      71           0 :         return( -1 );
      72             : 
      73             :     /* Check if header information okay (only try Big-Endian for now).  */
      74           0 :     if ( head->MagicNumber!=SUN_RAS_MAGIC || \
      75           0 :          head->Type<0 || head->Type>TypeRGB || \
      76           0 :          (head->ColorMapType!=ClutNone && head->ColorMapType!=ClutRGB) || \
      77           0 :          (head->Depth!=1 && head->Depth!=8 && head->Depth!=24 && head->Depth!=32) || \
      78           0 :          (head->Depth>=24 && head->ColorMapType!=ClutNone) || \
      79           0 :          head->ColorMapLength>3*256 )
      80           0 :         return( -1 );
      81             : 
      82           0 :     return( 0 );
      83             : }
      84             : 
      85           0 : static GImage *ReadRasBitmap(GImage *ret,int width, int height, FILE *fp ) {
      86           0 :     struct _GImage *base = ret->u.image;
      87             :     int i,j,len;
      88             :     unsigned char *pt, *buf;
      89             : 
      90           0 :     len = ((width+15)/16)*2;    /* pad out to 16 bits */
      91           0 :     if ( (buf=(unsigned char *) malloc(len*sizeof(unsigned char)))==NULL ) {
      92           0 :         NoMoreMemMessage();
      93           0 :         GImageDestroy(ret);
      94           0 :         return( NULL );
      95             :     }
      96             : 
      97           0 :     for ( i=0; i<height; ++i ) {
      98           0 :         if ( fread(buf,len,1,fp)<1 ) {
      99           0 :             free(buf);
     100           0 :             GImageDestroy(ret);
     101           0 :             return( NULL );
     102             :         }
     103           0 :         pt = (unsigned char *) (base->data + i*base->bytes_per_line);
     104           0 :         for ( j=0; j<(width+7)>>3; ++j )
     105           0 :             pt[j]=256-buf[j];
     106             :     }
     107           0 :     free(buf);
     108           0 :     return( ret );
     109             : }
     110             : 
     111           0 : static GImage *ReadRas8Bit(GImage *ret,int width, int height, FILE *fp ) {
     112           0 :     struct _GImage *base = ret->u.image;
     113             :     int i;
     114             : 
     115           0 :     for ( i=0; i<height; ++i ) {
     116           0 :         if ( fread((base->data + i*base->bytes_per_line),width,1,fp)<1 ) {
     117           0 :             goto errorReadRas8Bit;
     118             :         }
     119           0 :         if ( width&1 )              /* pad out to 16 bits */
     120           0 :             if ( fgetc(fp)<0 )
     121           0 :                 goto errorReadRas8Bit;
     122             :     }
     123           0 :     return( ret );
     124             : 
     125             : errorReadRas8Bit:
     126           0 :     GImageDestroy(ret);
     127           0 :     return( NULL );
     128             : }
     129             : 
     130           0 : static GImage *ReadRas24Bit(GImage *ret,int width, int height, FILE *fp ) {
     131           0 :     struct _GImage *base = ret->u.image;
     132           0 :     int ch1,ch2,ch3=0;
     133             :     int i;
     134             :     long *ipt,*end;
     135             : 
     136           0 :     for ( i=0; i<height; ++i ) {
     137           0 :         for ( ipt = (long *) (base->data + i*base->bytes_per_line), end = ipt+width; ipt<end; ) {
     138           0 :             if ( (ch1=fgetc(fp))<0 || (ch2=fgetc(fp))<0 || (ch3=fgetc(fp))<0 )
     139             :                 goto errorReadRas24Bit;
     140           0 :             *ipt++ = COLOR_CREATE(ch3,ch2,ch1);
     141             :         }
     142           0 :         if ( width&1 )              /* pad out to 16 bits */
     143           0 :             if ( fgetc(fp)<0 )
     144           0 :                 goto errorReadRas24Bit;
     145             :     }
     146           0 :     return( ret );
     147             : 
     148             : errorReadRas24Bit:
     149           0 :     GImageDestroy(ret);
     150           0 :     return( NULL );
     151             : }
     152             : 
     153           0 : static GImage *ReadRas32Bit(GImage *ret,int width, int height, FILE *fp ) {
     154           0 :     struct _GImage *base = ret->u.image;
     155           0 :     int ch1,ch2,ch3=0;
     156             :     int i;
     157             :     long *ipt, *end;
     158             : 
     159           0 :     for ( i=0; i<height; ++i )
     160           0 :         for ( ipt = (long *) (base->data + i*base->bytes_per_line), end = ipt+width; ipt<end; ) {
     161           0 :             fgetc(fp);  /* pad byte */
     162           0 :             ch1 = fgetc(fp); ch2 = fgetc(fp); ch3 = fgetc(fp);
     163           0 :             *ipt++ = COLOR_CREATE(ch3,ch2,ch1);
     164             :         }
     165           0 :     if ( ch3==EOF ) {
     166           0 :         GImageDestroy(ret);
     167           0 :         ret = NULL;
     168             :     }
     169           0 : return ret;
     170             : }
     171             : 
     172           0 : static GImage *ReadRas24RBit(GImage *ret,int width, int height, FILE *fp ) {
     173           0 :     struct _GImage *base = ret->u.image;
     174           0 :     int ch1,ch2,ch3=0;
     175             :     int i;
     176             :     long *ipt,*end;
     177             : 
     178           0 :     for ( i=0; i<height; ++i ) {
     179           0 :         for ( ipt = (long *) (base->data + i*base->bytes_per_line), end = ipt+width; ipt<end; ) {
     180           0 :             if ( (ch1=fgetc(fp))<0 || (ch2=fgetc(fp))<0 || (ch3=fgetc(fp))<0 )
     181             :                 goto errorReadRas24RBit;
     182           0 :             *ipt++ = COLOR_CREATE(ch1,ch2,ch3);
     183             :         }
     184           0 :         if ( width&1 )              /* pad out to 16 bits */
     185           0 :             if ( fgetc(fp)<0 )
     186           0 :                 goto errorReadRas24RBit;
     187             :     }
     188           0 :     return( ret );
     189             : 
     190             : errorReadRas24RBit:
     191           0 :     GImageDestroy(ret);
     192           0 :     return( NULL );
     193             : }
     194             : 
     195           0 : static GImage *ReadRas32RBit(GImage *ret,int width, int height, FILE *fp ) {
     196           0 :     struct _GImage *base = ret->u.image;
     197           0 :     int ch1,ch2,ch3=0;
     198             :     int i;
     199             :     long *ipt, *end;
     200             : 
     201           0 :     for ( i=0; i<height; ++i )
     202           0 :         for ( ipt = (long *) (base->data + i*base->bytes_per_line), end = ipt+width; ipt<end; ) {
     203           0 :             fgetc(fp);  /* pad byte */
     204           0 :             ch1 = fgetc(fp); ch2 = fgetc(fp); ch3 = fgetc(fp);
     205           0 :             *ipt++ = COLOR_CREATE(ch1,ch2,ch3);
     206             :         }
     207           0 :     if ( ch3==EOF ) {
     208           0 :         GImageDestroy(ret);
     209           0 :         ret = NULL;
     210             :     }
     211           0 : return ret;
     212             : }
     213             : 
     214           0 : static GImage *ReadRle8Bit(GImage *ret,int width, int height, FILE *fp ) {
     215             : /* TODO: Make this an input filter that goes in front of other routines */
     216             : /* above so that in can be re-used by the different converters above.   */
     217           0 :     struct _GImage *base = ret->u.image;
     218           0 :     int x,y,cnt,val = 0;
     219           0 :     unsigned char *pt = NULL;
     220             : 
     221           0 :     x=0; y=0; cnt=0;
     222             :     while ( 1 ) {
     223           0 :         while ( cnt && x ) {
     224           0 :             --cnt; if ( --x || (width&1)-1 ) * pt++ = val;
     225             :         }
     226           0 :         if ( x==0 ) {
     227           0 :             pt = (unsigned char *) (base->data + y*base->bytes_per_line);
     228           0 :             if ( ++y>height )
     229           0 :                 return( ret );
     230           0 :             x=((width+1)>>1)<<1;
     231             :         }
     232           0 :         if ( cnt==0 ) {
     233           0 :             if ( (val=fgetc(fp))<0 ) goto errorReadRle8Bit;
     234           0 :             cnt++;
     235           0 :             if ( val==0x80 ) {
     236           0 :                 if ( (cnt=fgetc(fp))<0 ) goto errorReadRle8Bit;
     237           0 :                 if ( cnt++!=0 )
     238             :                     /* prepare to go insert 'val', 'cnt' times */
     239           0 :                     if ( (val=fgetc(fp))<0 ) goto errorReadRle8Bit;
     240             :             }
     241             :         }
     242           0 :     }
     243             : 
     244             : errorReadRle8Bit:
     245           0 :     GImageDestroy(ret);
     246           0 :     return( NULL );
     247             : }
     248             : 
     249           0 : GImage *GImageReadRas(char *filename) {
     250             : /* Import a *.ras image (or *.im{1,8,24,32}), else return NULL if error */
     251             :     FILE *fp;                   /* source file */
     252             :     struct _SunRaster header;
     253           0 :     GImage *ret = NULL;
     254             :     struct _GImage *base;
     255             : 
     256           0 :     if ( (fp=fopen(filename,"rb"))==NULL ) {
     257           0 :         fprintf(stderr,"Can't open \"%s\"\n", filename);
     258           0 :         return( NULL );
     259             :     }
     260             : 
     261           0 :     if ( getrasheader(&header,fp) )
     262           0 :         goto errorGImageReadRas;
     263             : 
     264             :     /* Create memory to hold image, exit with NULL if not enough memory */
     265           0 :     if ( (header.Depth==1 && \
     266           0 :           (ret=GImageCreate(it_bitmap,header.Width,header.Height))==NULL) || \
     267           0 :           (header.Depth!=1 && \
     268           0 :           (ret=GImageCreate(header.Depth==24?it_true:it_index,header.Width,header.Height))==NULL) ) {
     269           0 :         fclose(fp);
     270           0 :         return( NULL );
     271             :     }
     272             : 
     273             :     /* Convert *.ras ColorMap to one that FF can use */
     274           0 :     base = ret->u.image;
     275           0 :     if ( header.ColorMapLength!=0 && base->clut!=NULL ) {
     276             :         unsigned char clutb[3*256]; int i,n;
     277           0 :         if ( fread(clutb,header.ColorMapLength,1,fp)<1 )
     278           0 :             goto errorGImageReadRas;
     279             : //      if ( header.ColorMapType==ClutRaw ) {
     280             : //          n = header.ColorMapLength;
     281             : //          base->clut->clut_len = n;
     282             : //          for ( i=0; i<n; ++i )
     283             : //              base->clut->clut[i] = clutb[i];
     284             : //      } else {
     285           0 :         n = header.ColorMapLength/3;
     286           0 :         base->clut->clut_len = n;
     287           0 :         for ( i=0; i<n; ++i )
     288           0 :             base->clut->clut[i] = COLOR_CREATE(clutb[i],clutb[i+n],clutb[i+2*n]);
     289             : //      }
     290             :     }
     291             : 
     292           0 :     if ( header.Type==TypeOld || header.Type==TypeStandard ) {  /* Synonymous */
     293           0 :             if ( header.Depth==1 )
     294           0 :                 ret = ReadRasBitmap(ret,header.Width,header.Height,fp);
     295           0 :             else if ( header.Depth==8 )
     296           0 :                 ret = ReadRas8Bit(ret,header.Width,header.Height,fp);
     297           0 :             else if ( header.Depth==24 )
     298           0 :                 ret = ReadRas24Bit(ret,header.Width,header.Height,fp);
     299             :             else
     300           0 :                 ret = ReadRas32Bit(ret,header.Width,header.Height,fp);
     301           0 :     } else if ( header.Type==TypeRGB ) {
     302             :             /* I think this type is the same as standard except rgb not bgr */
     303           0 :             if ( header.Depth==1 )
     304           0 :                 ret = ReadRasBitmap(ret,header.Width,header.Height,fp);
     305           0 :             else if ( header.Depth==8 )
     306           0 :                 ret = ReadRas8Bit(ret,header.Width,header.Height,fp);
     307           0 :             else if ( header.Depth==24 )
     308           0 :                 ret = ReadRas24RBit(ret,header.Width,header.Height,fp);
     309             :             else
     310           0 :                 ret = ReadRas32RBit(ret,header.Width,header.Height,fp);
     311           0 :     } else if ( header.Type==TypeByteEncoded ) {
     312           0 :             if ( header.Depth==8 )
     313           0 :                 ret = ReadRle8Bit(ret,header.Width,header.Height,fp);
     314             :             else {
     315             :                 /* Don't bother with most rle formats */
     316             :                 /* TODO: if someone wants to do this - accept more formats */
     317           0 :                 fprintf(stderr,"Unsupported input file type\n");
     318           0 :                 goto errorGImageReadRas;
     319             :             }
     320             :     } else {
     321             :             /* Don't bother with other formats */
     322             :             /* TODO: if someone wants to do this - accept more formats */
     323           0 :         fprintf(stderr,"Unsupported input file type\n");
     324           0 :             goto errorGImageReadRas;
     325             :         }
     326           0 :     if ( ret!=NULL ) {
     327             :             /* All okay if reached here, return converted image */
     328           0 :             fclose(fp);
     329           0 :             return( ret );
     330             :     }
     331             : 
     332             : errorGImageReadRas:
     333           0 :     fprintf(stderr,"Bad input file \"%s\"\n",filename );
     334           0 :     GImageDestroy(ret);
     335           0 :     fclose(fp);
     336           0 :     return( NULL );
     337             : }

Generated by: LCOV version 1.10