OLD | NEW |
| (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 } | |
OLD | NEW |