Bug Summary

File:Bitmap.c
Warning:line 544, column 39
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple amd64-unknown-openbsd6.8 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Bitmap.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mthread-model posix -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/local/lib/clang/10.0.1 -I /usr/X11R6/include -I /usr/local/include -fdebug-compilation-dir /home/ben/Projects/ClassiCube/src -ferror-limit 19 -fmessage-length 0 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -fobjc-runtime=gnustep -fdiagnostics-show-option -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/ClassiCube/src/scan/2020-12-10-180422-33404-1 -x c Bitmap.c
1#include "Bitmap.h"
2#include "Platform.h"
3#include "PackedCol.h"
4#include "ExtMath.h"
5#include "Deflate.h"
6#include "Logger.h"
7#include "Stream.h"
8#include "Errors.h"
9#include "Utils.h"
10
11void Bitmap_UNSAFE_CopyBlock(int srcX, int srcY, int dstX, int dstY,
12 struct Bitmap* src, struct Bitmap* dst, int size) {
13 int x, y;
14 for (y = 0; y < size; y++) {
15 BitmapCol* srcRow = Bitmap_GetRow(src, srcY + y)((src)->scan0 + (srcY + y) * (src)->width) + srcX;
16 BitmapCol* dstRow = Bitmap_GetRow(dst, dstY + y)((dst)->scan0 + (dstY + y) * (dst)->width) + dstX;
17 for (x = 0; x < size; x++) { dstRow[x] = srcRow[x]; }
18 }
19}
20
21void Bitmap_Allocate(struct Bitmap* bmp, int width, int height) {
22 bmp->width = width; bmp->height = height;
23 bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, 4, "bitmap data");
24}
25
26void Bitmap_TryAllocate(struct Bitmap* bmp, int width, int height) {
27 bmp->width = width; bmp->height = height;
28 bmp->scan0 = (BitmapCol*)Mem_TryAlloc(width * height, 4);
29}
30
31void Bitmap_AllocateClearedPow2(struct Bitmap* bmp, int width, int height) {
32 width = Math_NextPowOf2(width);
33 height = Math_NextPowOf2(height);
34
35 bmp->width = width; bmp->height = height;
36 bmp->scan0 = (BitmapCol*)Mem_AllocCleared(width * height, 4, "bitmap data");
37}
38
39void Bitmap_TryAllocateClearedPow2(struct Bitmap* bmp, int width, int height) {
40 width = Math_NextPowOf2(width);
41 height = Math_NextPowOf2(height);
42
43 bmp->width = width; bmp->height = height;
44 bmp->scan0 = (BitmapCol*)Mem_TryAllocCleared(width * height, 4);
45}
46
47void Bitmap_Scale(struct Bitmap* dst, struct Bitmap* src,
48 int srcX, int srcY, int srcWidth, int srcHeight) {
49 BitmapCol* dstRow;
50 BitmapCol* srcRow;
51 int x, y, width, height;
52
53 width = dst->width;
54 height = dst->height;
55
56 for (y = 0; y < height; y++) {
57 srcRow = Bitmap_GetRow(src, srcY + (y * srcHeight / height))((src)->scan0 + (srcY + (y * srcHeight / height)) * (src)->
width)
;
58 dstRow = Bitmap_GetRow(dst, y)((dst)->scan0 + (y) * (dst)->width);
59
60 for (x = 0; x < width; x++) {
61 dstRow[x] = srcRow[srcX + (x * srcWidth / width)];
62 }
63 }
64}
65
66
67/*########################################################################################################################*
68*------------------------------------------------------PNG decoder--------------------------------------------------------*
69*#########################################################################################################################*/
70#define PNG_SIG_SIZE8 8
71#define PNG_IHDR_SIZE13 13
72#define PNG_PALETTE256 256
73#define PNG_FourCC(a, b, c, d)(((cc_uint32)a << 24) | ((cc_uint32)b << 16) | ((
cc_uint32)c << 8) | (cc_uint32)d)
(((cc_uint32)a << 24) | ((cc_uint32)b << 16) | ((cc_uint32)c << 8) | (cc_uint32)d)
74
75enum PngCol {
76 PNG_COL_GRAYSCALE = 0, PNG_COL_RGB = 2, PNG_COL_INDEXED = 3,
77 PNG_COL_GRAYSCALE_A = 4, PNG_COL_RGB_A = 6
78};
79
80enum PngFilter {
81 PNG_FILTER_NONE, PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVERAGE, PNG_FILTER_PAETH
82};
83
84typedef void (*Png_RowExpander)(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst);
85static const cc_uint8 pngSig[PNG_SIG_SIZE8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
86
87cc_bool Png_Detect(const cc_uint8* data, cc_uint32 len) {
88 int i;
89 if (len < PNG_SIG_SIZE8) return false0;
90
91 for (i = 0; i < PNG_SIG_SIZE8; i++) {
92 if (data[i] != pngSig[i]) return false0;
93 }
94 return true1;
95}
96
97static void Png_Reconstruct(cc_uint8 type, cc_uint8 bytesPerPixel, cc_uint8* line, cc_uint8* prior, cc_uint32 lineLen) {
98 cc_uint32 i, j;
99 switch (type) {
100 case PNG_FILTER_NONE:
101 return;
102
103 case PNG_FILTER_SUB:
104 for (i = bytesPerPixel, j = 0; i < lineLen; i++, j++) {
105 line[i] += line[j];
106 }
107 return;
108
109 case PNG_FILTER_UP:
110 for (i = 0; i < lineLen; i++) {
111 line[i] += prior[i];
112 }
113 return;
114
115 case PNG_FILTER_AVERAGE:
116 for (i = 0; i < bytesPerPixel; i++) {
117 line[i] += (prior[i] >> 1);
118 }
119 for (j = 0; i < lineLen; i++, j++) {
120 line[i] += ((prior[i] + line[j]) >> 1);
121 }
122 return;
123
124 case PNG_FILTER_PAETH:
125 /* TODO: verify this is right */
126 for (i = 0; i < bytesPerPixel; i++) {
127 line[i] += prior[i];
128 }
129 for (j = 0; i < lineLen; i++, j++) {
130 cc_uint8 a = line[j], b = prior[i], c = prior[j];
131 int p = a + b - c;
132 int pa = Math_AbsI(p - a);
133 int pb = Math_AbsI(p - b);
134 int pc = Math_AbsI(p - c);
135
136 if (pa <= pb && pa <= pc) { line[i] += a; }
137 else if (pb <= pc) { line[i] += b; }
138 else { line[i] += c; }
139 }
140 return;
141 }
142}
143
144#define Bitmap_Set(dst, r,g,b,a)dst = (((cc_uint8)(r) << 16) | ((cc_uint8)(g) << 8
) | ((cc_uint8)(b) << 0) | ((cc_uint8)(a) << 24))
;
dst = BitmapCol_Make(r, g, b, a)(((cc_uint8)(r) << 16) | ((cc_uint8)(g) << 8) | (
(cc_uint8)(b) << 0) | ((cc_uint8)(a) << 24))
;
145
146#define PNG_Do_Grayscale(dstI, src, scale)rgb = (src) * scale; dst[dstI] = (((cc_uint8)(rgb) << 16
) | ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0
) | ((cc_uint8)(255) << 24));;
rgb = (src) * scale; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255)dst[dstI] = (((cc_uint8)(rgb) << 16) | ((cc_uint8)(rgb)
<< 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8)(255
) << 24));
;
147#define PNG_Do_Grayscale_8(dstI, srcI)rgb = src[srcI]; dst[dstI] = (((cc_uint8)(rgb) << 16) |
((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0) |
((cc_uint8)(255) << 24));;
rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255)dst[dstI] = (((cc_uint8)(rgb) << 16) | ((cc_uint8)(rgb)
<< 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8)(255
) << 24));
;
148#define PNG_Do_Grayscale_A__8(dstI, srcI)rgb = src[srcI]; dst[dstI] = (((cc_uint8)(rgb) << 16) |
((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0) |
((cc_uint8)(src[srcI + 1]) << 24));;
rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, src[srcI + 1])dst[dstI] = (((cc_uint8)(rgb) << 16) | ((cc_uint8)(rgb)
<< 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8)(src
[srcI + 1]) << 24));
;
149#define PNG_Do_RGB__8(dstI, srcI)dst[dstI] = (((cc_uint8)(src[srcI]) << 16) | ((cc_uint8
)(src[srcI + 1]) << 8) | ((cc_uint8)(src[srcI + 2]) <<
0) | ((cc_uint8)(255) << 24));;
Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], 255)dst[dstI] = (((cc_uint8)(src[srcI]) << 16) | ((cc_uint8
)(src[srcI + 1]) << 8) | ((cc_uint8)(src[srcI + 2]) <<
0) | ((cc_uint8)(255) << 24));
;
150#define PNG_Do_RGB_A__8(dstI, srcI)dst[dstI] = (((cc_uint8)(src[srcI]) << 16) | ((cc_uint8
)(src[srcI + 1]) << 8) | ((cc_uint8)(src[srcI + 2]) <<
0) | ((cc_uint8)(src[srcI + 3]) << 24));;
Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], src[srcI + 3])dst[dstI] = (((cc_uint8)(src[srcI]) << 16) | ((cc_uint8
)(src[srcI + 1]) << 8) | ((cc_uint8)(src[srcI + 2]) <<
0) | ((cc_uint8)(src[srcI + 3]) << 24));
;
151
152#define PNG_Mask_1(i)(7 - (i & 7)) (7 - (i & 7))
153#define PNG_Mask_2(i)((3 - (i & 3)) * 2) ((3 - (i & 3)) * 2)
154#define PNG_Mask_4(i)((1 - (i & 1)) * 4) ((1 - (i & 1)) * 4)
155#define PNG_Get__1(i)((src[i >> 3] >> (7 - (i & 7))) & 1) ((src[i >> 3] >> PNG_Mask_1(i)(7 - (i & 7))) & 1)
156#define PNG_Get__2(i)((src[i >> 2] >> ((3 - (i & 3)) * 2)) & 3
)
((src[i >> 2] >> PNG_Mask_2(i)((3 - (i & 3)) * 2)) & 3)
157
158static void Png_Expand_GRAYSCALE_1(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
159 int i; cc_uint8 rgb; /* NOTE: not optimised*/
160 for (i = 0; i < width; i++) { PNG_Do_Grayscale(i, PNG_Get__1(i), 255)rgb = (((src[i >> 3] >> (7 - (i & 7))) & 1
)) * 255; dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8
)(rgb) << 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8
)(255) << 24));;
; }
161}
162
163static void Png_Expand_GRAYSCALE_2(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
164 int i; cc_uint8 rgb; /* NOTE: not optimised */
165 for (i = 0; i < width; i++) { PNG_Do_Grayscale(i, PNG_Get__2(i), 85)rgb = (((src[i >> 2] >> ((3 - (i & 3)) * 2)) &
3)) * 85; dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8
)(rgb) << 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8
)(255) << 24));;
; }
166}
167
168static void Png_Expand_GRAYSCALE_4(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
169 int i, j; cc_uint8 rgb;
170
171 for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) {
172 PNG_Do_Grayscale(i, src[j] >> 4, 17)rgb = (src[j] >> 4) * 17; dst[i] = (((cc_uint8)(rgb) <<
16) | ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) <<
0) | ((cc_uint8)(255) << 24));;
; PNG_Do_Grayscale(i + 1, src[j] & 0x0F, 17)rgb = (src[j] & 0x0F) * 17; dst[i + 1] = (((cc_uint8)(rgb
) << 16) | ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb
) << 0) | ((cc_uint8)(255) << 24));;
;
173 }
174 for (; i < width; i++) {
175 PNG_Do_Grayscale(i, (src[j] >> PNG_Mask_4(i)) & 15, 17)rgb = ((src[j] >> ((1 - (i & 1)) * 4)) & 15) * 17
; dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8)(rgb) <<
8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8)(255) <<
24));;
;
176 }
177}
178
179static void Png_Expand_GRAYSCALE_8(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
180 int i; cc_uint8 rgb;
181
182 for (i = 0; i < (width & ~0x3); i += 4) {
183 PNG_Do_Grayscale_8(i , i )rgb = src[i]; dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8
)(rgb) << 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8
)(255) << 24));;
; PNG_Do_Grayscale_8(i + 1, i + 1)rgb = src[i + 1]; dst[i + 1] = (((cc_uint8)(rgb) << 16)
| ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0
) | ((cc_uint8)(255) << 24));;
;
184 PNG_Do_Grayscale_8(i + 2, i + 2)rgb = src[i + 2]; dst[i + 2] = (((cc_uint8)(rgb) << 16)
| ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0
) | ((cc_uint8)(255) << 24));;
; PNG_Do_Grayscale_8(i + 3, i + 3)rgb = src[i + 3]; dst[i + 3] = (((cc_uint8)(rgb) << 16)
| ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0
) | ((cc_uint8)(255) << 24));;
;
185 }
186 for (; i < width; i++) { PNG_Do_Grayscale_8(i, i)rgb = src[i]; dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8
)(rgb) << 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8
)(255) << 24));;
; }
187}
188
189static void Png_Expand_GRAYSCALE_16(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
190 int i; cc_uint8 rgb; /* NOTE: not optimised */
191 for (i = 0; i < width; i++) {
192 rgb = src[i * 2]; Bitmap_Set(dst[i], rgb, rgb, rgb, 255)dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8)(rgb) <<
8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8)(255) <<
24));
;
193 }
194}
195
196static void Png_Expand_RGB_8(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
197 int i, j;
198
199 for (i = 0, j = 0; i < (width & ~0x03); i += 4, j += 12) {
200 PNG_Do_RGB__8(i , j )dst[i] = (((cc_uint8)(src[j]) << 16) | ((cc_uint8)(src[
j + 1]) << 8) | ((cc_uint8)(src[j + 2]) << 0) | (
(cc_uint8)(255) << 24));;
; PNG_Do_RGB__8(i + 1, j + 3)dst[i + 1] = (((cc_uint8)(src[j + 3]) << 16) | ((cc_uint8
)(src[j + 3 + 1]) << 8) | ((cc_uint8)(src[j + 3 + 2]) <<
0) | ((cc_uint8)(255) << 24));;
;
201 PNG_Do_RGB__8(i + 2, j + 6)dst[i + 2] = (((cc_uint8)(src[j + 6]) << 16) | ((cc_uint8
)(src[j + 6 + 1]) << 8) | ((cc_uint8)(src[j + 6 + 2]) <<
0) | ((cc_uint8)(255) << 24));;
; PNG_Do_RGB__8(i + 3, j + 9)dst[i + 3] = (((cc_uint8)(src[j + 9]) << 16) | ((cc_uint8
)(src[j + 9 + 1]) << 8) | ((cc_uint8)(src[j + 9 + 2]) <<
0) | ((cc_uint8)(255) << 24));;
;
202 }
203 for (; i < width; i++, j += 3) { PNG_Do_RGB__8(i, j)dst[i] = (((cc_uint8)(src[j]) << 16) | ((cc_uint8)(src[
j + 1]) << 8) | ((cc_uint8)(src[j + 2]) << 0) | (
(cc_uint8)(255) << 24));;
; }
204}
205
206static void Png_Expand_RGB_16(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
207 int i, j; /* NOTE: not optimised */
208 for (i = 0, j = 0; i < width; i++, j += 6) {
209 Bitmap_Set(dst[i], src[j], src[j + 2], src[j + 4], 255)dst[i] = (((cc_uint8)(src[j]) << 16) | ((cc_uint8)(src[
j + 2]) << 8) | ((cc_uint8)(src[j + 4]) << 0) | (
(cc_uint8)(255) << 24));
;
210 }
211}
212
213static void Png_Expand_INDEXED_1(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
214 int i; /* NOTE: not optimised */
215 for (i = 0; i < width; i++) { dst[i] = palette[PNG_Get__1(i)((src[i >> 3] >> (7 - (i & 7))) & 1)]; }
216}
217
218static void Png_Expand_INDEXED_2(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
219 int i; /* NOTE: not optimised */
220 for (i = 0; i < width; i++) { dst[i] = palette[PNG_Get__2(i)((src[i >> 2] >> ((3 - (i & 3)) * 2)) & 3
)
]; }
221}
222
223static void Png_Expand_INDEXED_4(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
224 int i, j; cc_uint8 cur;
225
226 for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) {
227 cur = src[j];
228 dst[i] = palette[cur >> 4]; dst[i + 1] = palette[cur & 0x0F];
229 }
230 for (; i < width; i++) {
231 dst[i] = palette[(src[j] >> PNG_Mask_4(i)((1 - (i & 1)) * 4)) & 15];
232 }
233}
234
235static void Png_Expand_INDEXED_8(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
236 int i;
237
238 for (i = 0; i < (width & ~0x3); i += 4) {
239 dst[i] = palette[src[i]]; dst[i + 1] = palette[src[i + 1]];
240 dst[i + 2] = palette[src[i + 2]]; dst[i + 3] = palette[src[i + 3]];
241 }
242 for (; i < width; i++) { dst[i] = palette[src[i]]; }
243}
244
245static void Png_Expand_GRAYSCALE_A_8(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
246 int i, j; cc_uint8 rgb;
247
248 for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 8) {
249 PNG_Do_Grayscale_A__8(i , j )rgb = src[j]; dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8
)(rgb) << 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8
)(src[j + 1]) << 24));;
; PNG_Do_Grayscale_A__8(i + 1, j + 2)rgb = src[j + 2]; dst[i + 1] = (((cc_uint8)(rgb) << 16)
| ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0
) | ((cc_uint8)(src[j + 2 + 1]) << 24));;
;
250 PNG_Do_Grayscale_A__8(i + 2, j + 4)rgb = src[j + 4]; dst[i + 2] = (((cc_uint8)(rgb) << 16)
| ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0
) | ((cc_uint8)(src[j + 4 + 1]) << 24));;
; PNG_Do_Grayscale_A__8(i + 3, j + 6)rgb = src[j + 6]; dst[i + 3] = (((cc_uint8)(rgb) << 16)
| ((cc_uint8)(rgb) << 8) | ((cc_uint8)(rgb) << 0
) | ((cc_uint8)(src[j + 6 + 1]) << 24));;
;
251 }
252 for (; i < width; i++, j += 2) { PNG_Do_Grayscale_A__8(i, j)rgb = src[j]; dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8
)(rgb) << 8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8
)(src[j + 1]) << 24));;
; }
253}
254
255static void Png_Expand_GRAYSCALE_A_16(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
256 int i; cc_uint8 rgb; /* NOTE: not optimised*/
257 for (i = 0; i < width; i++) {
258 rgb = src[i * 4]; Bitmap_Set(dst[i], rgb, rgb, rgb, src[i * 4 + 2])dst[i] = (((cc_uint8)(rgb) << 16) | ((cc_uint8)(rgb) <<
8) | ((cc_uint8)(rgb) << 0) | ((cc_uint8)(src[i * 4 + 2
]) << 24));
;
259 }
260}
261
262static void Png_Expand_RGB_A_8(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
263 int i, j;
264
265 for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 16) {
266 PNG_Do_RGB_A__8(i , j )dst[i] = (((cc_uint8)(src[j]) << 16) | ((cc_uint8)(src[
j + 1]) << 8) | ((cc_uint8)(src[j + 2]) << 0) | (
(cc_uint8)(src[j + 3]) << 24));;
; PNG_Do_RGB_A__8(i + 1, j + 4 )dst[i + 1] = (((cc_uint8)(src[j + 4]) << 16) | ((cc_uint8
)(src[j + 4 + 1]) << 8) | ((cc_uint8)(src[j + 4 + 2]) <<
0) | ((cc_uint8)(src[j + 4 + 3]) << 24));;
;
267 PNG_Do_RGB_A__8(i + 2, j + 8)dst[i + 2] = (((cc_uint8)(src[j + 8]) << 16) | ((cc_uint8
)(src[j + 8 + 1]) << 8) | ((cc_uint8)(src[j + 8 + 2]) <<
0) | ((cc_uint8)(src[j + 8 + 3]) << 24));;
; PNG_Do_RGB_A__8(i + 3, j + 12)dst[i + 3] = (((cc_uint8)(src[j + 12]) << 16) | ((cc_uint8
)(src[j + 12 + 1]) << 8) | ((cc_uint8)(src[j + 12 + 2])
<< 0) | ((cc_uint8)(src[j + 12 + 3]) << 24));;
;
268 }
269 for (; i < width; i++, j += 4) { PNG_Do_RGB_A__8(i, j)dst[i] = (((cc_uint8)(src[j]) << 16) | ((cc_uint8)(src[
j + 1]) << 8) | ((cc_uint8)(src[j + 2]) << 0) | (
(cc_uint8)(src[j + 3]) << 24));;
; }
270}
271
272static void Png_Expand_RGB_A_16(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst) {
273 int i, j; /* NOTE: not optimised*/
274 for (i = 0, j = 0; i < width; i++, j += 8) {
275 Bitmap_Set(dst[i], src[j], src[j + 2], src[j + 4], src[j + 6])dst[i] = (((cc_uint8)(src[j]) << 16) | ((cc_uint8)(src[
j + 2]) << 8) | ((cc_uint8)(src[j + 4]) << 0) | (
(cc_uint8)(src[j + 6]) << 24));
;
276 }
277}
278
279static Png_RowExpander Png_GetExpander(cc_uint8 col, cc_uint8 bitsPerSample) {
280 switch (col) {
281 case PNG_COL_GRAYSCALE:
282 switch (bitsPerSample) {
283 case 1: return Png_Expand_GRAYSCALE_1;
284 case 2: return Png_Expand_GRAYSCALE_2;
285 case 4: return Png_Expand_GRAYSCALE_4;
286 case 8: return Png_Expand_GRAYSCALE_8;
287 case 16: return Png_Expand_GRAYSCALE_16;
288 }
289 return NULL((void*)0);
290
291 case PNG_COL_RGB:
292 switch (bitsPerSample) {
293 case 8: return Png_Expand_RGB_8;
294 case 16: return Png_Expand_RGB_16;
295 }
296 return NULL((void*)0);
297
298 case PNG_COL_INDEXED:
299 switch (bitsPerSample) {
300 case 1: return Png_Expand_INDEXED_1;
301 case 2: return Png_Expand_INDEXED_2;
302 case 4: return Png_Expand_INDEXED_4;
303 case 8: return Png_Expand_INDEXED_8;
304 }
305 return NULL((void*)0);
306
307 case PNG_COL_GRAYSCALE_A:
308 switch (bitsPerSample) {
309 case 8: return Png_Expand_GRAYSCALE_A_8;
310 case 16: return Png_Expand_GRAYSCALE_A_16;
311 }
312 return NULL((void*)0);
313
314 case PNG_COL_RGB_A:
315 switch (bitsPerSample) {
316 case 8: return Png_Expand_RGB_A_8;
317 case 16: return Png_Expand_RGB_A_16;
318 }
319 return NULL((void*)0);
320 }
321 return NULL((void*)0);
322}
323
324/* Sets alpha to 0 for any pixels in the bitmap whose RGB is same as col */
325static void ComputeTransparency(struct Bitmap* bmp, BitmapCol col) {
326 BitmapCol trnsRGB = col & BITMAPCOL_RGB_MASK((0xFFU << 16) | (0xFFU << 8) | (0xFFU << 0
))
;
327 int x, y, width = bmp->width, height = bmp->height;
328
329 for (y = 0; y < height; y++) {
330 BitmapCol* row = Bitmap_GetRow(bmp, y)((bmp)->scan0 + (y) * (bmp)->width);
331 for (x = 0; x < width; x++) {
332 BitmapCol rgb = row[x] & BITMAPCOL_RGB_MASK((0xFFU << 16) | (0xFFU << 8) | (0xFFU << 0
))
;
333 row[x] = (rgb == trnsRGB) ? trnsRGB : row[x];
334 }
335 }
336}
337
338/* Most bits per sample is 16. Most samples per pixel is 4. Add 1 for filter byte. */
339/* Need to store both current and prior row, per PNG specification. */
340#define PNG_BUFFER_SIZE((0x8000 * 2 * 4 + 1) * 2) ((PNG_MAX_DIMS0x8000 * 2 * 4 + 1) * 2)
341
342/* TODO: Test a lot of .png files and ensure output is right */
343cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
344 cc_uint8 tmp[PNG_PALETTE256 * 3];
345 cc_uint32 dataSize, fourCC;
346 cc_result res;
347
348 /* header variables */
349 static cc_uint32 samplesPerPixel[7] = { 1, 0, 3, 1, 2, 0, 4 };
350 cc_uint8 col, bitsPerSample, bytesPerPixel;
351 Png_RowExpander rowExpander;
352 cc_uint32 scanlineSize, scanlineBytes;
353
354 /* palette data */
355 BitmapCol trnsCol;
356 BitmapCol palette[PNG_PALETTE256];
357 cc_uint32 i;
358
359 /* idat state */
360 cc_uint32 curY = 0, begY, rowY, endY;
361 cc_uint8 buffer[PNG_BUFFER_SIZE((0x8000 * 2 * 4 + 1) * 2)];
362 cc_uint32 bufferRows, bufferLen;
363 cc_uint32 bufferIdx, read, left;
364
365 /* idat decompressor */
366 struct InflateState inflate;
367 struct Stream compStream, datStream;
368 struct ZLibHeader zlibHeader;
369
370 bmp->width = 0; bmp->height = 0;
371 bmp->scan0 = NULL((void*)0);
372
373 res = Stream_Read(stream, tmp, PNG_SIG_SIZE8);
374 if (res) return res;
375 if (!Png_Detect(tmp, PNG_SIG_SIZE8)) return PNG_ERR_INVALID_SIG;
376
377 trnsCol = BITMAPCOL_BLACK(((cc_uint8)(0) << 16) | ((cc_uint8)(0) << 8) | (
(cc_uint8)(0) << 0) | ((cc_uint8)(255) << 24))
;
378 for (i = 0; i < PNG_PALETTE256; i++) { palette[i] = BITMAPCOL_BLACK(((cc_uint8)(0) << 16) | ((cc_uint8)(0) << 8) | (
(cc_uint8)(0) << 0) | ((cc_uint8)(255) << 24))
; }
379
380 Inflate_MakeStream2(&compStream, &inflate, stream);
381 ZLibHeader_Init(&zlibHeader);
382
383 for (;;) {
384 res = Stream_Read(stream, tmp, 8);
385 if (res) return res;
386 dataSize = Stream_GetU32_BE(tmp + 0);
387 fourCC = Stream_GetU32_BE(tmp + 4);
388
389 switch (fourCC) {
390 case PNG_FourCC('I','H','D','R')(((cc_uint32)'I' << 24) | ((cc_uint32)'H' << 16) |
((cc_uint32)'D' << 8) | (cc_uint32)'R')
: {
391 if (dataSize != PNG_IHDR_SIZE13) return PNG_ERR_INVALID_HDR_SIZE;
392 res = Stream_Read(stream, tmp, PNG_IHDR_SIZE13);
393 if (res) return res;
394
395 bmp->width = (int)Stream_GetU32_BE(tmp + 0);
396 bmp->height = (int)Stream_GetU32_BE(tmp + 4);
397 if (bmp->width < 0 || bmp->width > PNG_MAX_DIMS0x8000) return PNG_ERR_TOO_WIDE;
398 if (bmp->height < 0 || bmp->height > PNG_MAX_DIMS0x8000) return PNG_ERR_TOO_TALL;
399
400 bmp->scan0 = (BitmapCol*)Mem_TryAlloc(bmp->width * bmp->height, 4);
401 if (!bmp->scan0) return ERR_OUT_OF_MEMORY;
402
403 bitsPerSample = tmp[8]; col = tmp[9];
404 rowExpander = Png_GetExpander(col, bitsPerSample);
405 if (rowExpander == NULL((void*)0)) return PNG_ERR_INVALID_COL_BPP;
406
407 if (tmp[10] != 0) return PNG_ERR_COMP_METHOD;
408 if (tmp[11] != 0) return PNG_ERR_FILTER;
409 if (tmp[12] != 0) return PNG_ERR_INTERLACED;
410
411 bytesPerPixel = ((samplesPerPixel[col] * bitsPerSample) + 7) >> 3;
412 scanlineSize = ((samplesPerPixel[col] * bitsPerSample * bmp->width) + 7) >> 3;
413 scanlineBytes = scanlineSize + 1; /* Add 1 byte for filter byte of each scanline */
414
415 Mem_Set(buffer, 0, scanlineBytes); /* Prior row should be 0 per PNG spec */
416 bufferIdx = scanlineBytes;
417 bufferRows = PNG_BUFFER_SIZE((0x8000 * 2 * 4 + 1) * 2) / scanlineBytes;
418 bufferLen = bufferRows * scanlineBytes;
419 } break;
420
421 case PNG_FourCC('P','L','T','E')(((cc_uint32)'P' << 24) | ((cc_uint32)'L' << 16) |
((cc_uint32)'T' << 8) | (cc_uint32)'E')
: {
422 if (dataSize > PNG_PALETTE256 * 3) return PNG_ERR_PAL_SIZE;
423 if ((dataSize % 3) != 0) return PNG_ERR_PAL_SIZE;
424 res = Stream_Read(stream, tmp, dataSize);
425 if (res) return res;
426
427 for (i = 0; i < dataSize; i += 3) {
428 palette[i / 3] &= BITMAPCOL_A_MASK(0xFFU << 24); /* set RGB to 0 */
429 palette[i / 3] |= tmp[i ] << BITMAPCOL_R_SHIFT16;
430 palette[i / 3] |= tmp[i + 1] << BITMAPCOL_G_SHIFT8;
431 palette[i / 3] |= tmp[i + 2] << BITMAPCOL_B_SHIFT0;
432 }
433 } break;
434
435 case PNG_FourCC('t','R','N','S')(((cc_uint32)'t' << 24) | ((cc_uint32)'R' << 16) |
((cc_uint32)'N' << 8) | (cc_uint32)'S')
: {
436 if (col == PNG_COL_GRAYSCALE) {
437 if (dataSize != 2) return PNG_ERR_TRANS_COUNT;
438 res = Stream_Read(stream, tmp, dataSize);
439 if (res) return res;
440
441 /* RGB is 16 bits big endian, ignore least significant 8 bits */
442 trnsCol = BitmapCol_Make(tmp[0], tmp[0], tmp[0], 0)(((cc_uint8)(tmp[0]) << 16) | ((cc_uint8)(tmp[0]) <<
8) | ((cc_uint8)(tmp[0]) << 0) | ((cc_uint8)(0) <<
24))
;
443 } else if (col == PNG_COL_INDEXED) {
444 if (dataSize > PNG_PALETTE256) return PNG_ERR_TRANS_COUNT;
445 res = Stream_Read(stream, tmp, dataSize);
446 if (res) return res;
447
448 /* set alpha component of palette */
449 for (i = 0; i < dataSize; i++) {
450 palette[i] &= BITMAPCOL_RGB_MASK((0xFFU << 16) | (0xFFU << 8) | (0xFFU << 0
))
; /* set A to 0 */
451 palette[i] |= tmp[i] << PACKEDCOL_A_SHIFT24;
452 }
453 } else if (col == PNG_COL_RGB) {
454 if (dataSize != 6) return PNG_ERR_TRANS_COUNT;
455 res = Stream_Read(stream, tmp, dataSize);
456 if (res) return res;
457
458 /* R,G,B is 16 bits big endian, ignore least significant 8 bits */
459 trnsCol = BitmapCol_Make(tmp[0], tmp[2], tmp[4], 0)(((cc_uint8)(tmp[0]) << 16) | ((cc_uint8)(tmp[2]) <<
8) | ((cc_uint8)(tmp[4]) << 0) | ((cc_uint8)(0) <<
24))
;
460 } else {
461 return PNG_ERR_TRANS_INVALID;
462 }
463 } break;
464
465 case PNG_FourCC('I','D','A','T')(((cc_uint32)'I' << 24) | ((cc_uint32)'D' << 16) |
((cc_uint32)'A' << 8) | (cc_uint32)'T')
: {
466 Stream_ReadonlyPortion(&datStream, stream, dataSize);
467 inflate.Source = &datStream;
468
469 /* TODO: This assumes zlib header will be in 1 IDAT chunk */
470 while (!zlibHeader.done) {
471 if ((res = ZLibHeader_Read(&datStream, &zlibHeader))) return res;
472 }
473 if (!bmp->scan0) return PNG_ERR_NO_DATA;
474
475 while (curY < bmp->height) {
476 /* Need to leave one row in buffer untouched for storing prior scanline. Illustrated example of process:
477 * |=====| #-----| |-----| #-----| |-----|
478 * initial #-----| read 3 |-----| read 3 |-----| read 1 |-----| read 3 |-----| etc
479 * state |-----| -----> |-----| -----> |=====| -----> |-----| -----> |=====|
480 * |-----| |=====| #-----| |=====| #-----|
481 *
482 * (==== is prior scanline, # is current index in buffer)
483 * Having initial state this way allows doing two 'read 3' first time (assuming large idat chunks)
484 */
485
486 begY = bufferIdx / scanlineBytes;
487 left = bufferLen - bufferIdx;
488 /* if row is at 0, last row in buffer is prior row */
489 /* hence subtract a row, as don't want to overwrite it */
490 if (begY == 0) left -= scanlineBytes;
491
492 res = compStream.Read(&compStream, &buffer[bufferIdx], left, &read);
493 if (res) return res;
494 if (!read) break;
495
496 bufferIdx += read;
497 endY = bufferIdx / scanlineBytes;
498 /* reached end of buffer, cycle back to start */
499 if (bufferIdx == bufferLen) bufferIdx = 0;
500
501 /* NOTE: Need to check curY too, in case IDAT is corrupted and has extra data */
502 for (rowY = begY; rowY < endY && curY < bmp->height; rowY++, curY++) {
503 cc_uint32 priorY = rowY == 0 ? bufferRows : rowY;
504 cc_uint8* prior = &buffer[(priorY - 1) * scanlineBytes];
505 cc_uint8* scanline = &buffer[rowY * scanlineBytes];
506
507 if (scanline[0] > PNG_FILTER_PAETH) return PNG_ERR_INVALID_SCANLINE;
508 Png_Reconstruct(scanline[0], bytesPerPixel, &scanline[1], &prior[1], scanlineSize);
509 rowExpander(bmp->width, palette, &scanline[1], Bitmap_GetRow(bmp, curY)((bmp)->scan0 + (curY) * (bmp)->width));
510 }
511 }
512
513 if (curY == bmp->height) {
514 if (!BitmapCol_A(trnsCol)((cc_uint8)(trnsCol >> 24))) ComputeTransparency(bmp, trnsCol);
515 return 0;
516 }
517 } break;
518
519 case PNG_FourCC('I','E','N','D')(((cc_uint32)'I' << 24) | ((cc_uint32)'E' << 16) |
((cc_uint32)'N' << 8) | (cc_uint32)'D')
:
520 /* Reading all image data should be handled by above if in the IDAT chunk */
521 /* If we reached here, it means not all of the image data was read */
522 return PNG_ERR_REACHED_IEND;
523
524 default:
525 if ((res = stream->Skip(stream, dataSize))) return res;
526 break;
527 }
528
529 if ((res = stream->Skip(stream, 4))) return res; /* Skip CRC32 */
530 }
531}
532
533
534/*########################################################################################################################*
535*------------------------------------------------------PNG encoder--------------------------------------------------------*
536*#########################################################################################################################*/
537static void Png_Filter(cc_uint8 filter, const cc_uint8* cur, const cc_uint8* prior, cc_uint8* best, int lineLen, int bpp) {
538 /* 3 bytes per pixel constant */
539 cc_uint8 a, b, c;
540 int i, p, pa, pb, pc;
541
542 switch (filter) {
27
Control jumps to 'case PNG_FILTER_SUB:' at line 543
543 case PNG_FILTER_SUB:
544 for (i = 0; i < bpp; i++) { best[i] = cur[i]; }
28
The value 0 is assigned to 'i'
29
Loop condition is true. Entering loop body
30
Assigned value is garbage or undefined
545
546 for (; i < lineLen; i++) {
547 best[i] = cur[i] - cur[i - bpp];
548 }
549 break;
550
551 case PNG_FILTER_UP:
552 for (i = 0; i < lineLen; i++) {
553 best[i] = cur[i] - prior[i];
554 }
555 break;
556
557 case PNG_FILTER_AVERAGE:
558 for (i = 0; i < bpp; i++) { best[i] = cur[i] - (prior[i] >> 1); }
559
560 for (; i < lineLen; i++) {
561 best[i] = cur[i] - ((prior[i] + cur[i - bpp]) >> 1);
562 }
563 break;
564
565 case PNG_FILTER_PAETH:
566 for (i = 0; i < bpp; i++) { best[i] = cur[i] - prior[i]; }
567
568 for (; i < lineLen; i++) {
569 a = cur[i - bpp]; b = prior[i]; c = prior[i - bpp];
570 p = a + b - c;
571
572 pa = Math_AbsI(p - a);
573 pb = Math_AbsI(p - b);
574 pc = Math_AbsI(p - c);
575
576 if (pa <= pb && pa <= pc) { best[i] = cur[i] - a; }
577 else if (pb <= pc) { best[i] = cur[i] - b; }
578 else { best[i] = cur[i] - c; }
579 }
580 break;
581 }
582}
583
584static void Png_MakeRow(const BitmapCol* src, cc_uint8* dst, int lineLen, cc_bool alpha) {
585 cc_uint8* end = dst + lineLen;
586 BitmapCol col; /* if we use *src, register gets reloaded each time */
587
588 if (alpha
18.1
'alpha' is 0
) {
19
Taking false branch
589 for (; dst < end; src++, dst += 4) {
590 col = *src;
591 dst[0] = BitmapCol_R(col)((cc_uint8)(col >> 16)); dst[1] = BitmapCol_G(col)((cc_uint8)(col >> 8));
592 dst[2] = BitmapCol_B(col)((cc_uint8)(col >> 0)); dst[3] = BitmapCol_A(col)((cc_uint8)(col >> 24));
593 }
594 } else {
595 for (; dst < end; src++, dst += 3) {
20
Assuming 'dst' is >= 'end'
21
Loop condition is false. Execution continues on line 595
596 col = *src;
597 dst[0] = BitmapCol_R(col)((cc_uint8)(col >> 16)); dst[1] = BitmapCol_G(col)((cc_uint8)(col >> 8));
598 dst[2] = BitmapCol_B(col)((cc_uint8)(col >> 0));
599 }
600 }
601}
602
603static void Png_EncodeRow(const cc_uint8* cur, const cc_uint8* prior, cc_uint8* best, int lineLen, cc_bool alpha) {
604 cc_uint8* dst;
605 int bestFilter, bestEstimate = Int32_MaxValue((cc_int32)2147483647L);
606 int x, filter, estimate;
607
608 dst = best + 1;
609 /* NOTE: Waste of time trying the PNG_NONE filter */
610 for (filter = PNG_FILTER_SUB; filter <= PNG_FILTER_PAETH; filter++) {
24
Loop condition is true. Entering loop body
611 Png_Filter(filter, cur, prior, dst, lineLen, alpha
24.1
'alpha' is 0
? 4 : 3)
;
25
'?' condition is false
26
Calling 'Png_Filter'
612
613 /* Estimate how well this filtered line will compress, based on */
614 /* smallest sum of magnitude of each byte (signed) in the line */
615 /* (see note in PNG specification, 12.8 "Filter selection" ) */
616 estimate = 0;
617 for (x = 0; x < lineLen; x++) {
618 estimate += Math_AbsI((cc_int8)dst[x]);
619 }
620
621 if (estimate > bestEstimate) continue;
622 bestEstimate = estimate;
623 bestFilter = filter;
624 }
625
626 /* The bytes in dst are from last filter run (paeth) */
627 /* However, we want dst to be bytes from the best filter */
628 if (bestFilter != PNG_FILTER_PAETH) {
629 Png_Filter(bestFilter, cur, prior, dst, lineLen, alpha ? 4 : 3);
630 }
631
632 best[0] = bestFilter;
633}
634
635static int Png_SelectRow(struct Bitmap* bmp, int y) { return y; }
636cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream,
637 Png_RowSelector selectRow, cc_bool alpha) {
638 cc_uint8 tmp[32];
639 /* TODO: This should be * 4 for alpha (should switch to mem_alloc though) */
640 cc_uint8 prevLine[PNG_MAX_DIMS0x8000 * 3], curLine[PNG_MAX_DIMS0x8000 * 3];
641 cc_uint8 bestLine[PNG_MAX_DIMS0x8000 * 3 + 1];
642
643 struct ZLibState zlState;
644 struct Stream chunk, zlStream;
645 cc_uint32 stream_end, stream_beg;
646 int y, lineSize;
647 cc_result res;
648
649 /* stream may not start at 0 (e.g. when making default.zip) */
650 if ((res = stream->Position(stream, &stream_beg))) return res;
1
Assuming 'res' is 0
2
Taking false branch
651
652 if (!selectRow) selectRow = Png_SelectRow;
3
Assuming 'selectRow' is non-null
4
Taking false branch
653 if ((res = Stream_Write(stream, pngSig, PNG_SIG_SIZE8))) return res;
5
Assuming 'res' is 0
6
Taking false branch
654 Stream_WriteonlyCrc32(&chunk, stream);
655
656 /* Write header chunk */
657 Stream_SetU32_BE(&tmp[0], PNG_IHDR_SIZE13);
658 Stream_SetU32_BE(&tmp[4], PNG_FourCC('I','H','D','R')(((cc_uint32)'I' << 24) | ((cc_uint32)'H' << 16) |
((cc_uint32)'D' << 8) | (cc_uint32)'R')
);
659 {
660 Stream_SetU32_BE(&tmp[8], bmp->width);
661 Stream_SetU32_BE(&tmp[12], bmp->height);
662 tmp[16] = 8; /* bits per sample */
663 tmp[17] = alpha ? PNG_COL_RGB_A : PNG_COL_RGB;
7
Assuming 'alpha' is 0
8
'?' condition is false
664 tmp[18] = 0; /* DEFLATE compression method */
665 tmp[19] = 0; /* ADAPTIVE filter method */
666 tmp[20] = 0; /* Not using interlacing */
667 }
668 Stream_SetU32_BE(&tmp[21], Utils_CRC32(&tmp[4], 17));
669
670 /* Write PNG body */
671 Stream_SetU32_BE(&tmp[25], 0); /* size of IDAT, filled in later */
672 if ((res = Stream_Write(stream, tmp, 29))) return res;
9
Assuming 'res' is 0
10
Taking false branch
673 Stream_SetU32_BE(&tmp[0], PNG_FourCC('I','D','A','T')(((cc_uint32)'I' << 24) | ((cc_uint32)'D' << 16) |
((cc_uint32)'A' << 8) | (cc_uint32)'T')
);
674 if ((res = Stream_Write(&chunk, tmp, 4))) return res;
11
Assuming 'res' is 0
12
Taking false branch
675
676 ZLib_MakeStream(&zlStream, &zlState, &chunk);
677 lineSize = bmp->width * (alpha
12.1
'alpha' is 0
? 4 : 3);
13
'?' condition is false
678 Mem_Set(prevLine, 0, lineSize);
679
680 for (y = 0; y < bmp->height; y++) {
14
Assuming 'y' is < field 'height'
15
Loop condition is true. Entering loop body
681 int row = selectRow(bmp, y);
682 BitmapCol* src = Bitmap_GetRow(bmp, row)((bmp)->scan0 + (row) * (bmp)->width);
683 cc_uint8* prev = (y & 1) == 0 ? prevLine : curLine;
16
'?' condition is true
684 cc_uint8* cur = (y & 1) == 0 ? curLine : prevLine;
17
'?' condition is true
685
686 Png_MakeRow(src, cur, lineSize, alpha);
18
Calling 'Png_MakeRow'
22
Returning from 'Png_MakeRow'
687 Png_EncodeRow(cur, prev, bestLine, lineSize, alpha);
23
Calling 'Png_EncodeRow'
688
689 /* +1 for filter byte */
690 if ((res = Stream_Write(&zlStream, bestLine, lineSize + 1))) return res;
691 }
692 if ((res = zlStream.Close(&zlStream))) return res;
693 Stream_SetU32_BE(&tmp[0], chunk.Meta.CRC32.CRC32 ^ 0xFFFFFFFFUL);
694
695 /* Write end chunk */
696 Stream_SetU32_BE(&tmp[4], 0);
697 Stream_SetU32_BE(&tmp[8], PNG_FourCC('I','E','N','D')(((cc_uint32)'I' << 24) | ((cc_uint32)'E' << 16) |
((cc_uint32)'N' << 8) | (cc_uint32)'D')
);
698 Stream_SetU32_BE(&tmp[12], 0xAE426082UL); /* CRC32 of IEND */
699 if ((res = Stream_Write(stream, tmp, 16))) return res;
700
701 /* Come back to fixup size of data in data chunk */
702 if ((res = stream->Length(stream, &stream_end))) return res;
703 if ((res = stream->Seek(stream, stream_beg + 33))) return res;
704
705 Stream_SetU32_BE(&tmp[0], (stream_end - stream_beg) - 57);
706 if ((res = Stream_Write(stream, tmp, 4))) return res;
707 return stream->Seek(stream, stream_end);
708}