static unsigned char* _jpeg_decode_row( wprint_image_info_t *image_info, int row ) { int i, j, rows; int start_row; int rows_cached; if ((row < 0) || (row >= image_info->sampled_height)) return(NULL); rows_cached = wprint_image_input_rows_cached(image_info); if ((image_info->swath_start == -1) || (row < image_info->swath_start) || (row >= (image_info->swath_start + rows_cached))) { start_row = ((image_info->swath_start < 0) ? 0 : (image_info->swath_start + rows_cached)); if (image_info->decoder_data.jpg_info.buff == NULL) { rows_cached = wprint_image_compute_rows_to_cache(image_info); image_info->decoder_data.jpg_info.buff = (JSAMPARRAY*)malloc(sizeof(JSAMPARRAY) * rows_cached); for(i = 0; i < rows_cached; i++) { image_info->decoder_data.jpg_info.buff[i] = NULL; image_info->decoder_data.jpg_info.buff[i] = (JSAMPARRAY) (*image_info->decoder_data.jpg_info.cinfo.mem->alloc_sarray) ( (j_common_ptr) &image_info->decoder_data.jpg_info.cinfo, JPOOL_IMAGE, BYTES_PER_PIXEL(image_info->decoder_data.jpg_info.cinfo.output_width), 1); if (image_info->decoder_data.jpg_info.buff[i] == NULL) break; } rows_cached = MIN(i, rows_cached); } else if ((image_info->swath_start != -1) && (row < image_info->swath_start)) { start_row = 0; jpeg_abort((void *) &image_info->decoder_data.jpg_info.cinfo); jpeg_destroy_decompress(&image_info->decoder_data.jpg_info.cinfo); if (_jpeg_get_hdr(image_info) == ERROR) return(NULL); for(i = 0; i < rows_cached; i++) { image_info->decoder_data.jpg_info.buff[i] = (JSAMPARRAY) (*image_info->decoder_data.jpg_info.cinfo.mem->alloc_sarray) ( (j_common_ptr) &image_info->decoder_data.jpg_info.cinfo, JPOOL_IMAGE, BYTES_PER_PIXEL(image_info->decoder_data.jpg_info.cinfo.output_width), 1); if (image_info->decoder_data.jpg_info.buff[i] == NULL) break; } rows_cached = MIN(i, rows_cached); } if (rows_cached == 0) return(NULL); if (setjmp(image_info->decoder_data.jpg_info.jerr.env)) { image_info->wprint_ifc->debug(DBG_ERROR, "ERROR: JPEG read error or corrupt file"); return(NULL); } image_info->swath_start = ((row / rows_cached) * rows_cached); for(i = start_row; i <= image_info->swath_start; i += rows_cached) { rows = MIN(rows_cached, (image_info->sampled_height - i)); for(j = 0; j < rows; j++) { jpeg_read_scanlines(&image_info->decoder_data.jpg_info.cinfo, image_info->decoder_data.jpg_info.buff[j], 1); if (image_info->decoder_data.jpg_info.jerr.pub.num_warnings != 0) { image_info->wprint_ifc->debug(DBG_ERROR, "ERROR: JPEG scanline error"); return(NULL); } } } } return((unsigned char*)image_info->decoder_data.jpg_info.buff[row - image_info->swath_start][0]); } /* _jpeg_decode_row */
GLOBAL void jpeg_abort_compress( j_compress_ptr cinfo ) { jpeg_abort( (j_common_ptr) cinfo );/* use common routine */ }
GLOBAL void jpeg_finish_compress (j_compress_ptr cinfo) { JDIMENSION iMCU_row; if (cinfo->global_state == CSTATE_SCANNING || cinfo->global_state == CSTATE_RAW_OK) { /* Terminate first pass */ if (cinfo->next_scanline < cinfo->image_height) ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); (*cinfo->master->finish_pass) (cinfo); } else if (cinfo->global_state != CSTATE_WRCOEFS) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform any remaining passes */ while (! cinfo->master->is_last_pass) { (*cinfo->master->prepare_for_pass) (cinfo); for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) iMCU_row; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } (*cinfo->master->finish_pass) (cinfo); } /* Write EOI, do final cleanup */ (*cinfo->marker->write_file_trailer) (cinfo); (*cinfo->dest->term_destination) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); }
vl::Error vl::ImageReader::Impl::readPixels(float * memory, char const * filename) { vl::Error error = vl::vlSuccess ; int row_stride ; const int blockSize = 32 ; char unsigned * pixels = NULL ; JSAMPARRAY scanlines = NULL ; bool requiresAbort = false ; /* initialize the image as null */ ImageShape shape ; /* open file */ FILE* fp = fopen(filename, "r") ; if (fp == NULL) { error = vl::vlErrorUnknown ; return error ; } /* handle LibJPEG errors */ if (setjmp(onJpegError)) { error = vl::vlErrorUnknown ; std::snprintf(lastErrorMessage, sizeof(lastErrorMessage), "libjpeg: %s", jpegLastErrorMsg) ; goto done ; } /* set which file to read */ jpeg_stdio_src(&decompressor, fp); /* read image metadata */ jpeg_read_header(&decompressor, TRUE) ; requiresAbort = true ; /* figure out if the image is grayscale (depth = 1) or color (depth = 3) */ decompressor.quantize_colors = FALSE ; if (decompressor.jpeg_color_space == JCS_GRAYSCALE) { shape.depth = 1 ; decompressor.out_color_space = JCS_GRAYSCALE ; } else { shape.depth = 3 ; decompressor.out_color_space = JCS_RGB ; } /* get the output dimension */ jpeg_calc_output_dimensions(&decompressor) ; shape.width = decompressor.output_width ; shape.height = decompressor.output_height ; /* allocate scaline buffer */ pixels = (char unsigned*)malloc(sizeof(char) * shape.width * shape.height * shape.depth) ; if (pixels == NULL) { error = vl::vlErrorUnknown ; goto done ; } scanlines = (char unsigned**)malloc(sizeof(char*) * shape.height) ; if (scanlines == NULL) { error = vl::vlErrorUnknown ; goto done ; } for (int y = 0 ; y < shape.height ; ++y) { scanlines[y] = pixels + shape.depth * shape.width * y ; } /* decompress each scanline and transpose the result into MATLAB format */ jpeg_start_decompress(&decompressor); while(decompressor.output_scanline < shape.height) { jpeg_read_scanlines(&decompressor, scanlines + decompressor.output_scanline, shape.height - decompressor.output_scanline); } { Image image(shape, memory) ; switch (shape.depth) { case 3 : vl::impl::imageFromPixels<impl::pixelFormatRGB>(image, pixels, shape.width*3) ; break ; case 1 : vl::impl::imageFromPixels<impl::pixelFormatL>(image, pixels, shape.width*1) ; break ; default : error = vl::vlErrorUnknown ; goto done ; } jpeg_finish_decompress(&decompressor) ; requiresAbort = false ; } done: if (requiresAbort) { jpeg_abort((j_common_ptr)&decompressor) ; } if (scanlines) free(scanlines) ; if (pixels) free(pixels) ; fclose(fp) ; return error ; }
GLOBAL int jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) { int retcode; if (cinfo->global_state != DSTATE_START && cinfo->global_state != DSTATE_INHEADER) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); retcode = jpeg_consume_input(cinfo); switch (retcode) { case JPEG_REACHED_SOS: retcode = JPEG_HEADER_OK; break; case JPEG_REACHED_EOI: if (require_image) /* Complain if application wanted an image */ ERREXIT(cinfo, JERR_NO_IMAGE); /* Reset to start state; it would be safer to require the application to * call jpeg_abort, but we can't change it now for compatibility reasons. * A side effect is to free any temporary memory (there shouldn't be any). */ jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ retcode = JPEG_HEADER_TABLES_ONLY; break; case JPEG_SUSPENDED: /* no work */ break; } return retcode; }
vl::Image vl::ImageReader::Impl::read(char const * filename, float * memory) { int row_stride ; const int blockSize = 32 ; char unsigned * pixels = NULL ; JSAMPARRAY scanlines = NULL ; bool requiresAbort = false ; /* initialize the image as null */ Image image ; image.width = 0 ; image.height = 0 ; image.depth = 0 ; image.memory = NULL ; image.error = 0 ; /* open file */ FILE* fp = fopen(filename, "r") ; if (fp == NULL) { image.error = 1 ; return image ; } /* handle LibJPEG errors */ if (setjmp(onJpegError)) { image.error = 1 ; goto done ; } /* set which file to read */ jpeg_stdio_src(&decompressor, fp); /* read image metadata */ jpeg_read_header(&decompressor, TRUE) ; requiresAbort = true ; /* get the output dimension (this may differ from the input if we were to scale the image) */ jpeg_calc_output_dimensions(&decompressor) ; image.width = decompressor.output_width ; image.height = decompressor.output_height ; image.depth = decompressor.output_components ; /* allocate image memory */ if (memory == NULL) { image.memory = (float*)malloc(sizeof(float)*image.depth*image.width*image.height) ; } else { image.memory = memory ; } if (image.memory == NULL) { image.error = 1 ; goto done ; } /* allocate scaline buffer */ pixels = (char unsigned*)malloc(sizeof(char) * image.width * image.height * image.depth) ; if (pixels == NULL) { image.error = 1 ; goto done ; } scanlines = (char unsigned**)malloc(sizeof(char*) * image.height) ; if (scanlines == NULL) { image.error = 1 ; goto done ; } for (int y = 0 ; y < image.height ; ++y) { scanlines[y] = pixels + image.depth * image.width * y ; } /* decompress each scanline and transpose the result into MATLAB format */ jpeg_start_decompress(&decompressor); while(decompressor.output_scanline < image.height) { jpeg_read_scanlines(&decompressor, scanlines + decompressor.output_scanline, image.height - decompressor.output_scanline); } switch (image.depth) { case 3 : vl::impl::imageFromPixels<impl::pixelFormatRGB>(image, pixels, image.width*3) ; break ; case 1 : vl::impl::imageFromPixels<impl::pixelFormatL>(image, pixels, image.width*1) ; break ; } jpeg_finish_decompress(&decompressor) ; requiresAbort = false ; done: if (requiresAbort) { jpeg_abort((j_common_ptr)&decompressor) ; } if (scanlines) free(scanlines) ; if (pixels) free(pixels) ; fclose(fp) ; return image ; }