Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: core/src/fxcodec/lbmp/fx_bmp.cpp

Issue 1800523005: Move core/src/ up to core/. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/src/fxcodec/lbmp/fx_bmp.h ('k') | core/src/fxcodec/lgif/fx_gif.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/src/fxcodec/lbmp/fx_bmp.h"
8
9 #include <algorithm>
10
11 namespace {
12
13 const size_t kBmpCoreHeaderSize = 12;
14 const size_t kBmpInfoHeaderSize = 40;
15
16 // TODO(thestig): Replace with FXDWORD_GET_LSBFIRST?
17 FX_DWORD GetDWord_LSBFirst(uint8_t* p) {
18 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
19 }
20
21 void SetDWord_LSBFirst(uint8_t* p, FX_DWORD v) {
22 p[0] = (uint8_t)v;
23 p[1] = (uint8_t)(v >> 8);
24 p[2] = (uint8_t)(v >> 16);
25 p[3] = (uint8_t)(v >> 24);
26 }
27 } // namespace
28
29 FX_WORD GetWord_LSBFirst(uint8_t* p) {
30 return p[0] | (p[1] << 8);
31 }
32 void SetWord_LSBFirst(uint8_t* p, FX_WORD v) {
33 p[0] = (uint8_t)v;
34 p[1] = (uint8_t)(v >> 8);
35 }
36 void bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg) {
37 if (bmp_ptr && bmp_ptr->bmp_error_fn) {
38 bmp_ptr->bmp_error_fn(bmp_ptr, err_msg);
39 }
40 }
41 bmp_decompress_struct_p bmp_create_decompress() {
42 bmp_decompress_struct_p bmp_ptr = FX_Alloc(bmp_decompress_struct, 1);
43 if (bmp_ptr == NULL) {
44 return NULL;
45 }
46 FXSYS_memset(bmp_ptr, 0, sizeof(bmp_decompress_struct));
47 bmp_ptr->decode_status = BMP_D_STATUS_HEADER;
48 bmp_ptr->bmp_header_ptr = FX_Alloc(BmpFileHeader, 1);
49 return bmp_ptr;
50 }
51 void bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr) {
52 if (bmp_ptr_ptr == NULL || *bmp_ptr_ptr == NULL) {
53 return;
54 }
55 bmp_decompress_struct_p bmp_ptr = *bmp_ptr_ptr;
56 *bmp_ptr_ptr = NULL;
57 if (bmp_ptr->out_row_buffer) {
58 FX_Free(bmp_ptr->out_row_buffer);
59 }
60 FX_Free(bmp_ptr->pal_ptr);
61 FX_Free(bmp_ptr->bmp_header_ptr);
62 FX_Free(bmp_ptr);
63 }
64 int32_t bmp_read_header(bmp_decompress_struct_p bmp_ptr) {
65 if (bmp_ptr == NULL) {
66 return 0;
67 }
68 FX_DWORD skip_size_org = bmp_ptr->skip_size;
69 if (bmp_ptr->decode_status == BMP_D_STATUS_HEADER) {
70 ASSERT(sizeof(BmpFileHeader) == 14);
71 BmpFileHeader* bmp_header_ptr = NULL;
72 if (bmp_read_data(bmp_ptr, (uint8_t**)&bmp_header_ptr, 14) == NULL) {
73 return 2;
74 }
75 bmp_ptr->bmp_header_ptr->bfType =
76 GetWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfType);
77 bmp_ptr->bmp_header_ptr->bfOffBits =
78 GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfOffBits);
79 bmp_ptr->data_size = GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfSize);
80 if (bmp_ptr->bmp_header_ptr->bfType != BMP_SIGNATURE) {
81 bmp_error(bmp_ptr, "Not A Bmp Image");
82 return 0;
83 }
84 if (bmp_ptr->avail_in < sizeof(FX_DWORD)) {
85 bmp_ptr->skip_size = skip_size_org;
86 return 2;
87 }
88 bmp_ptr->img_ifh_size =
89 GetDWord_LSBFirst(bmp_ptr->next_in + bmp_ptr->skip_size);
90 bmp_ptr->pal_type = 0;
91 static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize,
92 "BmpCoreHeader has wrong size");
93 static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize,
94 "BmpInfoHeader has wrong size");
95 switch (bmp_ptr->img_ifh_size) {
96 case kBmpCoreHeaderSize: {
97 bmp_ptr->pal_type = 1;
98 BmpCoreHeaderPtr bmp_core_header_ptr = NULL;
99 if (bmp_read_data(bmp_ptr, (uint8_t**)&bmp_core_header_ptr,
100 bmp_ptr->img_ifh_size) == NULL) {
101 bmp_ptr->skip_size = skip_size_org;
102 return 2;
103 }
104 bmp_ptr->width =
105 GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcWidth);
106 bmp_ptr->height =
107 GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcHeight);
108 bmp_ptr->bitCounts =
109 GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcBitCount);
110 bmp_ptr->compress_flag = BMP_RGB;
111 bmp_ptr->imgTB_flag = FALSE;
112 } break;
113 case kBmpInfoHeaderSize: {
114 BmpInfoHeaderPtr bmp_info_header_ptr = NULL;
115 if (bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr,
116 bmp_ptr->img_ifh_size) == NULL) {
117 bmp_ptr->skip_size = skip_size_org;
118 return 2;
119 }
120 bmp_ptr->width =
121 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);
122 bmp_ptr->height =
123 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
124 bmp_ptr->bitCounts =
125 GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);
126 bmp_ptr->compress_flag =
127 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression);
128 bmp_ptr->color_used =
129 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed);
130 bmp_ptr->dpi_x = (int32_t)GetDWord_LSBFirst(
131 (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);
132 bmp_ptr->dpi_y = (int32_t)GetDWord_LSBFirst(
133 (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);
134 if (bmp_ptr->height < 0) {
135 bmp_ptr->height = -bmp_ptr->height;
136 bmp_ptr->imgTB_flag = TRUE;
137 }
138 } break;
139 default: {
140 if (bmp_ptr->img_ifh_size >
141 std::min(kBmpInfoHeaderSize, sizeof(BmpInfoHeader))) {
142 BmpInfoHeaderPtr bmp_info_header_ptr = NULL;
143 if (bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr,
144 bmp_ptr->img_ifh_size) == NULL) {
145 bmp_ptr->skip_size = skip_size_org;
146 return 2;
147 }
148 FX_WORD biPlanes;
149 bmp_ptr->width =
150 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);
151 bmp_ptr->height =
152 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
153 bmp_ptr->bitCounts =
154 GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);
155 bmp_ptr->compress_flag =
156 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression);
157 bmp_ptr->color_used =
158 GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed);
159 biPlanes = GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biPlanes);
160 bmp_ptr->dpi_x = GetDWord_LSBFirst(
161 (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);
162 bmp_ptr->dpi_y = GetDWord_LSBFirst(
163 (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);
164 if (bmp_ptr->height < 0) {
165 bmp_ptr->height = -bmp_ptr->height;
166 bmp_ptr->imgTB_flag = TRUE;
167 }
168 if (bmp_ptr->compress_flag == BMP_RGB && biPlanes == 1 &&
169 bmp_ptr->color_used == 0) {
170 break;
171 }
172 }
173 bmp_error(bmp_ptr, "Unsupported Bmp File");
174 return 0;
175 }
176 }
177 ASSERT(bmp_ptr->width > 0);
178 ASSERT(bmp_ptr->compress_flag <= BMP_BITFIELDS);
179 switch (bmp_ptr->bitCounts) {
180 case 1:
181 case 4:
182 case 8:
183 case 16:
184 case 24: {
185 if (bmp_ptr->color_used > ((FX_DWORD)1) << bmp_ptr->bitCounts) {
186 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
187 return 0;
188 }
189 }
190 case 32: {
191 if (bmp_ptr->width <= 0 || bmp_ptr->compress_flag > BMP_BITFIELDS) {
192 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
193 return 0;
194 }
195 } break;
196 default:
197 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
198 return 0;
199 }
200 bmp_ptr->src_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, bmp_ptr->bitCounts);
201 switch (bmp_ptr->bitCounts) {
202 case 1:
203 case 4:
204 case 8:
205 bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 8);
206 bmp_ptr->components = 1;
207 break;
208 case 16:
209 case 24:
210 bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 24);
211 bmp_ptr->components = 3;
212 break;
213 case 32:
214 bmp_ptr->out_row_bytes = bmp_ptr->src_row_bytes;
215 bmp_ptr->components = 4;
216 break;
217 }
218 FX_Free(bmp_ptr->out_row_buffer);
219 bmp_ptr->out_row_buffer = FX_Alloc(uint8_t, bmp_ptr->out_row_bytes);
220 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
221 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_PAL);
222 }
223 if (bmp_ptr->decode_status == BMP_D_STATUS_PAL) {
224 skip_size_org = bmp_ptr->skip_size;
225 if (bmp_ptr->compress_flag == BMP_BITFIELDS) {
226 if (bmp_ptr->bitCounts != 16 && bmp_ptr->bitCounts != 32) {
227 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
228 return 0;
229 }
230 FX_DWORD* mask;
231 if (bmp_read_data(bmp_ptr, (uint8_t**)&mask, 3 * sizeof(FX_DWORD)) ==
232 NULL) {
233 bmp_ptr->skip_size = skip_size_org;
234 return 2;
235 }
236 bmp_ptr->mask_red = GetDWord_LSBFirst((uint8_t*)&mask[0]);
237 bmp_ptr->mask_green = GetDWord_LSBFirst((uint8_t*)&mask[1]);
238 bmp_ptr->mask_blue = GetDWord_LSBFirst((uint8_t*)&mask[2]);
239 if (bmp_ptr->mask_red & bmp_ptr->mask_green ||
240 bmp_ptr->mask_red & bmp_ptr->mask_blue ||
241 bmp_ptr->mask_green & bmp_ptr->mask_blue) {
242 bmp_error(bmp_ptr, "The Bitfield Bmp File Is Corrupt");
243 return 0;
244 }
245 if (bmp_ptr->bmp_header_ptr->bfOffBits < 26 + bmp_ptr->img_ifh_size) {
246 bmp_ptr->bmp_header_ptr->bfOffBits = 26 + bmp_ptr->img_ifh_size;
247 }
248 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE);
249 return 1;
250 } else if (bmp_ptr->bitCounts == 16) {
251 bmp_ptr->mask_red = 0x7C00;
252 bmp_ptr->mask_green = 0x03E0;
253 bmp_ptr->mask_blue = 0x001F;
254 }
255 bmp_ptr->pal_num = 0;
256 if (bmp_ptr->bitCounts < 16) {
257 bmp_ptr->pal_num = 1 << bmp_ptr->bitCounts;
258 if (bmp_ptr->color_used != 0) {
259 bmp_ptr->pal_num = bmp_ptr->color_used;
260 }
261 uint8_t* src_pal_ptr = NULL;
262 FX_DWORD src_pal_size = bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4);
263 if (bmp_read_data(bmp_ptr, (uint8_t**)&src_pal_ptr, src_pal_size) ==
264 NULL) {
265 bmp_ptr->skip_size = skip_size_org;
266 return 2;
267 }
268 FX_Free(bmp_ptr->pal_ptr);
269 bmp_ptr->pal_ptr = FX_Alloc(FX_DWORD, bmp_ptr->pal_num);
270 int32_t src_pal_index = 0;
271 if (bmp_ptr->pal_type == BMP_PAL_OLD) {
272 while (src_pal_index < bmp_ptr->pal_num) {
273 bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE(
274 0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
275 src_pal_ptr += 3;
276 }
277 } else {
278 while (src_pal_index < bmp_ptr->pal_num) {
279 bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE(
280 src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
281 src_pal_ptr += 4;
282 }
283 }
284 }
285 if (bmp_ptr->bmp_header_ptr->bfOffBits <
286 14 + bmp_ptr->img_ifh_size +
287 bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4)) {
288 bmp_ptr->bmp_header_ptr->bfOffBits =
289 14 + bmp_ptr->img_ifh_size +
290 bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4);
291 }
292 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE);
293 }
294 return 1;
295 }
296 int32_t bmp_decode_image(bmp_decompress_struct_p bmp_ptr) {
297 if (bmp_ptr->decode_status == BMP_D_STATUS_DATA_PRE) {
298 bmp_ptr->avail_in = 0;
299 if (!bmp_ptr->bmp_get_data_position_fn(
300 bmp_ptr, bmp_ptr->bmp_header_ptr->bfOffBits)) {
301 bmp_ptr->decode_status = BMP_D_STATUS_TAIL;
302 bmp_error(bmp_ptr, "The Bmp File Is Corrupt, Unexpected Stream Offset");
303 return 0;
304 }
305 bmp_ptr->row_num = 0;
306 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
307 }
308 if (bmp_ptr->decode_status == BMP_D_STATUS_DATA) {
309 switch (bmp_ptr->compress_flag) {
310 case BMP_RGB:
311 case BMP_BITFIELDS:
312 return bmp_decode_rgb(bmp_ptr);
313 case BMP_RLE8:
314 return bmp_decode_rle8(bmp_ptr);
315 case BMP_RLE4:
316 return bmp_decode_rle4(bmp_ptr);
317 }
318 }
319 bmp_error(bmp_ptr, "Any Uncontrol Error");
320 return 0;
321 }
322 int32_t bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr) {
323 uint8_t* row_buf = bmp_ptr->out_row_buffer;
324 uint8_t* des_buf = NULL;
325 while (bmp_ptr->row_num < bmp_ptr->height) {
326 if (bmp_read_data(bmp_ptr, &des_buf, bmp_ptr->src_row_bytes) == NULL) {
327 return 2;
328 }
329 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
330 switch (bmp_ptr->bitCounts) {
331 case 1: {
332 for (int32_t col = 0; col < bmp_ptr->width; col++) {
333 *row_buf++ = des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
334 }
335 } break;
336 case 4: {
337 for (int32_t col = 0; col < bmp_ptr->width; col++) {
338 *row_buf++ = (col & 0x01) ? (des_buf[col >> 1] & 0x0F)
339 : ((des_buf[col >> 1] & 0xF0) >> 4);
340 }
341 } break;
342 case 16: {
343 FX_WORD* buf = (FX_WORD*)des_buf;
344 uint8_t blue_bits = 0;
345 uint8_t green_bits = 0;
346 uint8_t red_bits = 0;
347 for (int32_t i = 0; i < 16; i++) {
348 if ((bmp_ptr->mask_blue >> i) & 0x01) {
349 blue_bits++;
350 }
351 if ((bmp_ptr->mask_green >> i) & 0x01) {
352 green_bits++;
353 }
354 if ((bmp_ptr->mask_red >> i) & 0x01) {
355 red_bits++;
356 }
357 }
358 green_bits += blue_bits;
359 red_bits += green_bits;
360 blue_bits = 8 - blue_bits;
361 green_bits -= 8;
362 red_bits -= 8;
363 for (int32_t col = 0; col < bmp_ptr->width; col++) {
364 *buf = GetWord_LSBFirst((uint8_t*)buf);
365 *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_blue) << blue_bits);
366 *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_green) >> green_bits);
367 *row_buf++ = (uint8_t)((*buf++ & bmp_ptr->mask_red) >> red_bits);
368 }
369 } break;
370 case 8:
371 case 24:
372 case 32:
373 FXSYS_memcpy(bmp_ptr->out_row_buffer, des_buf, bmp_ptr->src_row_bytes);
374 break;
375 }
376 row_buf = bmp_ptr->out_row_buffer;
377 bmp_ptr->bmp_get_row_fn(bmp_ptr,
378 bmp_ptr->imgTB_flag
379 ? bmp_ptr->row_num++
380 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
381 bmp_ptr->out_row_buffer);
382 }
383 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
384 return 1;
385 }
386 int32_t bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) {
387 uint8_t* first_byte_ptr = NULL;
388 uint8_t* second_byte_ptr = NULL;
389 bmp_ptr->col_num = 0;
390 while (TRUE) {
391 FX_DWORD skip_size_org = bmp_ptr->skip_size;
392 if (bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
393 return 2;
394 }
395 switch (*first_byte_ptr) {
396 case RLE_MARKER: {
397 if (bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
398 bmp_ptr->skip_size = skip_size_org;
399 return 2;
400 }
401 switch (*first_byte_ptr) {
402 case RLE_EOL: {
403 if (bmp_ptr->row_num >= bmp_ptr->height) {
404 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
405 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
406 return 0;
407 }
408 bmp_ptr->bmp_get_row_fn(
409 bmp_ptr, bmp_ptr->imgTB_flag
410 ? bmp_ptr->row_num++
411 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
412 bmp_ptr->out_row_buffer);
413 bmp_ptr->col_num = 0;
414 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
415 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
416 continue;
417 }
418 case RLE_EOI: {
419 if (bmp_ptr->row_num < bmp_ptr->height) {
420 bmp_ptr->bmp_get_row_fn(
421 bmp_ptr, bmp_ptr->imgTB_flag
422 ? bmp_ptr->row_num++
423 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
424 bmp_ptr->out_row_buffer);
425 }
426 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
427 return 1;
428 }
429 case RLE_DELTA: {
430 uint8_t* delta_ptr;
431 if (bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) {
432 bmp_ptr->skip_size = skip_size_org;
433 return 2;
434 }
435 bmp_ptr->col_num += (int32_t)delta_ptr[0];
436 int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1];
437 if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes ||
438 bmp_row_num_next >= bmp_ptr->height) {
439 bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported");
440 return 0;
441 }
442 while (bmp_ptr->row_num < bmp_row_num_next) {
443 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
444 bmp_ptr->bmp_get_row_fn(
445 bmp_ptr, bmp_ptr->imgTB_flag
446 ? bmp_ptr->row_num++
447 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
448 bmp_ptr->out_row_buffer);
449 }
450 } break;
451 default: {
452 if ((int32_t)(*first_byte_ptr) >
453 bmp_ptr->src_row_bytes - bmp_ptr->col_num) {
454 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
455 return 0;
456 }
457 if (bmp_read_data(bmp_ptr, &second_byte_ptr,
458 *first_byte_ptr & 1 ? *first_byte_ptr + 1
459 : *first_byte_ptr) == NULL) {
460 bmp_ptr->skip_size = skip_size_org;
461 return 2;
462 }
463 FXSYS_memcpy(bmp_ptr->out_row_buffer + bmp_ptr->col_num,
464 second_byte_ptr, *first_byte_ptr);
465 bmp_ptr->col_num += (int32_t)(*first_byte_ptr);
466 }
467 }
468 } break;
469 default: {
470 if (bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) {
471 bmp_ptr->skip_size = skip_size_org;
472 return 2;
473 }
474 if ((int32_t)(*first_byte_ptr) >
475 bmp_ptr->src_row_bytes - bmp_ptr->col_num) {
476 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
477 return 0;
478 }
479 FXSYS_memset(bmp_ptr->out_row_buffer + bmp_ptr->col_num,
480 *second_byte_ptr, *first_byte_ptr);
481 bmp_ptr->col_num += (int32_t)(*first_byte_ptr);
482 }
483 }
484 }
485 bmp_error(bmp_ptr, "Any Uncontrol Error");
486 return 0;
487 }
488 int32_t bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) {
489 uint8_t* first_byte_ptr = NULL;
490 uint8_t* second_byte_ptr = NULL;
491 bmp_ptr->col_num = 0;
492 while (TRUE) {
493 FX_DWORD skip_size_org = bmp_ptr->skip_size;
494 if (bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
495 return 2;
496 }
497 switch (*first_byte_ptr) {
498 case RLE_MARKER: {
499 if (bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
500 bmp_ptr->skip_size = skip_size_org;
501 return 2;
502 }
503 switch (*first_byte_ptr) {
504 case RLE_EOL: {
505 if (bmp_ptr->row_num >= bmp_ptr->height) {
506 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
507 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
508 return 0;
509 }
510 bmp_ptr->bmp_get_row_fn(
511 bmp_ptr, bmp_ptr->imgTB_flag
512 ? bmp_ptr->row_num++
513 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
514 bmp_ptr->out_row_buffer);
515 bmp_ptr->col_num = 0;
516 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
517 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
518 continue;
519 }
520 case RLE_EOI: {
521 if (bmp_ptr->row_num < bmp_ptr->height) {
522 bmp_ptr->bmp_get_row_fn(
523 bmp_ptr, bmp_ptr->imgTB_flag
524 ? bmp_ptr->row_num++
525 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
526 bmp_ptr->out_row_buffer);
527 }
528 bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
529 return 1;
530 }
531 case RLE_DELTA: {
532 uint8_t* delta_ptr;
533 if (bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) {
534 bmp_ptr->skip_size = skip_size_org;
535 return 2;
536 }
537 bmp_ptr->col_num += (int32_t)delta_ptr[0];
538 int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1];
539 if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes ||
540 bmp_row_num_next >= bmp_ptr->height) {
541 bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported");
542 return 0;
543 }
544 while (bmp_ptr->row_num < bmp_row_num_next) {
545 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
546 bmp_ptr->bmp_get_row_fn(
547 bmp_ptr, bmp_ptr->imgTB_flag
548 ? bmp_ptr->row_num++
549 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
550 bmp_ptr->out_row_buffer);
551 }
552 } break;
553 default: {
554 uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1);
555 if ((int32_t)*first_byte_ptr >=
556 bmp_ptr->out_row_bytes - bmp_ptr->col_num) {
557 if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {
558 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
559 return 0;
560 }
561 *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;
562 }
563 if (bmp_read_data(bmp_ptr, &second_byte_ptr,
564 size & 1 ? size + 1 : size) == NULL) {
565 bmp_ptr->skip_size = skip_size_org;
566 return 2;
567 }
568 for (uint8_t i = 0; i < *first_byte_ptr; i++) {
569 if (i & 0x01) {
570 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
571 (*second_byte_ptr++ & 0x0F);
572 } else {
573 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
574 ((*second_byte_ptr & 0xF0) >> 4);
575 }
576 }
577 }
578 }
579 } break;
580 default: {
581 if (bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) {
582 bmp_ptr->skip_size = skip_size_org;
583 return 2;
584 }
585 if ((int32_t)*first_byte_ptr >
586 bmp_ptr->out_row_bytes - bmp_ptr->col_num) {
587 uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1);
588 if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {
589 bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
590 return 0;
591 }
592 *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;
593 }
594 for (uint8_t i = 0; i < *first_byte_ptr; i++) {
595 if (i & 0x01) {
596 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
597 (*second_byte_ptr & 0x0F);
598 } else {
599 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
600 ((*second_byte_ptr & 0xF0) >> 4);
601 }
602 }
603 }
604 }
605 }
606 bmp_error(bmp_ptr, "Any Uncontrol Error");
607 return 0;
608 }
609 uint8_t* bmp_read_data(bmp_decompress_struct_p bmp_ptr,
610 uint8_t** des_buf_pp,
611 FX_DWORD data_size) {
612 if (bmp_ptr == NULL || bmp_ptr->avail_in < bmp_ptr->skip_size + data_size) {
613 return NULL;
614 }
615 *des_buf_pp = bmp_ptr->next_in + bmp_ptr->skip_size;
616 bmp_ptr->skip_size += data_size;
617 return *des_buf_pp;
618 }
619 void bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, int32_t status) {
620 bmp_ptr->decode_status = status;
621 bmp_ptr->next_in += bmp_ptr->skip_size;
622 bmp_ptr->avail_in -= bmp_ptr->skip_size;
623 bmp_ptr->skip_size = 0;
624 }
625 void bmp_input_buffer(bmp_decompress_struct_p bmp_ptr,
626 uint8_t* src_buf,
627 FX_DWORD src_size) {
628 bmp_ptr->next_in = src_buf;
629 bmp_ptr->avail_in = src_size;
630 bmp_ptr->skip_size = 0;
631 }
632 FX_DWORD bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr,
633 uint8_t** avial_buf_ptr) {
634 if (avial_buf_ptr) {
635 *avial_buf_ptr = NULL;
636 if (bmp_ptr->avail_in > 0) {
637 *avial_buf_ptr = bmp_ptr->next_in;
638 }
639 }
640 return bmp_ptr->avail_in;
641 }
642 bmp_compress_struct_p bmp_create_compress() {
643 bmp_compress_struct_p bmp_ptr;
644 bmp_ptr = FX_Alloc(bmp_compress_struct, 1);
645 if (bmp_ptr) {
646 FXSYS_memset(bmp_ptr, 0, sizeof(bmp_compress_struct));
647 }
648 return bmp_ptr;
649 }
650 void bmp_destroy_compress(bmp_compress_struct_p bmp_ptr) {
651 if (bmp_ptr) {
652 if (bmp_ptr->src_free && bmp_ptr->src_buf) {
653 FX_Free(bmp_ptr->src_buf);
654 }
655 FX_Free(bmp_ptr);
656 }
657 }
658 static void WriteFileHeader(BmpFileHeaderPtr head_ptr, uint8_t* dst_buf) {
659 FX_DWORD offset;
660 offset = 0;
661 SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfType);
662 offset += 2;
663 SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfSize);
664 offset += 4;
665 SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved1);
666 offset += 2;
667 SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved2);
668 offset += 2;
669 SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfOffBits);
670 offset += 4;
671 }
672 static void WriteInfoHeader(BmpInfoHeaderPtr info_head_ptr, uint8_t* dst_buf) {
673 FX_DWORD offset;
674 offset = sizeof(BmpFileHeader);
675 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSize);
676 offset += 4;
677 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biWidth);
678 offset += 4;
679 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biHeight);
680 offset += 4;
681 SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biPlanes);
682 offset += 2;
683 SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biBitCount);
684 offset += 2;
685 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biCompression);
686 offset += 4;
687 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSizeImage);
688 offset += 4;
689 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biXPelsPerMeter);
690 offset += 4;
691 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biYPelsPerMeter);
692 offset += 4;
693 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrUsed);
694 offset += 4;
695 SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrImportant);
696 offset += 4;
697 }
698 static void bmp_encode_bitfields(bmp_compress_struct_p bmp_ptr,
699 uint8_t*& dst_buf,
700 FX_DWORD& dst_size) {
701 if (bmp_ptr->info_header.biBitCount != 16 &&
702 bmp_ptr->info_header.biBitCount != 32) {
703 return;
704 }
705 FX_DWORD size, dst_pos, i;
706 size = bmp_ptr->src_pitch * bmp_ptr->src_row *
707 bmp_ptr->info_header.biBitCount / 16;
708 dst_pos = bmp_ptr->file_header.bfOffBits;
709 dst_size += size;
710 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
711 if (dst_buf == NULL) {
712 return;
713 }
714 FXSYS_memset(&dst_buf[dst_pos], 0, size);
715 FX_DWORD mask_red;
716 FX_DWORD mask_green;
717 FX_DWORD mask_blue;
718 mask_red = 0x7C00;
719 mask_green = 0x03E0;
720 mask_blue = 0x001F;
721 if (bmp_ptr->info_header.biCompression == BMP_BITFIELDS) {
722 if (bmp_ptr->bit_type == BMP_BIT_565) {
723 mask_red = 0xF800;
724 mask_green = 0x07E0;
725 mask_blue = 0x001F;
726 }
727 if (bmp_ptr->info_header.biBitCount == 32) {
728 mask_red = 0xFF0000;
729 mask_green = 0x00FF00;
730 mask_blue = 0x0000FF;
731 }
732 SetDWord_LSBFirst(&dst_buf[dst_pos], mask_red);
733 dst_pos += 4;
734 SetDWord_LSBFirst(&dst_buf[dst_pos], mask_green);
735 dst_pos += 4;
736 SetDWord_LSBFirst(&dst_buf[dst_pos], mask_blue);
737 dst_pos += 4;
738 bmp_ptr->file_header.bfOffBits = dst_pos;
739 }
740 uint8_t blue_bits = 0;
741 uint8_t green_bits = 0;
742 uint8_t red_bits = 0;
743 for (i = 0; i < bmp_ptr->info_header.biBitCount; i++) {
744 if ((mask_blue >> i) & 0x01) {
745 blue_bits++;
746 }
747 if ((mask_green >> i) & 0x01) {
748 green_bits++;
749 }
750 if ((mask_red >> i) & 0x01) {
751 red_bits++;
752 }
753 }
754 green_bits += blue_bits;
755 red_bits += green_bits;
756 blue_bits = 8 - blue_bits;
757 green_bits -= 8;
758 red_bits -= 8;
759 i = 0;
760 for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--, i = 0) {
761 while (i < bmp_ptr->src_width * bmp_ptr->src_bpp / 8) {
762 uint8_t b = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];
763 uint8_t g = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];
764 uint8_t r = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];
765 if (bmp_ptr->src_bpp == 32) {
766 i++;
767 }
768 FX_DWORD pix_val = 0;
769 pix_val |= (b >> blue_bits) & mask_blue;
770 pix_val |= (g << green_bits) & mask_green;
771 pix_val |= (r << red_bits) & mask_red;
772 if (bmp_ptr->info_header.biBitCount == 16) {
773 SetWord_LSBFirst(&dst_buf[dst_pos], pix_val);
774 dst_pos += 2;
775 } else {
776 SetDWord_LSBFirst(&dst_buf[dst_pos], pix_val);
777 dst_pos += 4;
778 }
779 }
780 }
781 dst_size = dst_pos;
782 }
783
784 static void bmp_encode_rgb(bmp_compress_struct_p bmp_ptr,
785 uint8_t*& dst_buf,
786 FX_DWORD& dst_size) {
787 if (bmp_ptr->info_header.biBitCount == 16) {
788 bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size);
789 return;
790 }
791 FX_DWORD size, dst_pos;
792 FX_DWORD dst_pitch =
793 (bmp_ptr->src_width * bmp_ptr->info_header.biBitCount + 31) / 32 * 4;
794 size = dst_pitch * bmp_ptr->src_row;
795 dst_pos = bmp_ptr->file_header.bfOffBits;
796 dst_size += size;
797 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
798 if (dst_buf == NULL) {
799 return;
800 }
801 FXSYS_memset(&dst_buf[dst_pos], 0, size);
802 for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--) {
803 FXSYS_memcpy(&dst_buf[dst_pos],
804 &bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch],
805 bmp_ptr->src_pitch);
806 dst_pos += dst_pitch;
807 }
808 dst_size = dst_pos;
809 }
810 static uint8_t bmp_rle8_search(const uint8_t* buf, int32_t len) {
811 uint8_t num;
812 num = 1;
813 while (num < len) {
814 if (buf[num - 1] != buf[num] || num == 0xFF) {
815 break;
816 }
817 num++;
818 }
819 return num;
820 }
821 static void bmp_encode_rle8(bmp_compress_struct_p bmp_ptr,
822 uint8_t*& dst_buf,
823 FX_DWORD& dst_size) {
824 FX_DWORD size, dst_pos, index;
825 uint8_t rle[2] = {0};
826 size = bmp_ptr->src_pitch * bmp_ptr->src_row * 2;
827 dst_pos = bmp_ptr->file_header.bfOffBits;
828 dst_size += size;
829 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
830 if (dst_buf == NULL) {
831 return;
832 }
833 FXSYS_memset(&dst_buf[dst_pos], 0, size);
834 for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1;) {
835 index = row_num * bmp_ptr->src_pitch;
836 rle[0] = bmp_rle8_search(&bmp_ptr->src_buf[index + i], size - index - i);
837 rle[1] = bmp_ptr->src_buf[index + i];
838 if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) {
839 rle[0] = uint8_t(bmp_ptr->src_pitch - i);
840 if (rle[0]) {
841 dst_buf[dst_pos++] = rle[0];
842 dst_buf[dst_pos++] = rle[1];
843 }
844 dst_buf[dst_pos++] = RLE_MARKER;
845 dst_buf[dst_pos++] = RLE_EOL;
846 i = 0;
847 row_num--;
848 } else {
849 i += rle[0];
850 dst_buf[dst_pos++] = rle[0];
851 dst_buf[dst_pos++] = rle[1];
852 }
853 }
854 dst_buf[dst_pos++] = RLE_MARKER;
855 dst_buf[dst_pos++] = RLE_EOI;
856 dst_size = dst_pos;
857 }
858 static uint8_t bmp_rle4_search(const uint8_t* buf, int32_t len) {
859 uint8_t num;
860 num = 2;
861 while (num < len) {
862 if (buf[num - 2] != buf[num] || num == 0xFF) {
863 break;
864 }
865 num++;
866 }
867 return num;
868 }
869 static void bmp_encode_rle4(bmp_compress_struct_p bmp_ptr,
870 uint8_t*& dst_buf,
871 FX_DWORD& dst_size) {
872 FX_DWORD size, dst_pos, index;
873 uint8_t rle[2] = {0};
874 size = bmp_ptr->src_pitch * bmp_ptr->src_row;
875 dst_pos = bmp_ptr->file_header.bfOffBits;
876 dst_size += size;
877 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
878 if (dst_buf == NULL) {
879 return;
880 }
881 FXSYS_memset(&dst_buf[dst_pos], 0, size);
882 for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1;
883 rle[1] = 0) {
884 index = row_num * bmp_ptr->src_pitch;
885 rle[0] = bmp_rle4_search(&bmp_ptr->src_buf[index + i], size - index - i);
886 rle[1] |= (bmp_ptr->src_buf[index + i] & 0x0f) << 4;
887 rle[1] |= bmp_ptr->src_buf[index + i + 1] & 0x0f;
888 if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) {
889 rle[0] = uint8_t(bmp_ptr->src_pitch - i);
890 if (rle[0]) {
891 dst_buf[dst_pos++] = rle[0];
892 dst_buf[dst_pos++] = rle[1];
893 }
894 dst_buf[dst_pos++] = RLE_MARKER;
895 dst_buf[dst_pos++] = RLE_EOL;
896 i = 0;
897 row_num--;
898 } else {
899 i += rle[0];
900 dst_buf[dst_pos++] = rle[0];
901 dst_buf[dst_pos++] = rle[1];
902 }
903 }
904 dst_buf[dst_pos++] = RLE_MARKER;
905 dst_buf[dst_pos++] = RLE_EOI;
906 dst_size = dst_pos;
907 }
908 FX_BOOL bmp_encode_image(bmp_compress_struct_p bmp_ptr,
909 uint8_t*& dst_buf,
910 FX_DWORD& dst_size) {
911 FX_DWORD head_size = sizeof(BmpFileHeader) + sizeof(BmpInfoHeader);
912 FX_DWORD pal_size = sizeof(FX_DWORD) * bmp_ptr->pal_num;
913 if (bmp_ptr->info_header.biClrUsed > 0 &&
914 bmp_ptr->info_header.biClrUsed < bmp_ptr->pal_num) {
915 pal_size = sizeof(FX_DWORD) * bmp_ptr->info_header.biClrUsed;
916 }
917 dst_size = head_size + sizeof(FX_DWORD) * bmp_ptr->pal_num;
918 dst_buf = FX_TryAlloc(uint8_t, dst_size);
919 if (dst_buf == NULL) {
920 return FALSE;
921 }
922 FXSYS_memset(dst_buf, 0, dst_size);
923 bmp_ptr->file_header.bfOffBits = head_size;
924 if (bmp_ptr->pal_ptr && pal_size) {
925 FXSYS_memcpy(&dst_buf[head_size], bmp_ptr->pal_ptr, pal_size);
926 bmp_ptr->file_header.bfOffBits += pal_size;
927 }
928 WriteInfoHeader(&bmp_ptr->info_header, dst_buf);
929 switch (bmp_ptr->info_header.biCompression) {
930 case BMP_RGB:
931 bmp_encode_rgb(bmp_ptr, dst_buf, dst_size);
932 break;
933 case BMP_BITFIELDS:
934 bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size);
935 break;
936 case BMP_RLE8:
937 bmp_encode_rle8(bmp_ptr, dst_buf, dst_size);
938 break;
939 case BMP_RLE4:
940 bmp_encode_rle4(bmp_ptr, dst_buf, dst_size);
941 break;
942 default:
943 break;
944 }
945 bmp_ptr->file_header.bfSize = dst_size;
946 WriteFileHeader(&bmp_ptr->file_header, dst_buf);
947 return TRUE;
948 }
OLDNEW
« no previous file with comments | « core/src/fxcodec/lbmp/fx_bmp.h ('k') | core/src/fxcodec/lgif/fx_gif.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698