Pillow

Форк
0
/
TgaRleEncode.c 
158 строк · 4.3 Кб
1

2
#include "Imaging.h"
3

4
#include <assert.h>
5
#include <string.h>
6

7
static int
8
comparePixels(const UINT8 *buf, int x, int bytesPerPixel) {
9
    buf += x * bytesPerPixel;
10
    return memcmp(buf, buf + bytesPerPixel, bytesPerPixel) == 0;
11
}
12

13
int
14
ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
15
    UINT8 *dst;
16
    int bytesPerPixel;
17

18
    if (state->state == 0) {
19
        if (state->ystep < 0) {
20
            state->ystep = -1;
21
            state->y = state->ysize - 1;
22
        } else {
23
            state->ystep = 1;
24
        }
25

26
        state->state = 1;
27
    }
28

29
    dst = buf;
30
    bytesPerPixel = (state->bits + 7) / 8;
31

32
    while (1) {
33
        int flushCount;
34

35
        /*
36
         * state->count is the numbers of bytes in the packet,
37
         * excluding the 1-byte descriptor.
38
         */
39
        if (state->count == 0) {
40
            UINT8 *row;
41
            UINT8 descriptor;
42
            int startX;
43

44
            assert(state->x <= state->xsize);
45

46
            /* Make sure we have space for the descriptor. */
47
            if (bytes < 1) {
48
                break;
49
            }
50

51
            if (state->x == state->xsize) {
52
                state->x = 0;
53

54
                state->y += state->ystep;
55
                if (state->y < 0 || state->y >= state->ysize) {
56
                    state->errcode = IMAGING_CODEC_END;
57
                    break;
58
                }
59
            }
60

61
            if (state->x == 0) {
62
                state->shuffle(
63
                    state->buffer,
64
                    (UINT8 *)im->image[state->y + state->yoff] +
65
                        state->xoff * im->pixelsize,
66
                    state->xsize
67
                );
68
            }
69

70
            row = state->buffer;
71

72
            /* Start with a raw packet for 1 px. */
73
            descriptor = 0;
74
            startX = state->x;
75
            state->count = bytesPerPixel;
76

77
            if (state->x + 1 < state->xsize) {
78
                int maxLookup;
79
                int isRaw;
80

81
                isRaw = !comparePixels(row, state->x, bytesPerPixel);
82
                ++state->x;
83

84
                /*
85
                 * A packet can contain up to 128 pixels;
86
                 * 2 are already behind (state->x points to
87
                 * the second one).
88
                 */
89
                maxLookup = state->x + 126;
90
                /* A packet must not span multiple rows. */
91
                if (maxLookup > state->xsize - 1) {
92
                    maxLookup = state->xsize - 1;
93
                }
94

95
                if (isRaw) {
96
                    while (state->x < maxLookup) {
97
                        if (!comparePixels(row, state->x, bytesPerPixel)) {
98
                            ++state->x;
99
                        } else {
100
                            /* Two identical pixels will go to RLE packet. */
101
                            --state->x;
102
                            break;
103
                        }
104
                    }
105

106
                    state->count += (state->x - startX) * bytesPerPixel;
107
                } else {
108
                    descriptor |= 0x80;
109

110
                    while (state->x < maxLookup) {
111
                        if (comparePixels(row, state->x, bytesPerPixel)) {
112
                            ++state->x;
113
                        } else {
114
                            break;
115
                        }
116
                    }
117
                }
118
            }
119

120
            /*
121
             * state->x currently points to the last pixel to be
122
             * included in the packet. The pixel count in the
123
             * descriptor is 1 less than actual number of pixels in
124
             * the packet, that is, state->x == startX if we encode
125
             * only 1 pixel.
126
             */
127
            descriptor += state->x - startX;
128
            *dst++ = descriptor;
129
            --bytes;
130

131
            /* Advance to past-the-last encoded pixel. */
132
            ++state->x;
133
        }
134

135
        assert(bytes >= 0);
136
        assert(state->count > 0);
137
        assert(state->x > 0);
138
        assert(state->count <= state->x * bytesPerPixel);
139

140
        if (bytes == 0) {
141
            break;
142
        }
143

144
        flushCount = state->count;
145
        if (flushCount > bytes) {
146
            flushCount = bytes;
147
        }
148

149
        memcpy(
150
            dst, state->buffer + (state->x * bytesPerPixel - state->count), flushCount
151
        );
152
        dst += flushCount;
153
        bytes -= flushCount;
154

155
        state->count -= flushCount;
156
    }
157

158
    return dst - buf;
159
}
160

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

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

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

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