LTP GCOV extension - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_packbits.c
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 136
Code covered: 59.6 % Executed lines: 81

       1                 : /* $Id: tif_packbits.c,v 1.20 2010-03-10 18:56:49 bfriesen Exp $ */
       2                 : 
       3                 : /*
       4                 :  * Copyright (c) 1988-1997 Sam Leffler
       5                 :  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
       6                 :  *
       7                 :  * Permission to use, copy, modify, distribute, and sell this software and 
       8                 :  * its documentation for any purpose is hereby granted without fee, provided
       9                 :  * that (i) the above copyright notices and this permission notice appear in
      10                 :  * all copies of the software and related documentation, and (ii) the names of
      11                 :  * Sam Leffler and Silicon Graphics may not be used in any advertising or
      12                 :  * publicity relating to the software without the specific, prior written
      13                 :  * permission of Sam Leffler and Silicon Graphics.
      14                 :  * 
      15                 :  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
      16                 :  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
      17                 :  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
      18                 :  * 
      19                 :  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
      20                 :  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
      21                 :  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
      22                 :  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
      23                 :  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
      24                 :  * OF THIS SOFTWARE.
      25                 :  */
      26                 : 
      27                 : #include "tiffiop.h"
      28                 : #ifdef PACKBITS_SUPPORT
      29                 : /*
      30                 :  * TIFF Library.
      31                 :  *
      32                 :  * PackBits Compression Algorithm Support
      33                 :  */
      34                 : #include <stdio.h>
      35                 : 
      36                 : static int
      37                 : PackBitsPreEncode(TIFF* tif, uint16 s)
      38              51 : {
      39                 :   (void) s;
      40                 : 
      41              51 :   if (!(tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t))))
      42               0 :     return (0);
      43                 :   /*
      44                 :    * Calculate the scanline/tile-width size in bytes.
      45                 :    */
      46              51 :   if (isTiled(tif))
      47              49 :     *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif);
      48                 :   else
      49               2 :     *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif);
      50              51 :   return (1);
      51                 : }
      52                 : 
      53                 : static int
      54                 : PackBitsPostEncode(TIFF* tif)
      55              51 : {
      56              51 :         if (tif->tif_data)
      57              51 :             _TIFFfree(tif->tif_data);
      58              51 :   return (1);
      59                 : }
      60                 : 
      61                 : /*
      62                 :  * Encode a run of pixels.
      63                 :  */
      64                 : static int
      65                 : PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
      66            5568 : {
      67            5568 :   unsigned char* bp = (unsigned char*) buf;
      68                 :   uint8* op;
      69                 :   uint8* ep;
      70                 :   uint8* lastliteral;
      71                 :   long n, slop;
      72                 :   int b;
      73                 :   enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
      74                 : 
      75                 :   (void) s;
      76            5568 :   op = tif->tif_rawcp;
      77            5568 :   ep = tif->tif_rawdata + tif->tif_rawdatasize;
      78            5568 :   state = BASE;
      79            5568 :   lastliteral = 0;
      80           18688 :   while (cc > 0) {
      81                 :     /*
      82                 :      * Find the longest string of identical bytes.
      83                 :      */
      84            7552 :     b = *bp++, cc--, n = 1;
      85           66176 :     for (; cc > 0 && b == *bp; cc--, bp++)
      86           58624 :       n++;
      87            7552 :   again:
      88            7552 :     if (op + 2 >= ep) {    /* insure space for new data */
      89                 :       /*
      90                 :        * Be careful about writing the last
      91                 :        * literal.  Must write up to that point
      92                 :        * and then copy the remainder to the
      93                 :        * front of the buffer.
      94                 :        */
      95               0 :       if (state == LITERAL || state == LITERAL_RUN) {
      96               0 :         slop = (long)(op - lastliteral);
      97               0 :         tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
      98               0 :         if (!TIFFFlushData1(tif))
      99               0 :           return (-1);
     100               0 :         op = tif->tif_rawcp;
     101               0 :         while (slop-- > 0)
     102               0 :           *op++ = *lastliteral++;
     103               0 :         lastliteral = tif->tif_rawcp;
     104                 :       } else {
     105               0 :         tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
     106               0 :         if (!TIFFFlushData1(tif))
     107               0 :           return (-1);
     108               0 :         op = tif->tif_rawcp;
     109                 :       }
     110                 :     }
     111            7552 :     switch (state) {
     112                 :     case BASE:    /* initial state, set run/literal */
     113            5568 :       if (n > 1) {
     114            5504 :         state = RUN;
     115            5504 :         if (n > 128) {
     116               0 :           *op++ = (uint8) -127;
     117               0 :           *op++ = (uint8) b;
     118               0 :           n -= 128;
     119               0 :           goto again;
     120                 :         }
     121            5504 :         *op++ = (uint8)(-(n-1));
     122            5504 :         *op++ = (uint8) b;
     123                 :       } else {
     124              64 :         lastliteral = op;
     125              64 :         *op++ = 0;
     126              64 :         *op++ = (uint8) b;
     127              64 :         state = LITERAL;
     128                 :       }
     129            5568 :       break;
     130                 :     case LITERAL:   /* last object was literal string */
     131            1984 :       if (n > 1) {
     132               0 :         state = LITERAL_RUN;
     133               0 :         if (n > 128) {
     134               0 :           *op++ = (uint8) -127;
     135               0 :           *op++ = (uint8) b;
     136               0 :           n -= 128;
     137               0 :           goto again;
     138                 :         }
     139               0 :         *op++ = (uint8)(-(n-1));  /* encode run */
     140               0 :         *op++ = (uint8) b;
     141                 :       } else {      /* extend literal */
     142            1984 :         if (++(*lastliteral) == 127)
     143               0 :           state = BASE;
     144            1984 :         *op++ = (uint8) b;
     145                 :       }
     146            1984 :       break;
     147                 :     case RUN:   /* last object was run */
     148               0 :       if (n > 1) {
     149               0 :         if (n > 128) {
     150               0 :           *op++ = (uint8) -127;
     151               0 :           *op++ = (uint8) b;
     152               0 :           n -= 128;
     153               0 :           goto again;
     154                 :         }
     155               0 :         *op++ = (uint8)(-(n-1));
     156               0 :         *op++ = (uint8) b;
     157                 :       } else {
     158               0 :         lastliteral = op;
     159               0 :         *op++ = 0;
     160               0 :         *op++ = (uint8) b;
     161               0 :         state = LITERAL;
     162                 :       }
     163               0 :       break;
     164                 :     case LITERAL_RUN: /* literal followed by a run */
     165                 :       /*
     166                 :        * Check to see if previous run should
     167                 :        * be converted to a literal, in which
     168                 :        * case we convert literal-run-literal
     169                 :        * to a single literal.
     170                 :        */
     171               0 :       if (n == 1 && op[-2] == (uint8) -1 &&
     172                 :           *lastliteral < 126) {
     173               0 :         state = (((*lastliteral) += 2) == 127 ?
     174                 :             BASE : LITERAL);
     175               0 :         op[-2] = op[-1];  /* replicate */
     176                 :       } else
     177               0 :         state = RUN;
     178               0 :       goto again;
     179                 :     }
     180                 :   }
     181            5568 :   tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
     182            5568 :   tif->tif_rawcp = op;
     183            5568 :   return (1);
     184                 : }
     185                 : 
     186                 : /*
     187                 :  * Encode a rectangular chunk of pixels.  We break it up
     188                 :  * into row-sized pieces to insure that encoded runs do
     189                 :  * not span rows.  Otherwise, there can be problems with
     190                 :  * the decoder if data is read, for example, by scanlines
     191                 :  * when it was encoded by strips.
     192                 :  */
     193                 : static int
     194                 : PackBitsEncodeChunk(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     195              51 : {
     196              51 :   tmsize_t rowsize = *(tmsize_t*)tif->tif_data;
     197                 : 
     198            5670 :   while (cc > 0) {
     199            5568 :     tmsize_t chunk = rowsize;
     200                 :     
     201            5568 :     if( cc < chunk )
     202               0 :         chunk = cc;
     203                 : 
     204            5568 :     if (PackBitsEncode(tif, bp, chunk, s) < 0)
     205               0 :         return (-1);
     206            5568 :     bp += chunk;
     207            5568 :     cc -= chunk;
     208                 :   }
     209              51 :   return (1);
     210                 : }
     211                 : 
     212                 : static int
     213                 : PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
     214               8 : {
     215                 :   static const char module[] = "PackBitsDecode";
     216                 :   char *bp;
     217                 :   tmsize_t cc;
     218                 :   long n;
     219                 :   int b;
     220                 : 
     221                 :   (void) s;
     222               8 :   bp = (char*) tif->tif_rawcp;
     223               8 :   cc = tif->tif_rawcc;
     224            8081 :   while (cc > 0 && occ > 0) {
     225            8065 :     n = (long) *bp++, cc--;
     226                 :     /*
     227                 :      * Watch out for compilers that
     228                 :      * don't sign extend chars...
     229                 :      */
     230            8065 :     if (n >= 128)
     231               0 :       n -= 256;
     232            8065 :     if (n < 0) {   /* replicate next byte -n+1 times */
     233            7959 :       if (n == -128)  /* nop */
     234               0 :         continue;
     235            7959 :       n = -n + 1;
     236            7959 :       if( occ < (tmsize_t)n )
     237                 :       {
     238               0 :         TIFFWarningExt(tif->tif_clientdata, module,
     239                 :             "Discarding %lu bytes to avoid buffer overrun",
     240                 :             (unsigned long) ((tmsize_t)n - occ));
     241               0 :         n = (long)occ;
     242                 :       }
     243            7959 :       occ -= n;
     244            7959 :       b = *bp++, cc--;      /* TODO: may be reading past input buffer here when input data is corrupt or ends prematurely */
     245           47865 :       while (n-- > 0)
     246           31947 :         *op++ = (uint8) b;
     247                 :     } else {    /* copy next n+1 bytes literally */
     248             106 :       if (occ < (tmsize_t)(n + 1))
     249                 :       {
     250               0 :         TIFFWarningExt(tif->tif_clientdata, module,
     251                 :             "Discarding %lu bytes to avoid buffer overrun",
     252                 :             (unsigned long) ((tmsize_t)n - occ + 1));
     253               0 :         n = (long)occ - 1;
     254                 :       }
     255             106 :       _TIFFmemcpy(op, bp, ++n);  /* TODO: may be reading past input buffer here when input data is corrupt or ends prematurely */
     256             106 :       op += n; occ -= n;
     257             106 :       bp += n; cc -= n;
     258                 :     }
     259                 :   }
     260               8 :   tif->tif_rawcp = (uint8*) bp;
     261               8 :   tif->tif_rawcc = cc;
     262               8 :   if (occ > 0) {
     263               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     264                 :         "Not enough data for scanline %lu",
     265                 :         (unsigned long) tif->tif_row);
     266               0 :     return (0);
     267                 :   }
     268               8 :   return (1);
     269                 : }
     270                 : 
     271                 : int
     272                 : TIFFInitPackBits(TIFF* tif, int scheme)
     273              12 : {
     274                 :   (void) scheme;
     275              12 :   tif->tif_decoderow = PackBitsDecode;
     276              12 :   tif->tif_decodestrip = PackBitsDecode;
     277              12 :   tif->tif_decodetile = PackBitsDecode;
     278              12 :   tif->tif_preencode = PackBitsPreEncode;
     279              12 :   tif->tif_postencode = PackBitsPostEncode;
     280              12 :   tif->tif_encoderow = PackBitsEncode;
     281              12 :   tif->tif_encodestrip = PackBitsEncodeChunk;
     282              12 :   tif->tif_encodetile = PackBitsEncodeChunk;
     283              12 :   return (1);
     284                 : }
     285                 : #endif /* PACKBITS_SUPPORT */
     286                 : 
     287                 : /* vim: set ts=8 sts=8 sw=8 noet: */
     288                 : /*
     289                 :  * Local Variables:
     290                 :  * mode: c
     291                 :  * c-basic-offset: 8
     292                 :  * fill-column: 78
     293                 :  * End:
     294                 :  */

Generated by: LTP GCOV extension version 1.5