static CONSUME_INPUT decompress_data_d_diff(jpeg_decompress cinfo, byte[][][] output_buf, int[] output_buf_ind) { jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef; d_diff_controller diff = (d_diff_controller)losslsd.diff_private; // Loop to process as much as one whole iMCU row for (uint yoffset = diff.MCU_vert_offset; yoffset < diff.MCU_rows_per_iMCU_row; yoffset++) { // Process restart marker if needed; may have to suspend if (cinfo.restart_interval != 0) { if (diff.restart_rows_to_go == 0) { if (!process_restart_d_diff(cinfo)) { return(CONSUME_INPUT.JPEG_SUSPENDED); } } } uint MCU_col_num = diff.MCU_ctr; // index of current MCU within row // Try to fetch an MCU-row (or remaining portion of suspended MCU-row). uint MCU_count = losslsd.entropy_decode_mcus(cinfo, diff.diff_buf, yoffset, MCU_col_num, cinfo.MCUs_per_row - MCU_col_num); if (MCU_count != cinfo.MCUs_per_row - MCU_col_num) { // Suspension forced; update state counters and exit diff.MCU_vert_offset = yoffset; diff.MCU_ctr += MCU_count; return(CONSUME_INPUT.JPEG_SUSPENDED); } // Account for restart interval (no-op if not using restarts) diff.restart_rows_to_go--; // Completed an MCU row, but perhaps not an iMCU row diff.MCU_ctr = 0; } uint last_iMCU_row = cinfo.total_iMCU_rows - 1; // Undifference and scale each scanline of the disassembled MCU-row // separately. We do not process dummy samples at the end of a scanline // or dummy rows at the end of the image. for (int comp = 0; comp < cinfo.comps_in_scan; comp++) { jpeg_component_info compptr = cinfo.cur_comp_info[comp]; int ci = compptr.component_index; int stop = cinfo.input_iMCU_row == last_iMCU_row?compptr.last_row_height:compptr.v_samp_factor; for (int row = 0, prev_row = compptr.v_samp_factor - 1; row < stop; prev_row = row, row++) { losslsd.predict_undifference[ci](cinfo, ci, diff.diff_buf[ci][row], diff.undiff_buf[ci][prev_row], diff.undiff_buf[ci][row], compptr.width_in_blocks); losslsd.scaler_scale(cinfo, diff.undiff_buf[ci][row], output_buf[ci][output_buf_ind[ci] + row], compptr.width_in_blocks); } } // Completed the iMCU row, advance counters for next one. // // NB: output_data will increment output_iMCU_row. // This counter is not needed for the single-pass case // or the input side of the multi-pass case. if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows) { start_iMCU_row_d_diff(cinfo); return(CONSUME_INPUT.JPEG_ROW_COMPLETED); } // Completed the scan cinfo.inputctl.finish_input_pass(cinfo); return(CONSUME_INPUT.JPEG_SCAN_COMPLETED); }