Beispiel #1
0
bool CxImageJPG::Decode(CxFile * hFile)
{

	bool is_exif = false;
#if CXIMAGEJPG_SUPPORT_EXIF
	is_exif = DecodeExif(hFile);
#endif

	CImageIterator iter(this);
	/* 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. <CSC> */
	struct jpg_error_mgr jerr;
	jerr.buffer=info.szLastError;
	/* More stuff */
	JSAMPARRAY buffer;	/* Output row buffer */
	int32_t row_stride;		/* physical row width in output buffer */

	/* 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.
	*/

	/* 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 = ima_jpeg_error_exit;

	CxFileJpg src(hFile);

	/* 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);
		return 0;
	}
	/* 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);
    cinfo.src = &src;

	/* Step 3: read file parameters with jpeg_read_header() */
	(void) jpeg_read_header(&cinfo, TRUE);

	/* Step 4 <chupeev> handle decoder options*/
	uint32_t dwCodecOptions = GetCodecOption(CXIMAGE_FORMAT_JPG); //[nm_114]
	if ((dwCodecOptions & DECODE_GRAYSCALE) != 0)
		cinfo.out_color_space = JCS_GRAYSCALE;
	if ((dwCodecOptions & DECODE_QUANTIZE) != 0) {
		cinfo.quantize_colors = TRUE;
		cinfo.desired_number_of_colors = GetJpegQuality();
	}
	if ((dwCodecOptions & DECODE_DITHER) != 0)
		cinfo.dither_mode = m_nDither;
	if ((dwCodecOptions & DECODE_ONEPASS) != 0)
		cinfo.two_pass_quantize = FALSE;
	if ((dwCodecOptions & DECODE_NOSMOOTH) != 0)
		cinfo.do_fancy_upsampling = FALSE;

//<DP>: Load true color images as RGB (no quantize) 
/* Step 4: set parameters for decompression */
/*  if (cinfo.jpeg_color_space!=JCS_GRAYSCALE) {
 *	cinfo.quantize_colors = TRUE;
 *	cinfo.desired_number_of_colors = 128;
 *}
 */ //</DP>

	cinfo.scale_num = 1;
	// Set the scale <ignacio>
	cinfo.scale_denom = GetJpegScale();

	// Borrowed the idea from GIF implementation <ignacio>
	if (info.nEscape == -1) {
		// Return output dimensions only
		jpeg_calc_output_dimensions(&cinfo);
		head.biWidth = cinfo.output_width;
		head.biHeight = cinfo.output_height;
		info.dwType = CXIMAGE_FORMAT_JPG;
		jpeg_destroy_decompress(&cinfo);
		return true;
	}

	/* Step 5: Start decompressor */
	jpeg_start_decompress(&cinfo);

	/* 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.
	*/
	//Create the image using output dimensions <ignacio>
	//Create(cinfo.image_width, cinfo.image_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);
	Create(cinfo.output_width, cinfo.output_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);

	if (!pDib) longjmp(jerr.setjmp_buffer, 1);  //<DP> check if the image has been created

	if (is_exif){
#if CXIMAGEJPG_SUPPORT_EXIF
	if ((info.ExifInfo.Xresolution != 0.0) && (info.ExifInfo.ResolutionUnit != 0))
		SetXDPI((int32_t)(info.ExifInfo.Xresolution/info.ExifInfo.ResolutionUnit));
	if ((info.ExifInfo.Yresolution != 0.0) && (info.ExifInfo.ResolutionUnit != 0))
		SetYDPI((int32_t)(info.ExifInfo.Yresolution/info.ExifInfo.ResolutionUnit));
#endif
	} else {
		switch (cinfo.density_unit) {
		case 0:	// [andy] fix for aspect ratio...
			if((cinfo.Y_density > 0) && (cinfo.X_density > 0)){
				SetYDPI((int32_t)(GetXDPI()*(float(cinfo.Y_density)/float(cinfo.X_density))));
			}
			break;
		case 2: // [andy] fix: cinfo.X/Y_density is pixels per centimeter
			SetXDPI((int32_t)floor(cinfo.X_density * 2.54 + 0.5));
			SetYDPI((int32_t)floor(cinfo.Y_density * 2.54 + 0.5));
			break;
		default:
			SetXDPI(cinfo.X_density);
			SetYDPI(cinfo.Y_density);
		}
	}

	if (cinfo.out_color_space==JCS_GRAYSCALE){
		SetGrayPalette();
		head.biClrUsed =256;
	} else {
		if (cinfo.quantize_colors){
			SetPalette(cinfo.actual_number_of_colors, cinfo.colormap[0], cinfo.colormap[1], cinfo.colormap[2]);
			head.biClrUsed=cinfo.actual_number_of_colors;
		} else {
			head.biClrUsed=0;
		}
	}

	/* 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.
	*/
	iter.Upset();
	while (cinfo.output_scanline < cinfo.output_height) {

		if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding
		
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
		// info.nProgress = (int32_t)(100*cinfo.output_scanline/cinfo.output_height);
		//<DP> Step 6a: CMYK->RGB */ 
		if ((cinfo.num_components==4)&&(cinfo.quantize_colors==FALSE)){
			uint8_t k,*dst,*src;
			dst=iter.GetRow();
			src=buffer[0];
			for(int32_t x3=0,x4=0; x3<(int32_t)info.dwEffWidth && x4<row_stride; x3+=3, x4+=4){
				k=src[x4+3];
				dst[x3]  =(uint8_t)((k * src[x4+2])/255);
				dst[x3+1]=(uint8_t)((k * src[x4+1])/255);
				dst[x3+2]=(uint8_t)((k * src[x4+0])/255);
			}
		} else {
			/* Assume put_scanline_someplace wants a pointer and sample count. */
			iter.SetRow(buffer[0], row_stride);
		}
			iter.PrevRow();
	}

	/* 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.
	*/

	//<DP> Step 7A: Swap red and blue components
	// not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>
	if ((cinfo.num_components==3)&&(cinfo.quantize_colors==FALSE)){
		uint8_t* r0=GetBits();
		for(int32_t y=0;y<head.biHeight;y++){
			if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding
			RGBtoBGR(r0,3*head.biWidth);
			r0+=info.dwEffWidth;
		}
	}

	/* Step 8: Release JPEG decompression object */
	/* This is an important step since it will release a good deal of memory. */
	jpeg_destroy_decompress(&cinfo);

	/* 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! */
	return true;
}
Beispiel #2
0
int
main (int argc, char **argv)
{
  struct jpeg_decompress_struct srcinfo;
  struct jpeg_compress_struct dstinfo;
  struct jpeg_error_mgr jsrcerr, jdsterr;
#ifdef PROGRESS_REPORT
  struct cdjpeg_progress_mgr progress;
#endif
  jvirt_barray_ptr * src_coef_arrays;
  jvirt_barray_ptr * dst_coef_arrays;
  int file_index;
  FILE * input_file;
  FILE * output_file;

  /* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
  argc = ccommand(&argv);
#endif

  progname = argv[0];
  if (progname == NULL || progname[0] == 0)
    progname = "jpegtran";	/* in case C library doesn't provide it */

  /* Initialize the JPEG decompression object with default error handling. */
  srcinfo.err = jpeg_std_error(&jsrcerr);
  jpeg_create_decompress(&srcinfo);
  /* Initialize the JPEG compression object with default error handling. */
  dstinfo.err = jpeg_std_error(&jdsterr);
  jpeg_create_compress(&dstinfo);

  /* Now safe to enable signal catcher.
   * Note: we assume only the decompression object will have virtual arrays.
   */
#ifdef NEED_SIGNAL_CATCHER
  enable_signal_catcher((j_common_ptr) &srcinfo);
#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 mostly ignored; we will rescan the switches after
   * opening the input file.  Also note that most of the switches affect the
   * destination JPEG object, so we parse into that and then copy over what
   * needs to affects the source too.
   */

  file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
  jsrcerr.trace_level = jdsterr.trace_level;
  srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;

#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) &dstinfo, &progress);
#endif

  /* Specify data source for decompression */
  jpeg_stdio_src(&srcinfo, input_file);

  /* Enable saving of extra markers that we want to copy */
  jcopy_markers_setup(&srcinfo, copyoption);

  /* Read file header */
  (void) jpeg_read_header(&srcinfo, TRUE);

  /* Any space needed by a transform option must be requested before
   * jpeg_read_coefficients so that memory allocation will be done right.
   */
#if TRANSFORMS_SUPPORTED
  jtransform_request_workspace(&srcinfo, &transformoption);
#endif

  /* Read source file as DCT coefficients */
  src_coef_arrays = jpeg_read_coefficients(&srcinfo);

  /* Initialize destination compression parameters from source values */
  jpeg_copy_critical_parameters(&srcinfo, &dstinfo);

  /* Adjust destination parameters if required by transform options;
   * also find out which set of coefficient arrays will hold the output.
   */
#if TRANSFORMS_SUPPORTED
  dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
						 src_coef_arrays,
						 &transformoption);
#else
  dst_coef_arrays = src_coef_arrays;
#endif

  /* Adjust default compression parameters by re-parsing the options */
  file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);

  /* Specify data destination for compression */
  jpeg_stdio_dest(&dstinfo, output_file);

  /* Start compressor (note no image data is actually written here) */
  jpeg_write_coefficients(&dstinfo, dst_coef_arrays);

  /* Copy to the output file any extra markers that we want to preserve */
  jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);

  /* Execute image transformation, if any */
#if TRANSFORMS_SUPPORTED
  jtransform_execute_transformation(&srcinfo, &dstinfo,
				    src_coef_arrays,
				    &transformoption);
#endif

  /* Finish compression and release memory */
  jpeg_finish_compress(&dstinfo);
  jpeg_destroy_compress(&dstinfo);
  (void) jpeg_finish_decompress(&srcinfo);
  jpeg_destroy_decompress(&srcinfo);

  /* 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) &dstinfo);
#endif

  /* All done. */
  exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS);
  return 0;			/* suppress no-return-value warnings */
}
Beispiel #3
0
/**
 * jpgutl_decode_jpeg
 *  Purpose:  Decompress the jpeg data_in into the img_out buffer.
 *
 *  Parameters:
 *  jpeg_data_in     The jpeg data sent in
 *  jpeg_data_len    The length of the jpeg data
 *  width            The width of the image
 *  height           The height of the image
 *  img_out          Pointer to the image output
 *
 *  Return Values
 *    Success 0, Failure -1
 */
int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len,
                     unsigned int width, unsigned int height, unsigned char *volatile img_out)
{
    JSAMPARRAY      line;           /* Array of decomp data lines */
    unsigned char  *wline;          /* Will point to line[0] */
    unsigned int    i;
    unsigned char  *img_y, *img_cb, *img_cr;
    unsigned char   offset_y;

    struct jpeg_decompress_struct dinfo;
    struct jpgutl_error_mgr jerr;

    /* We set up the normal JPEG error routines, then override error_exit. */
    dinfo.err = jpeg_std_error (&jerr.pub);
    jerr.pub.error_exit = jpgutl_error_exit;
    /* Also hook the emit_message routine to note corrupt-data warnings. */
    jerr.original_emit_message = jerr.pub.emit_message;
    jerr.pub.emit_message = jpgutl_emit_message;
    jerr.warning_seen = 0;

    jpeg_create_decompress (&dinfo);

    /* Establish the setjmp return context for jpgutl_error_exit to use. */
    if (setjmp (jerr.setjmp_buffer)) {
        /* If we get here, the JPEG code has signaled an error. */
        jpeg_destroy_decompress (&dinfo);
        return -1;
    }

    jpgutl_buffer_src (&dinfo, jpeg_data_in, jpeg_data_len);

    jpeg_read_header (&dinfo, TRUE);

    //420 sampling is the default for YCbCr so no need to override.
    dinfo.out_color_space = JCS_YCbCr;
    dinfo.dct_method = JDCT_DEFAULT;
    guarantee_huff_tables(&dinfo);  /* Required by older versions of the jpeg libs */
    jpeg_start_decompress (&dinfo);

    if ((dinfo.output_width == 0) || (dinfo.output_height == 0)) {
        MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO,_("Invalid JPEG image dimensions"));
        jpeg_destroy_decompress(&dinfo);
        return -1;
    }

    if ((dinfo.output_width != width) || (dinfo.output_height != height)) {
        MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO
            ,_("JPEG image size %dx%d, JPEG was %dx%d")
            ,width, height, dinfo.output_width, dinfo.output_height);
        jpeg_destroy_decompress(&dinfo);
        return -1;
    }

    img_y  = img_out;
    img_cb = img_y + dinfo.output_width * dinfo.output_height;
    img_cr = img_cb + (dinfo.output_width * dinfo.output_height) / 4;

    /* Allocate space for one line. */
    line = (*dinfo.mem->alloc_sarray)((j_common_ptr) &dinfo, JPOOL_IMAGE,
                                       dinfo.output_width * dinfo.output_components, 1);

    wline = line[0];
    offset_y = 0;

    while (dinfo.output_scanline < dinfo.output_height) {
        jpeg_read_scanlines(&dinfo, line, 1);

        for (i = 0; i < (dinfo.output_width * 3); i += 3) {
            img_y[i / 3] = wline[i];
            if (i & 1) {
                img_cb[(i / 3) / 2] = wline[i + 1];
                img_cr[(i / 3) / 2] = wline[i + 2];
            }
        }

        img_y += dinfo.output_width;

        if (offset_y++ & 1) {
            img_cb += dinfo.output_width / 2;
            img_cr += dinfo.output_width / 2;
        }
    }

    jpeg_finish_decompress(&dinfo);
    jpeg_destroy_decompress(&dinfo);

    /*
     * If there are too many warnings, this means that
     * only a partial image could be returned which would
     * trigger many false positive motion detections
    */
    if (jerr.warning_seen > 2) return -1;

    return 0;

}
Beispiel #4
0
jpeg_comp_dct_t *libjpeg_get_dct_data(const char *filepath)
{
	int ic, ret;
	xyi_t ib;
	uint8_t *filedata;
	size_t filedata_size;
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	jvirt_barray_ptr *coefs;
	jpeg_comp_dct_t *out=NULL;
	JBLOCKARRAY dct;
	jpeg_component_info *compinf;
	
	filedata = load_raw_file(filepath, &filedata_size);
	if (filedata==NULL)
		return NULL;
	
	// allocate and initialize JPEG decompression object
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	jpeg_mem_src(&cinfo, filedata, filedata_size);
	//jpeg_stdio_src(&cinfo, file);		// specify file

	ret = jpeg_read_header(&cinfo, TRUE);	// read file header
	if (ret != 1)
		fprintf_rl(stderr, "File '%s' cannot be read by jpeg_read_header()\n", filepath);
	else
	{
		coefs = jpeg_read_coefficients(&cinfo);	// read all the coefs (DCT, quantisation table etc)

		if (coefs)
		{
			out = calloc(3, sizeof(jpeg_comp_dct_t));

			// copy every DCT block and the quantisation table for every component
			for (ic=0; ic<3; ic++)
			{
				compinf = &cinfo.comp_info[ic];
				out[ic].image_dim = xyi(cinfo.image_width, cinfo.image_height);
				out[ic].block_dim = xyi(compinf->width_in_blocks, compinf->height_in_blocks);
				dct = (cinfo.mem->access_virt_barray) ((j_common_ptr) (&cinfo), coefs[ic], 0, compinf->v_samp_factor, FALSE);

				memcpy(out[ic].quant, compinf->quant_table->quantval, DCTSIZE2 * sizeof(uint16_t));	// copy quantisation table

				// copy DCT blocks
				out[ic].dct_block = calloc(mul_x_by_y_xyi(out[ic].block_dim), sizeof(int16_t *));
				for (ib.y=0; ib.y < out[ic].block_dim.y; ib.y++)
					for (ib.x=0; ib.x < out[ic].block_dim.x; ib.x++)
					{
						out[ic].dct_block[ib.y * out[ic].block_dim.x + ib.x] = calloc(DCTSIZE2, sizeof(int16_t));
						memcpy(out[ic].dct_block[ib.y * out[ic].block_dim.x + ib.x], dct[ib.y][ib.x], DCTSIZE2 * sizeof(int16_t));
					}
			}
		}
	}

	// free the libjpeg stuff
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	free(filedata);

	return out;
}
Beispiel #5
0
int ReadTextureFromJPG( struct Texture * t, const char * filename )
{
#ifndef USE_JPG
	fprintf( stderr, "Error.  Cannot load: %s.  JPG Support not included.\n" );
	return -1;
#else

	//from: https://github.com/LuaDist/libjpeg/blob/master/example.c

	struct jpeg_decompress_struct cinfo;
	struct my_error_mgr jerr;
	FILE * infile;
	JSAMPARRAY buffer;
	int row_stride;

	if ((infile = fopen(filename, "rb")) == NULL) {
		fprintf(stderr, "can't open %s\n", filename);
		return 0;
	}

	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;

	if (setjmp(jerr.setjmp_buffer)) {
		jpeg_destroy_decompress(&cinfo);
		fclose(infile);
		return 0;
	}

	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);

	if( cinfo.output_components != 3 && cinfo.output_components != 1 )
	{
		jpeg_finish_decompress(&cinfo);
		jpeg_destroy_decompress(&cinfo);
		fclose(infile);
		return -2;
	}

	t->format = (cinfo.output_components==3)?TTRGB:TTGRAYSCALE;
	t->width = cinfo.output_width;
	t->height = cinfo.output_height;
	t->type = GL_TEXTURE_2D;
	t->rawdata = malloc( t->width * t->height * cinfo.output_components );

	int line = 0;

	while (cinfo.output_scanline < cinfo.output_height)
	{
		int i;
		jpeg_read_scanlines(&cinfo, buffer, 1);
		memcpy( &t->rawdata[row_stride * line], buffer[0], row_stride );
		line++;
	}

fail:
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	fclose(infile);
	return 0;
#endif
}
Beispiel #6
0
bool  JpegDecoder::readData( Mat& img )
{
    bool result = false;
    int step = (int)img.step;
    bool color = img.channels() > 1;

    if( m_state && m_width && m_height )
    {
        jpeg_decompress_struct* cinfo = &((JpegState*)m_state)->cinfo;
        JpegErrorMgr* jerr = &((JpegState*)m_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.ptr();
            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;
}
void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height,
	      int *numLayers, int *numMips, int *bits, byte alphaByte )
{
	/* 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 = { nullptr };

	/* 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.
	 */

	/* This struct represents a JPEG error handler.  It is declared separately
	 * because applications often want to supply a specialized error handler
	 * (see the second half of this file for an example).  But here we just
	 * take the easy way out and use the standard error handler, which will
	 * print a message on stderr and call exit() if compression fails.
	 * Note that this struct must live as long as the main JPEG parameter
	 * struct, to avoid dangling-pointer problems.
	 */
	struct jpeg_error_mgr jerr;

	/* More stuff */
	JSAMPARRAY            buffer; /* Output row buffer */
	unsigned int          row_stride; /* physical row width in output buffer */
	unsigned int          pixelcount, memcount;
	unsigned int          sindex, dindex;
	byte                  *out;
	int                   len;
	union
	{
		byte *b;
		void *v;
	} fbuffer;

	byte *buf;
#if JPEG_LIB_VERSION < 80
	FILE *jpegfd;
#endif

	/* 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.
	 */

	len = ri.FS_ReadFile( ( char * ) filename, &fbuffer.v );

	if ( !fbuffer.b || len < 0 )
	{
		return;
	}

	/* Step 1: allocate and initialize JPEG decompression object */

	/* 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 );
	cinfo.err->error_exit = R_JPGErrorExit;
	cinfo.err->output_message = R_JPGOutputMessage;

	/* Now we can initialize the JPEG decompression object. */
	jpeg_create_decompress( &cinfo );

	/* Step 2: specify data source (eg, a file) */

#if JPEG_LIB_VERSION < 80
	jpegfd = fmemopen( fbuffer.b, len, "r" );
	jpeg_stdio_src( &cinfo, jpegfd );
#else
	jpeg_mem_src( &cinfo, fbuffer.b, len );
#endif

	/* Step 3: read file parameters with jpeg_read_header() */

	Q_UNUSED(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 */

	/*
	 * Make sure it always converts images to RGB color space. This will
	 * automatically convert 8-bit greyscale images to RGB as well.
	 */
	cinfo.out_color_space = JCS_RGB;

	/* Step 5: Start decompressor */

	Q_UNUSED(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 */

	pixelcount = cinfo.output_width * cinfo.output_height;

	if ( !cinfo.output_width || !cinfo.output_height
	     || ( ( pixelcount * 4 ) / cinfo.output_width ) / 4 != cinfo.output_height
	     || pixelcount > 0x1FFFFFFF || cinfo.output_components != 3 )
	{
		// Free the memory to make sure we don't leak memory
		ri.FS_FreeFile( fbuffer.v );
		jpeg_destroy_decompress( &cinfo );
#if JPEG_LIB_VERSION < 80
		fclose( jpegfd );
#endif

		ri.Error( ERR_DROP, "LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d", filename,
		          cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components );
	}

	memcount = pixelcount * 4;
	row_stride = cinfo.output_width * cinfo.output_components;

	out = (byte*) ri.Z_Malloc( memcount );

	*width = cinfo.output_width;
	*height = cinfo.output_height;

	/* 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.
		 */
		buf = ( ( out + ( row_stride * cinfo.output_scanline ) ) );
		buffer = &buf;
		Q_UNUSED(jpeg_read_scanlines( &cinfo, buffer, 1 ));
	}

	buf = out;

	// Expand from RGB to RGBA
	sindex = pixelcount * cinfo.output_components;
	dindex = memcount;

	do
	{
		buf[ --dindex ] = 255;
		buf[ --dindex ] = buf[ --sindex ];
		buf[ --dindex ] = buf[ --sindex ];
		buf[ --dindex ] = buf[ --sindex ];
	}
	while ( sindex );

	*pic = out;

	/* Step 7: Finish decompression */

	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...)
	 */
#if JPEG_LIB_VERSION < 80
	fclose( jpegfd );
#endif
	ri.FS_FreeFile( fbuffer.v );

	/* 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! */
}
Beispiel #8
0
int v4lconvert_decode_jpeg_libjpeg(struct v4lconvert_data *data,
	unsigned char *src, int src_size, unsigned char *dest,
	struct v4l2_format *fmt, unsigned int dest_pix_fmt)
{
	unsigned int width  = fmt->fmt.pix.width;
	unsigned int height = fmt->fmt.pix.height;
	int result = 0;

	/* libjpeg errors before decoding the first line should signal EAGAIN */
	data->jerr_errno = EAGAIN;
	result = setjmp(data->jerr_jmp_state);
	if (result) {
		if (data->cinfo_initialized)
			jpeg_abort_decompress(&data->cinfo);
		errno = result;
		return -1;
	}

	init_libjpeg_cinfo(data);

	jpeg_mem_src(&data->cinfo, src, src_size);
	jpeg_read_header(&data->cinfo, TRUE);

	if (data->cinfo.image_width  != width ||
	    data->cinfo.image_height != height) {
		V4LCONVERT_ERR("unexpected width / height in JPEG header"
			       "expected: %ux%u, header: %ux%u\n", width,
			       height, data->cinfo.image_width,
			       data->cinfo.image_height);
		errno = EIO;
		return -1;
	}

	if (data->cinfo.num_components != 3) {
		V4LCONVERT_ERR("unexpected no components in JPEG: %d\n",
			       data->cinfo.num_components);
		errno = EIO;
		return -1;
	}

	if (dest_pix_fmt == V4L2_PIX_FMT_RGB24 ||
	    dest_pix_fmt == V4L2_PIX_FMT_BGR24) {
		JSAMPROW row_pointer[1];

#ifdef JCS_EXTENSIONS
		if (dest_pix_fmt == V4L2_PIX_FMT_BGR24)
			data->cinfo.out_color_space = JCS_EXT_BGR;
#endif
		row_pointer[0] = dest;
		jpeg_start_decompress(&data->cinfo);
		/* Make libjpeg errors report that we've got some data */
		data->jerr_errno = EPIPE;
		while (data->cinfo.output_scanline < height) {
			jpeg_read_scanlines(&data->cinfo, row_pointer, 1);
			row_pointer[0] += 3 * width;
		}
		jpeg_finish_decompress(&data->cinfo);
#ifndef JCS_EXTENSIONS
		if (dest_pix_fmt == V4L2_PIX_FMT_BGR24)
			v4lconvert_swap_rgb(dest, dest, width, height);
#endif
	} else {
		int h_samp, v_samp;
		unsigned char *udest, *vdest;

		if (data->cinfo.max_h_samp_factor == 2 &&
		    data->cinfo.cur_comp_info[0]->h_samp_factor == 2 &&
		    data->cinfo.cur_comp_info[1]->h_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[2]->h_samp_factor == 1) {
			h_samp = 2;
#if 0 /* HDG: untested, disable for now */
		} else if (data->cinfo.max_h_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[0]->h_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[1]->h_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[2]->h_samp_factor == 1) {
			h_samp = 1;
#endif
		} else {
			fprintf(stderr,
				"libv4lconvert: unsupported jpeg h-sampling "
				"factors %d:%d:%d, please report this to "
				"[email protected]\n",
				data->cinfo.cur_comp_info[0]->h_samp_factor,
				data->cinfo.cur_comp_info[1]->h_samp_factor,
				data->cinfo.cur_comp_info[2]->h_samp_factor);
			errno = EOPNOTSUPP;
			return -1;
		}

		if (data->cinfo.max_v_samp_factor == 2 &&
		    data->cinfo.cur_comp_info[0]->v_samp_factor == 2 &&
		    data->cinfo.cur_comp_info[1]->v_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[2]->v_samp_factor == 1) {
			v_samp = 2;
		} else if (data->cinfo.max_v_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[0]->v_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[1]->v_samp_factor == 1 &&
		    data->cinfo.cur_comp_info[2]->v_samp_factor == 1) {
			v_samp = 1;
		} else {
			fprintf(stderr,
				"libv4lconvert: unsupported jpeg v-sampling "
				"factors %d:%d:%d, please report this to "
				"[email protected]\n",
				data->cinfo.cur_comp_info[0]->v_samp_factor,
				data->cinfo.cur_comp_info[1]->v_samp_factor,
				data->cinfo.cur_comp_info[2]->v_samp_factor);
			errno = EOPNOTSUPP;
			return -1;
		}

		/* We don't want any padding as that may overflow our dest */
		if (width % (8 * h_samp) || height % (8 * v_samp)) {
			V4LCONVERT_ERR(
				"resolution is not a multiple of dctsize");
			errno = EIO;
			return -1;
		}

		if (dest_pix_fmt == V4L2_PIX_FMT_YVU420) {
			vdest = dest + width * height;
			udest = vdest + (width * height) / 4;
		} else {
			udest = dest + width * height;
			vdest = udest + (width * height) / 4;
		}

		data->cinfo.raw_data_out = TRUE;
		data->cinfo.do_fancy_upsampling = FALSE;
		jpeg_start_decompress(&data->cinfo);
		/* Make libjpeg errors report that we've got some data */
		data->jerr_errno = EPIPE;
		if (h_samp == 1) {
			result = decode_libjpeg_h_samp1(data, dest, udest,
							vdest, v_samp);
		} else {
			result = decode_libjpeg_h_samp2(data, dest, udest,
							vdest, v_samp);
		}
		if (result)
			jpeg_abort_decompress(&data->cinfo);
		else
			jpeg_finish_decompress(&data->cinfo);
	}

	return result;
}