| 408 | |
| 409 | template <typename T> |
| 410 | static bool WrapJPEGDecompress(RGBA8Image* image, T setup_func) |
| 411 | { |
| 412 | std::vector<u8> scanline; |
| 413 | jpeg_decompress_struct info = {}; |
| 414 | |
| 415 | // NOTE: Be **very** careful not to allocate memory after calling this function. |
| 416 | // It won't get freed, because fastjmp does not unwind the stack. |
| 417 | JPEGErrorHandler errhandler; |
| 418 | if (fastjmp_set(&errhandler.jbuf) != 0) |
| 419 | { |
| 420 | jpeg_destroy_decompress(&info); |
| 421 | return false; |
| 422 | } |
| 423 | info.err = &errhandler.err; |
| 424 | jpeg_create_decompress(&info); |
| 425 | setup_func(info); |
| 426 | |
| 427 | const int herr = jpeg_read_header(&info, TRUE); |
| 428 | if (herr != JPEG_HEADER_OK) |
| 429 | { |
| 430 | Console.ErrorFmt("jpeg_read_header() returned {}", herr); |
| 431 | return false; |
| 432 | } |
| 433 | |
| 434 | if (info.image_width == 0 || info.image_height == 0 || info.num_components < 3) |
| 435 | { |
| 436 | Console.ErrorFmt("Invalid image dimensions: {}x{}x{}", info.image_width, info.image_height, info.num_components); |
| 437 | return false; |
| 438 | } |
| 439 | |
| 440 | info.out_color_space = JCS_RGB; |
| 441 | info.out_color_components = 3; |
| 442 | |
| 443 | if (!jpeg_start_decompress(&info)) |
| 444 | { |
| 445 | Console.ErrorFmt("jpeg_start_decompress() returned failure"); |
| 446 | return false; |
| 447 | } |
| 448 | |
| 449 | image->SetSize(info.image_width, info.image_height); |
| 450 | scanline.resize(info.image_width * 3); |
| 451 | |
| 452 | u8* scanline_buffer[1] = {scanline.data()}; |
| 453 | bool result = true; |
| 454 | for (u32 y = 0; y < info.image_height; y++) |
| 455 | { |
| 456 | if (jpeg_read_scanlines(&info, scanline_buffer, 1) != 1) |
| 457 | { |
| 458 | Console.ErrorFmt("jpeg_read_scanlines() failed at row {}", y); |
| 459 | result = false; |
| 460 | break; |
| 461 | } |
| 462 | |
| 463 | // RGB -> RGBA |
| 464 | const u8* src_ptr = scanline.data(); |
| 465 | u32* dst_ptr = image->GetRowPixels(y); |
| 466 | for (u32 x = 0; x < info.image_width; x++) |
| 467 | { |
no test coverage detected