LCOV - code coverage report
Current view: top level - gutils - gimage.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 24 244 9.8 %
Date: 2017-08-04 Functions: 3 16 18.8 %

          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 "inc/basics.h"
      28             : #include "gimage.h"
      29             : 
      30           6 : GImage *GImageCreate(enum image_type type, int32 width, int32 height) {
      31             : /* Prepare to get a bitmap image. Cleanup and return NULL if not enough memory */
      32             :     GImage *gi;
      33             :     struct _GImage *base;
      34             : 
      35           6 :     if ( type<it_mono || type>it_rgba )
      36           0 :         return( NULL );
      37             : 
      38           6 :     gi = (GImage *) calloc(1,sizeof(GImage));
      39           6 :     base = (struct _GImage *) malloc(sizeof(struct _GImage));
      40           6 :     if ( gi==NULL || base==NULL )
      41             :         goto errorGImageCreate;
      42             : 
      43           6 :     gi->u.image = base;
      44           6 :     base->image_type = type;
      45           6 :     base->width = width;
      46           6 :     base->height = height;
      47           6 :     base->bytes_per_line = (type==it_true || type==it_rgba)?4*width:type==it_index?width:(width+7)/8;
      48           6 :     base->data = NULL;
      49           6 :     base->clut = NULL;
      50           6 :     base->trans = COLOR_UNKNOWN;
      51           6 :     if ( (base->data = (uint8 *) malloc(height*base->bytes_per_line))==NULL )
      52           0 :         goto errorGImageCreate;
      53           6 :     if ( type==it_index ) {
      54           2 :         if ( (base->clut = (GClut *) calloc(1,sizeof(GClut)))==NULL ) {
      55           0 :             free(base->data);
      56           0 :             goto errorGImageCreate;
      57             :         }
      58           2 :         base->clut->trans_index = COLOR_UNKNOWN;
      59             :     }
      60           6 :     return( gi );
      61             : 
      62             : errorGImageCreate:
      63           0 :     free(base);
      64           0 :     free(gi);
      65           0 :     NoMoreMemMessage();
      66           0 :     return( NULL );
      67             : }
      68             : 
      69             : 
      70           0 : GImage *_GImage_Create(enum image_type type, int32 width, int32 height) {
      71             :     GImage *gi;
      72             :     struct _GImage *base;
      73             : 
      74           0 :     if ( type<it_mono || type>it_rgba )
      75           0 :         return( NULL );
      76             : 
      77           0 :     gi = (GImage *) calloc(1,sizeof(GImage));
      78           0 :     base = (struct _GImage *) malloc(sizeof(struct _GImage));
      79           0 :     if ( gi==NULL || base==NULL )
      80             :         goto error_GImage_Create;
      81             : 
      82           0 :     gi->u.image = base;
      83           0 :     base->image_type = type;
      84           0 :     base->width = width;
      85           0 :     base->height = height;
      86           0 :     base->bytes_per_line = (type==it_true || type==it_rgba)?4*width:type==it_index?width:(width+7)/8;
      87           0 :     base->data = NULL;
      88           0 :     base->clut = NULL;
      89           0 :     if ( type==it_index ) {
      90           0 :         if ( (base->clut = (GClut *) calloc(1,sizeof(GClut)))==NULL )
      91           0 :           goto error_GImage_Create;
      92             :     }
      93           0 :     return( gi );
      94             : 
      95             : error_GImage_Create:
      96           0 :     free(base);
      97           0 :     free(gi);
      98           0 :     NoMoreMemMessage();
      99           0 :     return( NULL );
     100             : }
     101             : 
     102           0 : void GImageDestroy(GImage *gi) {
     103             : /* Free memory (if GImage exists) */
     104             :     int i;
     105             : 
     106           0 :     if (gi!=NULL ) {
     107           0 :         if ( gi->list_len!=0 ) {
     108           0 :             for ( i=0; i<gi->list_len; ++i ) {
     109           0 :                 free(gi->u.images[i]->clut);
     110           0 :                 free(gi->u.images[i]->data);
     111           0 :                 free(gi->u.images[i]);
     112             :             }
     113           0 :             free(gi->u.images);
     114             :         } else {
     115           0 :             free(gi->u.image->clut);
     116           0 :             free(gi->u.image->data);
     117           0 :             free(gi->u.image);
     118             :         }
     119           0 :         free(gi);
     120             :     }
     121           0 : }
     122             : 
     123           0 : GImage *GImageCreateAnimation(GImage **images, int n) {
     124             : /* Create an animation using n "images". Return gi and free "images" if     */
     125             : /* okay, else return NULL and keep "images" if memory error occurred, */
     126             :     GImage *gi;
     127             :     struct _GImage **imgs;
     128             :     int i;
     129             : 
     130             :     /* Check if "images" are okay to copy before creating an animation.       */
     131             :     /* We expect to find single images (not an array). Type must match. */
     132           0 :     for ( i=0; i<n; ++i ) {
     133           0 :         if ( images[i]->list_len!=0 || \
     134           0 :              images[i]->u.image->image_type!=images[0]->u.image->image_type ) {
     135           0 :             fprintf( stderr, "Images are not compatible to make an Animation\n" );
     136           0 :             return( NULL );
     137             :         }
     138             :     }
     139             : 
     140             :     /* First, create enough memory space to hold the complete animation */
     141           0 :     gi = (GImage *) calloc(1,sizeof(GImage));
     142           0 :     imgs = (struct _GImage **) malloc(n*sizeof(struct _GImage *));
     143           0 :     if ( gi==NULL || imgs==NULL ) {
     144           0 :         free(gi);
     145           0 :         free(imgs);
     146           0 :         NoMoreMemMessage();
     147           0 :         return( NULL );
     148             :     }
     149             : 
     150             :     /* Copy images[i] pointer into 'gi', then release each "images[i]".       */
     151           0 :     gi->list_len = n;
     152           0 :     gi->u.images = imgs;
     153           0 :     for ( i=0; i<n; ++i ) {
     154           0 :         imgs[i] = images[i]->u.image;
     155           0 :         free(images[i]);
     156             :     }
     157           0 :     return( gi );
     158             : }
     159             : 
     160             : /* -1 => add it at the end */
     161           0 : GImage *GImageAddImageBefore(GImage *dest, GImage *src, int pos) {
     162             :     struct _GImage **imgs;
     163             :     int n, i, j;
     164             :     enum image_type it;
     165             : 
     166           0 :     n = (src->list_len==0?1:src->list_len) + (dest->list_len==0?1:dest->list_len);
     167           0 :     imgs = (struct _GImage **) malloc(n*sizeof(struct _GImage *));
     168           0 :     if ( imgs==NULL ) {
     169           0 :         NoMoreMemMessage();
     170           0 :         return( NULL );
     171             :     }
     172             : 
     173           0 :     i = 0;
     174           0 :     if ( dest->list_len==0 ) {
     175           0 :         it = dest->u.image->image_type;
     176           0 :         if ( pos==-1 ) pos = 1;
     177           0 :         if ( pos!=0 ) imgs[i++] = dest->u.image;
     178             :     } else {
     179           0 :         it = dest->u.images[0]->image_type;
     180           0 :         if ( pos==-1 ) pos = dest->list_len;
     181           0 :         for ( i=0; i<pos; ++i )
     182           0 :             imgs[i] = dest->u.images[i];
     183             :     }
     184           0 :     j = i;
     185           0 :     if ( src->list_len==0 ) {
     186           0 :         if ( src->u.image->image_type!=it ) {
     187           0 :             free(imgs);
     188           0 : return( NULL );
     189             : }
     190           0 :         imgs[j++] = src->u.image;
     191             :     } else {
     192           0 :         for ( ; j<i+src->list_len; ++j ) {
     193           0 :             if ( src->u.images[j-i]->image_type!=it ) {
     194           0 :                 free(imgs);
     195           0 : return( NULL );
     196             : }
     197           0 :             imgs[j] = src->u.images[j-i];
     198             :         }
     199           0 :         free(src->u.images);
     200             :     }
     201           0 :     if ( dest->list_len==0 ) {
     202           0 :         if ( pos==0 ) imgs[j++] = dest->u.image;
     203             :     } else {
     204           0 :         for ( ; j<n; ++j )
     205           0 :             imgs[j] = dest->u.images[i++];
     206             :     }
     207           0 :     dest->u.images = imgs;
     208           0 :     dest->list_len = n;
     209           0 :     free(src);
     210           0 : return( dest );
     211             : }
     212             : 
     213           0 : void GImageDrawRect(GImage *img,GRect *r,Color col) {
     214             :     struct _GImage *base;
     215             :     int i;
     216             : 
     217           0 :     base = img->u.image;
     218           0 :     if ( r->y>=base->height || r->x>=base->width )
     219           0 : return;
     220             : 
     221           0 :     for ( i=0; i<r->width; ++i ) {
     222           0 :         if ( i+r->x>=base->width )
     223           0 :     break;
     224           0 :         base->data[r->y*base->bytes_per_line + i + r->x] = col;
     225           0 :         if ( r->y+r->height-1<base->height )
     226           0 :             base->data[(r->y+r->height-1)*base->bytes_per_line + i + r->x] = col;
     227             :     }
     228           0 :     for ( i=0; i<r->height; ++i ) {
     229           0 :         if ( i+r->y>=base->height )
     230           0 :     break;
     231           0 :         base->data[(r->y+i)*base->bytes_per_line + r->x] = col;
     232           0 :         if ( r->x+r->width-1<base->width )
     233           0 :             base->data[(r->y+i)*base->bytes_per_line + r->x+r->width-1] = col;
     234             :     }
     235             : }
     236             : 
     237           0 : void GImageDrawImage(GImage *dest,GImage *src,GRect *UNUSED(junk),int x, int y) {
     238             :     struct _GImage *sbase, *dbase;
     239             :     int i,j, di, sbi, dbi, val, factor, maxpix, sbit;
     240             : 
     241             :     /* This is designed to merge images which should be treated as alpha */
     242             :     /* channels. dest must be indexed, src may be either indexed or mono */
     243           0 :     dbase = dest->u.image;
     244           0 :     sbase =  src->u.image;
     245             : 
     246           0 :     if ( dbase->image_type != it_index ) {
     247           0 :         fprintf( stderr, "Bad call to GImageMaxImage\n" );
     248           0 : return;
     249             :     }
     250             : 
     251           0 :     maxpix = 1;
     252           0 :     if ( dbase->clut!=NULL )
     253           0 :         maxpix = dbase->clut->clut_len - 1;
     254             : 
     255           0 :     if ( dbase->clut!=NULL && sbase->clut!=NULL && sbase->clut->clut_len>1 ) {
     256           0 :         factor = (dbase->clut->clut_len - 1) / (sbase->clut->clut_len - 1);
     257           0 :         if ( factor==0 ) factor=1;
     258             :     } else
     259           0 :         factor = 1;
     260             : 
     261           0 :     if ( sbase->image_type == it_index ) {
     262           0 :         for ( i=0; i<sbase->height; ++i ) {
     263           0 :             di = y + i;
     264           0 :             if ( di<0 || di>=dbase->height )
     265           0 :         continue;
     266           0 :             sbi = i*sbase->bytes_per_line;
     267           0 :             dbi = di*dbase->bytes_per_line;
     268           0 :             for ( j=0; j<sbase->width; ++j ) {
     269           0 :                 if ( x+j<0 || x+j>=dbase->width )
     270           0 :             continue;
     271           0 :                 val = dbase->data[dbi+x+j] + sbase->data[sbi+j]*factor;
     272           0 :                 if ( val>255 ) val = 255;
     273           0 :                 dbase->data[dbi+x+j] = val;
     274             :             }
     275             :         }
     276           0 :     } else if ( sbase->image_type == it_mono ) {
     277           0 :         for ( i=0; i<sbase->height; ++i ) {
     278           0 :             di = y + i;
     279           0 :             if ( di<0 || di>=dbase->height )
     280           0 :         continue;
     281           0 :             sbi = i*sbase->bytes_per_line;
     282           0 :             dbi = di*dbase->bytes_per_line;
     283           0 :             for ( j=0, sbit=0x80; j<sbase->width; ++j ) {
     284           0 :                 if ( x+j<0 || x+j>=dbase->width )
     285           0 :             continue;
     286           0 :                 if ( sbase->data[sbi+(j>>3)] & sbit )
     287           0 :                     dbase->data[dbi+x+j] = maxpix;
     288           0 :                 if ( (sbit>>=1) == 0 )
     289           0 :                     sbit = 0x80;
     290             :             }
     291             :         }
     292             :     }
     293             : }
     294             : 
     295             : /* Blends src image with alpha channel over dest. Both images must be */
     296             : /* 32-bit truecolor. Alpha channel of dest must be all opaque.        */
     297           0 : void GImageBlendOver(GImage *dest,GImage *src,GRect *from,int x, int y) {
     298             :     struct _GImage *sbase, *dbase;
     299             :     int i, j, a, r, g, b;
     300             :     uint32 *dpt, *spt;
     301             : 
     302           0 :     dbase = dest->u.image;
     303           0 :     sbase =  src->u.image;
     304             : 
     305           0 :     if ( dbase->image_type != it_true ) {
     306           0 :         fprintf( stderr, "Bad call to GImageBlendOver\n" );
     307           0 : return;
     308             :     }
     309             : 
     310           0 :     if ( sbase->image_type != it_rgba ) {
     311           0 :         fprintf( stderr, "Bad call to GImageBlendOver\n" );
     312           0 : return;
     313             :     }
     314             : 
     315           0 :     for ( i=0; i<from->height; ++i ) {
     316           0 :         dpt = (uint32 *) (dbase->data + (i+y)*dbase->bytes_per_line + x*sizeof(uint32));
     317           0 :         spt = (uint32 *) (sbase->data + (i+from->y)*sbase->bytes_per_line + from->x*sizeof(uint32));
     318             :         
     319           0 :         for (j=0; j<from->width; j++) {
     320           0 :             a = COLOR_ALPHA(*spt);
     321           0 :             r = ((255-a)*COLOR_RED(*dpt)  + a*COLOR_RED(*spt))/255;
     322           0 :             g = ((255-a)*COLOR_GREEN(*dpt)+ a*COLOR_GREEN(*spt))/255;
     323           0 :             b = ((255-a)*COLOR_BLUE(*dpt) + a*COLOR_BLUE(*spt))/255;
     324           0 :             spt++;
     325           0 :             *dpt++ = 0xff000000 | COLOR_CREATE(r,g,b);
     326             :         }
     327             :     }
     328             : }
     329             : 
     330           5 : int GImageGetWidth(GImage *img) {
     331           5 :     if ( img->list_len==0 ) {
     332           5 : return( img->u.image->width );
     333             :     } else {
     334           0 : return( img->u.images[0]->width );
     335             :     }
     336             : }
     337             : 
     338           5 : int GImageGetHeight(GImage *img) {
     339           5 :     if ( img->list_len==0 ) {
     340           5 : return( img->u.image->height );
     341             :     } else {
     342           0 : return( img->u.images[0]->height );
     343             :     }
     344             : }
     345             : 
     346           0 : void *GImageGetUserData(GImage *img) {
     347           0 : return( img->userdata );
     348             : }
     349             : 
     350           0 : void GImageSetUserData(GImage *img,void *userdata) {
     351           0 :     img->userdata = userdata;
     352           0 : }
     353             : 
     354           0 : static Color _GImageGetPixelRGBA(struct _GImage *base,int x, int y) {
     355             :     Color val;
     356             : 
     357           0 :     if ( base->image_type==it_rgba ) {
     358           0 :         val = ((uint32*) (base->data + y*base->bytes_per_line))[x] ;
     359           0 : return( val==base->trans?(val&0xffffff):val );
     360           0 :     } else if ( base->image_type==it_true ) {
     361           0 :         val = ((uint32*) (base->data + y*base->bytes_per_line))[x] ;
     362           0 : return( val==base->trans?(val&0xffffff):(val|0xff000000) );
     363           0 :     } else if ( base->image_type==it_index ) {
     364           0 :         uint8 pixel = ((uint8*) (base->data + y*base->bytes_per_line))[x];
     365           0 :         val = base->clut->clut[pixel];
     366           0 : return( pixel==base->trans?(val&0xffffff):(val|0xff000000) );
     367             :     } else {
     368           0 :         uint8 pixel = (((uint8*) (base->data + y*base->bytes_per_line))[x>>3]&(1<<(7-(x&7))) )?1:0;
     369           0 :         if ( base->clut==NULL ) {
     370           0 :             if ( pixel )
     371           0 :                 val = COLOR_CREATE(0xff,0xff,0xff);
     372             :             else
     373           0 :                 val = COLOR_CREATE(0,0,0);
     374             :         } else
     375           0 :             val = base->clut->clut[pixel];
     376           0 : return( pixel==base->trans?(val&0xffffff):(val|0xff000000) );
     377             :     }
     378             : }
     379             : 
     380           0 : Color GImageGetPixelRGBA(GImage *image,int x, int y) {
     381           0 :     struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
     382           0 : return( _GImageGetPixelRGBA(base,x,y));
     383             : }
     384             : 
     385             : /* This routine is now obsolete. I include it for compatability. See GImageGetPixelRGBA */
     386           0 : Color _GImageGetPixelColor(struct _GImage *base,int x, int y) {
     387             :     Color val;
     388             : 
     389           0 :     if ( base->image_type==it_rgba ) {
     390           0 :         val = ((uint32*) (base->data + y*base->bytes_per_line))[x] ;
     391           0 : return( val==base->trans?~val:val );
     392           0 :     } else if ( base->image_type==it_true ) {
     393           0 :         val = ((uint32*) (base->data + y*base->bytes_per_line))[x] ;
     394           0 : return( val==base->trans?~val:val );
     395           0 :     } else if ( base->image_type==it_index ) {
     396           0 :         uint8 pixel = ((uint8*) (base->data + y*base->bytes_per_line))[x];
     397           0 :         val = base->clut->clut[pixel];
     398           0 : return( pixel==base->trans?~val:val );
     399             :     } else {
     400           0 :         uint8 pixel = (((uint8*) (base->data + y*base->bytes_per_line))[x>>3]&(1<<(7-(x&7))) )?1:0;
     401           0 :         if ( base->clut==NULL ) {
     402           0 :             if ( pixel )
     403           0 :                 val = COLOR_CREATE(0xff,0xff,0xff);
     404             :             else
     405           0 :                 val = COLOR_CREATE(0,0,0);
     406             :         } else
     407           0 :             val = base->clut->clut[pixel];
     408           0 : return( pixel==base->trans?~val:val );
     409             :     }
     410             : }
     411             : 
     412           0 : Color GImageGetPixelColor(GImage *image,int x, int y) {
     413           0 :     struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
     414           0 : return( _GImageGetPixelColor(base,x,y));
     415             : }

Generated by: LCOV version 1.10