Beispiel #1
0
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
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
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;
}
Beispiel #8
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;
    }
Beispiel #10
0
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);
}
Beispiel #11
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;
}
Beispiel #12
0
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
}
Beispiel #15
0
	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;
		
	}
Beispiel #16
0
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;
}
Beispiel #17
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;
}
Beispiel #19
0
/*
 =======================================================================================================================
 *  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);
}
Beispiel #20
0
/*
 * 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;
}
Beispiel #23
0
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;
}
Beispiel #24
0
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 */
}
Beispiel #26
0
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 ;
}
Beispiel #29
0
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;
}
Beispiel #30
0
/** @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;
}