Pillow
140 строк · 3.6 Кб
1/*
2* THIS IS WORK IN PROGRESS
3*
4* The Python Imaging Library.
5* $Id$
6*
7* decoder for SUN RLE data.
8*
9* history:
10* 97-01-04 fl Created
11*
12* Copyright (c) Fredrik Lundh 1997.
13* Copyright (c) Secret Labs AB 1997.
14*
15* See the README file for information on usage and redistribution.
16*/
17
18#include "Imaging.h"
19
20int
21ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
22int n;
23UINT8 *ptr;
24UINT8 extra_data = 0;
25UINT8 extra_bytes = 0;
26
27ptr = buf;
28
29for (;;) {
30if (bytes < 1) {
31return ptr - buf;
32}
33
34if (ptr[0] == 0x80) {
35if (bytes < 2) {
36break;
37}
38
39n = ptr[1];
40
41if (n == 0) {
42/* Literal 0x80 (2 bytes) */
43n = 1;
44
45state->buffer[state->x] = 0x80;
46
47ptr += 2;
48bytes -= 2;
49
50} else {
51/* Run (3 bytes) */
52if (bytes < 3) {
53break;
54}
55
56/* from (https://www.fileformat.info/format/sunraster/egff.htm)
57
58For example, a run of 100 pixels with the value of
590Ah would encode as the values 80h 64h 0Ah. A
60single pixel value of 80h would encode as the
61values 80h 00h. The four unencoded bytes 12345678h
62would be stored in the RLE stream as 12h 34h 56h
6378h. 100 pixels, n=100, not 100 pixels, n=99.
64
65But Wait! There's More!
66(https://www.fileformat.info/format/sunraster/spec/598a59c4fac64c52897585d390d86360/view.htm)
67
68If the first byte is 0x80, and the second byte is
69not zero, the record is three bytes long. The
70second byte is a count and the third byte is a
71value. Output (count+1) pixels of that value.
72
732 specs, same site, but Imagemagick and GIMP seem
74to agree on the second one.
75*/
76n += 1;
77
78if (state->x + n > state->bytes) {
79extra_bytes = n; /* full value */
80n = state->bytes - state->x;
81extra_bytes -= n;
82extra_data = ptr[2];
83}
84
85memset(state->buffer + state->x, ptr[2], n);
86
87ptr += 3;
88bytes -= 3;
89}
90
91} else {
92/* Literal byte */
93n = 1;
94
95state->buffer[state->x] = ptr[0];
96
97ptr += 1;
98bytes -= 1;
99}
100
101for (;;) {
102state->x += n;
103
104if (state->x >= state->bytes) {
105/* Got a full line, unpack it */
106state->shuffle(
107(UINT8 *)im->image[state->y + state->yoff] +
108state->xoff * im->pixelsize,
109state->buffer,
110state->xsize
111);
112
113state->x = 0;
114
115if (++state->y >= state->ysize) {
116/* End of file (errcode = 0) */
117return -1;
118}
119}
120
121if (extra_bytes == 0) {
122break;
123}
124
125if (state->x > 0) {
126break; // assert
127}
128
129if (extra_bytes >= state->bytes) {
130n = state->bytes;
131} else {
132n = extra_bytes;
133}
134memset(state->buffer + state->x, extra_data, n);
135extra_bytes -= n;
136}
137}
138
139return ptr - buf;
140}
141