opencv

Форк
0
/
tif_packbits.c 
323 строки · 9.5 Кб
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
static int PackBitsPreEncode(TIFF *tif, uint16_t s)
35
{
36
    (void)s;
37

38
    tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(tmsize_t));
39
    if (tif->tif_data == NULL)
40
        return (0);
41
    /*
42
     * Calculate the scanline/tile-width size in bytes.
43
     */
44
    if (isTiled(tif))
45
        *(tmsize_t *)tif->tif_data = TIFFTileRowSize(tif);
46
    else
47
        *(tmsize_t *)tif->tif_data = TIFFScanlineSize(tif);
48
    return (1);
49
}
50

51
static int PackBitsPostEncode(TIFF *tif)
52
{
53
    if (tif->tif_data)
54
        _TIFFfreeExt(tif, tif->tif_data);
55
    return (1);
56
}
57

58
/*
59
 * Encode a run of pixels.
60
 */
61
static int PackBitsEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
62
{
63
    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
    op = tif->tif_rawcp;
79
    ep = tif->tif_rawdata + tif->tif_rawdatasize;
80
    state = BASE;
81
    lastliteral = 0;
82
    while (cc > 0)
83
    {
84
        /*
85
         * Find the longest string of identical bytes.
86
         */
87
        b = *bp++;
88
        cc--;
89
        n = 1;
90
        for (; cc > 0 && b == *bp; cc--, bp++)
91
            n++;
92
    again:
93
        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
            if (state == LITERAL || state == LITERAL_RUN)
102
            {
103
                slop = (long)(op - lastliteral);
104
                tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
105
                if (!TIFFFlushData1(tif))
106
                    return (0);
107
                op = tif->tif_rawcp;
108
                while (slop-- > 0)
109
                    *op++ = *lastliteral++;
110
                lastliteral = tif->tif_rawcp;
111
            }
112
            else
113
            {
114
                tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
115
                if (!TIFFFlushData1(tif))
116
                    return (0);
117
                op = tif->tif_rawcp;
118
            }
119
        }
120
        switch (state)
121
        {
122
            case BASE: /* initial state, set run/literal */
123
                if (n > 1)
124
                {
125
                    state = RUN;
126
                    if (n > 128)
127
                    {
128
                        *op++ = (uint8_t)-127;
129
                        *op++ = (uint8_t)b;
130
                        n -= 128;
131
                        goto again;
132
                    }
133
                    *op++ = (uint8_t)(-(n - 1));
134
                    *op++ = (uint8_t)b;
135
                }
136
                else
137
                {
138
                    lastliteral = op;
139
                    *op++ = 0;
140
                    *op++ = (uint8_t)b;
141
                    state = LITERAL;
142
                }
143
                break;
144
            case LITERAL: /* last object was literal string */
145
                if (n > 1)
146
                {
147
                    state = LITERAL_RUN;
148
                    if (n > 128)
149
                    {
150
                        *op++ = (uint8_t)-127;
151
                        *op++ = (uint8_t)b;
152
                        n -= 128;
153
                        goto again;
154
                    }
155
                    *op++ = (uint8_t)(-(n - 1)); /* encode run */
156
                    *op++ = (uint8_t)b;
157
                }
158
                else
159
                { /* extend literal */
160
                    if (++(*lastliteral) == 127)
161
                        state = BASE;
162
                    *op++ = (uint8_t)b;
163
                }
164
                break;
165
            case RUN: /* last object was run */
166
                if (n > 1)
167
                {
168
                    if (n > 128)
169
                    {
170
                        *op++ = (uint8_t)-127;
171
                        *op++ = (uint8_t)b;
172
                        n -= 128;
173
                        goto again;
174
                    }
175
                    *op++ = (uint8_t)(-(n - 1));
176
                    *op++ = (uint8_t)b;
177
                }
178
                else
179
                {
180
                    lastliteral = op;
181
                    *op++ = 0;
182
                    *op++ = (uint8_t)b;
183
                    state = LITERAL;
184
                }
185
                break;
186
            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
                if (n == 1 && op[-2] == (uint8_t)-1 && *lastliteral < 126)
194
                {
195
                    state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL);
196
                    op[-2] = op[-1]; /* replicate */
197
                }
198
                else
199
                    state = RUN;
200
                goto again;
201
        }
202
    }
203
    tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
204
    tif->tif_rawcp = op;
205
    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
static int PackBitsEncodeChunk(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
216
{
217
    tmsize_t rowsize = *(tmsize_t *)tif->tif_data;
218

219
    while (cc > 0)
220
    {
221
        tmsize_t chunk = rowsize;
222

223
        if (cc < chunk)
224
            chunk = cc;
225

226
        if (PackBitsEncode(tif, bp, chunk, s) < 0)
227
            return (-1);
228
        bp += chunk;
229
        cc -= chunk;
230
    }
231
    return (1);
232
}
233

234
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
    bp = (int8_t *)tif->tif_rawcp;
244
    cc = tif->tif_rawcc;
245
    while (cc > 0 && occ > 0)
246
    {
247
        n = (long)*bp++;
248
        cc--;
249
        if (n < 0)
250
        {                  /* replicate next byte -n+1 times */
251
            if (n == -128) /* nop */
252
                continue;
253
            n = -n + 1;
254
            if (occ < (tmsize_t)n)
255
            {
256
                TIFFWarningExtR(tif, module,
257
                                "Discarding %" TIFF_SSIZE_FORMAT
258
                                " bytes to avoid buffer overrun",
259
                                (tmsize_t)n - occ);
260
                n = (long)occ;
261
            }
262
            if (cc == 0)
263
            {
264
                TIFFWarningExtR(
265
                    tif, module,
266
                    "Terminating PackBitsDecode due to lack of data.");
267
                break;
268
            }
269
            occ -= n;
270
            b = *bp++;
271
            cc--;
272
            while (n-- > 0)
273
                *op++ = (uint8_t)b;
274
        }
275
        else
276
        { /* copy next n+1 bytes literally */
277
            if (occ < (tmsize_t)(n + 1))
278
            {
279
                TIFFWarningExtR(tif, module,
280
                                "Discarding %" TIFF_SSIZE_FORMAT
281
                                " bytes to avoid buffer overrun",
282
                                (tmsize_t)n - occ + 1);
283
                n = (long)occ - 1;
284
            }
285
            if (cc < (tmsize_t)(n + 1))
286
            {
287
                TIFFWarningExtR(
288
                    tif, module,
289
                    "Terminating PackBitsDecode due to lack of data.");
290
                break;
291
            }
292
            _TIFFmemcpy(op, bp, ++n);
293
            op += n;
294
            occ -= n;
295
            bp += n;
296
            cc -= n;
297
        }
298
    }
299
    tif->tif_rawcp = (uint8_t *)bp;
300
    tif->tif_rawcc = cc;
301
    if (occ > 0)
302
    {
303
        TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
304
                      tif->tif_row);
305
        return (0);
306
    }
307
    return (1);
308
}
309

310
int TIFFInitPackBits(TIFF *tif, int scheme)
311
{
312
    (void)scheme;
313
    tif->tif_decoderow = PackBitsDecode;
314
    tif->tif_decodestrip = PackBitsDecode;
315
    tif->tif_decodetile = PackBitsDecode;
316
    tif->tif_preencode = PackBitsPreEncode;
317
    tif->tif_postencode = PackBitsPostEncode;
318
    tif->tif_encoderow = PackBitsEncode;
319
    tif->tif_encodestrip = PackBitsEncodeChunk;
320
    tif->tif_encodetile = PackBitsEncodeChunk;
321
    return (1);
322
}
323
#endif /* PACKBITS_SUPPORT */
324

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.