uvc_error_t uvc_mjpeg2yuyv(uvc_frame_t *in, uvc_frame_t *out) { out->actual_bytes = 0; // XXX if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG)) return UVC_ERROR_INVALID_PARAM; if (uvc_ensure_frame_size(out, in->width * in->height * 2) < 0) return UVC_ERROR_NO_MEM; size_t lines_read = 0; int i, j; int num_scanlines; register uint8_t *yuyv, *ycbcr; out->width = in->width; out->height = in->height; out->frame_format = UVC_FRAME_FORMAT_YUYV; out->step = in->width * 2; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; struct jpeg_decompress_struct dinfo; struct error_mgr jerr; dinfo.err = jpeg_std_error(&jerr.super); jerr.super.error_exit = _error_exit; if (setjmp(jerr.jmp)) { goto fail; } jpeg_create_decompress(&dinfo); jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/); // XXX jpeg_read_header(&dinfo, TRUE); if (dinfo.dc_huff_tbl_ptrs[0] == NULL) { /* This frame is missing the Huffman tables: fill in the standard ones */ insert_huff_tables(&dinfo); } dinfo.out_color_space = JCS_YCbCr; dinfo.dct_method = JDCT_IFAST; // start decompressor jpeg_start_decompress(&dinfo); // these dinfo.xxx valiables are only valid after jpeg_start_decompress const int row_stride = dinfo.output_width * dinfo.output_components; // allocate buffer register JSAMPARRAY buffer = (*dinfo.mem->alloc_sarray) ((j_common_ptr) &dinfo, JPOOL_IMAGE, row_stride, MAX_READLINE); // local copy uint8_t *data = out->data; const int out_step = out->step; if (LIKELY(dinfo.output_height == out->height)) { for (; dinfo.output_scanline < dinfo.output_height ;) { // convert lines of mjpeg data to YCbCr num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE); // convert YCbCr to yuyv(YUV422) for (j = 0; j < num_scanlines; j++) { yuyv = data + (lines_read + j) * out_step; ycbcr = buffer[j]; for (i = 0; i < row_stride; i += 24) { // step by YCbCr x 8 pixels = 3 x 8 bytes YCbCr_YUYV_2(ycbcr + i, yuyv); YCbCr_YUYV_2(ycbcr + i + 6, yuyv); YCbCr_YUYV_2(ycbcr + i + 12, yuyv); YCbCr_YUYV_2(ycbcr + i + 18, yuyv); } } lines_read += num_scanlines; } out->actual_bytes = in->width * in->height * 2; // XXX } jpeg_finish_decompress(&dinfo); jpeg_destroy_decompress(&dinfo); return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; fail: jpeg_destroy_decompress(&dinfo); return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER+1; }
//! creates a surface from the file IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const { #ifndef _IRR_COMPILE_WITH_LIBJPEG_ os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG); return 0; #else if (!file) return 0; Filename = file->getFileName(); u8 **rowPtr=0; u8* input = new u8[file->getSize()]; file->read(input, file->getSize()); // allocate and initialize JPEG decompression object struct jpeg_decompress_struct cinfo; struct irr_jpeg_error_mgr jerr; //We have to set up the error handler first, in case the initialization //step fails. (Unlikely, but it could happen if you are out of memory.) //This routine fills in the contents of struct jerr, and returns jerr's //address which we place into the link field in cinfo. cinfo.err = jpeg_std_error(&jerr.pub); cinfo.err->error_exit = error_exit; cinfo.err->output_message = output_message; // compatibility fudge: // we need to use setjmp/longjmp for error handling as gcc-linux // crashes when throwing within external c code if (setjmp(jerr.setjmp_buffer)) { // If we get here, the JPEG code has signaled an error. // We need to clean up the JPEG object and return. jpeg_destroy_decompress(&cinfo); delete [] input; // if the row pointer was created, we delete it. if (rowPtr) delete [] rowPtr; // return null pointer return 0; } // Now we can initialize the JPEG decompression object. jpeg_create_decompress(&cinfo); // specify data source jpeg_source_mgr jsrc; // Set up data pointer jsrc.bytes_in_buffer = file->getSize(); jsrc.next_input_byte = (JOCTET*)input; cinfo.src = &jsrc; jsrc.init_source = init_source; jsrc.fill_input_buffer = fill_input_buffer; jsrc.skip_input_data = skip_input_data; jsrc.resync_to_restart = jpeg_resync_to_restart; jsrc.term_source = term_source; // Decodes JPG input from whatever source // Does everything AFTER jpeg_create_decompress // and BEFORE jpeg_destroy_decompress // Caller is responsible for arranging these + setting up cinfo // read file parameters with jpeg_read_header() jpeg_read_header(&cinfo, TRUE); bool useCMYK=false; if (cinfo.jpeg_color_space==JCS_CMYK) { cinfo.out_color_space=JCS_CMYK; cinfo.out_color_components=4; useCMYK=true; } else { cinfo.out_color_space=JCS_RGB; cinfo.out_color_components=3; } cinfo.output_gamma=2.2; cinfo.do_fancy_upsampling=FALSE; // Start decompressor jpeg_start_decompress(&cinfo); // Get image data u16 rowspan = cinfo.image_width * cinfo.out_color_components; u32 width = cinfo.image_width; u32 height = cinfo.image_height; // Allocate memory for buffer u8* output = new u8[rowspan * height]; // Here we use the library's state variable cinfo.output_scanline as the // loop counter, so that we don't have to keep track ourselves. // Create array of row pointers for lib rowPtr = new u8* [height]; for( u32 i = 0; i < height; i++ ) rowPtr[i] = &output[ i * rowspan ]; u32 rowsRead = 0; while( cinfo.output_scanline < cinfo.output_height ) rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead ); delete [] rowPtr; // Finish decompression jpeg_finish_decompress(&cinfo); // Release JPEG decompression object // This is an important step since it will release a good deal of memory. jpeg_destroy_decompress(&cinfo); // convert image IImage* image = 0; if (useCMYK) { image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(width, height)); const u32 size = 3*width*height; u8* data = (u8*)image->lock(); if (data) { for (u32 i=0,j=0; i<size; i+=3, j+=4) { // Also works without K, but has more contrast with K multiplied in // data[i+0] = output[j+2]; // data[i+1] = output[j+1]; // data[i+2] = output[j+0]; data[i+0] = (char)(output[j+2]*(output[j+3]/255.f)); data[i+1] = (char)(output[j+1]*(output[j+3]/255.f)); data[i+2] = (char)(output[j+0]*(output[j+3]/255.f)); } } image->unlock(); delete [] output; } else image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(width, height), output); delete [] input; return image; #endif }
static int readdctd(fz_stream *stm, unsigned char *buf, int len) { fz_dctd *state = stm->state; j_decompress_ptr cinfo = &state->cinfo; unsigned char *p = buf; unsigned char *ep = buf + len; if (setjmp(state->jb)) { if (cinfo->src) state->chain->rp = state->chain->wp - cinfo->src->bytes_in_buffer; return fz_throw("jpeg error: %s", state->msg); } if (!state->init) { cinfo->client_data = state; cinfo->err = &state->errmgr; jpeg_std_error(cinfo->err); cinfo->err->error_exit = error_exit; jpeg_create_decompress(cinfo); cinfo->src = &state->srcmgr; cinfo->src->init_source = init_source; cinfo->src->fill_input_buffer = fill_input_buffer; cinfo->src->skip_input_data = skip_input_data; cinfo->src->resync_to_restart = jpeg_resync_to_restart; cinfo->src->term_source = term_source; cinfo->src->next_input_byte = state->chain->rp; cinfo->src->bytes_in_buffer = state->chain->wp - state->chain->rp; jpeg_read_header(cinfo, 1); /* speed up jpeg decoding a bit */ cinfo->dct_method = JDCT_FASTEST; cinfo->do_fancy_upsampling = FALSE; /* default value if ColorTransform is not set */ if (state->colortransform == -1) { if (state->cinfo.num_components == 3) state->colortransform = 1; else state->colortransform = 0; } if (cinfo->saw_Adobe_marker) state->colortransform = cinfo->Adobe_transform; /* Guess the input colorspace, and set output colorspace accordingly */ switch (cinfo->num_components) { case 3: if (state->colortransform) cinfo->jpeg_color_space = JCS_YCbCr; else cinfo->jpeg_color_space = JCS_RGB; break; case 4: if (state->colortransform) cinfo->jpeg_color_space = JCS_YCCK; else cinfo->jpeg_color_space = JCS_CMYK; break; } jpeg_start_decompress(cinfo); state->stride = cinfo->output_width * cinfo->output_components; state->scanline = fz_malloc(state->stride); state->rp = state->scanline; state->wp = state->scanline; state->init = 1; } while (state->rp < state->wp && p < ep) *p++ = *state->rp++; while (p < ep) { if (cinfo->output_scanline == cinfo->output_height) break; if (p + state->stride <= ep) { jpeg_read_scanlines(cinfo, &p, 1); p += state->stride; } else { jpeg_read_scanlines(cinfo, &state->scanline, 1); state->rp = state->scanline; state->wp = state->scanline + state->stride; } while (state->rp < state->wp && p < ep) *p++ = *state->rp++; } return p - buf; }
static bool read_jpeg_image(QImage *outImage, QSize scaledSize, QRect scaledClipRect, QRect clipRect, volatile int inQuality, j_decompress_ptr info, struct my_error_mgr* err ) { if (!setjmp(err->setjmp_buffer)) { // -1 means default quality. int quality = inQuality; if (quality < 0) quality = 75; // If possible, merge the scaledClipRect into either scaledSize // or clipRect to avoid doing a separate scaled clipping pass. // Best results are achieved by clipping before scaling, not after. if (!scaledClipRect.isEmpty()) { if (scaledSize.isEmpty() && clipRect.isEmpty()) { // No clipping or scaling before final clip. clipRect = scaledClipRect; scaledClipRect = QRect(); } else if (scaledSize.isEmpty()) { // Clipping, but no scaling: combine the clip regions. scaledClipRect.translate(clipRect.topLeft()); clipRect = scaledClipRect.intersected(clipRect); scaledClipRect = QRect(); } else if (clipRect.isEmpty()) { // No clipping, but scaling: if we can map back to an // integer pixel boundary, then clip before scaling. if ((info->image_width % scaledSize.width()) == 0 && (info->image_height % scaledSize.height()) == 0) { int x = scaledClipRect.x() * info->image_width / scaledSize.width(); int y = scaledClipRect.y() * info->image_height / scaledSize.height(); int width = (scaledClipRect.right() + 1) * info->image_width / scaledSize.width() - x; int height = (scaledClipRect.bottom() + 1) * info->image_height / scaledSize.height() - y; clipRect = QRect(x, y, width, height); scaledSize = scaledClipRect.size(); scaledClipRect = QRect(); } } else { // Clipping and scaling: too difficult to figure out, // and not a likely use case, so do it the long way. } } // Determine the scale factor to pass to libjpeg for quick downscaling. if (!scaledSize.isEmpty() && info->image_width && info->image_height) { if (clipRect.isEmpty()) { double f = qMin(double(info->image_width) / scaledSize.width(), double(info->image_height) / scaledSize.height()); // libjpeg supports M/8 scaling with M=[1,16]. All downscaling factors // are a speed improvement, but upscaling during decode is slower. info->scale_num = qBound(1, qCeil(8/f), 8); info->scale_denom = 8; } else { info->scale_denom = qMin(clipRect.width() / scaledSize.width(), clipRect.height() / scaledSize.height()); // Only scale by powers of two when clipping so we can // keep the exact pixel boundaries if (info->scale_denom < 2) info->scale_denom = 1; else if (info->scale_denom < 4) info->scale_denom = 2; else if (info->scale_denom < 8) info->scale_denom = 4; else info->scale_denom = 8; info->scale_num = 1; // Correct the scale factor so that we clip accurately. // It is recommended that the clip rectangle be aligned // on an 8-pixel boundary for best performance. while (info->scale_denom > 1 && ((clipRect.x() % info->scale_denom) != 0 || (clipRect.y() % info->scale_denom) != 0 || (clipRect.width() % info->scale_denom) != 0 || (clipRect.height() % info->scale_denom) != 0)) { info->scale_denom /= 2; } } } // If high quality not required, use fast decompression if( quality < HIGH_QUALITY_THRESHOLD ) { info->dct_method = JDCT_IFAST; info->do_fancy_upsampling = false; } (void) jpeg_calc_output_dimensions(info); // Determine the clip region to extract. QRect imageRect(0, 0, info->output_width, info->output_height); QRect clip; if (clipRect.isEmpty()) { clip = imageRect; } else if (info->scale_denom == info->scale_num) { clip = clipRect.intersected(imageRect); } else { // The scale factor was corrected above to ensure that // we don't miss pixels when we scale the clip rectangle. clip = QRect(clipRect.x() / int(info->scale_denom), clipRect.y() / int(info->scale_denom), clipRect.width() / int(info->scale_denom), clipRect.height() / int(info->scale_denom)); clip = clip.intersected(imageRect); } // Allocate memory for the clipped QImage. if (!ensureValidImage(outImage, info, clip.size())) longjmp(err->setjmp_buffer, 1); // Avoid memcpy() overhead if grayscale with no clipping. bool quickGray = (info->output_components == 1 && clip == imageRect); if (!quickGray) { // Ask the jpeg library to allocate a temporary row. // The library will automatically delete it for us later. // The libjpeg docs say we should do this before calling // jpeg_start_decompress(). We can't use "new" here // because we are inside the setjmp() block and an error // in the jpeg input stream would cause a memory leak. JSAMPARRAY rows = (info->mem->alloc_sarray) ((j_common_ptr)info, JPOOL_IMAGE, info->output_width * info->output_components, 1); (void) jpeg_start_decompress(info); while (info->output_scanline < info->output_height) { int y = int(info->output_scanline) - clip.y(); if (y >= clip.height()) break; // We've read the entire clip region, so abort. (void) jpeg_read_scanlines(info, rows, 1); if (y < 0) continue; // Haven't reached the starting line yet. if (info->output_components == 3) { uchar *in = rows[0] + clip.x() * 3; QRgb *out = (QRgb*)outImage->scanLine(y); rgb888ToRgb32ConverterPtr(out, in, clip.width()); } else if (info->out_color_space == JCS_CMYK) { // Convert CMYK->RGB. uchar *in = rows[0] + clip.x() * 4; QRgb *out = (QRgb*)outImage->scanLine(y); for (int i = 0; i < clip.width(); ++i) { int k = in[3]; *out++ = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255); in += 4; } } else if (info->output_components == 1) { // Grayscale. memcpy(outImage->scanLine(y), rows[0] + clip.x(), clip.width()); } } } else { // Load unclipped grayscale data directly into the QImage. (void) jpeg_start_decompress(info); while (info->output_scanline < info->output_height) { uchar *row = outImage->scanLine(info->output_scanline); (void) jpeg_read_scanlines(info, &row, 1); } } if (info->output_scanline == info->output_height) (void) jpeg_finish_decompress(info); if (info->density_unit == 1) { outImage->setDotsPerMeterX(int(100. * info->X_density / 2.54)); outImage->setDotsPerMeterY(int(100. * info->Y_density / 2.54)); } else if (info->density_unit == 2) { outImage->setDotsPerMeterX(int(100. * info->X_density)); outImage->setDotsPerMeterY(int(100. * info->Y_density)); } if (scaledSize.isValid() && scaledSize != clip.size()) { *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, quality >= HIGH_QUALITY_THRESHOLD ? Qt::SmoothTransformation : Qt::FastTransformation); } if (!scaledClipRect.isEmpty()) *outImage = outImage->copy(scaledClipRect); return !outImage->isNull(); } else return false; }
static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int flags) { JSAMPARRAY row_pointer; JSAMPLE * buffer = NULL; int row_stride; int x, y, depth, r, g, b, k; struct ImBuf * ibuf = NULL; uchar * rect; jpeg_saved_marker_ptr marker; char *str, *key, *value; /* install own app1 handler */ ibuf_ftype = 0; jpeg_set_marker_processor(cinfo, 0xe1, handle_app1); cinfo->dct_method = JDCT_FLOAT; jpeg_save_markers(cinfo, JPEG_COM, 0xffff); if (jpeg_read_header(cinfo, FALSE) == JPEG_HEADER_OK) { x = cinfo->image_width; y = cinfo->image_height; depth = cinfo->num_components; if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space = JCS_CMYK; jpeg_start_decompress(cinfo); if (ibuf_ftype == 0) { ibuf_ftype = JPG_STD; if (cinfo->max_v_samp_factor == 1) { if (cinfo->max_h_samp_factor == 1) ibuf_ftype = JPG_MAX; else ibuf_ftype = JPG_VID; } } if (flags & IB_test) { jpeg_abort_decompress(cinfo); ibuf = IMB_allocImBuf(x, y, 8 * depth, 0); } else if ((ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect)) == NULL) { jpeg_abort_decompress(cinfo); } else { row_stride = cinfo->output_width * depth; row_pointer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1); for (y = ibuf->y - 1; y >= 0; y--) { jpeg_read_scanlines(cinfo, row_pointer, 1); rect = (uchar *) (ibuf->rect + y * ibuf->x); buffer = row_pointer[0]; switch(depth) { case 1: for (x=ibuf->x; x >0; x--) { rect[3] = 255; rect[0] = rect[1] = rect[2] = *buffer++; rect += 4; } break; case 3: for (x=ibuf->x; x >0; x--) { rect[3] = 255; rect[0] = *buffer++; rect[1] = *buffer++; rect[2] = *buffer++; rect += 4; } break; case 4: for (x=ibuf->x; x >0; x--) { r = *buffer++; g = *buffer++; b = *buffer++; k = *buffer++; k = 255 - k; r -= k; if (r & 0xffffff00) { if (r < 0) r = 0; else r = 255; } g -= k; if (g & 0xffffff00) { if (g < 0) g = 0; else g = 255; } b -= k; if (b & 0xffffff00) { if (b < 0) b = 0; else b = 255; } rect[3] = 255 - k; rect[2] = b; rect[1] = g; rect[0] = r; rect += 4; } } } marker= cinfo->marker_list; while(marker) { if(marker->marker != JPEG_COM) goto next_stamp_marker; /* * Because JPEG format don't support the * pair "key/value" like PNG, we store the * stampinfo in a single "encode" string: * "Blender:key:value" * * That is why we need split it to the * common key/value here. */ if(strncmp((char *) marker->data, "Blender", 7)) { /* * Maybe the file have text that * we don't know "what it's", in that * case we keep the text (with a * key "None"). * This is only for don't "lose" * the information when we write * it back to disk. */ IMB_metadata_add_field(ibuf, "None", (char *) marker->data); ibuf->flags |= IB_metadata; goto next_stamp_marker; } str = BLI_strdup ((char *) marker->data); key = strchr (str, ':'); /* * A little paranoid, but the file maybe * is broken... and a "extra" check is better * that a segfaul ;) */ if (!key) { MEM_freeN(str); goto next_stamp_marker; } key++; value = strchr (key, ':'); if (!value) { MEM_freeN(str); goto next_stamp_marker; } *value = '\0'; /* need finish the key string */ value++; IMB_metadata_add_field(ibuf, key, value); ibuf->flags |= IB_metadata; MEM_freeN(str); next_stamp_marker: marker= marker->next; } jpeg_finish_decompress(cinfo); } jpeg_destroy((j_common_ptr) cinfo); if(ibuf) { ibuf->ftype = ibuf_ftype; ibuf->profile = IB_PROFILE_SRGB; } } return(ibuf); }
int read_jpeg(const char *filename, int *width, int *height, unsigned char **rgb) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; unsigned char *ptr = NULL; unsigned int i, ipos; FILE *infile = fopen(filename, "rb"); cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); *width = cinfo.output_width; *height = cinfo.output_height; rgb[0] = malloc(3 * cinfo.output_width * cinfo.output_height); if (rgb[0] == NULL) { fprintf(stderr, "Can't allocate memory for JPEG file.\n"); return(0); } if (cinfo.output_components == 3) { ptr = rgb[0]; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, &ptr, 1); ptr += 3 * cinfo.output_width; } } else if (cinfo.output_components == 1) { ptr = malloc(cinfo.output_width); if (ptr == NULL) { fprintf(stderr, "Can't allocate memory for JPEG file.\n"); return(0); } ipos = 0; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, &ptr, 1); for (i = 0; i < cinfo.output_width; i++) { memset(rgb[0] + ipos, ptr[i], 3); ipos += 3; } } free(ptr); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return(1); }
/* * Magical JPEG loader. You probably shouldn't edit this. */ int loadTextureFromJPEG(char* filename, TextureInfo *info) { //Gonna need a file pointer. FILE *fd; //Init the structs required by libjpeg struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; //This will keep track of where we are in the file unsigned char * line; //Redirect stderr so things aren't messy cinfo.err = jpeg_std_error(&jerr); //Init the decompress struct jpeg_create_decompress(&cinfo); //Try to open the file. Better code would return an error value, //but I'm just making it exit instead. if (0 == (fd = fopen(filename, "rb"))) { printf("Error opening file"); exit(1); } //Self evident. info->filename = filename; //Point libjpeg at the file jpeg_stdio_src(&cinfo, fd); //Read in the JPEG header jpeg_read_header(&cinfo, TRUE); //Used to keep track of offset in 1-D pixel array unsigned int size = cinfo.image_width; //Populate the texture-info struct. //If it's not GL_RGB, then you have a really strange JPEG. info->height = cinfo.image_height; info->width = cinfo.image_width; info->format = GL_RGB; //If your JPEG somehow has alpha, you're gonna have a bad time. info->hasAlpha = false; //Assign an array for pixels unsigned char* image = (unsigned char*) malloc(sizeof(char) * 3 * cinfo.image_height * cinfo.image_width); //Begin magic. jpeg_start_decompress(&cinfo); while (cinfo.output_scanline < cinfo.output_height) { line = image + (3 * size) * cinfo.output_scanline; jpeg_read_scanlines(&cinfo, &line, 1); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); //Allocate an array for the pixels. Why two? You'll see. info->textureData = (unsigned char*) malloc(sizeof(char) * 3 * cinfo.image_height * cinfo.image_width); //Copy the pixels from image to textureData in reverse row order. Because GL. for(int y = info->height-1; y >= 0; y--){ for(int x = 0; x < info->width*3; x++){ info->textureData[(info->height-y-1)*(info->width*3)+x] = image[y*info->width*3+x]; } } free(image); return 0; }
RImage *RLoadJPEG(RContext * context, const char *file_name) { RImage *image = NULL; struct jpeg_decompress_struct cinfo; int i; unsigned char *ptr; JSAMPROW buffer[1], bptr; FILE *file; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; file = fopen(file_name, "rb"); if (!file) { RErrorCode = RERR_OPEN; return NULL; } cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress(&cinfo); fclose(file); return NULL; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, file); jpeg_read_header(&cinfo, TRUE); if (cinfo.image_width < 1 || cinfo.image_height < 1) { RErrorCode = RERR_BADIMAGEFILE; goto bye; } bptr = buffer[0] = (JSAMPROW) malloc(cinfo.image_width * cinfo.num_components); if (!buffer[0]) { RErrorCode = RERR_NOMEMORY; goto bye; } if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { cinfo.out_color_space = JCS_GRAYSCALE; } else cinfo.out_color_space = JCS_RGB; cinfo.quantize_colors = FALSE; cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_calc_output_dimensions(&cinfo); if (context->flags.optimize_for_speed) image = RCreateImage(cinfo.image_width, cinfo.image_height, True); else image = RCreateImage(cinfo.image_width, cinfo.image_height, False); if (!image) { RErrorCode = RERR_NOMEMORY; goto bye; } jpeg_start_decompress(&cinfo); ptr = image->data; if (cinfo.out_color_space == JCS_RGB) { if (context->flags.optimize_for_speed) { while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1); bptr = buffer[0]; for (i = 0; i < cinfo.image_width; i++) { *ptr++ = *bptr++; *ptr++ = *bptr++; *ptr++ = *bptr++; ptr++; /* skip alpha channel */ } } } else { while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1); bptr = buffer[0]; memcpy(ptr, bptr, cinfo.image_width * 3); ptr += cinfo.image_width * 3; } } } else { while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1); bptr = buffer[0]; for (i = 0; i < cinfo.image_width; i++) { *ptr++ = *bptr; *ptr++ = *bptr; *ptr++ = *bptr++; } } } jpeg_finish_decompress(&cinfo); bye: jpeg_destroy_decompress(&cinfo); fclose(file); if (buffer[0]) free(buffer[0]); return image; }
bool decode(const Vector<char>& data, bool sizeOnly) { m_decodingSizeOnly = sizeOnly; unsigned newByteCount = data.size() - m_bufferLength; unsigned readOffset = m_bufferLength - m_info.src->bytes_in_buffer; m_info.src->bytes_in_buffer += newByteCount; m_info.src->next_input_byte = (JOCTET*)(data.data()) + readOffset; // If we still have bytes to skip, try to skip those now. if (m_bytesToSkip) skipBytes(m_bytesToSkip); m_bufferLength = data.size(); // We need to do the setjmp here. Otherwise bad things will happen if (setjmp(m_err.setjmp_buffer)) { m_state = JPEG_SINK_NON_JPEG_TRAILER; close(); return false; } switch (m_state) { case JPEG_HEADER: { /* Read file parameters with jpeg_read_header() */ if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) return true; /* I/O suspension */ /* let libjpeg take care of gray->RGB and YCbCr->RGB conversions */ switch (m_info.jpeg_color_space) { case JCS_GRAYSCALE: case JCS_RGB: case JCS_YCbCr: m_info.out_color_space = JCS_RGB; break; case JCS_CMYK: case JCS_YCCK: default: m_state = JPEG_ERROR; return false; } /* * Don't allocate a giant and superfluous memory buffer * when the image is a sequential JPEG. */ m_info.buffered_image = jpeg_has_multiple_scans(&m_info); /* Used to set up image size so arrays can be allocated */ jpeg_calc_output_dimensions(&m_info); /* * Make a one-row-high sample array that will go away * when done with image. Always make it big enough to * hold an RGB row. Since this uses the IJG memory * manager, it must be allocated before the call to * jpeg_start_compress(). */ int row_stride = m_info.output_width * 4; // RGBA buffer m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info, JPOOL_IMAGE, row_stride, 1); m_state = JPEG_START_DECOMPRESS; // We can fill in the size now that the header is available. if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) { m_state = JPEG_ERROR; return false; } if (m_decodingSizeOnly) { // We can stop here. // Reduce our buffer length and available data. m_bufferLength -= m_info.src->bytes_in_buffer; m_info.src->bytes_in_buffer = 0; return true; } } case JPEG_START_DECOMPRESS: { /* Set parameters for decompression */ /* FIXME -- Should reset dct_method and dither mode * for final pass of progressive JPEG */ m_info.dct_method = JDCT_ISLOW; m_info.dither_mode = JDITHER_FS; m_info.do_fancy_upsampling = true; m_info.enable_2pass_quant = false; m_info.do_block_smoothing = true; /* Start decompressor */ if (!jpeg_start_decompress(&m_info)) return true; /* I/O suspension */ /* If this is a progressive JPEG ... */ m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; } case JPEG_DECOMPRESS_SEQUENTIAL: { if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) { if (!m_decoder->outputScanlines()) return true; /* I/O suspension */ /* If we've completed image output ... */ assert(m_info.output_scanline == m_info.output_height); m_state = JPEG_DONE; } } case JPEG_DECOMPRESS_PROGRESSIVE: { if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { int status; do { status = jpeg_consume_input(&m_info); } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI)); for (;;) { if (m_info.output_scanline == 0) { int scan = m_info.input_scan_number; /* if we haven't displayed anything yet (output_scan_number==0) and we have enough data for a complete scan, force output of the last full scan */ if ((m_info.output_scan_number == 0) && (scan > 1) && (status != JPEG_REACHED_EOI)) scan--; if (!jpeg_start_output(&m_info, scan)) return true; /* I/O suspension */ } if (m_info.output_scanline == 0xffffff) m_info.output_scanline = 0; if (!m_decoder->outputScanlines()) { if (m_info.output_scanline == 0) /* didn't manage to read any lines - flag so we don't call jpeg_start_output() multiple times for the same scan */ m_info.output_scanline = 0xffffff; return true; /* I/O suspension */ } if (m_info.output_scanline == m_info.output_height) { if (!jpeg_finish_output(&m_info)) return true; /* I/O suspension */ if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number)) break; m_info.output_scanline = 0; } } m_state = JPEG_DONE; } } case JPEG_DONE: { /* Finish decompression */ if (!jpeg_finish_decompress(&m_info)) return true; /* I/O suspension */ m_state = JPEG_SINK_NON_JPEG_TRAILER; /* we're done */ break; } case JPEG_SINK_NON_JPEG_TRAILER: break; case JPEG_ERROR: break; } return true; }
static Status jpg_decode_impl(rpU8 data, size_t size, jpeg_decompress_struct* cinfo, Tex* t) { src_prepare(cinfo, data, size); // ignore return value since: // - suspension is not possible with the mem data source // - we passed TRUE to raise an error if table-only JPEG file (void)jpeg_read_header(cinfo, TRUE); // set libjpg output format. we cannot go with the default because // Photoshop writes non-standard CMYK files that must be converted to RGB. size_t flags = 0; cinfo->out_color_space = JCS_RGB; if(cinfo->num_components == 1) { flags |= TEX_GREY; cinfo->out_color_space = JCS_GRAYSCALE; } // lower quality, but faster cinfo->dct_method = JDCT_IFAST; cinfo->do_fancy_upsampling = FALSE; // ignore return value since suspension is not possible with the // mem data source. // note: since we've set out_color_space, JPEG will always // return an acceptable image format; no need to check. (void)jpeg_start_decompress(cinfo); // scaled output image dimensions and final bpp are now available. int w = cinfo->output_width; int h = cinfo->output_height; int bpp = cinfo->output_components * 8; // alloc destination buffer const size_t pitch = w * bpp / 8; const size_t imgSize = pitch * h; // for allow_rows shared_ptr<u8> img; AllocateAligned(img, imgSize, pageSize); // read rows std::vector<RowPtr> rows = tex_codec_alloc_rows(img.get(), h, pitch, TEX_TOP_DOWN, 0); // could use cinfo->output_scanline to keep track of progress, // but we need to count lines_left anyway (paranoia). JSAMPARRAY row = (JSAMPARRAY)&rows[0]; JDIMENSION lines_left = h; while(lines_left != 0) { JDIMENSION lines_read = jpeg_read_scanlines(cinfo, row, lines_left); row += lines_read; lines_left -= lines_read; // we've decoded in-place; no need to further process } // ignore return value since suspension is not possible with the // mem data source. (void)jpeg_finish_decompress(cinfo); Status ret = INFO::OK; if(cinfo->err->num_warnings != 0) ret = WARN::TEX_INVALID_DATA; // store image info and validate return ret | t->wrap(w,h,bpp,flags,img,0); }
void HILL_read_jpeg( HILL_input_stream i, struct HILL_image_data *img ) { unsigned width, height; enum HILL_pixel_format fmt; unsigned y; size_t bytes_per_row=0; size_t bytes=0; struct jpeg_decompression_data jpeg; struct jpeg_error_mgr jerr; struct jpeg_source_mgr jsrc; jpeg.i=i; if(setjmp(jpeg.env))/*Could not read the image*/ { jpeg_destroy_decompress(&jpeg.cinfo); return; } /*Set the jpeg structures*/ jpeg_std_error(&jerr); jerr.error_exit=read_jpeg_error_exit; jpeg.cinfo.err=&jerr; jpeg.cinfo.client_data=&jpeg; jpeg_create_decompress(&jpeg.cinfo); jsrc.init_source=read_jpeg_init_source; jsrc.fill_input_buffer=read_jpeg_fill_input_buffer; jsrc.skip_input_data=read_jpeg_skip_input_data; jsrc.resync_to_restart=jpeg_resync_to_restart; jsrc.term_source=read_jpeg_term_source; jpeg.cinfo.src=&jsrc; /*Check the file header*/ if(jpeg_read_header(&jpeg.cinfo, TRUE)!=JPEG_HEADER_OK) { img->err=HILL_IMAGE_NOT_SUPPORTED;/*Not a JPEG image*/ longjmp(jpeg.env, 2);/*since we have this construct, why not use it?*/ } img->err=HILL_IMAGE_CORRUPTED;/*Assume the image is corrupted until done*/ /*Get the pixel format*/ switch(jpeg.cinfo.jpeg_color_space) { case JCS_GRAYSCALE: jpeg.cinfo.out_color_space=JCS_GRAYSCALE; fmt=HILL_BW8; break; case JCS_EXT_RGBA: fmt=HILL_RGBA8; jpeg.cinfo.out_color_space=JCS_EXT_RGBA; break; case JCS_RGB: fmt=HILL_RGB8; jpeg.cinfo.out_color_space=JCS_RGB; break; default: /*probably YUV or CMYK, translate it please*/ fmt=HILL_RGB8; jpeg.cinfo.out_color_space=JCS_RGB; } if(jpeg_start_decompress(&jpeg.cinfo)==0) {/*Image is corrupted*/ longjmp(jpeg.env, 3); } width=jpeg.cinfo.output_width; height=jpeg.cinfo.output_height; /*============= *READ THE JPEG *=============*/ bytes_per_row=(width*HILL_get_pixel_format_bits(fmt))/8; bytes=height*bytes_per_row; img->w=width; img->h=height; img->fmt=fmt; img->data=malloc(bytes); for(y=0; y < height; ) { uint8_t *scanline=(uint8_t*)img->data+y*bytes_per_row; y+=jpeg_read_scanlines(&jpeg.cinfo, ((JSAMPARRAY)&(scanline)), 1); } jpeg_finish_decompress(&jpeg.cinfo); jpeg_destroy_decompress(&jpeg.cinfo); img->err=HILL_IMAGE_NO_ERROR; }
int main(int argc, char **argv) { JSAMPARRAY buf = malloc(sizeof(JSAMPROW)*BUF_LINES); jpeg_saved_marker_ptr exif_marker, cmarker; MD5_CTX *MD5 = malloc(sizeof(MD5_CTX)); volatile int i; int c,j,lines_read, err_count; unsigned char ch; char namebuf[1024]; long fs; unsigned char *md5buf,digest[16]; char digest_text[33]; global_total_errors=0; if (rcsid); /* to keep compiler from not complaining about rcsid */ cinfo.err = jpeg_std_error(&jerr.pub); jpeg_create_decompress(&cinfo); jerr.pub.error_exit=my_error_exit; jerr.pub.output_message=my_output_message; if (!buf || !MD5) no_memory(); if (argc<2) { if (quiet_mode < 2) fprintf(stderr,"jpeginfo: file arguments missing\n" "Try 'jpeginfo " "--help" "' for more information.\n"); exit(1); } /* parse command line parameters */ while(1) { opt_index=0; if ( (c=getopt_long(argc,argv,"livVdcChqm:f:5", long_options,&opt_index)) == -1) break; switch (c) { case 'm': if (!strcasecmp(optarg,"all")) del_mode=0; else if (!strcasecmp(optarg,"erronly")) del_mode=1; else if (!quiet_mode) fprintf(stderr,"Unknown parameter for -m, --mode.\n"); break; case 'f': if (!strcmp(optarg,"-")) listfile=stdin; else if ((listfile=fopen(optarg,"r"))==NULL) { fprintf(stderr,"Cannot open file '%s'.\n",optarg); exit(2); } input_from_file=1; break; case 'v': verbose_mode=1; break; case 'V': fprintf(stderr,"jpeginfo v" VERSION " " HOST_TYPE "\nCopyright (c) Timo Kokkonen, 1995-2002.\n"); exit(0); case 'd': delete_mode=1; break; case 'c': check_mode=1; break; case 'h': p_usage(); break; case 'q': quiet_mode++; break; case 'l': list_mode=1; break; case 'i': longinfo_mode=1; break; case '5': md5_mode=1; break; case 'C': com_mode=1; break; case '?': break; default: if (!quiet_mode) fprintf(stderr,"jpeginfo: error parsing parameters.\n"); } } if (delete_mode && verbose_mode && !quiet_mode) fprintf(stderr,"jpeginfo: delete mode enabled (%s)\n", !del_mode?"normal":"errors only"); i=1; do { if (input_from_file) { if (!fgetstr(namebuf,sizeof(namebuf),listfile)) break; current=namebuf; } else current=argv[i]; if (current[0]==0) continue; if (current[0]=='-' && !input_from_file) continue; if (setjmp(jerr.setjmp_buffer)) { jpeg_abort_decompress(&cinfo); fclose(infile); if (list_mode && quiet_mode < 2) printf(" %s",current); if (quiet_mode < 2) printf(" [ERROR]\n"); if (delete_mode) delete_file(current,verbose_mode,quiet_mode); continue; } if ((infile=fopen(current,"r"))==NULL) { if (!quiet_mode) fprintf(stderr, "jpeginfo: can't open '%s'\n", current); continue; } if (is_dir(infile)) { fclose(infile); if (verbose_mode) printf("directory: %s skipped\n",current); continue; } fs=filesize(infile); if (md5_mode) { md5buf=malloc(fs); if (!md5buf) no_memory(); fread(md5buf,1,fs,infile); rewind(infile); MD5Init(MD5); MD5Update(MD5,md5buf,fs); MD5Final(digest,MD5); md2str(digest,digest_text); free(md5buf); } if (!list_mode && quiet_mode < 2) printf("%s ",current); global_error_counter=0; err_count=jerr.pub.num_warnings; if (com_mode) jpeg_save_markers(&cinfo, JPEG_COM, 0xffff); jpeg_save_markers(&cinfo, EXIF_JPEG_MARKER, 0xffff); jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); /* check for Exif marker */ exif_marker=NULL; cmarker=cinfo.marker_list; while (cmarker) { if (cmarker->marker == EXIF_JPEG_MARKER) { if (!memcmp(cmarker->data,EXIF_IDENT_STRING,6)) exif_marker=cmarker; } cmarker=cmarker->next; } if (quiet_mode < 2) { printf("%4d x %-4d %2dbit ",(int)cinfo.image_width, (int)cinfo.image_height,(int)cinfo.num_components*8); if (exif_marker) printf("Exif "); else if (cinfo.saw_JFIF_marker) printf("JFIF "); else if (cinfo.saw_Adobe_marker) printf("Adobe "); else printf("n/a "); if (longinfo_mode) { printf("%s %s",(cinfo.progressive_mode?"Progressive":"Normal"), (cinfo.arith_code?"Arithmetic":"Huffman") ); if (cinfo.density_unit==1||cinfo.density_unit==2) printf(",%ddp%c",MIN(cinfo.X_density,cinfo.Y_density), (cinfo.density_unit==1?'i':'c') ); if (cinfo.CCIR601_sampling) printf(",CCIR601"); printf(" %7ld ",fs); } else printf("%c %7ld ",(cinfo.progressive_mode?'P':'N'),fs); if (md5_mode) printf("%s ",digest_text); if (list_mode) printf("%s ",current); if (com_mode) { cmarker=cinfo.marker_list; while (cmarker) { if (cmarker->marker == JPEG_COM) { printf("\""); for (j=0;j<cmarker->data_length;j++) { ch = cmarker->data[j]; if (ch < 32 || iscntrl(ch)) continue; printf("%c",cmarker->data[j]); } printf("\" "); } cmarker=cmarker->next; } } } if (check_mode) { cinfo.out_color_space=JCS_GRAYSCALE; /* to speed up the process... */ cinfo.scale_denom = 8; cinfo.scale_num = 1; jpeg_start_decompress(&cinfo); for (j=0;j<BUF_LINES;j++) { buf[j]=malloc(sizeof(JSAMPLE)*cinfo.output_width* cinfo.out_color_components); if (!buf[j]) no_memory(); } while (cinfo.output_scanline < cinfo.output_height) { lines_read = jpeg_read_scanlines(&cinfo, buf,BUF_LINES); } jpeg_finish_decompress(&cinfo); for(j=0;j<BUF_LINES;j++) free(buf[j]); if (!global_error_counter) { if (quiet_mode < 2) printf(" [OK]\n"); } else { if (quiet_mode < 2) printf(" [WARNING]\n"); if (delete_mode && !del_mode) delete_file(current,verbose_mode,quiet_mode); } } else { /* !check_mode */ if (quiet_mode < 2) printf("\n"); jpeg_abort_decompress(&cinfo); } fclose(infile); } while (++i<argc || input_from_file); jpeg_destroy_decompress(&cinfo); free(buf); free(MD5); return (global_total_errors>0?1:0); /* return 1 if any errors found file(s) we checked */ }
UInt64 JPGImageFileType::restoreData( ImagePtr &OSG_JPG_ARG(image ), const UChar8 *OSG_JPG_ARG(buffer ), Int32 OSG_JPG_ARG(memSize)) { #ifdef OSG_WITH_JPG UInt64 retCode = 0; struct local_error_mgr { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; }; unsigned char *destData; Image::PixelFormat pixelFormat = osg::Image::OSG_INVALID_PF; unsigned long imageSize; typedef struct local_error_mgr *local_error_ptr; struct local_error_mgr jerr; struct jpeg_decompress_struct cinfo; JSAMPARRAY imagebuffer; int row_stride; cinfo.err = jpeg_std_error(&jerr.pub); if(setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return 0; } jpeg_create_decompress(&cinfo); jpeg_memory_src(&cinfo, buffer, memSize); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); switch(cinfo.output_components) { case 1: pixelFormat = Image::OSG_L_PF; break; case 2: pixelFormat = Image::OSG_LA_PF; break; case 3: pixelFormat = Image::OSG_RGB_PF; break; case 4: pixelFormat = Image::OSG_RGBA_PF; break; }; if(image->set(pixelFormat, cinfo.output_width, cinfo.output_height)) { imageSize = image->getSize(); destData = image->editData() + imageSize; row_stride = cinfo.output_width * cinfo.output_components; imagebuffer = (*cinfo.mem->alloc_sarray) (reinterpret_cast<j_common_ptr>(&cinfo), JPOOL_IMAGE, row_stride, 1); while(cinfo.output_scanline < cinfo.output_height) { destData -= row_stride; jpeg_read_scanlines(&cinfo, imagebuffer, 1); memcpy(destData, *imagebuffer, row_stride); } retCode = imageSize; } else retCode = 0; jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return retCode; #else SWARNING << getMimeType() << " read is not compiled into the current binary " << std::endl; return 0; #endif }
/*! Tries to fill the image object with the data read from the given input stream. Returns true on success. */ bool JPGImageFileType::read(ImagePtr &OSG_JPG_ARG(image), std::istream &OSG_JPG_ARG(is), const std::string &OSG_JPG_ARG(mimetype)) { #ifdef OSG_WITH_JPG struct osg_jpeg_error_mgr jerr; struct jpeg_decompress_struct cinfo; cinfo.err = jpeg_std_error(&jerr.pub); if (setjmp(jerr.setjmp_buffer)) return false; cinfo.err->error_exit = osg_jpeg_error_exit; cinfo.err->output_message = osg_jpeg_output_message; jpeg_create_decompress(&cinfo); SourceManager *sourceManager = new ((*cinfo.mem->alloc_small)(reinterpret_cast<j_common_ptr>(&cinfo), JPOOL_IMAGE, sizeof(SourceManager))) SourceManager(&cinfo, is); cinfo.src = reinterpret_cast<jpeg_source_mgr*>(sourceManager); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); Image::PixelFormat pixelFormat; switch (cinfo.output_components) { case 1: pixelFormat = Image::OSG_L_PF; break; case 3: pixelFormat = Image::OSG_RGB_PF; break; default: pixelFormat = Image::OSG_INVALID_PF; break; }; bool retCode; if (image->set(pixelFormat, cinfo.output_width, cinfo.output_height) == true) { Real32 res_x = Real32(cinfo.X_density); Real32 res_y = Real32(cinfo.Y_density); UInt16 res_unit = UInt16(cinfo.density_unit); if(res_unit == 2) // centimeter { // convert dpcm to dpi. res_x *= 2.54f; res_y *= 2.54f; res_unit = Image::OSG_RESUNIT_INCH; } image->setResX(res_x); image->setResY(res_y); image->setResUnit(res_unit); unsigned char *destData = image->editData() + image->getSize(); int row_stride = cinfo.output_width * cinfo.output_components; while (cinfo.output_scanline < cinfo.output_height) { destData -= row_stride; jpeg_read_scanlines(&cinfo, &destData, 1); } retCode = true; } else retCode = false; jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return retCode; #else SWARNING << getMimeType() << " read is not compiled into the current binary " << std::endl; return false; #endif }
bool JPEG::Decode (Resource *resource, ImageBuffer* imageBuffer) { struct jpeg_decompress_struct cinfo; //struct jpeg_error_mgr jerr; //cinfo.err = jpeg_std_error (&jerr); struct ErrorData jpegError; cinfo.err = jpeg_std_error (&jpegError.base); jpegError.base.error_exit = OnError; jpegError.base.output_message = OnOutput; FILE_HANDLE *file = NULL; if (setjmp (jpegError.on_error)) { if (file) { lime::fclose (file); } jpeg_destroy_decompress (&cinfo); return false; } jpeg_create_decompress (&cinfo); if (resource->path) { file = lime::fopen (resource->path, "rb"); if (file->isFile ()) { jpeg_stdio_src (&cinfo, file->getFile ()); } else { ByteArray data = ByteArray::FromFile (resource->path); MySrcManager manager (data.Bytes (), data.Size ()); cinfo.src = &manager.pub; } } else { MySrcManager manager (resource->data->Bytes (), resource->data->Size ()); cinfo.src = &manager.pub; } bool decoded = false; if (jpeg_read_header (&cinfo, TRUE) == JPEG_HEADER_OK) { cinfo.out_color_space = JCS_RGB; jpeg_start_decompress (&cinfo); int components = cinfo.num_components; imageBuffer->Resize (cinfo.output_width, cinfo.output_height); unsigned char *bytes = imageBuffer->data->Bytes (); unsigned char *scanline = new unsigned char [imageBuffer->width * imageBuffer->height * components]; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines (&cinfo, &scanline, 1); // convert 24-bit scanline to 32-bit const unsigned char *line = scanline; const unsigned char *const end = line + imageBuffer->width * components; while (line != end) { *bytes++ = *line++; *bytes++ = *line++; *bytes++ = *line++; *bytes++ = 0xFF; } } delete[] scanline; jpeg_finish_decompress (&cinfo); decoded = true; } if (file) { lime::fclose (file); } jpeg_destroy_decompress (&cinfo); return decoded; }
int loadJPG(ePtr<gPixmap> &result, const char *filename, ePtr<gPixmap> alpha) { struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile; JSAMPARRAY buffer; int row_stride; infile = fopen(filename, "rb"); result = 0; if (alpha) { if (alpha->surface->bpp != 8) { eWarning("alpha channel for jpg must be 8bit"); alpha = 0; } } if (!infile) return -1; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { result = 0; jpeg_destroy_decompress(&cinfo); fclose(infile); return -1; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, infile); (void) jpeg_read_header(&cinfo, TRUE); cinfo.out_color_space = JCS_RGB; cinfo.scale_denom = 1; (void) jpeg_start_decompress(&cinfo); int grayscale = cinfo.output_components == 1; if (alpha) { if (((int)cinfo.output_width != alpha->surface->x) || ((int)cinfo.output_height != alpha->surface->y)) { eWarning("alpha channel size (%dx%d) must match jpeg size (%dx%d)", alpha->surface->x, alpha->surface->y, cinfo.output_width, cinfo.output_height); alpha = 0; } if (grayscale) { eWarning("we don't support grayscale + alpha at the moment"); alpha = 0; } } result = new gPixmap(eSize(cinfo.output_width, cinfo.output_height), grayscale ? 8 : 32); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); while (cinfo.output_scanline < cinfo.output_height) { int y = cinfo.output_scanline; (void) jpeg_read_scanlines(&cinfo, buffer, 1); unsigned char *dst = ((unsigned char*)result->surface->data) + result->surface->stride * y; unsigned char *src = (unsigned char*)buffer[0]; unsigned char *palpha = alpha ? ((unsigned char*)alpha->surface->data + alpha->surface->stride * y) : 0; if (grayscale) memcpy(dst, src, cinfo.output_width); else { int x; for (x = 0; x < (int)cinfo.output_width; ++x) { *dst++ = src[2]; *dst++ = src[1]; *dst++ = src[0]; src += 3; if (palpha) *dst++ = *palpha++; else *dst++ = 0xFF; } } } (void) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(infile); return 0; }
DLLEXPORT int DLLCALL tjDecompress(tjhandle h, unsigned char *srcbuf, unsigned long size, unsigned char *dstbuf, int width, int pitch, int height, int ps, int flags) { int i, row, retval=0; JSAMPROW *row_pointer=NULL, *outbuf[MAX_COMPONENTS]; int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS], tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; JSAMPLE *_tmpbuf=NULL; JSAMPROW *tmpbuf[MAX_COMPONENTS]; checkhandle(h); for(i=0; i<MAX_COMPONENTS; i++) { tmpbuf[i]=NULL; outbuf[i]=NULL; } if(srcbuf==NULL || size<=0 || dstbuf==NULL || width<=0 || pitch<0 || height<=0) _throw("Invalid argument in tjDecompress()"); if(ps!=3 && ps!=4 && ps!=1) _throw("This decompressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale output"); if(!j->initd) _throw("Instance has not been initialized for decompression"); if(pitch==0) pitch=width*ps; if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1"); else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); if(setjmp(j->jerr.jb)) { // this will execute if LIBJPEG has an error retval=-1; goto bailout; } j->jsms.bytes_in_buffer = size; j->jsms.next_input_byte = srcbuf; jpeg_read_header(&j->dinfo, TRUE); if(flags&TJ_YUV) { j_decompress_ptr dinfo=&j->dinfo; JSAMPLE *ptr=dstbuf; for(i=0; i<dinfo->num_components; i++) { jpeg_component_info *compptr=&dinfo->comp_info[i]; int ih; iw[i]=compptr->width_in_blocks*DCTSIZE; ih=compptr->height_in_blocks*DCTSIZE; cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor) *compptr->h_samp_factor/dinfo->max_h_samp_factor; ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor) *compptr->v_samp_factor/dinfo->max_v_samp_factor; if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1; th[i]=compptr->v_samp_factor*DCTSIZE; tmpbufsize+=iw[i]*th[i]; if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL) _throw("Memory allocation failed in tjDecompress()"); for(row=0; row<ch[i]; row++) { outbuf[i][row]=ptr; ptr+=PAD(cw[i], 4); } } if(usetmpbuf) { if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL) _throw("Memory allocation failed in tjDecompress()"); ptr=_tmpbuf; for(i=0; i<dinfo->num_components; i++) { if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) _throw("Memory allocation failed in tjDecompress()"); for(row=0; row<th[i]; row++) { tmpbuf[i][row]=ptr; ptr+=iw[i]; } } } } else { if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL) _throw("Memory allocation failed in tjDecompress()"); for(i=0; i<height; i++) { if(flags&TJ_BOTTOMUP) row_pointer[i]= &dstbuf[(height-i-1)*pitch]; else row_pointer[i]= &dstbuf[i*pitch]; } } if(ps==1) j->dinfo.out_color_space = JCS_GRAYSCALE; #if JCS_EXTENSIONS==1 else j->dinfo.out_color_space = JCS_EXT_RGB; if(ps==3 && (flags&TJ_BGR)) j->dinfo.out_color_space = JCS_EXT_BGR; else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST)) j->dinfo.out_color_space = JCS_EXT_RGBX; else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST)) j->dinfo.out_color_space = JCS_EXT_BGRX; else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST)) j->dinfo.out_color_space = JCS_EXT_XBGR; else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST)) j->dinfo.out_color_space = JCS_EXT_XRGB; #else #error "TurboJPEG requires JPEG colorspace extensions" #endif if(flags&TJ_FASTUPSAMPLE) j->dinfo.do_fancy_upsampling=FALSE; if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE; jpeg_start_decompress(&j->dinfo); if(flags&TJ_YUV) { j_decompress_ptr dinfo=&j->dinfo; for(row=0; row<dinfo->output_height; row+=dinfo->max_v_samp_factor*DCTSIZE) { JSAMPARRAY yuvptr[MAX_COMPONENTS]; int crow[MAX_COMPONENTS]; for(i=0; i<dinfo->num_components; i++) { jpeg_component_info *compptr=&dinfo->comp_info[i]; crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor; if(usetmpbuf) yuvptr[i]=tmpbuf[i]; else yuvptr[i]=&outbuf[i][crow[i]]; } jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE); if(usetmpbuf) { int j; for(i=0; i<dinfo->num_components; i++) { for(j=0; j<min(th[i], ch[i]-crow[i]); j++) { memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]); } } } } } else { while(j->dinfo.output_scanline<j->dinfo.output_height) { jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline], j->dinfo.output_height-j->dinfo.output_scanline); } } jpeg_finish_decompress(&j->dinfo); bailout: if(j->dinfo.global_state>DSTATE_START) jpeg_abort_decompress(&j->dinfo); for(i=0; i<MAX_COMPONENTS; i++) { if(tmpbuf[i]) free(tmpbuf[i]); if(outbuf[i]) free(outbuf[i]); } if(_tmpbuf) free(_tmpbuf); if(row_pointer) free(row_pointer); return retval; }
int JPEG2NV21(Uint8 *yuv, Uint8 *jpegdata, int jpeglen, int sx, int sy, bool needRotation, bool cameraMirrored, int rotationDegree) { int i, y; int inlen; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; JSAMPARRAY scanline; unsigned char *wline; unsigned char *y_buffer; unsigned char *cbcr_buffer; Uint8* dst; if (needRotation || cameraMirrored) //if(rotationDegree != 0 || cameraMirrored) dst = (unsigned char*)malloc(sx*sy+2*((sx+1)/2)*((sy+1)/2)); else dst = yuv; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return 0; } jpeg_create_decompress(&cinfo); jpeg_mem_src(&cinfo, jpegdata, jpeglen); (void) jpeg_read_header(&cinfo, TRUE); //cinfo.raw_data_out = TRUE; cinfo.out_color_space = JCS_YCbCr; (void) jpeg_start_decompress(&cinfo); y_buffer = dst; cbcr_buffer = y_buffer + cinfo.output_width * cinfo.output_height; scanline = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width * cinfo.output_components, 1); wline = scanline[0]; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, scanline, (JDIMENSION)1); for (i = 0; i < cinfo.output_width; i++) y_buffer[i] = wline[i*3]; y_buffer += cinfo.output_width; if (y++ & 1) { for (int i = 0; i < cinfo.output_width; i+=2) { cbcr_buffer[i] = wline[(i*3) + 2]; // V cbcr_buffer[i + 1] = wline[(i*3) + 1]; // U } cbcr_buffer += cinfo.output_width; } } (void) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); if (needRotation || cameraMirrored) { int nRotate = 0; int flipUD = 0; if(rotationDegree == 180 || rotationDegree == 270) { cameraMirrored = !cameraMirrored; //used to support 4-side rotation flipUD = 1; //used to support 4-side rotation } if(rotationDegree == 90 || rotationDegree == 270) nRotate = 1; //used to support 4-side rotation // ToDo: not sure if it should be 'cameraMirrored, 0,' or '0, cameraMirrored,' TransformNV21(dst, yuv, sx, sy, NULL, cameraMirrored, flipUD, nRotate); free(dst); } return 1; }
/* ======================================================================================================================= * TODO: ======================================================================================================================= */ void cModelTexture::LoadJPEGOrig (char const* filename, int bitsperpixel, void* where) { struct jpeg_decompress_struct cinfo; /* * struct my_error_mgr jerr; */ FILE* infile; /* source file */ JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ struct jpeg_error_mgr pub; int y; /* jerr.boError * FALSE; * */ if ((infile = fopen (filename, "rb")) == NULL) { return ; } cinfo.err = jpeg_std_error (&pub); pub.error_exit = NULL; /* * cinfo.err = jpeg_std_error(&jerr.pub); * jerr.pub.error_exit = my_error_exit; * if (jerr.boError) { ; * jpeg_destroy_decompress(&cinfo); * fclose(infile); * return; * } */ jpeg_create_decompress (&cinfo); jpeg_stdio_src (&cinfo, infile); (void) jpeg_read_header (&cinfo, TRUE); (void) jpeg_start_decompress (&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1); y = 0; /* * cinfo.output_height-1; */ while (cinfo.output_scanline < cinfo.output_height) { unsigned char* super; (void) jpeg_read_scanlines (&cinfo, buffer, 1); super = *buffer; for (WORD x = 0; x < cinfo.output_width; x++) { unsigned char r; unsigned char g; unsigned char b; r = *super; super++; g = *super; super++; b = *super; super++; ((BYTE*) where)[(x * 3) + ((y * cinfo.output_width) * 3) + 0] = r; ((BYTE*) where)[(x * 3) + ((y * cinfo.output_width) * 3) + 1] = g; ((BYTE*) where)[(x * 3) + ((y * cinfo.output_width) * 3) + 2] = b; } y++; /* ; * */ } (void) jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); fclose (infile); }
/* * zoom out picture. the factor should between 0.5 and 1.0. It can be 0.5, but can not be 1.0. * (双线性插值算法缩小图片,缩放比例(0.5-1.0),貌似缩放后图片会有明显的模糊) */ int zoomOutJpegFile(char *inFileName, char *outFileName, float factor) { if (factor > 1 || factor < 0.5f) { printf("the zoom factor is error, should between 0.5f and 1.0f. (0.5f<=factor<1.0f)"); return -1; } // init decompress struct struct jpeg_decompress_struct in; struct jpeg_error_mgr jInErr; JSAMPROW inRowPointer[1]; FILE *inFile = fopen(inFileName, "rb"); if (!inFile) { printf("Error opening jpeg file %s\n!", inFileName); return -1; } in.err = jpeg_std_error(&jInErr); jpeg_create_decompress(&in); jpeg_stdio_src(&in, inFile); jpeg_read_header(&in, TRUE); jpeg_start_decompress(&in); // init compress struct struct jpeg_compress_struct out; struct jpeg_error_mgr jOutErr; JSAMPROW outRowPointer[1]; FILE *outFile = fopen(outFileName, "wb"); if (!outFile) { printf("Error opening file %s\n", outFileName); return -1; } out.err = jpeg_std_error( &jOutErr); jpeg_create_compress(&out); jpeg_stdio_dest(&out, outFile); int width = in.output_width; int height = in.output_height; int bytesPerPixel = in.num_components; int destWidth = (int) (width * factor); int destHeight = (int) (height * factor); out.image_width = destWidth; out.image_height = destHeight; out.input_components = bytesPerPixel; out.in_color_space = JCS_RGB; jpeg_set_defaults(&out); jpeg_start_compress(&out, TRUE); // Process RGB data. int outRowStride = destWidth * bytesPerPixel; int inRowStride = width * bytesPerPixel; outRowPointer[0] = (unsigned char *) malloc(outRowStride); inRowPointer[0] = (unsigned char *) malloc(inRowStride); JSAMPROW baseInRowPointer[1]; baseInRowPointer[0] = (unsigned char *) malloc(inRowStride); unsigned char bUpLeft, bUpRight, bDownLeft, bDownRight; unsigned char gUpLeft, gUpRight, gDownLeft, gDownRight; unsigned char rUpLeft, rUpRight, rDownLeft, rDownRight; unsigned char b, g, r; float fX, fY; int iX, iY; int i, j; int currentBaseLocation = -1; int count = 0; // Process the first line. jpeg_read_scanlines(&in, inRowPointer, 1); for (j = 0; j < destWidth; j++) { fX = ((float) j) / factor; iX = (int) fX; bUpLeft = inRowPointer[0][iX * 3 + 0]; bUpRight = inRowPointer[0][(iX + 1) * 3 + 0]; gUpLeft = inRowPointer[0][iX * 3 + 1]; gUpRight = inRowPointer[0][(iX + 1) * 3 + 1]; rUpLeft = inRowPointer[0][iX * 3 + 2]; rUpRight = inRowPointer[0][(iX + 1) * 3 + 2]; b = bUpLeft * (iX + 1 - fX) + bUpRight * (fX - iX); g = gUpLeft * (iX + 1 - fX) + gUpRight * (fX - iX); r = rUpLeft * (iX + 1 - fX) + rUpRight * (fX - iX); outRowPointer[0][j * 3 + 0] = b; outRowPointer[0][j * 3 + 1] = g; outRowPointer[0][j * 3 + 2] = r; } jpeg_write_scanlines(&out, outRowPointer, 1); currentBaseLocation = 0; // Process the other lines between the first and last. for (i = 1; i < destHeight - 1; i++) { fY = ((float) i) / factor; iY = (int) fY; if (iY == currentBaseLocation) { in.output_scanline = iY; swapJsampRow(inRowPointer[0], baseInRowPointer[0]); jpeg_read_scanlines(&in, baseInRowPointer, 1); } else { in.output_scanline = iY - 1; jpeg_read_scanlines(&in, inRowPointer, 1); jpeg_read_scanlines(&in, baseInRowPointer, 1); } currentBaseLocation = iY + 1; for (j = 0; j < destWidth; j++) { fX = ((float) j) / factor; iX = (int) fX; bUpLeft = inRowPointer[0][iX * 3 + 0]; bUpRight = inRowPointer[0][(iX + 1) * 3 + 0]; bDownLeft = baseInRowPointer[0][iX * 3 + 0]; bDownRight = baseInRowPointer[0][(iX + 1) * 3 + 0]; gUpLeft = inRowPointer[0][iX * 3 + 1]; gUpRight = inRowPointer[0][(iX + 1) * 3 + 1]; gDownLeft = baseInRowPointer[0][iX * 3 + 1]; gDownRight = baseInRowPointer[0][(iX + 1) * 3 + 1]; rUpLeft = inRowPointer[0][iX * 3 + 2]; rUpRight = inRowPointer[0][(iX + 1) * 3 + 2]; rDownLeft = baseInRowPointer[0][iX * 3 + 2]; rDownRight = baseInRowPointer[0][(iX + 1) * 3 + 2]; b = bUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + bUpRight * (fX - iX) * (iY + 1 - fY) + bDownLeft * (iX + 1 - fX) * (fY - iY) + bDownRight * (fX - iX) * (fY - iY); g = gUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + gUpRight * (fX - iX) * (iY + 1 - fY) + gDownLeft * (iX + 1 - fX) * (fY - iY) + gDownRight * (fX - iX) * (fY - iY); r = rUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + rUpRight * (fX - iX) * (iY + 1 - fY) + rDownLeft * (iX + 1 - fX) * (fY - iY) + rDownRight * (fX - iX) * (fY - iY); outRowPointer[0][j * 3 + 0] = b; outRowPointer[0][j * 3 + 1] = g; outRowPointer[0][j * 3 + 2] = r; } jpeg_write_scanlines(&out, outRowPointer, 1); } //Process the last line. in.output_scanline = height - 1; jpeg_read_scanlines(&in, inRowPointer, 1); for (j = 0; j < destWidth; j++) { fX = ((float) j) / factor; iX = (int) fX; bUpLeft = inRowPointer[0][iX * 3 + 0]; bUpRight = inRowPointer[0][(iX + 1) * 3 + 0]; gUpLeft = inRowPointer[0][iX * 3 + 1]; gUpRight = inRowPointer[0][(iX + 1) * 3 + 1]; rUpLeft = inRowPointer[0][iX * 3 + 2]; rUpRight = inRowPointer[0][(iX + 1) * 3 + 2]; b = bUpLeft * (iX + 1 - fX) + bUpRight * (fX - iX); g = gUpLeft * (iX + 1 - fX) + gUpRight * (fX - iX); r = rUpLeft * (iX + 1 - fX) + rUpRight * (fX - iX); outRowPointer[0][j * 3 + 0] = b; outRowPointer[0][j * 3 + 1] = g; outRowPointer[0][j * 3 + 2] = r; } jpeg_write_scanlines(&out, outRowPointer, 1); //free memory free(inRowPointer[0]); free(baseInRowPointer[0]); free(outRowPointer[0]); // close resource jpeg_finish_decompress(&in); jpeg_destroy_decompress(&in); fclose(inFile); jpeg_finish_compress(&out); jpeg_destroy_compress(&out); fclose(outFile); return 1; }
bool JpegDecoder::readData( Mat& img ) { bool result = false; int step = (int)img.step; bool color = img.channels() > 1; JpegState* state = (JpegState*)m_state; if( state && m_width && m_height ) { jpeg_decompress_struct* cinfo = &state->cinfo; JpegErrorMgr* jerr = &state->jerr; JSAMPARRAY buffer = 0; if( setjmp( jerr->setjmp_buffer ) == 0 ) { /* check if this is a mjpeg image format */ if ( cinfo->ac_huff_tbl_ptrs[0] == NULL && cinfo->ac_huff_tbl_ptrs[1] == NULL && cinfo->dc_huff_tbl_ptrs[0] == NULL && cinfo->dc_huff_tbl_ptrs[1] == NULL ) { /* yes, this is a mjpeg image format, so load the correct huffman table */ my_jpeg_load_dht( cinfo, my_jpeg_odml_dht, cinfo->ac_huff_tbl_ptrs, cinfo->dc_huff_tbl_ptrs ); } if( color ) { if( cinfo->num_components != 4 ) { cinfo->out_color_space = JCS_RGB; cinfo->out_color_components = 3; } else { cinfo->out_color_space = JCS_CMYK; cinfo->out_color_components = 4; } } else { if( cinfo->num_components != 4 ) { cinfo->out_color_space = JCS_GRAYSCALE; cinfo->out_color_components = 1; } else { cinfo->out_color_space = JCS_CMYK; cinfo->out_color_components = 4; } } jpeg_start_decompress( cinfo ); buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo, JPOOL_IMAGE, m_width*4, 1 ); uchar* data = img.data; for( ; m_height--; data += step ) { jpeg_read_scanlines( cinfo, buffer, 1 ); if( color ) { if( cinfo->out_color_components == 3 ) icvCvt_RGB2BGR_8u_C3R( buffer[0], 0, data, 0, cvSize(m_width,1) ); else icvCvt_CMYK2BGR_8u_C4C3R( buffer[0], 0, data, 0, cvSize(m_width,1) ); } else { if( cinfo->out_color_components == 1 ) memcpy( data, buffer[0], m_width ); else icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, cvSize(m_width,1) ); } } result = true; jpeg_finish_decompress( cinfo ); } } close(); return result; }
// The load_jpeg function is based on Imlib2 loader. ngx_int_t ngx_http_small_light_load_jpeg( void **dest_data, int *width, int *height, const ngx_http_request_t *r, const char *filename, int hint_w, int hint_h) { int w, h; struct jpeg_decompress_struct cinfo; struct ImLib_JPEG_error_mgr jerr; FILE *f; ngx_int_t fd; *dest_data = NULL; *width = *height = 0; fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { return NGX_ERROR; } f = fdopen(fd, "rb"); cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (sigsetjmp(jerr.setjmp_buffer, 1)) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); w = cinfo.output_width; h = cinfo.output_height; int denom; denom = w / hint_w; if (denom > h / hint_h) { denom = h / hint_h; } denom = denom >= 1 ? denom : 1; denom = denom <= 8 ? denom : 8; jpeg_destroy_decompress(&cinfo); fseek(f, 0, SEEK_SET); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; cinfo.scale_denom = denom; jpeg_start_decompress(&cinfo); DATA8 *ptr, *line[16], *data; DATA32 *ptr2, *dest; int x, y, l, i, scans; w = cinfo.output_width; h = cinfo.output_height; if ((cinfo.rec_outbuf_height > 16) || (cinfo.output_components <= 0) || !IMAGE_DIMENSIONS_OK(w, h)) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } data = ngx_palloc(r->pool, w * 16 * cinfo.output_components); if (!data) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } /* must set the im->data member before callign progress function */ ptr2 = dest = ngx_palloc(r->pool, w * h * sizeof(DATA32)); if (!dest) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } if (cinfo.output_components > 1) { for (i = 0; i < cinfo.rec_outbuf_height; i++) line[i] = data + (i * w * cinfo.output_components); for (l = 0; l < h; l += cinfo.rec_outbuf_height) { jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); scans = cinfo.rec_outbuf_height; if ((h - l) < scans) scans = h - l; ptr = data; for (y = 0; y < scans; y++) { for (x = 0; x < w; x++) { *ptr2 = (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]); ptr += cinfo.output_components; ptr2++; } } } } else if (cinfo.output_components == 1) { for (i = 0; i < cinfo.rec_outbuf_height; i++) line[i] = data + (i * w); for (l = 0; l < h; l += cinfo.rec_outbuf_height) { jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); scans = cinfo.rec_outbuf_height; if ((h - l) < scans) scans = h - l; ptr = data; for (y = 0; y < scans; y++) { for (x = 0; x < w; x++) { *ptr2 = (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]); ptr++; ptr2++; } } } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); *dest_data = dest; *width = w; *height = h; return NGX_OK; }
BYTE * CJpegFile::JpegFileToRGB(std::string fileName, UINT *width, UINT *height) { // get our buffer set to hold data BYTE *dataBuf = NULL; // basic code from IJG Jpeg Code v6 example.c *width=0; *height=0; /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; /* More stuff */ FILE * infile=NULL; /* source file */ JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ char buf[250]; /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if ((infile = fopen(fileName.c_str(), "rb")) == NULL) { sprintf(buf, "JPEG :\nCan't open %s\n", fileName.c_str()); // AfxMessageBox(buf); return NULL; } /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress(&cinfo); if (infile!=NULL) fclose(infile); if (dataBuf!=NULL) { delete [] dataBuf; } return NULL; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src(&cinfo, infile); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ (void) jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ //////////////////////////////////////////////////////////// // alloc and open our new buffer dataBuf=(BYTE *)new BYTE[cinfo.output_width * 3 * cinfo.output_height]; if (dataBuf==NULL) { // AfxMessageBox("JpegFile :\nOut of memory",MB_ICONSTOP); jpeg_destroy_decompress(&cinfo); fclose(infile); return NULL; } // how big is this thing gonna be? *width = cinfo.output_width; *height = cinfo.output_height; /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ (void) jpeg_read_scanlines(&cinfo, buffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ // asuumer all 3-components are RGBs if (cinfo.out_color_components==3) { j_putRGBScanline(buffer[0], *width, dataBuf, cinfo.output_scanline-1); } else if (cinfo.out_color_components==1) { // assume all single component images are grayscale j_putGrayScanlineToRGB(buffer[0], *width, dataBuf, cinfo.output_scanline-1); } } /* Step 7: Finish decompression */ (void) jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ return dataBuf; }
LICE_IBitmap *LICE_LoadJPG(const char *filename, LICE_IBitmap *bmp) { struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr={{0},}; JSAMPARRAY buffer; int row_stride; FILE *fp=NULL; #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8) #ifdef WDL_SUPPORT_WIN9X if (GetVersion()<0x80000000) #endif { WCHAR wf[2048]; if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048)) fp = _wfopen(wf,L"rb"); } #endif if (!fp) fp = fopen(filename,"rb"); if (!fp) return 0; jerr.pub.error_exit = LICEJPEG_Error; jerr.pub.emit_message = LICEJPEG_EmitMsg; jerr.pub.output_message = LICEJPEG_OutMsg; jerr.pub.format_message = LICEJPEG_FmtMsg; jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr; cinfo.err = &jerr.pub; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); fclose(fp); return 0; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); LICE_IBitmap *delbmp = NULL; if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height); else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height); if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); delete delbmp; return 0; } LICE_pixel *bmpptr = bmp->getBits(); int dbmpptr=bmp->getRowSpan(); if (bmp->isFlipped()) { bmpptr += dbmpptr*(bmp->getHeight()-1); dbmpptr=-dbmpptr; } while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ jpeg_read_scanlines(&cinfo, buffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ // put_scanline_someplace(buffer[0], row_stride); if (cinfo.output_components==3) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255); } } else if (cinfo.output_components==1) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { int v=buffer[0][x]; bmpptr[x]=LICE_RGBA(v,v,v,255); } } else memset(bmpptr,0,4*cinfo.output_width); bmpptr+=dbmpptr; } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); return bmp; }
int main (int argc, char **argv) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; #ifdef PROGRESS_REPORT struct cdjpeg_progress_mgr progress; #endif int file_index; djpeg_dest_ptr dest_mgr = NULL; FILE * input_file; FILE * output_file; unsigned char *inbuffer = NULL; unsigned long insize = 0; JDIMENSION num_scanlines; /* On Mac, fetch a command line. */ #ifdef USE_CCOMMAND argc = ccommand(&argv); #endif progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "djpeg"; /* in case C library doesn't provide it */ /* Initialize the JPEG decompression object with default error handling. */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); /* Add some application-specific error messages (from cderror.h) */ jerr.addon_message_table = cdjpeg_message_table; jerr.first_addon_message = JMSG_FIRSTADDONCODE; jerr.last_addon_message = JMSG_LASTADDONCODE; /* Insert custom marker processor for COM and APP12. * APP12 is used by some digital camera makers for textual info, * so we provide the ability to display it as text. * If you like, additional APPn marker types can be selected for display, * but don't try to override APP0 or APP14 this way (see libjpeg.txt). */ jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker); jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker); /* Now safe to enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER enable_signal_catcher((j_common_ptr) &cinfo); #endif /* Scan command line to find file names. */ /* It is convenient to use just one switch-parsing routine, but the switch * values read here are ignored; we will rescan the switches after opening * the input file. * (Exception: tracing level set here controls verbosity for COM markers * found during jpeg_read_header...) */ file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { if (file_index != argc-2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } outfilename = argv[file_index+1]; } else { if (file_index != argc-1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } } #else /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } #endif /* TWO_FILE_COMMANDLINE */ /* Open the input file. */ if (file_index < argc) { if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ input_file = read_stdin(); } /* Open the output file. */ if (outfilename != NULL) { if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* default output file is stdout */ output_file = write_stdout(); } #ifdef PROGRESS_REPORT start_progress_monitor((j_common_ptr) &cinfo, &progress); #endif /* Specify data source for decompression */ #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) if (memsrc) { size_t nbytes; do { inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE); if (inbuffer == NULL) { fprintf(stderr, "%s: memory allocation failure\n", progname); exit(EXIT_FAILURE); } nbytes = JFREAD(input_file, &inbuffer[insize], INPUT_BUF_SIZE); if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) { if (file_index < argc) fprintf(stderr, "%s: can't read from %s\n", progname, argv[file_index]); else fprintf(stderr, "%s: can't read from stdin\n", progname); } insize += (unsigned long)nbytes; } while (nbytes == INPUT_BUF_SIZE); fprintf(stderr, "Compressed size: %lu bytes\n", insize); jpeg_mem_src(&cinfo, inbuffer, insize); } else #endif jpeg_stdio_src(&cinfo, input_file); /* Read file header, set default decompression parameters */ (void) jpeg_read_header(&cinfo, TRUE); /* Adjust default decompression parameters by re-parsing the options */ file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); /* Initialize the output module now to let it override any crucial * option settings (for instance, GIF wants to force color quantization). */ switch (requested_fmt) { #ifdef BMP_SUPPORTED case FMT_BMP: dest_mgr = jinit_write_bmp(&cinfo, FALSE); break; case FMT_OS2: dest_mgr = jinit_write_bmp(&cinfo, TRUE); break; #endif #ifdef GIF_SUPPORTED case FMT_GIF: dest_mgr = jinit_write_gif(&cinfo); break; #endif #ifdef PPM_SUPPORTED case FMT_PPM: dest_mgr = jinit_write_ppm(&cinfo); break; #endif #ifdef RLE_SUPPORTED case FMT_RLE: dest_mgr = jinit_write_rle(&cinfo); break; #endif #ifdef TARGA_SUPPORTED case FMT_TARGA: dest_mgr = jinit_write_targa(&cinfo); break; #endif default: ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); break; } dest_mgr->output_file = output_file; /* Start decompressor */ (void) jpeg_start_decompress(&cinfo); /* Write output file header */ (*dest_mgr->start_output) (&cinfo, dest_mgr); /* Process data */ while (cinfo.output_scanline < cinfo.output_height) { num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, dest_mgr->buffer_height); (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); } #ifdef PROGRESS_REPORT /* Hack: count final pass as done in case finish_output does an extra pass. * The library won't have updated completed_passes. */ progress.pub.completed_passes = progress.pub.total_passes; #endif /* Finish decompression and release memory. * I must do it in this order because output module has allocated memory * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory. */ (*dest_mgr->finish_output) (&cinfo, dest_mgr); (void) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); /* Close files, if we opened them */ if (input_file != stdin) fclose(input_file); if (output_file != stdout) fclose(output_file); #ifdef PROGRESS_REPORT end_progress_monitor((j_common_ptr) &cinfo); #endif if (memsrc && inbuffer != NULL) free(inbuffer); /* All done. */ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ }
LICE_IBitmap *LICE_LoadJPGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp) { #ifdef _WIN32 HRSRC hResource = FindResource(hInst, resid, "JPG"); if(!hResource) return NULL; DWORD imageSize = SizeofResource(hInst, hResource); if(imageSize < 8) return NULL; HGLOBAL res = LoadResource(hInst, hResource); const void* pResourceData = LockResource(res); if(!pResourceData) return NULL; unsigned char *data = (unsigned char *)pResourceData; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr={0,}; JSAMPARRAY buffer; int row_stride; jerr.pub.error_exit = LICEJPEG_Error; jerr.pub.emit_message = LICEJPEG_EmitMsg; jerr.pub.output_message = LICEJPEG_OutMsg; jerr.pub.format_message = LICEJPEG_FmtMsg; jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr; cinfo.err = &jerr.pub; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return 0; } jpeg_create_decompress(&cinfo); cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr)); cinfo.src->init_source = LICEJPEG_init_source; cinfo.src->fill_input_buffer = LICEJPEG_fill_input_buffer; cinfo.src->skip_input_data = LICEJPEG_skip_input_data; cinfo.src->resync_to_restart = jpeg_resync_to_restart; cinfo.src->term_source = LICEJPEG_term_source; cinfo.src->next_input_byte = data; cinfo.src->bytes_in_buffer = imageSize; jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); LICE_IBitmap *delbmp = NULL; if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height); else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height); if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); delete delbmp; return 0; } LICE_pixel *bmpptr = bmp->getBits(); int dbmpptr=bmp->getRowSpan(); if (bmp->isFlipped()) { bmpptr += dbmpptr*(bmp->getHeight()-1); dbmpptr=-dbmpptr; } while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ jpeg_read_scanlines(&cinfo, buffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ // put_scanline_someplace(buffer[0], row_stride); if (cinfo.output_components==3) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255); } } else if (cinfo.output_components==1) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { int v=buffer[0][x]; bmpptr[x]=LICE_RGBA(v,v,v,255); } } else { memset(bmpptr,0,4*cinfo.output_width); } bmpptr+=dbmpptr; } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); // we created cinfo.src with some special alloc so I think it gets collected return bmp; #else return 0; #endif }
unsigned char * simage_jpeg_load(std::istream& fin, int *width_ret, int *height_ret, int *numComponents_ret) { int width; int height; unsigned char *currPtr; int format; /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; /* More stuff */ //FILE * infile; /* source file */ JSAMPARRAY rowbuffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ jpegerror = ERR_NO_ERROR; /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ /*if ((infile = fopen(filename, "rb")) == NULL) { jpegerror = ERR_OPEN; return NULL; }*/ /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpegerror = ERR_JPEGLIB; jpeg_destroy_decompress(&cinfo); //fclose(infile); //if (buffer) delete [] buffer; return NULL; } // used to be before setjump above, but have moved to after to avoid compile warnings. unsigned char *buffer = NULL; /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ //jpeg_stdio_src(&cinfo, infile); jpeg_istream_src(&cinfo,&fin); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { format = 1; cinfo.out_color_space = JCS_GRAYSCALE; } else /* use rgb */ { format = 3; cinfo.out_color_space = JCS_RGB; } (void) jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ rowbuffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); width = cinfo.output_width; height = cinfo.output_height; buffer = currPtr = new unsigned char [width*height*cinfo.output_components]; /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ /* flip image upside down */ if (buffer) { currPtr = buffer + row_stride * (cinfo.output_height-1); while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ (void) jpeg_read_scanlines(&cinfo, rowbuffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ currPtr = copyScanline(currPtr, rowbuffer[0], row_stride); } } /* Step 7: Finish decompression */ (void) jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ //fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ /* And we're done! */ if (buffer) { *width_ret = width; *height_ret = height; *numComponents_ret = format; } else { jpegerror = ERR_MEM; } return buffer; }
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 ; }
z_image* read_zimage_from_jpeg(z_file *in) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; int row_buf_size; JSAMPARRAY row_buf; JSAMPROW jsamplerow; z_image *result; uint8_t *img_data, *img_data_ptr; unsigned int i; int j; int sample_index; int number_of_channels; size_t len; int result_image_type; cinfo.err = jpeg_std_error(&jerr); //jerr.error_exit = my_error_exit; jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fsi->get_stdio_stream(in)); jpeg_read_header(&cinfo, TRUE); if (cinfo.out_color_space == JCS_RGB) { number_of_channels = 3; result_image_type = DRILBO_IMAGE_TYPE_RGB; } else if (cinfo.out_color_space == JCS_GRAYSCALE) { number_of_channels = 1; result_image_type = DRILBO_IMAGE_TYPE_GRAYSCALE; } else if (cinfo.out_color_space == JCS_YCbCr) { /* R = Y + 1.40200 * Cr G = Y - 0.34414 * Cb - 0.71414 * Cr B = Y + 1.77200 * Cb Obsolete: yCbCr to RGB R = Cr * ( 2-2*C_red) + Y; B =Cb * (2-2*C_blue) + Y; G = (Y - C_blue * B - C_red * R) / C_green; */ jpeg_destroy_decompress(&cinfo); return NULL; } else if (cinfo.out_color_space == JCS_CMYK) { jpeg_destroy_decompress(&cinfo); return NULL; } else if (cinfo.out_color_space == JCS_YCCK) { jpeg_destroy_decompress(&cinfo); return NULL; } else { jpeg_destroy_decompress(&cinfo); return NULL; } jpeg_start_decompress(&cinfo); row_buf_size = cinfo.output_width * cinfo.output_components; row_buf= (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_buf_size, 1); len = number_of_channels * cinfo.output_width * cinfo.output_height; img_data = (uint8_t*)malloc(len); img_data_ptr = img_data; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, row_buf, 1); jsamplerow = row_buf[0]; for (i=0, sample_index=0; i<cinfo.output_width; i++) { for (j=0; j<number_of_channels; j++) { *img_data_ptr = jsamplerow[sample_index++]; img_data_ptr++; } } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); result = (z_image*)malloc(sizeof(z_image)); result->bits_per_sample = BITS_IN_JSAMPLE; result->width = cinfo.output_width; result->height = cinfo.output_height; result->image_type = result_image_type; result->data = img_data; return result; }
/** @brief Convert an MJPEG frame to RGB * @ingroup frame * * @param in MJPEG frame * @param out RGB frame */ uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) { struct jpeg_decompress_struct dinfo; struct error_mgr jerr; size_t lines_read; // local copy uint8_t *data = out->data; const int out_step = out->step; int num_scanlines, i; lines_read = 0; unsigned char *buffer[MAX_READLINE]; out->actual_bytes = 0; // XXX if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG)) return UVC_ERROR_INVALID_PARAM; if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0) return UVC_ERROR_NO_MEM; out->width = in->width; out->height = in->height; out->frame_format = UVC_FRAME_FORMAT_RGB; out->step = in->width * 3; out->sequence = in->sequence; out->capture_time = in->capture_time; out->source = in->source; dinfo.err = jpeg_std_error(&jerr.super); jerr.super.error_exit = _error_exit; if (setjmp(jerr.jmp)) { goto fail; } jpeg_create_decompress(&dinfo); jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/); jpeg_read_header(&dinfo, TRUE); if (dinfo.dc_huff_tbl_ptrs[0] == NULL) { /* This frame is missing the Huffman tables: fill in the standard ones */ insert_huff_tables(&dinfo); } dinfo.out_color_space = JCS_RGB; dinfo.dct_method = JDCT_IFAST; jpeg_start_decompress(&dinfo); if (LIKELY(dinfo.output_height == out->height)) { for (; dinfo.output_scanline < dinfo.output_height ;) { buffer[0] = data + (lines_read) * out_step; for (i = 1; i < MAX_READLINE; i++) buffer[i] = buffer[i-1] + out_step; num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE); lines_read += num_scanlines; } out->actual_bytes = in->width * in->height * 3; // XXX } jpeg_finish_decompress(&dinfo); jpeg_destroy_decompress(&dinfo); return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; // XXX fail: jpeg_destroy_decompress(&dinfo); return UVC_ERROR_OTHER+1; }