| 441 | } |
| 442 | |
| 443 | bool Jpeg::decodeStream( |
| 444 | const JpegConfig& config, |
| 445 | fl::filebuf_ptr input_stream, |
| 446 | Frame* frame, |
| 447 | fl::u32 max_time_per_chunk_ms, |
| 448 | fl::function<bool(float)> mProgresscallback) { |
| 449 | |
| 450 | if (!frame || !input_stream) { |
| 451 | return false; |
| 452 | } |
| 453 | |
| 454 | auto decoder = createDecoder(config); |
| 455 | |
| 456 | ProgressiveConfig prog_config; |
| 457 | prog_config.max_time_per_tick_ms = max_time_per_chunk_ms; |
| 458 | decoder->setProgressiveConfig(prog_config); |
| 459 | |
| 460 | if (!decoder->begin(input_stream)) { |
| 461 | return false; |
| 462 | } |
| 463 | |
| 464 | // Use callback-based decode with progress notifications |
| 465 | fl::optional<fl::function<bool()>> yield_func; |
| 466 | if (mProgresscallback) { |
| 467 | yield_func = fl::function<bool()>([&]() { |
| 468 | float progress = decoder->getProgress(); |
| 469 | return !mProgresscallback(progress); // Yield if callback returns false |
| 470 | }); |
| 471 | } |
| 472 | DecodeResult result = decoder->decode(yield_func); |
| 473 | |
| 474 | if (result == DecodeResult::Success) { |
| 475 | Frame decoded = decoder->getCurrentFrame(); |
| 476 | |
| 477 | if (frame->getWidth() != decoded.getWidth() || frame->getHeight() != decoded.getHeight()) { |
| 478 | return false; |
| 479 | } |
| 480 | |
| 481 | frame->copy(decoded); |
| 482 | return true; |
| 483 | } |
| 484 | |
| 485 | return false; |
| 486 | } |
| 487 | |
| 488 | JpegInfo Jpeg::parseInfo(fl::span<const fl::u8> data, fl::string* error_message) { |
| 489 | (void)data; |
nothing calls this directly
no test coverage detected