PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - gd/libgd - gd_gd2.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 367
Code covered: 48.2 % Executed lines: 177
Legend: not executed executed

       1                 : /*
       2                 :    * gd_gd2.c
       3                 :    *
       4                 :    * Implements the I/O and support for the GD2 format.
       5                 :    *
       6                 :    * Changing the definition of GD2_DBG (below) will cause copious messages
       7                 :    * to be displayed while it processes requests.
       8                 :    *
       9                 :    * Designed, Written & Copyright 1999, Philip Warner.
      10                 :    *
      11                 :  */
      12                 : 
      13                 : #include <stdio.h>
      14                 : #include <errno.h>
      15                 : #include <math.h>
      16                 : #include <string.h>
      17                 : #include <stdlib.h>
      18                 : #include "gd.h"
      19                 : #include "gdhelpers.h"
      20                 : 
      21                 : #include <zlib.h>
      22                 : 
      23                 : #define TRUE 1
      24                 : #define FALSE 0
      25                 : 
      26                 : /* 2.11: not part of the API, as the save routine can figure it out
      27                 :  *      from im->trueColor, and the load routine doesn't need to tell
      28                 :  *      the end user the saved format. NOTE: adding 2 is assumed
      29                 :  *      to result in the correct format value for truecolor!
      30                 : */
      31                 : #define GD2_FMT_TRUECOLOR_RAW 3
      32                 : #define GD2_FMT_TRUECOLOR_COMPRESSED 4
      33                 : 
      34                 : #define gd2_compressed(fmt) (((fmt) == GD2_FMT_COMPRESSED) || ((fmt) == GD2_FMT_TRUECOLOR_COMPRESSED))
      35                 : #define gd2_truecolor(fmt) (((fmt) == GD2_FMT_TRUECOLOR_RAW) || ((fmt) == GD2_FMT_TRUECOLOR_COMPRESSED))
      36                 : 
      37                 : /* Use this for commenting out debug-print statements. */
      38                 : /* Just use the first '#define' to allow all the prints... */
      39                 : /* #define GD2_DBG(s) (s) */
      40                 : #define GD2_DBG(s)
      41                 : 
      42                 : typedef struct
      43                 : {
      44                 :         int offset;
      45                 :         int size;
      46                 : } t_chunk_info;
      47                 : 
      48                 : extern int _gdGetColors(gdIOCtx * in, gdImagePtr im, int gd2xFlag);
      49                 : extern void _gdPutColors(gdImagePtr im, gdIOCtx * out);
      50                 : 
      51                 : /* */
      52                 : /* Read the extra info in the gd2 header. */
      53                 : /* */
      54                 : static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** chunkIdx)
      55               7 : {
      56                 :         int i;
      57                 :         int ch;
      58                 :         char id[5];
      59                 :         t_chunk_info *cidx;
      60                 :         int sidx;
      61                 :         int nc;
      62                 : 
      63                 :         GD2_DBG(php_gd_error("Reading gd2 header info"));
      64                 : 
      65              35 :         for (i = 0; i < 4; i++) {
      66              28 :                 ch = gdGetC(in);
      67              28 :                 if (ch == EOF) {
      68               0 :                         goto fail1;
      69                 :                 }
      70              28 :                 id[i] = ch;
      71                 :         }
      72               7 :         id[4] = 0;
      73                 : 
      74                 :         GD2_DBG(php_gd_error("Got file code: %s", id));
      75                 : 
      76                 :         /* Equiv. of 'magick'.  */
      77               7 :         if (strcmp(id, GD2_ID) != 0) {
      78                 :                 GD2_DBG(php_gd_error("Not a valid gd2 file"));
      79               0 :                 goto fail1;
      80                 :         }
      81                 : 
      82                 :         /* Version */
      83               7 :         if (gdGetWord(vers, in) != 1) {
      84               0 :                 goto fail1;
      85                 :         }
      86                 :         GD2_DBG(php_gd_error("Version: %d", *vers));
      87                 : 
      88               7 :         if ((*vers != 1) && (*vers != 2)) {
      89                 :                 GD2_DBG(php_gd_error("Bad version: %d", *vers));
      90               0 :                 goto fail1;
      91                 :         }
      92                 : 
      93                 :         /* Image Size */
      94               7 :         if (!gdGetWord(sx, in)) {
      95                 :                 GD2_DBG(php_gd_error("Could not get x-size"));
      96               0 :                 goto fail1;
      97                 :         }
      98               7 :         if (!gdGetWord(sy, in)) {
      99                 :                 GD2_DBG(php_gd_error("Could not get y-size"));
     100               0 :                 goto fail1;
     101                 :         }
     102                 :         GD2_DBG(php_gd_error("Image is %dx%d", *sx, *sy));
     103                 : 
     104                 :         /* Chunk Size (pixels, not bytes!) */
     105               7 :         if (gdGetWord(cs, in) != 1) {
     106               0 :                 goto fail1;
     107                 :         }
     108                 :         GD2_DBG(php_gd_error("ChunkSize: %d", *cs));
     109                 : 
     110               7 :         if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) {
     111                 :                 GD2_DBG(php_gd_error("Bad chunk size: %d", *cs));
     112                 :                 goto fail1;
     113                 :         }
     114                 : 
     115                 :         /* Data Format */
     116               7 :         if (gdGetWord(fmt, in) != 1) {
     117               0 :                 goto fail1;
     118                 :         }
     119                 :         GD2_DBG(php_gd_error("Format: %d", *fmt));
     120                 : 
     121               7 :         if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED) && (*fmt != GD2_FMT_TRUECOLOR_RAW) && (*fmt != GD2_FMT_TRUECOLOR_COMPRESSED)) {
     122                 :                 GD2_DBG(php_gd_error("Bad data format: %d", *fmt));
     123               0 :                 goto fail1;
     124                 :         }
     125                 : 
     126                 :         /* # of chunks wide */
     127               7 :         if (gdGetWord(ncx, in) != 1) {
     128               0 :                 goto fail1;
     129                 :         }
     130                 :         GD2_DBG(php_gd_error("%d Chunks Wide", *ncx));
     131                 : 
     132                 :         /* # of chunks high */
     133               7 :         if (gdGetWord(ncy, in) != 1) {
     134               0 :                 goto fail1;
     135                 :         }
     136                 :         GD2_DBG(php_gd_error("%d Chunks vertically", *ncy));
     137                 : 
     138               7 :         if (gd2_compressed(*fmt)) {
     139               0 :                 nc = (*ncx) * (*ncy);
     140                 :                 GD2_DBG(php_gd_error("Reading %d chunk index entries", nc));
     141               0 :                 sidx = sizeof(t_chunk_info) * nc;
     142               0 :                 if (sidx <= 0) {
     143               0 :                         goto fail1;
     144                 :                 }
     145               0 :                 cidx = gdCalloc(sidx, 1);
     146               0 :                 for (i = 0; i < nc; i++) {
     147               0 :                         if (gdGetInt(&cidx[i].offset, in) != 1) {
     148               0 :                                 goto fail1;
     149                 :                         }
     150               0 :                         if (gdGetInt(&cidx[i].size, in) != 1) {
     151               0 :                                 goto fail1;
     152                 :                         }
     153                 :                 }
     154               0 :                 *chunkIdx = cidx;
     155                 :         }
     156                 : 
     157                 :         GD2_DBG(php_gd_error("gd2 header complete"));
     158                 : 
     159               7 :         return 1;
     160                 : 
     161               0 : fail1:
     162               0 :         return 0;
     163                 : }
     164                 : 
     165                 : static gdImagePtr _gd2CreateFromFile (gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** cidx)
     166               6 : {
     167                 :         gdImagePtr im;
     168                 : 
     169               6 :         if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1) {
     170                 :                 GD2_DBG(php_gd_error("Bad GD2 header"));
     171               0 :                 goto fail1;
     172                 :         }
     173                 : 
     174              12 :         if (gd2_truecolor(*fmt)) {
     175               6 :                 im = gdImageCreateTrueColor(*sx, *sy);
     176                 :         } else {
     177               0 :                 im = gdImageCreate(*sx, *sy);
     178                 :         }
     179               6 :         if (im == NULL) {
     180                 :                 GD2_DBG(php_gd_error("Could not create gdImage"));
     181               0 :                 goto fail1;
     182                 :         }
     183                 : 
     184               6 :         if (!_gdGetColors(in, im, (*vers) == 2)) {
     185                 :                 GD2_DBG(php_gd_error("Could not read color palette"));
     186               0 :                 goto fail2;
     187                 :         }
     188                 :         GD2_DBG(php_gd_error("Image palette completed: %d colours", im->colorsTotal));
     189                 : 
     190               6 :         return im;
     191                 : 
     192               0 : fail2:
     193               0 :         gdImageDestroy(im);
     194               0 :         return 0;
     195                 : 
     196               0 : fail1:
     197               0 :         return 0;
     198                 : }
     199                 : 
     200                 : static int _gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf, uLongf * chunkLen, gdIOCtx * in)
     201               0 : {
     202                 :         int zerr;
     203                 : 
     204               0 :         if (gdTell(in) != offset) {
     205                 :                 GD2_DBG(php_gd_error("Positioning in file to %d", offset));
     206               0 :                 gdSeek(in, offset);
     207                 :         } else {
     208                 :                 GD2_DBG(php_gd_error("Already Positioned in file to %d", offset));
     209                 :         }
     210                 : 
     211                 :         /* Read and uncompress an entire chunk. */
     212                 :         GD2_DBG(php_gd_error("Reading file"));
     213               0 :         if (gdGetBuf(compBuf, compSize, in) != compSize) {
     214               0 :                 return FALSE;
     215                 :         }
     216                 :         GD2_DBG(php_gd_error("Got %d bytes. Uncompressing into buffer of %d bytes", compSize, (int)*chunkLen));
     217               0 :         zerr = uncompress((unsigned char *) chunkBuf, chunkLen, (unsigned char *) compBuf, compSize);
     218               0 :         if (zerr != Z_OK) {
     219                 :                 GD2_DBG(php_gd_error("Error %d from uncompress", zerr));
     220               0 :                 return FALSE;
     221                 :         }
     222                 :         GD2_DBG(php_gd_error("Got chunk"));
     223                 : 
     224               0 :         return TRUE;
     225                 : }
     226                 : 
     227                 : gdImagePtr gdImageCreateFromGd2 (FILE * inFile)
     228               3 : {
     229               3 :         gdIOCtx *in = gdNewFileCtx(inFile);
     230                 :         gdImagePtr im;
     231                 : 
     232               3 :         im = gdImageCreateFromGd2Ctx(in);
     233                 : 
     234               3 :         in->gd_free(in);
     235                 : 
     236               3 :         return im;
     237                 : }
     238                 : 
     239                 : gdImagePtr gdImageCreateFromGd2Ptr (int size, void *data)
     240               0 : {
     241                 :         gdImagePtr im;
     242               0 :         gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
     243               0 :         im = gdImageCreateFromGd2Ctx(in);
     244               0 :         in->gd_free(in);
     245                 : 
     246               0 :         return im;
     247                 : }
     248                 : 
     249                 : gdImagePtr gdImageCreateFromGd2Ctx (gdIOCtxPtr in)
     250               6 : {
     251                 :         int sx, sy;
     252                 :         int i;
     253                 :         int ncx, ncy, nc, cs, cx, cy;
     254                 :         int x, y, ylo, yhi, xlo, xhi;
     255                 :         int vers, fmt;
     256               6 :         t_chunk_info *chunkIdx = NULL;  /* So we can gdFree it with impunity. */
     257               6 :         unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */
     258               6 :         int chunkNum = 0;
     259               6 :         int chunkMax = 0;
     260                 :         uLongf chunkLen;
     261               6 :         int chunkPos = 0;
     262               6 :         int compMax = 0;
     263                 :         int bytesPerPixel;
     264               6 :         char *compBuf = NULL;           /* So we can gdFree it with impunity. */
     265                 : 
     266                 :         gdImagePtr im;
     267                 : 
     268                 :         /* Get the header */
     269               6 :         if (!(im = _gd2CreateFromFile(in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx))) {
     270               0 :                  return 0;
     271                 :         }
     272                 : 
     273               6 :         bytesPerPixel = im->trueColor ? 4 : 1;
     274               6 :         nc = ncx * ncy;
     275                 : 
     276               6 :         if (gd2_compressed(fmt)) {
     277                 :                 /* Find the maximum compressed chunk size. */
     278               0 :                 compMax = 0;
     279               0 :                 for (i = 0; (i < nc); i++) {
     280               0 :                         if (chunkIdx[i].size > compMax) {
     281               0 :                                 compMax = chunkIdx[i].size;
     282                 :                         }
     283                 :                 }
     284               0 :                 compMax++;
     285                 : 
     286                 :                 /* Allocate buffers */
     287               0 :                 chunkMax = cs * bytesPerPixel * cs;
     288               0 :                 if (chunkMax <= 0) {
     289               0 :                         return 0;
     290                 :                 }
     291               0 :                 chunkBuf = gdCalloc(chunkMax, 1);
     292               0 :                 compBuf = gdCalloc(compMax, 1);
     293                 : 
     294                 :                 GD2_DBG(php_gd_error("Largest compressed chunk is %d bytes", compMax));
     295                 :         }
     296                 : 
     297                 :         /* Read the data... */
     298              14 :         for (cy = 0; (cy < ncy); cy++) {
     299              22 :                 for (cx = 0; (cx < ncx); cx++) {
     300              14 :                         ylo = cy * cs;
     301              14 :                         yhi = ylo + cs;
     302              14 :                         if (yhi > im->sy) {
     303               8 :                                 yhi = im->sy;
     304                 :                         }
     305                 : 
     306                 :                         GD2_DBG(php_gd_error("Processing Chunk %d (%d, %d), y from %d to %d", chunkNum, cx, cy, ylo, yhi));
     307                 : 
     308              14 :                         if (gd2_compressed(fmt)) {
     309               0 :                                 chunkLen = chunkMax;
     310                 : 
     311               0 :                                 if (!_gd2ReadChunk(chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, (char *) chunkBuf, &chunkLen, in)) {
     312                 :                                         GD2_DBG(php_gd_error("Error reading comproessed chunk"));
     313               0 :                                         goto fail2;
     314                 :                                 }
     315                 : 
     316               0 :                                 chunkPos = 0;
     317                 :                         }
     318                 : 
     319             897 :                         for (y = ylo; (y < yhi); y++) {
     320             883 :                                 xlo = cx * cs;
     321             883 :                                 xhi = xlo + cs;
     322             883 :                                 if (xhi > im->sx) {
     323             371 :                                         xhi = im->sx;
     324                 :                                 }
     325                 : 
     326            1766 :                                 if (!gd2_compressed(fmt)) {
     327           72444 :                                         for (x = xlo; x < xhi; x++) {
     328           71561 :                                                 if (im->trueColor) {
     329           71561 :                                                         if (!gdGetInt(&im->tpixels[y][x], in)) {
     330               0 :                                                                 im->tpixels[y][x] = 0;
     331                 :                                                         }
     332                 :                                                 } else {
     333                 :                                                         int ch;
     334               0 :                                                         if (!gdGetByte(&ch, in)) {
     335               0 :                                                                 ch = 0;
     336                 :                                                         }
     337               0 :                                                         im->pixels[y][x] = ch;
     338                 :                                                 }
     339                 :                                         }
     340                 :                                 } else {
     341               0 :                                         for (x = xlo; x < xhi; x++) {
     342               0 :                                                 if (im->trueColor) {
     343                 :                                                         /* 2.0.1: work around a gcc bug by being verbose. TBB */
     344               0 :                                                         int a = chunkBuf[chunkPos++] << 24;
     345               0 :                                                         int r = chunkBuf[chunkPos++] << 16;
     346               0 :                                                         int g = chunkBuf[chunkPos++] << 8;
     347               0 :                                                         int b = chunkBuf[chunkPos++];
     348               0 :                                                         im->tpixels[y][x] = a + r + g + b;
     349                 :                                                 } else {
     350               0 :                                                         im->pixels[y][x] = chunkBuf[chunkPos++];
     351                 :                                                 }
     352                 :                                         }
     353                 :                                 }
     354                 :                         }
     355              14 :                         chunkNum++;
     356                 :                 }
     357                 :         }
     358                 : 
     359                 :         GD2_DBG(php_gd_error("Freeing memory"));
     360                 : 
     361               6 :         if (chunkBuf) {
     362               0 :                 gdFree(chunkBuf);
     363                 :         }
     364               6 :         if (compBuf) {
     365               0 :                 gdFree(compBuf);
     366                 :         }
     367               6 :         if (chunkIdx) {
     368               0 :                 gdFree(chunkIdx);
     369                 :         }
     370                 : 
     371                 :         GD2_DBG(php_gd_error("Done"));
     372                 : 
     373               6 :         return im;
     374                 : 
     375               0 : fail2:
     376               0 :         gdImageDestroy(im);
     377               0 :         if (chunkBuf) {
     378               0 :                 gdFree(chunkBuf);
     379                 :         }
     380               0 :         if (compBuf) {
     381               0 :                 gdFree(compBuf);
     382                 :         }
     383               0 :         if (chunkIdx) {
     384               0 :                 gdFree(chunkIdx);
     385                 :         }
     386                 : 
     387               0 :         return 0;
     388                 : }
     389                 : 
     390                 : gdImagePtr gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w, int h)
     391               0 : {
     392                 :         gdImagePtr im;
     393               0 :         gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
     394               0 :         im = gdImageCreateFromGd2PartCtx(in, srcx, srcy, w, h);
     395               0 :         in->gd_free(in);
     396                 : 
     397               0 :         return im;
     398                 : }
     399                 : 
     400                 : gdImagePtr gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h)
     401               1 : {
     402                 :         gdImagePtr im;
     403               1 :         gdIOCtx *in = gdNewFileCtx(inFile);
     404                 : 
     405               1 :         im = gdImageCreateFromGd2PartCtx(in, srcx, srcy, w, h);
     406                 : 
     407               1 :         in->gd_free(in);
     408                 : 
     409               1 :         return im;
     410                 : }
     411                 : 
     412                 : gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
     413               1 : {
     414                 :         int scx, scy, ecx, ecy, fsx, fsy;
     415                 :         int nc, ncx, ncy, cs, cx, cy;
     416                 :         int x, y, ylo, yhi, xlo, xhi;
     417                 :         int dstart, dpos;
     418                 :         int i;
     419                 :         /* 2.0.12: unsigned is correct; fixes problems with color munging. Thanks to Steven Brown. */
     420                 :         unsigned int ch;
     421                 :         int vers, fmt;
     422               1 :         t_chunk_info *chunkIdx = NULL;
     423               1 :         unsigned char *chunkBuf = NULL;
     424                 :         int chunkNum;
     425               1 :         int chunkMax = 0;
     426                 :         uLongf chunkLen;
     427               1 :         int chunkPos = 0;
     428                 :         int compMax;
     429               1 :         char *compBuf = NULL;
     430                 : 
     431                 :         gdImagePtr im;
     432                 : 
     433               1 :         if (w<1 || h <1) {
     434               0 :                 return 0;
     435                 :         }
     436                 : 
     437                 :         /* The next few lines are basically copied from gd2CreateFromFile
     438                 :          * we change the file size, so don't want to use the code directly.
     439                 :          * but we do need to know the file size.
     440                 :          */
     441               1 :         if (_gd2GetHeader(in, &fsx, &fsy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx) != 1) {
     442               0 :                 goto fail1;
     443                 :         }
     444                 : 
     445                 :         GD2_DBG(php_gd_error("File size is %dx%d", fsx, fsy));
     446                 : 
     447                 :         /* This is the difference - make a file based on size of chunks. */
     448               2 :         if (gd2_truecolor(fmt)) {
     449               1 :                 im = gdImageCreateTrueColor(w, h);
     450                 :         } else {
     451               0 :                 im = gdImageCreate(w, h);
     452                 :         }
     453               1 :         if (im == NULL) {
     454               0 :                 goto fail1;
     455                 :         }
     456                 : 
     457               1 :         if (!_gdGetColors(in, im, vers == 2)) {
     458               0 :                 goto fail2;
     459                 :         }
     460                 :         GD2_DBG(php_gd_error("Image palette completed: %d colours", im->colorsTotal));
     461                 : 
     462                 :         /* Process the header info */
     463               1 :         nc = ncx * ncy;
     464                 : 
     465               1 :         if (gd2_compressed(fmt)) {
     466                 :                 /* Find the maximum compressed chunk size. */
     467               0 :                 compMax = 0;
     468               0 :                 for (i = 0; (i < nc); i++) {
     469               0 :                         if (chunkIdx[i].size > compMax) {
     470               0 :                                 compMax = chunkIdx[i].size;
     471                 :                         }
     472                 :                 }
     473               0 :                 compMax++;
     474                 : 
     475               0 :                 if (im->trueColor) {
     476               0 :                         chunkMax = cs * cs * 4;
     477                 :                 } else {
     478               0 :                         chunkMax = cs * cs;
     479                 :                 }
     480               0 :                 if (chunkMax <= 0) {
     481               0 :                         goto fail2;
     482                 :                 }
     483                 : 
     484               0 :                 chunkBuf = gdCalloc(chunkMax, 1);
     485               0 :                 compBuf = gdCalloc(compMax, 1);
     486                 :         }
     487                 : 
     488                 :         /* Work out start/end chunks */
     489               1 :         scx = srcx / cs;
     490               1 :         scy = srcy / cs;
     491               1 :         if (scx < 0) {
     492               0 :                 scx = 0;
     493                 :         }
     494               1 :         if (scy < 0) {
     495               0 :                 scy = 0;
     496                 :         }
     497                 : 
     498               1 :         ecx = (srcx + w) / cs;
     499               1 :         ecy = (srcy + h) / cs;
     500               1 :         if (ecx >= ncx) {
     501               0 :                 ecx = ncx - 1;
     502                 :         }
     503               1 :         if (ecy >= ncy) {
     504               0 :                 ecy = ncy - 1;
     505                 :         }
     506                 : 
     507                 :         /* Remember file position of image data. */
     508               1 :         dstart = gdTell(in);
     509                 :         GD2_DBG(php_gd_error("Data starts at %d", dstart));
     510                 : 
     511                 :         /* Loop through the chunks. */
     512               2 :         for (cy = scy; (cy <= ecy); cy++) {
     513               1 :                 ylo = cy * cs;
     514               1 :                 yhi = ylo + cs;
     515               1 :                 if (yhi > fsy) {
     516               1 :                         yhi = fsy;
     517                 :                 }
     518                 : 
     519               2 :                 for (cx = scx; cx <= ecx; cx++) {
     520                 : 
     521               1 :                         xlo = cx * cs;
     522               1 :                         xhi = xlo + cs;
     523               1 :                         if (xhi > fsx) {
     524               1 :                                 xhi = fsx;
     525                 :                         }
     526                 : 
     527                 :                         GD2_DBG(php_gd_error("Processing Chunk (%d, %d), from %d to %d", cx, cy, ylo, yhi));
     528                 : 
     529               2 :                         if (!gd2_compressed(fmt)) {
     530                 :                                 GD2_DBG(php_gd_error("Using raw format data"));
     531               1 :                                 if (im->trueColor) {
     532               1 :                                         dpos = (cy * (cs * fsx) * 4 + cx * cs * (yhi - ylo) * 4) + dstart;
     533                 :                                 } else {
     534               0 :                                         dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo) + dstart;
     535                 :                                 }
     536                 : 
     537                 :                                 /* gd 2.0.11: gdSeek returns TRUE on success, not 0. Longstanding bug. 01/16/03 */
     538               1 :                                 if (!gdSeek(in, dpos)) {
     539               0 :                                         php_gd_error_ex(E_WARNING, "Error from seek: %d", errno);
     540               0 :                                         goto fail2;
     541                 :                                 }
     542                 :                                 GD2_DBG(php_gd_error("Reading (%d, %d) from position %d", cx, cy, dpos - dstart));
     543                 :                         } else {
     544               0 :                                 chunkNum = cx + cy * ncx;
     545                 : 
     546               0 :                                 chunkLen = chunkMax;
     547               0 :                                 if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, (char *)chunkBuf, &chunkLen, in)) {
     548               0 :                                         php_gd_error("Error reading comproessed chunk");
     549               0 :                                         goto fail2;
     550                 :                                 }
     551               0 :                                 chunkPos = 0;
     552                 :                                 GD2_DBG(php_gd_error("Reading (%d, %d) from chunk %d", cx, cy, chunkNum));
     553                 :                         }
     554                 : 
     555                 :                         GD2_DBG(php_gd_error("   into (%d, %d) - (%d, %d)", xlo, ylo, xhi, yhi));
     556                 : 
     557              11 :                         for (y = ylo; (y < yhi); y++) {
     558             110 :                                 for (x = xlo; x < xhi; x++) {
     559             200 :                                         if (!gd2_compressed(fmt)) {
     560             100 :                                                 if (im->trueColor) {
     561             100 :                                                         if (!gdGetInt((int *)&ch, in)) {
     562               0 :                                                                 ch = 0;
     563                 :                                                         }
     564                 :                                                 } else {
     565               0 :                                                         ch = gdGetC(in);
     566               0 :                                                         if ((int)ch == EOF) {
     567               0 :                                                                 ch = 0;
     568                 :                                                         }
     569                 :                                                 }
     570                 :                                         } else {
     571               0 :                                                 if (im->trueColor) {
     572               0 :                                                         ch = chunkBuf[chunkPos++];
     573               0 :                                                         ch = (ch << 8) + chunkBuf[chunkPos++];
     574               0 :                                                         ch = (ch << 8) + chunkBuf[chunkPos++];
     575               0 :                                                         ch = (ch << 8) + chunkBuf[chunkPos++];
     576                 :                                                 } else {
     577               0 :                                                         ch = chunkBuf[chunkPos++];
     578                 :                                                 }
     579                 :                                         }
     580                 : 
     581                 :                                         /* Only use a point that is in the image. */
     582             100 :                                         if ((x >= srcx) && (x < (srcx + w)) && (x < fsx) && (x >= 0) && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0)) {
     583               4 :                                                 if (im->trueColor) {
     584               4 :                                                         im->tpixels[y - srcy][x - srcx] = ch;
     585                 :                                                 } else {
     586               0 :                                                         im->pixels[y - srcy][x - srcx] = ch;
     587                 :                                                 }
     588                 :                                         }
     589                 :                                 }
     590                 :                         }
     591                 :                 }
     592                 :         }
     593                 : 
     594               1 :         if (chunkBuf) {
     595               0 :                 gdFree(chunkBuf);
     596                 :         }
     597               1 :         if (compBuf) {
     598               0 :                 gdFree(compBuf);
     599                 :         }
     600               1 :         if (chunkIdx) {
     601               0 :                 gdFree(chunkIdx);
     602                 :         }
     603                 : 
     604               1 :         return im;
     605                 : 
     606               0 : fail2:
     607               0 :         gdImageDestroy(im);
     608               0 : fail1:
     609               0 :         if (chunkBuf) {
     610               0 :                 gdFree(chunkBuf);
     611                 :         }
     612               0 :         if (compBuf) {
     613               0 :                 gdFree(compBuf);
     614                 :         }
     615               0 :         if (chunkIdx) {
     616               0 :                 gdFree(chunkIdx);
     617                 :         }
     618                 : 
     619               0 :         return 0;
     620                 : }
     621                 : 
     622                 : static void _gd2PutHeader (gdImagePtr im, gdIOCtx * out, int cs, int fmt, int cx, int cy)
     623               7 : {
     624                 :         int i;
     625                 : 
     626                 :         /* Send the gd2 id, to verify file format. */
     627              35 :         for (i = 0; i < 4; i++) {
     628              28 :                 gdPutC((unsigned char) (GD2_ID[i]), out);
     629                 :         }
     630                 : 
     631                 :         /* We put the version info first, so future versions can easily change header info. */
     632                 : 
     633               7 :         gdPutWord(GD2_VERS, out);
     634               7 :         gdPutWord(im->sx, out);
     635               7 :         gdPutWord(im->sy, out);
     636               7 :         gdPutWord(cs, out);
     637               7 :         gdPutWord(fmt, out);
     638               7 :         gdPutWord(cx, out);
     639               7 :         gdPutWord(cy, out);
     640               7 : }
     641                 : 
     642                 : static void _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt)
     643               7 : {
     644                 :         int ncx, ncy, cx, cy;
     645                 :         int x, y, ylo, yhi, xlo, xhi;
     646                 :         int chunkLen;
     647               7 :         int chunkNum = 0;
     648               7 :         char *chunkData = NULL; /* So we can gdFree it with impunity. */
     649               7 :         char *compData = NULL;  /* So we can gdFree it with impunity. */
     650                 :         uLongf compLen;
     651               7 :         int idxPos = 0;
     652                 :         int idxSize;
     653               7 :         t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */
     654                 :         int posSave;
     655               7 :         int bytesPerPixel = im->trueColor ? 4 : 1;
     656               7 :         int compMax = 0;
     657                 : 
     658                 :         /* Force fmt to a valid value since we don't return anything. */
     659               7 :         if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) {
     660               0 :                 fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED : GD2_FMT_COMPRESSED;
     661                 :         }
     662               7 :         if (im->trueColor) {
     663               5 :                 fmt += 2;
     664                 :         }
     665                 :         /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems
     666                 :          * a little silly to expect performance improvements on a 64x64 bit scale, and
     667                 :          * 4096 because we buffer one chunk, and a 16MB buffer seems a little large - it may be
     668                 :          * OK for one user, but for another to read it, they require the buffer.
     669                 :          */
     670               7 :         if (cs == 0) {
     671               0 :                 cs = GD2_CHUNKSIZE;
     672               7 :         } else if (cs < GD2_CHUNKSIZE_MIN) {
     673               0 :                 cs = GD2_CHUNKSIZE_MIN;
     674               7 :         } else if (cs > GD2_CHUNKSIZE_MAX) {
     675               0 :                 cs = GD2_CHUNKSIZE_MAX;
     676                 :         }
     677                 : 
     678                 :         /* Work out number of chunks. */
     679               7 :         ncx = im->sx / cs + 1;
     680               7 :         ncy = im->sy / cs + 1;
     681                 : 
     682                 :         /* Write the standard header. */
     683               7 :         _gd2PutHeader (im, out, cs, fmt, ncx, ncy);
     684                 : 
     685               7 :         if (gd2_compressed(fmt)) {
     686                 :                 /* Work out size of buffer for compressed data, If CHUNKSIZE is large,
     687                 :                  * then these will be large!
     688                 :                  */
     689                 : 
     690                 :                 /* The zlib notes say output buffer size should be (input size) * 1.01 * 12
     691                 :                  * - we'll use 1.02 to be paranoid.
     692                 :                  */
     693               0 :                 compMax = (int)(cs * bytesPerPixel * cs * 1.02f) + 12;
     694                 : 
     695                 :                 /* Allocate the buffers.  */
     696               0 :                 chunkData = safe_emalloc(cs * bytesPerPixel, cs, 0);
     697               0 :                 memset(chunkData, 0, cs * bytesPerPixel * cs);
     698               0 :                 if (compMax <= 0) {
     699               0 :                         goto fail;
     700                 :                 }
     701               0 :                 compData = gdCalloc(compMax, 1);
     702                 : 
     703                 :                 /* Save the file position of chunk index, and allocate enough space for
     704                 :                  * each chunk_info block .
     705                 :                  */
     706               0 :                 idxPos = gdTell(out);
     707               0 :                 idxSize = ncx * ncy * sizeof(t_chunk_info);
     708                 :                 GD2_DBG(php_gd_error("Index size is %d", idxSize));
     709               0 :                 gdSeek(out, idxPos + idxSize);
     710                 : 
     711               0 :                 chunkIdx = safe_emalloc(idxSize, sizeof(t_chunk_info), 0);
     712               0 :                 memset(chunkIdx, 0, idxSize * sizeof(t_chunk_info));
     713                 :         }
     714                 : 
     715               7 :         _gdPutColors (im, out);
     716                 : 
     717                 :         GD2_DBG(php_gd_error("Size: %dx%d", im->sx, im->sy));
     718                 :         GD2_DBG(php_gd_error("Chunks: %dx%d", ncx, ncy));
     719                 : 
     720              16 :         for (cy = 0; (cy < ncy); cy++) {
     721              24 :                 for (cx = 0; (cx < ncx); cx++) {
     722              15 :                         ylo = cy * cs;
     723              15 :                         yhi = ylo + cs;
     724              15 :                         if (yhi > im->sy) {
     725               9 :                                 yhi = im->sy;
     726                 :                         }
     727                 : 
     728                 :                         GD2_DBG(php_gd_error("Processing Chunk (%dx%d), y from %d to %d", cx, cy, ylo, yhi));
     729              15 :                         chunkLen = 0;
     730            1103 :                         for (y = ylo; (y < yhi); y++) {
     731                 :                                 GD2_DBG(php_gd_error("y=%d: ",y));
     732            1088 :                                 xlo = cx * cs;
     733            1088 :                                 xhi = xlo + cs;
     734            1088 :                                 if (xhi > im->sx) {
     735             576 :                                         xhi = im->sx;
     736                 :                                 }
     737                 : 
     738            1088 :                                 if (gd2_compressed(fmt)) {
     739               0 :                                         for (x = xlo; x < xhi; x++) {
     740                 :                                                 GD2_DBG(php_gd_error("%d...",x));
     741               0 :                                                 if (im->trueColor) {
     742               0 :                                                         int p = im->tpixels[y][x];
     743               0 :                                                         chunkData[chunkLen++] = gdTrueColorGetAlpha(p);
     744               0 :                                                         chunkData[chunkLen++] = gdTrueColorGetRed(p);
     745               0 :                                                         chunkData[chunkLen++] = gdTrueColorGetGreen(p);
     746               0 :                                                         chunkData[chunkLen++] = gdTrueColorGetBlue(p);
     747                 :                                                 } else {
     748               0 :                                                         chunkData[chunkLen++] = im->pixels[y][x];
     749                 :                                                 }
     750                 :                                         }
     751                 :                                 } else {
     752           81574 :                                         for (x = xlo; x < xhi; x++) {
     753                 :                                                 GD2_DBG(php_gd_error("%d, ",x));
     754                 : 
     755           80486 :                                                 if (im->trueColor) {
     756           72361 :                                                         gdPutInt(im->tpixels[y][x], out);
     757                 :                                                 } else {
     758            8125 :                                                         gdPutC((unsigned char) im->pixels[y][x], out);
     759                 :                                                 }
     760                 :                                         }
     761                 :                                 }
     762                 :                                 GD2_DBG(php_gd_error("y=%d done.",y));
     763                 :                         }
     764                 : 
     765              15 :                         if (gd2_compressed(fmt)) {
     766               0 :                                 compLen = compMax;
     767               0 :                                 if (compress((unsigned char *) &compData[0], &compLen, (unsigned char *) &chunkData[0], chunkLen) != Z_OK) {
     768               0 :                                         php_gd_error("Error from compressing");
     769                 :                                 } else {
     770               0 :                                         chunkIdx[chunkNum].offset = gdTell(out);
     771               0 :                                         chunkIdx[chunkNum++].size = compLen;
     772                 :                                         GD2_DBG(php_gd_error("Chunk %d size %d offset %d", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset));
     773                 : 
     774               0 :                                         if (gdPutBuf (compData, compLen, out) <= 0) {
     775                 :                                                 /* Any alternate suggestions for handling this? */
     776               0 :                                                 php_gd_error_ex(E_WARNING, "Error %d on write", errno);
     777                 :                                         }
     778                 :                                 }
     779                 :                         }
     780                 :                 }
     781                 :         }
     782                 : 
     783               7 :         if (gd2_compressed(fmt)) {
     784                 :                 /* Save the position, write the index, restore position (paranoia). */
     785                 :                 GD2_DBG(php_gd_error("Seeking %d to write index", idxPos));
     786               0 :                 posSave = gdTell(out);
     787               0 :                 gdSeek(out, idxPos);
     788                 :                 GD2_DBG(php_gd_error("Writing index"));
     789               0 :                 for (x = 0; x < chunkNum; x++) {
     790                 :                         GD2_DBG(php_gd_error("Chunk %d size %d offset %d", x, chunkIdx[x].size, chunkIdx[x].offset));
     791               0 :                         gdPutInt(chunkIdx[x].offset, out);
     792               0 :                         gdPutInt(chunkIdx[x].size, out);
     793                 :                 }
     794               0 :                 gdSeek(out, posSave);
     795                 :         }
     796               7 : fail:
     797                 :         GD2_DBG(php_gd_error("Freeing memory"));
     798               7 :         if (chunkData) {
     799               0 :                 gdFree(chunkData);
     800                 :         }
     801               7 :         if (compData) {
     802               0 :                 gdFree(compData);
     803                 :         }
     804               7 :         if (chunkIdx) {
     805               0 :                 gdFree(chunkIdx);
     806                 :         }
     807                 :         GD2_DBG(php_gd_error("Done"));
     808               7 : }
     809                 : 
     810                 : void gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt)
     811               7 : {
     812               7 :         gdIOCtx *out = gdNewFileCtx(outFile);
     813                 : 
     814               7 :         _gdImageGd2(im, out, cs, fmt);
     815                 : 
     816               7 :         out->gd_free(out);
     817               7 : }
     818                 : 
     819                 : void *gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size)
     820               0 : {
     821                 :         void *rv;
     822               0 :         gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
     823                 : 
     824               0 :         _gdImageGd2(im, out, cs, fmt);
     825               0 :         rv = gdDPExtractData(out, size);
     826               0 :         out->gd_free(out);
     827                 : 
     828               0 :         return rv;
     829                 : }

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:07 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.