LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_packbits.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 119 153 77.8 %
Date: 2024-05-04 12:52:34 Functions: 6 6 100.0 %

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

Generated by: LCOV version 1.14