LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_packbits.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 120 154 77.9 %
Date: 2025-01-18 12:42:00 Functions: 8 8 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             : #ifndef PACKBITS_READ_ONLY
      35             : 
      36          15 : static int PackBitsPreEncode(TIFF *tif, uint16_t s)
      37             : {
      38             :     (void)s;
      39             : 
      40          15 :     tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(tmsize_t));
      41          15 :     if (tif->tif_data == NULL)
      42           0 :         return (0);
      43             :     /*
      44             :      * Calculate the scanline/tile-width size in bytes.
      45             :      */
      46          15 :     if (isTiled(tif))
      47           7 :         *(tmsize_t *)tif->tif_data = TIFFTileRowSize(tif);
      48             :     else
      49           8 :         *(tmsize_t *)tif->tif_data = TIFFScanlineSize(tif);
      50          15 :     return (1);
      51             : }
      52             : 
      53          15 : static int PackBitsPostEncode(TIFF *tif)
      54             : {
      55          15 :     if (tif->tif_data)
      56          15 :         _TIFFfreeExt(tif, tif->tif_data);
      57          15 :     return (1);
      58             : }
      59             : 
      60             : /*
      61             :  * Encode a run of pixels.
      62             :  */
      63        4708 : static int PackBitsEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
      64             : {
      65        4708 :     unsigned char *bp = (unsigned char *)buf;
      66             :     uint8_t *op;
      67             :     uint8_t *ep;
      68             :     uint8_t *lastliteral;
      69             :     long n, slop;
      70             :     int b;
      71             :     enum
      72             :     {
      73             :         BASE,
      74             :         LITERAL,
      75             :         RUN,
      76             :         LITERAL_RUN
      77             :     } state;
      78             : 
      79             :     (void)s;
      80        4708 :     op = tif->tif_rawcp;
      81        4708 :     ep = tif->tif_rawdata + tif->tif_rawdatasize;
      82        4708 :     state = BASE;
      83        4708 :     lastliteral = NULL;
      84        4708 :     while (cc > 0)
      85             :     {
      86             :         /*
      87             :          * Find the longest string of identical bytes.
      88             :          */
      89       74472 :         b = *bp++;
      90       74472 :         cc--;
      91       74472 :         n = 1;
      92      120752 :         for (; cc > 0 && b == *bp; cc--, bp++)
      93       46280 :             n++;
      94       74472 :     again:
      95       74590 :         if (op + 2 >= ep)
      96             :         { /* insure space for new data */
      97             :             /*
      98             :              * Be careful about writing the last
      99             :              * literal.  Must write up to that point
     100             :              * and then copy the remainder to the
     101             :              * front of the buffer.
     102             :              */
     103           0 :             if (state == LITERAL || state == LITERAL_RUN)
     104             :             {
     105           0 :                 slop = (long)(op - lastliteral);
     106           0 :                 tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
     107           0 :                 if (!TIFFFlushData1(tif))
     108           0 :                     return (0);
     109           0 :                 op = tif->tif_rawcp;
     110           0 :                 while (slop-- > 0)
     111           0 :                     *op++ = *lastliteral++;
     112           0 :                 lastliteral = tif->tif_rawcp;
     113             :             }
     114             :             else
     115             :             {
     116           0 :                 tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
     117           0 :                 if (!TIFFFlushData1(tif))
     118           0 :                     return (0);
     119           0 :                 op = tif->tif_rawcp;
     120             :             }
     121             :         }
     122       74590 :         switch (state)
     123             :         {
     124        5172 :             case BASE: /* initial state, set run/literal */
     125        5172 :                 if (n > 1)
     126             :                 {
     127        4280 :                     state = RUN;
     128        4280 :                     if (n > 128)
     129             :                     {
     130         118 :                         *op++ = (uint8_t)-127;
     131         118 :                         *op++ = (uint8_t)b;
     132         118 :                         n -= 128;
     133         118 :                         goto again;
     134             :                     }
     135        4162 :                     *op++ = (uint8_t)(-(n - 1));
     136        4162 :                     *op++ = (uint8_t)b;
     137             :                 }
     138             :                 else
     139             :                 {
     140         892 :                     lastliteral = op;
     141         892 :                     *op++ = 0;
     142         892 :                     *op++ = (uint8_t)b;
     143         892 :                     state = LITERAL;
     144             :                 }
     145        5054 :                 break;
     146       69298 :             case LITERAL: /* last object was literal string */
     147       69298 :                 if (n > 1)
     148             :                 {
     149           0 :                     state = LITERAL_RUN;
     150           0 :                     if (n > 128)
     151             :                     {
     152           0 :                         *op++ = (uint8_t)-127;
     153           0 :                         *op++ = (uint8_t)b;
     154           0 :                         n -= 128;
     155           0 :                         goto again;
     156             :                     }
     157           0 :                     *op++ = (uint8_t)(-(n - 1)); /* encode run */
     158           0 :                     *op++ = (uint8_t)b;
     159             :                 }
     160             :                 else
     161             :                 { /* extend literal */
     162       69298 :                     if (++(*lastliteral) == 127)
     163         464 :                         state = BASE;
     164       69298 :                     *op++ = (uint8_t)b;
     165             :                 }
     166       69298 :                 break;
     167         120 :             case RUN: /* last object was run */
     168         120 :                 if (n > 1)
     169             :                 {
     170         118 :                     if (n > 128)
     171             :                     {
     172           0 :                         *op++ = (uint8_t)-127;
     173           0 :                         *op++ = (uint8_t)b;
     174           0 :                         n -= 128;
     175           0 :                         goto again;
     176             :                     }
     177         118 :                     *op++ = (uint8_t)(-(n - 1));
     178         118 :                     *op++ = (uint8_t)b;
     179             :                 }
     180             :                 else
     181             :                 {
     182           2 :                     lastliteral = op;
     183           2 :                     *op++ = 0;
     184           2 :                     *op++ = (uint8_t)b;
     185           2 :                     state = LITERAL;
     186             :                 }
     187         120 :                 break;
     188           0 :             case LITERAL_RUN: /* literal followed by a run */
     189             :                 /*
     190             :                  * Check to see if previous run should
     191             :                  * be converted to a literal, in which
     192             :                  * case we convert literal-run-literal
     193             :                  * to a single literal.
     194             :                  */
     195           0 :                 if (n == 1 && op[-2] == (uint8_t)-1 && *lastliteral < 126)
     196             :                 {
     197           0 :                     state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL);
     198           0 :                     op[-2] = op[-1]; /* replicate */
     199             :                 }
     200             :                 else
     201           0 :                     state = RUN;
     202           0 :                 goto again;
     203             :         }
     204       79180 :     }
     205        4708 :     tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
     206        4708 :     tif->tif_rawcp = op;
     207        4708 :     return (1);
     208             : }
     209             : 
     210             : /*
     211             :  * Encode a rectangular chunk of pixels.  We break it up
     212             :  * into row-sized pieces to insure that encoded runs do
     213             :  * not span rows.  Otherwise, there can be problems with
     214             :  * the decoder if data is read, for example, by scanlines
     215             :  * when it was encoded by strips.
     216             :  */
     217          15 : static int PackBitsEncodeChunk(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
     218             : {
     219          15 :     tmsize_t rowsize = *(tmsize_t *)tif->tif_data;
     220             : 
     221        4723 :     while (cc > 0)
     222             :     {
     223        4708 :         tmsize_t chunk = rowsize;
     224             : 
     225        4708 :         if (cc < chunk)
     226           0 :             chunk = cc;
     227             : 
     228        4708 :         if (PackBitsEncode(tif, bp, chunk, s) < 0)
     229           0 :             return (-1);
     230        4708 :         bp += chunk;
     231        4708 :         cc -= chunk;
     232             :     }
     233          15 :     return (1);
     234             : }
     235             : 
     236             : #endif
     237             : 
     238         413 : static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
     239             : {
     240             :     static const char module[] = "PackBitsDecode";
     241             :     int8_t *bp;
     242             :     tmsize_t cc;
     243             :     long n;
     244             :     int b;
     245             : 
     246             :     (void)s;
     247         413 :     bp = (int8_t *)tif->tif_rawcp;
     248         413 :     cc = tif->tif_rawcc;
     249       29259 :     while (cc > 0 && occ > 0)
     250             :     {
     251       28850 :         n = (long)*bp++;
     252       28850 :         cc--;
     253       28850 :         if (n < 0)
     254             :         {                  /* replicate next byte -n+1 times */
     255       23842 :             if (n == -128) /* nop */
     256           6 :                 continue;
     257       23836 :             n = -n + 1;
     258       23836 :             if (occ < (tmsize_t)n)
     259             :             {
     260         122 :                 TIFFWarningExtR(tif, module,
     261             :                                 "Discarding %" TIFF_SSIZE_FORMAT
     262             :                                 " bytes to avoid buffer overrun",
     263             :                                 (tmsize_t)n - occ);
     264         122 :                 n = (long)occ;
     265             :             }
     266       23836 :             if (cc == 0)
     267             :             {
     268           1 :                 TIFFWarningExtR(
     269             :                     tif, module,
     270             :                     "Terminating PackBitsDecode due to lack of data.");
     271           1 :                 break;
     272             :             }
     273       23835 :             occ -= n;
     274       23835 :             b = *bp++;
     275       23835 :             cc--;
     276     1483095 :             while (n-- > 0)
     277     1459260 :                 *op++ = (uint8_t)b;
     278             :         }
     279             :         else
     280             :         { /* copy next n+1 bytes literally */
     281        5008 :             if (occ < (tmsize_t)(n + 1))
     282             :             {
     283          88 :                 TIFFWarningExtR(tif, module,
     284             :                                 "Discarding %" TIFF_SSIZE_FORMAT
     285             :                                 " bytes to avoid buffer overrun",
     286          88 :                                 (tmsize_t)n - occ + 1);
     287          88 :                 n = (long)occ - 1;
     288             :             }
     289        5008 :             if (cc < (tmsize_t)(n + 1))
     290             :             {
     291           3 :                 TIFFWarningExtR(
     292             :                     tif, module,
     293             :                     "Terminating PackBitsDecode due to lack of data.");
     294           3 :                 break;
     295             :             }
     296        5005 :             _TIFFmemcpy(op, bp, ++n);
     297        5005 :             op += n;
     298        5005 :             occ -= n;
     299        5005 :             bp += n;
     300        5005 :             cc -= n;
     301             :         }
     302             :     }
     303         413 :     tif->tif_rawcp = (uint8_t *)bp;
     304         413 :     tif->tif_rawcc = cc;
     305         413 :     if (occ > 0)
     306             :     {
     307           6 :         memset(op, 0, (size_t)occ);
     308           6 :         TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
     309             :                       tif->tif_row);
     310           6 :         return (0);
     311             :     }
     312         407 :     return (1);
     313             : }
     314             : 
     315         113 : int TIFFInitPackBits(TIFF *tif, int scheme)
     316             : {
     317             :     (void)scheme;
     318         113 :     tif->tif_decoderow = PackBitsDecode;
     319         113 :     tif->tif_decodestrip = PackBitsDecode;
     320         113 :     tif->tif_decodetile = PackBitsDecode;
     321             : #ifndef PACKBITS_READ_ONLY
     322         106 :     tif->tif_preencode = PackBitsPreEncode;
     323         106 :     tif->tif_postencode = PackBitsPostEncode;
     324         106 :     tif->tif_encoderow = PackBitsEncode;
     325         106 :     tif->tif_encodestrip = PackBitsEncodeChunk;
     326         106 :     tif->tif_encodetile = PackBitsEncodeChunk;
     327             : #endif
     328         113 :     return (1);
     329             : }
     330             : #endif /* PACKBITS_SUPPORT */

Generated by: LCOV version 1.14