示例#1
0
CPack::PackHeader * CPack::JStegReadImage(LPCTSTR szSrc, LPCTSTR szExt, CSBitmap & bmp, CString & szError, 
		BOOL * bCancel, CB_SET_PROGRESS fnSetProgress)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	struct jpeg_steg_mgr jsteg;
	FILE * infile = NULL;
	PackHeader * pRet = NULL, header;
	CCorBuffer sbuf;
	JStegParam param;
	JSAMPARRAY buffer;		/* Output row buffer */
	INT row_stride;		/* physical row width in output buffer */
	INT nProgress = 0;

	/* check ext */

	rc = wc = 0;

	memset(&cinfo, 0, sizeof(cinfo));

	memset(&param, 0, sizeof(param));
	param.bError = FALSE;
	param.buffer = &sbuf;
	cinfo.client_data = &param;

	if((infile = _tfopen(szSrc, _T("rb"))) == NULL ) {
		INT err = ferror(infile);
		szError.LoadString(IDS_ERROR_READ_FILE);
		goto error;
	}

	cinfo.err = jpeg_std_error(&jerr);
	jerr.error_exit = JStegErrorExit;

	jpeg_create_decompress(&cinfo);

	cinfo.steg = &jsteg;
	jsteg.steg_read = JStegReadData;
	jsteg.steg_write = JStegWriteData;

	jpeg_stdio_src(&cinfo, infile);

	(void) jpeg_read_header(&cinfo, TRUE);

	if(param.bError) {
		szError.LoadString(IDS_ERROR_UNSUPPORT_FILE);
		goto error;
	}

	(void) jpeg_start_decompress(&cinfo);

	if(cinfo.output_components != 3) {
		szError.LoadString(IDS_ERROR_UNSUPPORT_FILE);
		goto error;
	}

	if(!bmp.ReAllocBuffer(cinfo.output_width, cinfo.output_height)) {
		szError.LoadString(IDS_ERROR_INTERNAL);
		goto error;
	}

	/*
	img = (char*)malloc(cinfo.output_width * cinfo.output_height *
				 cinfo.output_components);
	*/

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

		(void) jpeg_read_scanlines(&cinfo, buffer, 1);

		/*memcpy(&img[(cinfo.output_scanline-1)*row_stride], buffer[0],
			row_stride);*/

		if(!bmp.SetBufferData((cinfo.output_scanline-1)*row_stride, row_stride, buffer[0])) {
			param.bError = TRUE;
			break;
		}

		if(param.bError) {
			break;
		}

		if(NULL != bCancel && *bCancel) {
			param.bError = TRUE;
			break;
		}
	}

	(void) jpeg_finish_decompress(&cinfo);

	jpeg_destroy_decompress(&cinfo);

	fclose(infile);

	infile = NULL;

	if(param.bError || (NULL != bCancel && *bCancel)) {
		if(NULL != bCancel && *bCancel) {
			szError.LoadString(IDS_ERROR_UNSUPPORT_FILE);
		} else {
			szError.LoadString(IDS_ERROR_CANCELED);
		}
		goto error;
	}

	{
		INT size = JStegGetCap(bmp.Columns() , bmp.Rows()); /* num of cors */
		TRACE(_T("JStegGetCap = %d, real size = %d\n"), size, sbuf.Size());
	}

	// test proper format from sbuf
	// is PFP_1PJ??
	if(sbuf.Size() / 8 < sizeof(PackHeader)) {
		szError.LoadString(IDS_ERROR_UNSUPPORT_FILE);
		goto error;
	}

	if(!RawPJReadDataInternal(sbuf, (LPBYTE)&header, sizeof(header), PFP_1PJ)) {
		szError.LoadString(IDS_ERROR_INTERNAL);
		goto error;
	}

	if(IsValidHeader(header)) {
		if(NULL != pRet) {
			free(pRet);
			pRet = NULL;
		}
		pRet = (PackHeader *)malloc(sizeof(header) + header.dwDataSize);
		if(NULL == pRet || !RawPJReadDataInternal(sbuf, (LPBYTE)pRet , sizeof(header) + header.dwDataSize,
			PFP_1PJ, bCancel, fnSetProgress)) {
			szError.LoadString(IDS_ERROR_INTERNAL);
			goto error;
		}
		return pRet;
	}

	// is PFP_2PJ??
	if(sbuf.Size() * 2 / 8 < sizeof(PackHeader)) {
		szError.LoadString(IDS_ERROR_UNSUPPORT_FILE);
		goto error;
	}
	if(!RawPJReadDataInternal(sbuf, (LPBYTE)&header, sizeof(header), PFP_2PJ)) {
		szError.LoadString(IDS_ERROR_INTERNAL);
		goto error;
	}

	if(IsValidHeader(header)) {
		pRet = (PackHeader *)malloc(sizeof(header) + header.dwDataSize);
		if(NULL == pRet || !RawPJReadDataInternal(sbuf, (LPBYTE)pRet , sizeof(header) + header.dwDataSize,
			PFP_2PJ, bCancel, fnSetProgress)) {
			szError.LoadString(IDS_ERROR_INTERNAL);
			goto error;
		}
		return pRet;
	}

	// is PFP_4PJ??
	if(sbuf.Size() * 4 / 8 < sizeof(PackHeader)) {
		szError.LoadString(IDS_ERROR_UNSUPPORT_FILE);
		goto error;
	}

	if(!RawPJReadDataInternal(sbuf, (LPBYTE)&header, sizeof(header), PFP_4PJ)) {
		szError.LoadString(IDS_ERROR_INTERNAL);
		goto error;
	}

	if(IsValidHeader(header)) {
		pRet = (PackHeader *)malloc(sizeof(header) + header.dwDataSize);
		if(NULL == pRet || !RawPJReadDataInternal(sbuf, (LPBYTE)pRet , sizeof(header) + header.dwDataSize,
			PFP_4PJ, bCancel, fnSetProgress)) {
			szError.LoadString(IDS_ERROR_INTERNAL);
			goto error;
		}
		return pRet;
	}

error:
	if(NULL != infile) {
		fclose(infile);
		infile = NULL;
	}
	if(NULL != pRet) {
		free(pRet);
		pRet = NULL;
	}
	return pRet;
}
示例#2
0
static BOOL  
LosslessTransform(const FilenameIO *filenameIO, FREE_IMAGE_JPEG_OPERATION operation, const char *crop, BOOL perfect) {
	// We assume all-in-memory processing and can therefore use only a
	// single file pointer for sequential input and output operation
	FILE *fp = NULL;

	// check for UNICODE filenames - previous structure filling was done before
	bool bUseUnicode = filenameIO && filenameIO->wsrc_file && filenameIO->wdst_file;

	// Set up the jpeglib structures
	jpeg_decompress_struct srcinfo;
	jpeg_compress_struct dstinfo;
	jpeg_error_mgr jsrcerr, jdsterr;
	jvirt_barray_ptr *src_coef_arrays = NULL;
	jvirt_barray_ptr *dst_coef_arrays = NULL;
	// Support for copying optional markers from source to destination file
	JCOPY_OPTION copyoption;
	// Image transformation options
	jpeg_transform_info transfoptions;
	
	// Initialize structures
	memset(&srcinfo, 0, sizeof(srcinfo));
	memset(&jsrcerr, 0, sizeof(jsrcerr));
	memset(&jdsterr, 0, sizeof(jdsterr));
	memset(&dstinfo, 0, sizeof(dstinfo));
	memset(&transfoptions, 0, sizeof(transfoptions));
	
	// Copy all extra markers from source file
	copyoption = JCOPYOPT_ALL;
	
	// Set up default JPEG parameters
	transfoptions.force_grayscale = FALSE;
	transfoptions.crop = FALSE;

	// Select the transform option
	switch(operation) {
		case FIJPEG_OP_FLIP_H:		// horizontal flip
			transfoptions.transform = JXFORM_FLIP_H;
			break;
		case FIJPEG_OP_FLIP_V:		// vertical flip
			transfoptions.transform = JXFORM_FLIP_V;
			break;
		case FIJPEG_OP_TRANSPOSE:	// transpose across UL-to-LR axis
			transfoptions.transform = JXFORM_TRANSPOSE;
			break;
		case FIJPEG_OP_TRANSVERSE:	// transpose across UR-to-LL axis
			transfoptions.transform = JXFORM_TRANSVERSE;
			break;
		case FIJPEG_OP_ROTATE_90:	// 90-degree clockwise rotation
			transfoptions.transform = JXFORM_ROT_90;
			break;
		case FIJPEG_OP_ROTATE_180:	// 180-degree rotation
			transfoptions.transform = JXFORM_ROT_180;
			break;
		case FIJPEG_OP_ROTATE_270:	// 270-degree clockwise (or 90 ccw)
			transfoptions.transform = JXFORM_ROT_270;
			break;
		default:
		case FIJPEG_OP_NONE:		// no transformation
			transfoptions.transform = JXFORM_NONE;
			break;
	}
	// (perfect == TRUE) ==> fail if there is non-transformable edge blocks
	transfoptions.perfect = (perfect == TRUE) ? TRUE : FALSE;
	// Drop non-transformable edge blocks: trim off any partial edge MCUs that the transform can't handle.
	transfoptions.trim = TRUE;

	try {

		// Initialize the JPEG decompression object with default error handling
		srcinfo.err = jpeg_std_error(&jsrcerr);
		srcinfo.err->error_exit = ls_jpeg_error_exit;
		srcinfo.err->output_message = ls_jpeg_output_message;
		jpeg_create_decompress(&srcinfo);

		// Initialize the JPEG compression object with default error handling
		dstinfo.err = jpeg_std_error(&jdsterr);
		dstinfo.err->error_exit = ls_jpeg_error_exit;
		dstinfo.err->output_message = ls_jpeg_output_message;
		jpeg_create_compress(&dstinfo);

		// crop option
		if(crop != NULL) {
			if(!jtransform_parse_crop_spec(&transfoptions, crop)) {
				FreeImage_OutputMessageProc(FIF_JPEG, "Bogus crop argument %s", crop);
				throw(1);
			}
		}

		// Open the input file
		if(bUseUnicode) {
#ifdef _WIN32
			if((fp = _wfopen(filenameIO->wsrc_file, L"rb")) == NULL) {
				FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open input file for reading");
			}
#else
			fp = NULL;
#endif // _WIN32
		} else {
			if((fp = fopen(filenameIO->src_file, "rb")) == NULL) {
				FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for reading", filenameIO->src_file);
			}
		}
		if(fp == NULL) {
			jpeg_destroy_compress(&dstinfo);
			jpeg_destroy_decompress(&srcinfo);
			return FALSE;
		}
		
		// Specify data source for decompression
		jpeg_stdio_src(&srcinfo, fp);
		
		// Enable saving of extra markers that we want to copy
		jcopy_markers_setup(&srcinfo, copyoption);
		
		// Read the file header
		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

		// Prepare transformation workspace
		// Fails right away if perfect flag is TRUE and transformation is not perfect
		if( !jtransform_request_workspace(&srcinfo, &transfoptions) ) {
			FreeImage_OutputMessageProc(FIF_JPEG, "Transformation is not perfect");
			throw(1);
		}

		// 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
		dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions);
		
		// Close the input file.
		// Note: we assume that jpeg_read_coefficients consumed all input
		// until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
		// only consume more while (! cinfo->inputctl->eoi_reached).
		// We cannot call jpeg_finish_decompress here since we still need the
		// virtual arrays allocated from the source object for processing.
		fclose(fp);

		// Open the output file
		if(bUseUnicode) {
#ifdef _WIN32
			if((fp = _wfopen(filenameIO->wdst_file, L"wb")) == NULL) {
				FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open output file for writing");
			}
#else
			fp = NULL;
#endif // _WIN32
		} else {
			if((fp = fopen(filenameIO->dst_file, "wb")) == NULL) {
				FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for writing", filenameIO->dst_file);
			}
		}
		if(fp == NULL) {
			throw(1);
		}
		
		// Specify data destination for compression
		jpeg_stdio_dest(&dstinfo, fp);
		
		// 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
		jtransform_execute_transformation(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions);
		
		// Finish compression and release memory
		jpeg_finish_compress(&dstinfo);
		jpeg_destroy_compress(&dstinfo);
		jpeg_finish_decompress(&srcinfo);
		jpeg_destroy_decompress(&srcinfo);
		
		// Close output file and return
		fclose(fp);
	}
	catch(...) {
		if(fp) fclose(fp);
		jpeg_destroy_compress(&dstinfo);
		jpeg_destroy_decompress(&srcinfo);
		return FALSE;
	}

	return TRUE;
}
示例#3
0
文件: jpeg_format.c 项目: mrkn/IMF
static void
load_jpeg(imf_file_format_t *base_fmt, imf_image_t *img, VALUE image_source)
{
  imf_jpeg_format_t *fmt = (imf_jpeg_format_t *) base_fmt;
  struct jpeg_decompress_struct *cinfo;
  struct jpeg_error_mgr jerr;
  JOCTET *buffer_ptr;

  assert(img != NULL);

  if (!rb_obj_is_kind_of(image_source, imf_cIMF_ImageSource)) {
    rb_raise(rb_eTypeError, "image_source must be an IMF::ImageSource object");
  }

  cinfo = &fmt->cinfo;
  cinfo->err = jpeg_std_error(&jerr);
  cinfo->err->error_exit = jpeg_error_exit;

  jpeg_create_decompress(cinfo);
  fmt->running = 1;

  /* setup source manager */
  fmt->srcmgr = init_source_manager(cinfo, image_source);

  jpeg_read_header(cinfo, TRUE);
  jpeg_start_decompress(cinfo);

  /* allocate image buffer */
  img->color_space = IMF_COLOR_SPACE_RGB;
  IMF_IMAGE_UNSET_ALPHA(img);
  img->component_size = sizeof(JSAMPLE);
  img->pixel_channels = cinfo->output_components;
  img->width = cinfo->output_width;
  img->height = cinfo->output_height;

  imf_image_allocate_image_buffer(img);

  /* allocate temporary scanline buffer */
  fmt->buffer = rb_str_tmp_new(sizeof(JSAMPLE) * cinfo->output_width * cinfo->output_components);
  buffer_ptr = (JOCTET *) RSTRING_PTR(fmt->buffer);

  size_t const pixel_size = img->pixel_channels * img->component_size;
  size_t const row_size = pixel_size * img->width;
  uint8_t *row_base_ptr = img->data;
  size_t y = 0;
  while (cinfo->output_scanline < cinfo->output_height) {
    jpeg_read_scanlines(cinfo, &buffer_ptr, 1);

    memcpy(row_base_ptr, buffer_ptr, row_size);

    row_base_ptr += img->row_stride;
    ++y;
  }

  /* release temporary buffer memory */
  buffer_ptr = NULL;
  rb_str_resize(fmt->buffer, 0L);

  jpeg_finish_decompress(cinfo);
  jpeg_destroy_decompress(cinfo);
  fmt->running = 0;
}
示例#4
0
VGImage createImageFromJpeg(const char *filename)
{
  FILE *infile;
  struct jpeg_decompress_struct jdc;
  struct jpeg_error_mgr jerr;
  JSAMPARRAY buffer;  
  unsigned int bstride;
  unsigned int bbpp;

  VGImage img;
  VGubyte *data;
  unsigned int width;
  unsigned int height;
  unsigned int dstride;
  unsigned int dbpp;
  
  VGubyte *brow;
  VGubyte *drow;
  unsigned int x;
  unsigned int lilEndianTest = 1;
  VGImageFormat rgbaFormat;

  /* Check for endianness */
  if (((unsigned char*)&lilEndianTest)[0] == 1)
    rgbaFormat = VG_lABGR_8888;
  else rgbaFormat = VG_lRGBA_8888;
  
  /* Try to open image file */
  infile = fopen(filename, "rb");
  if (infile == NULL) {
    printf("Failed opening '%s' for reading!\n", filename);
    return VG_INVALID_HANDLE; }
  
  /* Setup default error handling */
  jdc.err = jpeg_std_error(&jerr);
  jpeg_create_decompress(&jdc);
  
  /* Set input file */
  jpeg_stdio_src(&jdc, infile);
  
  /* Read header and start */
  jpeg_read_header(&jdc, TRUE);
  jpeg_start_decompress(&jdc);
  width = jdc.output_width;
  height = jdc.output_height;
  
  /* Allocate buffer using jpeg allocator */
  bbpp = jdc.output_components;
  bstride = width * bbpp;
  buffer = (*jdc.mem->alloc_sarray)
    ((j_common_ptr) &jdc, JPOOL_IMAGE, bstride, 1);
  
  /* Allocate image data buffer */
  dbpp = 4;
  dstride = width * dbpp;
  data = (VGubyte*)malloc(dstride * height);
  
  /* Iterate until all scanlines processed */
  while (jdc.output_scanline < height) {
    
    /* Read scanline into buffer */
    jpeg_read_scanlines(&jdc, buffer, 1);    
    drow = data + (height-jdc.output_scanline) * dstride;
    brow = buffer[0];
    
    /* Expand to RGBA */
    for (x=0; x<width; ++x, drow+=dbpp, brow+=bbpp) {
      switch (bbpp) {
      case 4:
        drow[0] = brow[0];
        drow[1] = brow[1];
        drow[2] = brow[2];
        drow[3] = brow[3];
        break;
      case 3:
        drow[0] = brow[0];
        drow[1] = brow[1];
        drow[2] = brow[2];
        drow[3] = 255;
        break; }
    }
  }
  
  /* Create VG image */
  img = vgCreateImage(rgbaFormat, width, height, VG_IMAGE_QUALITY_BETTER);
  vgImageSubData(img, data, dstride, rgbaFormat, 0, 0, width, height);
  
  /* Cleanup */
  jpeg_destroy_decompress(&jdc);
  fclose(infile);
  free(data);
  
  return img;
}
//! 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
}
bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#ifdef TIME_DECODE
    AutoTimeMillis atm("JPEG Decode");
#endif

    SkAutoMalloc  srcStorage;
    JPEGAutoClean autoClean;

    jpeg_decompress_struct  cinfo;
    skjpeg_error_mgr        sk_err;
    skjpeg_source_mgr       sk_stream(stream, this, false);

    cinfo.err = jpeg_std_error(&sk_err);
    sk_err.error_exit = skjpeg_error_exit;

    // All objects need to be instantiated before this setjmp call so that
    // they will be cleaned up properly if an error occurs.
    if (setjmp(sk_err.fJmpBuf)) {
        return return_false(cinfo, *bm, "setjmp");
    }

    jpeg_create_decompress(&cinfo);
    autoClean.set(&cinfo);

#ifdef SK_BUILD_FOR_ANDROID
    overwrite_mem_buffer_size(&cinfo);
#endif

    //jpeg_stdio_src(&cinfo, file);
    cinfo.src = &sk_stream;

    int status = jpeg_read_header(&cinfo, true);
    if (status != JPEG_HEADER_OK) {
        return return_false(cinfo, *bm, "read_header");
    }

    /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
        can) much faster that we, just use their num/denom api to approximate
        the size.
    */
    int sampleSize = this->getSampleSize();

    if (this->getPreferQualityOverSpeed()) {
        cinfo.dct_method = JDCT_ISLOW;
    } else {
        cinfo.dct_method = JDCT_IFAST;
    }

    cinfo.scale_num = 1;
    cinfo.scale_denom = sampleSize;

    /* this gives about 30% performance improvement. In theory it may
       reduce the visual quality, in practice I'm not seeing a difference
     */
    cinfo.do_fancy_upsampling = 0;

    /* this gives another few percents */
    cinfo.do_block_smoothing = 0;

    /* default format is RGB */
    cinfo.out_color_space = JCS_RGB;

    SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
    // only these make sense for jpegs
    if (config != SkBitmap::kARGB_8888_Config &&
        config != SkBitmap::kARGB_4444_Config &&
        config != SkBitmap::kRGB_565_Config) {
        config = SkBitmap::kARGB_8888_Config;
    }

#ifdef ANDROID_RGB
    cinfo.dither_mode = JDITHER_NONE;
    if (config == SkBitmap::kARGB_8888_Config) {
        cinfo.out_color_space = JCS_RGBA_8888;
    } else if (config == SkBitmap::kRGB_565_Config) {
        cinfo.out_color_space = JCS_RGB_565;
        if (this->getDitherImage()) {
            cinfo.dither_mode = JDITHER_ORDERED;
        }
    }
#endif

    if (sampleSize == 1 && mode == SkImageDecoder::kDecodeBounds_Mode) {
        bm->setConfig(config, cinfo.image_width, cinfo.image_height);
        bm->setIsOpaque(true);
        return true;
    }

    /*  image_width and image_height are the original dimensions, available
        after jpeg_read_header(). To see the scaled dimensions, we have to call
        jpeg_start_decompress(), and then read output_width and output_height.
    */
    if (!jpeg_start_decompress(&cinfo)) {
        /*  If we failed here, we may still have enough information to return
            to the caller if they just wanted (subsampled bounds). If sampleSize
            was 1, then we would have already returned. Thus we just check if
            we're in kDecodeBounds_Mode, and that we have valid output sizes.

            One reason to fail here is that we have insufficient stream data
            to complete the setup. However, output dimensions seem to get
            computed very early, which is why this special check can pay off.
         */
        if (SkImageDecoder::kDecodeBounds_Mode == mode &&
                valid_output_dimensions(cinfo)) {
            SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
                                       recompute_sampleSize(sampleSize, cinfo));
            bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight());
            bm->setIsOpaque(true);
            return true;
        } else {
            return return_false(cinfo, *bm, "start_decompress");
        }
    }
    sampleSize = recompute_sampleSize(sampleSize, cinfo);

    // should we allow the Chooser (if present) to pick a config for us???
    if (!this->chooseFromOneChoice(config, cinfo.output_width,
                                   cinfo.output_height)) {
        return return_false(cinfo, *bm, "chooseFromOneChoice");
    }

#ifdef ANDROID_RGB
    /* short-circuit the SkScaledBitmapSampler when possible, as this gives
       a significant performance boost.
    */
    if (sampleSize == 1 &&
        ((config == SkBitmap::kARGB_8888_Config && 
                cinfo.out_color_space == JCS_RGBA_8888) ||
        (config == SkBitmap::kRGB_565_Config && 
                cinfo.out_color_space == JCS_RGB_565)))
    {
        bm->lockPixels();
        JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
        bm->unlockPixels();
        bool reuseBitmap = (rowptr != NULL);
        if (reuseBitmap && ((int) cinfo.output_width != bm->width() ||
                (int) cinfo.output_height != bm->height())) {
            // Dimensions must match
            return false;
        }

        if (!reuseBitmap) {
            bm->setConfig(config, cinfo.output_width, cinfo.output_height);
            bm->setIsOpaque(true);
            if (SkImageDecoder::kDecodeBounds_Mode == mode) {
                return true;
            }
            if (!this->allocPixelRef(bm, NULL)) {
                return return_false(cinfo, *bm, "allocPixelRef");
            }
        } else if (SkImageDecoder::kDecodeBounds_Mode == mode) {
            return true;
        }
        SkAutoLockPixels alp(*bm);
        rowptr = (JSAMPLE*)bm->getPixels();
        INT32 const bpr =  bm->rowBytes();
        
        while (cinfo.output_scanline < cinfo.output_height) {
            int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
            // if row_count == 0, then we didn't get a scanline, so abort.
            // if we supported partial images, we might return true in this case
            if (0 == row_count) {
                return return_false(cinfo, *bm, "read_scanlines");
            }
            if (this->shouldCancelDecode()) {
                return return_false(cinfo, *bm, "shouldCancelDecode");
            }
            rowptr += bpr;
        }
        if (reuseBitmap) {
            bm->notifyPixelsChanged();
        }
        jpeg_finish_decompress(&cinfo);
        return true;
    }
#endif
    
    // check for supported formats
    SkScaledBitmapSampler::SrcConfig sc;
    if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
        sc = SkScaledBitmapSampler::kRGB;
#ifdef ANDROID_RGB
    } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
        sc = SkScaledBitmapSampler::kRGBX;
    } else if (JCS_RGB_565 == cinfo.out_color_space) {
        sc = SkScaledBitmapSampler::kRGB_565;
#endif
    } else if (1 == cinfo.out_color_components &&
               JCS_GRAYSCALE == cinfo.out_color_space) {
        sc = SkScaledBitmapSampler::kGray;
    } else {
        return return_false(cinfo, *bm, "jpeg colorspace");
    }

    SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height,
                                  sampleSize);

    bm->lockPixels();
    JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
    bool reuseBitmap = (rowptr != NULL);
    bm->unlockPixels();
    if (reuseBitmap && (sampler.scaledWidth() != bm->width() ||
            sampler.scaledHeight() != bm->height())) {
        // Dimensions must match
        return false;
    }

    if (!reuseBitmap) {
        bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
        // jpegs are always opaque (i.e. have no per-pixel alpha)
        bm->setIsOpaque(true);

        if (SkImageDecoder::kDecodeBounds_Mode == mode) {
            return true;
        }
        if (!this->allocPixelRef(bm, NULL)) {
            return return_false(cinfo, *bm, "allocPixelRef");
        }
    } else if (SkImageDecoder::kDecodeBounds_Mode == mode) {
        return true;
    }

    SkAutoLockPixels alp(*bm);                          
    if (!sampler.begin(bm, sc, this->getDitherImage())) {
        return return_false(cinfo, *bm, "sampler.begin");
    }

    uint8_t* srcRow = (uint8_t*)srcStorage.reset(cinfo.output_width * 4);

    //  Possibly skip initial rows [sampler.srcY0]
    if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
        return return_false(cinfo, *bm, "skip rows");
    }

    // now loop through scanlines until y == bm->height() - 1
    for (int y = 0;; y++) {
        JSAMPLE* rowptr = (JSAMPLE*)srcRow;
        int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
        if (0 == row_count) {
            return return_false(cinfo, *bm, "read_scanlines");
        }
        if (this->shouldCancelDecode()) {
            return return_false(cinfo, *bm, "shouldCancelDecode");
        }
        
        sampler.next(srcRow);
        if (bm->height() - 1 == y) {
            // we're done
            break;
        }

        if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
            return return_false(cinfo, *bm, "skip rows");
        }
    }

    // we formally skip the rest, so we don't get a complaint from libjpeg
    if (!skip_src_rows(&cinfo, srcRow,
                       cinfo.output_height - cinfo.output_scanline)) {
        return return_false(cinfo, *bm, "skip rows");
    }
    if (reuseBitmap) {
        bm->notifyPixelsChanged();
    }
    jpeg_finish_decompress(&cinfo);

//    SkDebugf("------------------- bm2 size %d [%d %d] %d\n", bm->getSize(), bm->width(), bm->height(), bm->config());
    return true;
}
		//! Returns JPG image
		IImage* SharedImageLoaderJpg::createImage(io::IReadFile* file)
		{
			IRR_ASSERT(file);

			s32 jfif = 0;
			file->seek(6);
			file->read(&jfif, sizeof(s32));

			bool isJpegFile = jfif == 0x4a464946 || jfif == 0x4649464a;

			IRR_ASSERT(isJpegFile);

			file->seek(0);

			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 SJpgErrorMgr 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 = StaticJpgExtension::errorExit;
			cinfo.err->output_message = StaticJpgExtension::outputMessage;

			// 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;
				}

				IRR_ASSERT(false);
			}

			// 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 = StaticJpgExtension::initSource;
			jsrc.fill_input_buffer = StaticJpgExtension::fillInputBuffer;
			jsrc.skip_input_data = StaticJpgExtension::skipInputData;
			jsrc.resync_to_restart = jpeg_resync_to_restart;
			jsrc.term_source = StaticJpgExtension::termSource;

			// 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.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* result = 0;
			if (useCMYK)
			{
				result = IImage::createEmptyImage(ECF_R8G8B8,
						dimension2du(width, height));

				const u32 size = 3 * width * height;
				u8* data = (u8*) result->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));
					}
				}
				result->unlock();
				delete[] output;
			}
			else
			{
				result = IImage::createRawImage(ECF_R8G8B8,
						dimension2du(width, height), output);
			}

			delete[] input;

			return result;
		}
int ReadJPEG(FILE* in_file, WebPPicture* const pic, Metadata* const metadata) {
  int ok = 0;
  int stride, width, height;
  struct jpeg_decompress_struct dinfo;
  struct my_error_mgr jerr;
  uint8_t* rgb = NULL;
  JSAMPROW buffer[1];

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

  if (setjmp(jerr.setjmp_buffer)) {
 Error:
    MetadataFree(metadata);
    jpeg_destroy_decompress(&dinfo);
    goto End;
  }

  jpeg_create_decompress(&dinfo);
  jpeg_stdio_src(&dinfo, in_file);
  if (metadata != NULL) SaveMetadataMarkers(&dinfo);
  jpeg_read_header(&dinfo, TRUE);

  dinfo.out_color_space = JCS_RGB;
  dinfo.dct_method = JDCT_IFAST;
  dinfo.do_fancy_upsampling = TRUE;

  jpeg_start_decompress(&dinfo);

  if (dinfo.output_components != 3) {
    goto Error;
  }

  width = dinfo.output_width;
  height = dinfo.output_height;
  stride = dinfo.output_width * dinfo.output_components * sizeof(*rgb);

  rgb = (uint8_t*)malloc(stride * height);
  if (rgb == NULL) {
    goto End;
  }
  buffer[0] = (JSAMPLE*)rgb;

  while (dinfo.output_scanline < dinfo.output_height) {
    if (jpeg_read_scanlines(&dinfo, buffer, 1) != 1) {
      goto End;
    }
    buffer[0] += stride;
  }

  if (metadata != NULL) {
    ok = ExtractMetadataFromJPEG(&dinfo, metadata);
    if (!ok) {
      fprintf(stderr, "Error extracting JPEG metadata!\n");
      goto Error;
    }
  }

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

  // WebP conversion.
  pic->width = width;
  pic->height = height;
  ok = WebPPictureImportRGB(pic, rgb, stride);
  if (!ok) goto Error;

 End:
  free(rgb);
  return ok;
}
示例#9
0
uint8_t* ImageDecoder::decodeJPEGImpl(jpeg_source_mgr *src, jpeg_source_mgr *headerTables, uint32_t* width, uint32_t* height, bool* hasAlpha)
{
	struct jpeg_decompress_struct cinfo;
	struct error_mgr err;

	cinfo.err = jpeg_std_error(&err);
	err.error_exit = error_exit;

	if (setjmp(err.jmpBuf)) {
		return NULL;
	}

	jpeg_create_decompress(&cinfo);
	
	if (headerTables)
	{
		cinfo.src = headerTables;
		jpeg_read_header(&cinfo, FALSE);
	}

	cinfo.src = src;

	if (headerTables)
	{
		// Must call init_source manually after switching src
		src->init_source(&cinfo);
	}

	jpeg_read_header(&cinfo, TRUE);
#ifdef JCS_EXTENSIONS
	//JCS_EXT_XRGB is a fast decoder that outputs alpha channel,
	//but is only available on libjpeg-turbo
	cinfo.out_color_space = JCS_EXT_XRGB;
	cinfo.output_components = 4;
#endif
	jpeg_start_decompress(&cinfo);

	*width = cinfo.output_width;
	*height = cinfo.output_height;
	if(cinfo.num_components != 3)
	{
		LOG(LOG_NOT_IMPLEMENTED,"Only RGB JPEG's are supported");
		/* TODO: is this the right thing for aborting? */
		jpeg_abort_decompress(&cinfo);
		jpeg_destroy_decompress(&cinfo);
		return NULL;
	}
	assert(cinfo.output_components == 3 || cinfo.output_components == 4);

	*hasAlpha = (cinfo.output_components == 4);

	int rowstride = cinfo.output_width * cinfo.output_components;
	JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, rowstride, 1);

	uint8_t* outData = new uint8_t[cinfo.output_height * rowstride];

	/* read one scanline at a time */
	int y=0;
	while (cinfo.output_scanline < cinfo.output_height) {
		jpeg_read_scanlines(&cinfo, buffer, 1);
		memcpy(&outData[y*rowstride], buffer[0], rowstride);
		y++;
	}

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	return outData;
}
示例#10
0
static RageSurface *RageSurface_Load_JPEG( RageFile *f, const char *fn, char errorbuf[JMSG_LENGTH_MAX] )
{
	struct jpeg_decompress_struct cinfo;

	struct my_jpeg_error_mgr jerr;
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
	jerr.pub.output_message = my_output_message;
	
	RageSurface *volatile img = NULL; /* volatile to prevent possible problems with setjmp */

	if( setjmp(jerr.setjmp_buffer) )
	{
		my_jpeg_error_mgr *myerr = (my_jpeg_error_mgr *) cinfo.err;
		memcpy( errorbuf, myerr->errorbuf, JMSG_LENGTH_MAX );
		
		jpeg_destroy_decompress( &cinfo );
		delete img;
		return NULL;
	}

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

	/* Step 2: specify data source (eg, a file) */
	RageFile_source_mgr RageFileJpegSource;
	RageFileJpegSource.pub.init_source = RageFile_JPEG_init_source;
	RageFileJpegSource.pub.fill_input_buffer = RageFile_JPEG_fill_input_buffer;
	RageFileJpegSource.pub.skip_input_data = RageFile_JPEG_skip_input_data;
	RageFileJpegSource.pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
	RageFileJpegSource.pub.term_source = RageFile_JPEG_term_source;
	RageFileJpegSource.file = f;

	cinfo.src = (jpeg_source_mgr *) &RageFileJpegSource;

	jpeg_read_header( &cinfo, TRUE );

	switch( cinfo.jpeg_color_space )
	{
	case JCS_GRAYSCALE:
		cinfo.out_color_space = JCS_GRAYSCALE;
		break;

	case JCS_YCCK:
	case JCS_CMYK:
		sprintf( errorbuf, "Color format \"%s\" not supported", cinfo.jpeg_color_space == JCS_YCCK? "YCCK":"CMYK" );
		jpeg_destroy_decompress( &cinfo );
		return NULL;

	default:
		cinfo.out_color_space = JCS_RGB;
		break;
	}

	jpeg_start_decompress( &cinfo );

	if( cinfo.out_color_space == JCS_GRAYSCALE )
	{
		img = CreateSurface( cinfo.output_width, cinfo.output_height, 8, 0, 0, 0, 0 );

		for( int i = 0; i < 256; ++i )
		{
			RageSurfaceColor color;
			color.r = color.g = color.b = (int8_t) i;
			color.a = 0xFF;
			img->fmt.palette->colors[i] = color;
		}
	} else {
		img = CreateSurface( cinfo.output_width, cinfo.output_height, 24,
				Swap24BE( 0xFF0000 ),
				Swap24BE( 0x00FF00 ),
				Swap24BE( 0x0000FF ),
				Swap24BE( 0x000000 ) );
	}

	while( cinfo.output_scanline < cinfo.output_height )
	{
		JSAMPROW p = (JSAMPROW) img->pixels;
		p += cinfo.output_scanline * img->pitch;
		jpeg_read_scanlines(&cinfo, &p, 1);
	}

	jpeg_finish_decompress( &cinfo );
	jpeg_destroy_decompress( &cinfo );

	return img;
}
示例#11
0
文件: djpeg.c 项目: ONLYOFFICE/core
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;
  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.doc).
   */
  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 */
  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

  /* All done. */
  exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  return 0;			/* suppress no-return-value warnings */
}
示例#12
0
imgdata loadJpeg( const char* filename){
    unsigned char a,r,g,b;
    int img_width, img_height;

    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    FILE *file;
    JSAMPARRAY pJpegBuffer;
    int row_stride;

    std::string image_name(filename);
    file = fopen(image_name.c_str(), "rb");
    if( file == NULL){
        std::string msg("Error opening ");
        throw std::runtime_error(msg + image_name);
    }
    printf("Loading in files %s\n", image_name.c_str());

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, file);
    jpeg_read_header(&cinfo, TRUE);
    jpeg_start_decompress(&cinfo);
    img_width  = cinfo.image_width;
    img_height = cinfo.image_height;
    printf("img_width %d img_height %d\n", img_width, img_height);

    unsigned char *img_data = new unsigned char [4 * img_height * img_width];
    unsigned char *pTest = img_data;
    if(!img_data){
        std::string msg("NO MEM FOR JPEG CONVERT!\n");
        throw std::runtime_error(msg);
    }

    row_stride = img_width * cinfo.output_components;
    pJpegBuffer = (*cinfo.mem->alloc_sarray)
      ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

    while( cinfo.output_scanline < cinfo.output_height){
        jpeg_read_scanlines(&cinfo, pJpegBuffer, 1);
        for( int x=0; x<img_width; x++){
            a = 0;
            r = pJpegBuffer[0][cinfo.output_components*x];
            if( cinfo.output_components > 2){
                g = pJpegBuffer[0][cinfo.output_components*x+1];
                b = pJpegBuffer[0][cinfo.output_components*x+2];
            }else{
                g = r;
                b = r;
            }
            //printf( "r %c g %c b %c\n", r,g,b);
            *(img_data++) = r;
            *(img_data++) = g;
            *(img_data++) = b;
            *(img_data++) = a;
        }
    }
    fclose(file);
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    imgdata retval;
    retval.height = img_height;
    retval.width = img_width;
    retval.data = pTest;

    return retval;
}
示例#13
0
文件: JPEG_band.cpp 项目: hdfeos/gdal
CPLErr JPEG_Codec::DecompressJPEG(buf_mgr &dst, buf_mgr &isrc)
#endif

{
    int nbands = img.pagesize.c;
    // Locals, clean up after themselves
    jpeg_decompress_struct cinfo;
    MRFJPEGStruct sJPEGStruct;
    struct jpeg_error_mgr sJErr;
    BitMask mask(img.pagesize.x, img.pagesize.y);
    RLEC3Packer packer;
    mask.set_packer(&packer);

    memset(&cinfo, 0, sizeof(cinfo));
    // Pass the mask address to the decompressor
    sJPEGStruct.mask = &mask;

    struct jpeg_source_mgr src;

    cinfo.err = jpeg_std_error( &sJErr );
    sJErr.error_exit = errorExit;
    sJErr.emit_message = emitMessage;
    cinfo.client_data = (void *) &(sJPEGStruct);

    src.next_input_byte = (JOCTET *)isrc.buffer;
    src.bytes_in_buffer = isrc.size;
    src.term_source = stub_source_dec;
    src.init_source = stub_source_dec;
    src.skip_input_data = skip_input_data_dec;
    src.fill_input_buffer = fill_input_buffer_dec;
    src.resync_to_restart = jpeg_resync_to_restart;

    jpeg_create_decompress(&cinfo);

    if (setjmp(sJPEGStruct.setjmpBuffer)) {
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error reading JPEG page");
        jpeg_destroy_decompress(&cinfo);
        return CE_Failure;
    }

    cinfo.src = &src;
    jpeg_set_marker_processor(&cinfo, JPEG_APP0 + 3, MaskProcessor);
    jpeg_read_header(&cinfo, TRUE);

    /* In some cases, libjpeg needs to allocate a lot of memory */
    /* http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf */
    if( jpeg_has_multiple_scans(&(cinfo)) )
    {
        /* In this case libjpeg will need to allocate memory or backing */
        /* store for all coefficients */
        /* See call to jinit_d_coef_controller() from master_selection() */
        /* in libjpeg */
        vsi_l_offset nRequiredMemory = 
            static_cast<vsi_l_offset>(cinfo.image_width) *
            cinfo.image_height * cinfo.num_components *
            ((cinfo.data_precision+7)/8);
        /* BLOCK_SMOOTHING_SUPPORTED is generally defined, so we need */
        /* to replicate the logic of jinit_d_coef_controller() */
        if( cinfo.progressive_mode )
            nRequiredMemory *= 3;

#ifndef GDAL_LIBJPEG_LARGEST_MEM_ALLOC
#define GDAL_LIBJPEG_LARGEST_MEM_ALLOC (100 * 1024 * 1024)
#endif

        if( nRequiredMemory > GDAL_LIBJPEG_LARGEST_MEM_ALLOC &&
            CPLGetConfigOption("GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC", nullptr) == nullptr )
        {
                CPLError(CE_Failure, CPLE_NotSupported,
                    "Reading this image would require libjpeg to allocate "
                    "at least " CPL_FRMT_GUIB " bytes. "
                    "This is disabled since above the " CPL_FRMT_GUIB " threshold. "
                    "You may override this restriction by defining the "
                    "GDAL_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, "
                    "or recompile GDAL by defining the "
                    "GDAL_LIBJPEG_LARGEST_MEM_ALLOC macro to a value greater "
                    "than " CPL_FRMT_GUIB,
                    static_cast<GUIntBig>(nRequiredMemory),
                    static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC),
                    static_cast<GUIntBig>(GDAL_LIBJPEG_LARGEST_MEM_ALLOC));
                jpeg_destroy_decompress(&cinfo);
                return CE_Failure;
        }
    }

    // Use float, it is actually faster than the ISLOW method by a tiny bit
    cinfo.dct_method = JDCT_FLOAT;

    //
    // Tolerate different input if we can do the conversion
    // Gray and RGB for example
    // This also means that a RGB MRF can be read as grayscale and vice versa
    // If libJPEG can't convert it will throw an error
    //
    if (nbands == 3 && cinfo.num_components != nbands)
        cinfo.out_color_space = JCS_RGB;
    if (nbands == 1 && cinfo.num_components != nbands)
        cinfo.out_color_space = JCS_GRAYSCALE;

    const int datasize = ((cinfo.data_precision == 8) ? 1 : 2);
    if( cinfo.image_width > static_cast<unsigned>(INT_MAX / (nbands * datasize)) )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG decompress buffer overflow");
        jpeg_destroy_decompress(&cinfo);
        return CE_Failure;
    }
    int linesize = cinfo.image_width * nbands * datasize;

    // We have a mismatch between the real and the declared data format
    // warn and fail if output buffer is too small
    if (linesize > static_cast<int>(INT_MAX / cinfo.image_height)) {
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG decompress buffer overflow");
        jpeg_destroy_decompress(&cinfo);
        return CE_Failure;
    }
    if (linesize*cinfo.image_height != dst.size) {
        CPLError(CE_Warning, CPLE_AppDefined, "MRF: read JPEG size is wrong");
        if (linesize*cinfo.image_height > dst.size) {
            CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG decompress buffer overflow");
            jpeg_destroy_decompress(&cinfo);
            return CE_Failure;
        }
    }

    struct jpeg_progress_mgr sJProgress;
    sJProgress.progress_monitor = ProgressMonitor;
    cinfo.progress = &sJProgress;

    jpeg_start_decompress(&cinfo);

    // Decompress, two lines at a time is what libjpeg does
    while (cinfo.output_scanline < cinfo.image_height) {
        char *rp[2];
        rp[0] = (char *)dst.buffer + linesize*cinfo.output_scanline;
        rp[1] = rp[0] + linesize;
        // if this fails, it calls the error handler
        // which will report an error
        if( jpeg_read_scanlines(&cinfo, JSAMPARRAY(rp), 2) == 0 )
        {
            jpeg_destroy_decompress(&cinfo);
            return CE_Failure;
        }
    }
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    // Apply the mask
    if (datasize == 1)
      apply_mask(sJPEGStruct, reinterpret_cast<char *>(dst.buffer), img.pagesize.c);
    else
      apply_mask(sJPEGStruct, reinterpret_cast<GUInt16 *>(dst.buffer), img.pagesize.c);

    return CE_None;
}
示例#14
0
image_s *
image_new_from_jpeg(const char *path, int is_file, const uint8_t *buf, int size, int scale, int rotate)
{
	image_s *vimage;
	FILE  *file = NULL;
	struct jpeg_decompress_struct cinfo;
	unsigned char *line[16], *ptr;
	int x, y, i, w, h, ofs;
	int maxbuf;
	struct jpeg_error_mgr pub;

	cinfo.err = jpeg_std_error(&pub);
	pub.error_exit = libjpeg_error_handler;
	jpeg_create_decompress(&cinfo);
	if( is_file )
	{
		if( (file = fopen(path, "r")) == NULL )
		{
			return NULL;
		}
		jpeg_stdio_src(&cinfo, file);
	}
	else
	{
		jpeg_memory_src(&cinfo, buf, size);
	}
	if( setjmp(setjmp_buffer) )
	{
		jpeg_destroy_decompress(&cinfo);
		if( is_file && file )
			fclose(file);
		return NULL;
	}
	jpeg_read_header(&cinfo, TRUE);
	cinfo.scale_denom = scale;
	cinfo.do_fancy_upsampling = FALSE;
	cinfo.do_block_smoothing = FALSE;
	cinfo.dct_method = JDCT_IFAST;
	jpeg_start_decompress(&cinfo);
	w = cinfo.output_width;
	h = cinfo.output_height;
	vimage = (rotate & (ROTATE_90|ROTATE_270)) ? image_new(h, w) : image_new(w, h);
	if(!vimage)
	{
		jpeg_destroy_decompress(&cinfo);
		if( is_file )
			fclose(file);
		return NULL;
	}

	if( setjmp(setjmp_buffer) )
	{
		jpeg_destroy_decompress(&cinfo);
		if( is_file && file )
			fclose(file);
		if( vimage )
		{
			free(vimage->buf);
			free(vimage);
		}
		return NULL;
	}

	if(cinfo.rec_outbuf_height > 16)
	{
		DPRINTF(E_WARN, L_METADATA, "ERROR image_from_jpeg : (image_from_jpeg.c) JPEG uses line buffers > 16. Cannot load.\n");
		jpeg_destroy_decompress(&cinfo);
		image_free(vimage);
		if( is_file )
			fclose(file);
		return NULL;
	}
	maxbuf = vimage->width * vimage->height;
	if(cinfo.output_components == 3)
	{
		int rx, ry;
		ofs = 0;
		if((ptr = malloc(w * 3 * cinfo.rec_outbuf_height + 16)) == NULL)
		{
			DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
			jpeg_destroy_decompress(&cinfo);
			image_free(vimage);
			if( is_file )
				fclose(file);
			return NULL;
		}

		for(y = 0; y < h; y += cinfo.rec_outbuf_height)
		{
			ry = (rotate & (ROTATE_90|ROTATE_180)) ? (y - h + 1) * -1 : y;
			for(i = 0; i < cinfo.rec_outbuf_height; i++)
			{
				line[i] = ptr + (w * 3 * i);
			}
			jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
			for(x = 0; x < w * cinfo.rec_outbuf_height; x++)
			{
				rx = (rotate & (ROTATE_180|ROTATE_270)) ? (x - w + 1) * -1 : x;
				ofs = (rotate & (ROTATE_90|ROTATE_270)) ? ry + (rx * h) : rx + (ry * w);
				if( ofs < maxbuf )
					vimage->buf[ofs] = COL(ptr[x + x + x], ptr[x + x + x + 1], ptr[x + x + x + 2]);
			}
		}
		free(ptr);
	}
	else if(cinfo.output_components == 1)
	{
		int rx, ry;
		ofs = 0;
		for(i = 0; i < cinfo.rec_outbuf_height; i++)
		{
			if((line[i] = malloc(w)) == NULL)
			{
				int t = 0;

				for(t = 0; t < i; t++) free(line[t]);
				jpeg_destroy_decompress(&cinfo);
				image_free(vimage);
				if( is_file )
					fclose(file);
				return NULL;
			}
		}
		for(y = 0; y < h; y += cinfo.rec_outbuf_height)
		{
			ry = (rotate & (ROTATE_90|ROTATE_180)) ? (y - h + 1) * -1 : y;
			jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
			for(i = 0; i < cinfo.rec_outbuf_height; i++)
			{
				for(x = 0; x < w; x++)
				{
					rx = (rotate & (ROTATE_180|ROTATE_270)) ?
						(x - w + 1) * -1 : x;
					ofs = (rotate & (ROTATE_90|ROTATE_270)) ?
						ry + (rx * h) : rx + (ry * w);
					if( ofs < maxbuf )
						vimage->buf[ofs] =
							COL(line[i][x], line[i][x], line[i][x]);
				}
			}
		}
		for(i = 0; i < cinfo.rec_outbuf_height; i++)
		{
			 free(line[i]);
		}
	}
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	if( is_file )
		fclose(file);

	return vimage;
}
示例#15
0
bool CCImage::_initWithJpgData(void * data, int nSize)
{
    /* these are standard libjpeg structures for reading(decompression) */
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    /* libjpeg data structure for storing one row, that is, scanline of an image */
    JSAMPROW row_pointer[1] = {0};
    unsigned long location = 0;
    unsigned int i = 0;

    bool bRet = false;
    do 
    {
        /* here we set up the standard libjpeg error handler */
        cinfo.err = jpeg_std_error( &jerr );

        /* setup decompression process and source, then read JPEG header */
        jpeg_create_decompress( &cinfo );

        jpeg_mem_src( &cinfo, (unsigned char *) data, nSize );

        /* reading the image header which contains image information */
        jpeg_read_header( &cinfo, true );

        // we only support RGB or grayscale
        if (cinfo.jpeg_color_space != JCS_RGB)
        {
            if (cinfo.jpeg_color_space == JCS_GRAYSCALE || cinfo.jpeg_color_space == JCS_YCbCr)
            {
                cinfo.out_color_space = JCS_RGB;
            }
        }
        else
        {
            break;
        }

        /* Start decompression jpeg here */
        jpeg_start_decompress( &cinfo );

        /* init image info */
        m_nWidth  = (short)(cinfo.image_width);
        m_nHeight = (short)(cinfo.image_height);
        m_bHasAlpha = false;
        m_bPreMulti = false;
        m_nBitsPerComponent = 8;
        row_pointer[0] = new unsigned char[cinfo.output_width*cinfo.output_components];
        CC_BREAK_IF(! row_pointer[0]);

        m_pData = new unsigned char[cinfo.output_width*cinfo.output_height*cinfo.output_components];
        CC_BREAK_IF(! m_pData);

        /* now actually read the jpeg into the raw buffer */
        /* read one scan line at a time */
        while( cinfo.output_scanline < cinfo.image_height )
        {
            jpeg_read_scanlines( &cinfo, row_pointer, 1 );
            for( i=0; i<cinfo.image_width*cinfo.num_components;i++) 
                m_pData[location++] = row_pointer[0][i];
        }

        jpeg_finish_decompress( &cinfo );
        jpeg_destroy_decompress( &cinfo );
        /* wrap up decompression, destroy objects, free pointers and close open files */        
        bRet = true;
    } while (0);

    CC_SAFE_DELETE_ARRAY(row_pointer[0]);
    return bRet;
}
示例#16
0
// JPG decompression now subroutinised so I can call it from the savegame stuff...
//
// (note, the param "byte* pJPGData" should be a malloc of 4K more than the JPG data because the decompressor will read 
//	up to 4K beyond what's actually presented during decompression).
//	
// This will Z_Malloc the output data buffer that gets fed back into "pic", so Z_Free it yourself later.
//
static void Decompress_JPG( const char *filename, unsigned char **pic, int *width, int *height ) 
{
	/* 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 = { NULL };
	/* 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;
	union {
		byte *b;
		void *v;
	} fbuffer;
	byte  *buf;
	/* 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.
	*/

	int 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) */

	jpeg_mem_src(&cinfo, fbuffer.b, len);

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

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

	(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 */
	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); 

		Com_Printf ("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);
        return;
	}

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

	out = (byte *)Z_Malloc(memcount, TAG_TEMP_WORKSPACE, qfalse);

	*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;
		(void) 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 */

	(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...)
	*/
	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! */
}
/* 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;
    int                            denom;
    DATA8                         *ptr, *line[16], *data;
    DATA32                        *ptr2, *dest;
    int                            x, y, l, i, scans;

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

    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;
}
示例#18
0
// Converts the JPEG image data in pBB into raw RGB data,
// and writes it to pDest. pDest must be large enough to
// hold width * height * 3 bytes of data.
bool UT_JPEG_getRGBData(const UT_ByteBuf* pBB, UT_Byte* pDest, UT_sint32 iDestRowSize, bool bBGR, bool bFlipHoriz)
{
	UT_return_val_if_fail(pBB, false);
	UT_return_val_if_fail(pDest, false);

    struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	/* set the data source */
	_JPEG_ByteBufSrc (&cinfo, pBB);

	jpeg_read_header(&cinfo, TRUE);
	jpeg_start_decompress(&cinfo);
    
	int row_stride = cinfo.output_width * cinfo.output_components;
	
	JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)
			((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

	UT_Byte* pCYMK = NULL;
	if (cinfo.output_components == 4)
		pCYMK = reinterpret_cast<UT_Byte*>(g_malloc(row_stride));

	for (UT_uint32 row = 0; row < cinfo.output_height; row++)
	{
		// determine the place directly into the output buffer
		// where we should decode the next line
		UT_Byte* pB = !bFlipHoriz ?
			pDest + row * iDestRowSize : 
			pDest + (cinfo.output_height - row - 1) * iDestRowSize;

		// we defer the data to a temporary buffer if we are dealing
		// with CYMK data.
		UT_Byte* pD = cinfo.output_components != 4 ? pB : pCYMK;

		// decode the next line
		jpeg_read_scanlines(&cinfo, &pD, 1);

		// postprocess the line
		switch (cinfo.output_components)
		{
			case 1:
				// convert greyscale -> RGB (which is equal to BGR)
				for (UT_sint32 col = cinfo.output_width-1; col >= 0; col--)
				{
					UT_Byte r = pB[col];
					pB[col*3] = r;
					pB[col*3+1] = r;
					pB[col*3+2] = r;
				}
				break;
			case 3:
				if (bBGR)
				{
					// convert RGB -> BGR
					for (UT_sint32 col = 0; col < row_stride; col+=3)
					{
						UT_Byte r = pB[col];
						pB[col] = pB[col+2];
						pB[col+2] = r;
					}
				}
				break;
			case 4:
				// convert CMYK -> RGB (or BGR), and store the 
				// results in the destination buffer (it was in a 
				// temporary buffer up till now)
				for (UT_uint32 pixel = 0; pixel < cinfo.output_width; pixel++)
				{
					UT_sint32 col = pixel * 4;

					UT_Byte r = (pCYMK[col] * pCYMK[col+3] + 127) / 255;
					UT_Byte g = (pCYMK[col+1] * pCYMK[col+3] + 127) / 255;
					UT_Byte b = (pCYMK[col+2] * pCYMK[col+3] + 127) / 255;

					pB[pixel*3] = !bBGR ? r : b;
					pB[pixel*3+1] = g;
					pB[pixel*3+2] = !bBGR ? b : r;
				}
				break;
		}
	}

	FREEP(pCYMK);

	/* This is an important step since it will release a good deal of memory. */
	jpeg_destroy_decompress(&cinfo);

    return true;
}
bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream,
                                        int *width, int *height) {
    SkAutoMalloc  srcStorage;
    SkJPEGImageIndex *index = new SkJPEGImageIndex;

    jpeg_decompress_struct  *cinfo = (jpeg_decompress_struct*)
                                        malloc(sizeof(jpeg_decompress_struct));
    skjpeg_error_mgr        sk_err;
    skjpeg_source_mgr       *sk_stream =
        new skjpeg_source_mgr(stream, this, true);
    if (cinfo == NULL || sk_stream == NULL) {
        return false;
    }

    cinfo->err = jpeg_std_error(&sk_err);
    sk_err.error_exit = skjpeg_error_exit;

    // All objects need to be instantiated before this setjmp call so that
    // they will be cleaned up properly if an error occurs.
    if (setjmp(sk_err.fJmpBuf)) {
        return false;
    }

    jpeg_create_decompress(cinfo);
    cinfo->do_fancy_upsampling = 0;
    cinfo->do_block_smoothing = 0;

#ifdef SK_BUILD_FOR_ANDROID
    overwrite_mem_buffer_size(cinfo);
#endif

    cinfo->src = sk_stream;
    int status = jpeg_read_header(cinfo, true);
    if (status != JPEG_HEADER_OK) {
        return false;
    }
    index->index = (huffman_index*)malloc(sizeof(huffman_index));
    jpeg_create_huffman_index(cinfo, index->index);

    cinfo->scale_num = 1;
    cinfo->scale_denom = 1;
    if (!jpeg_build_huffman_index(cinfo, index->index)) {
        return false;
    }
    if (fReporter)
        fReporter->reportMemory(index->index->mem_used);
    jpeg_destroy_decompress(cinfo);


    // Init decoder to image decode mode
    jpeg_create_decompress(cinfo);

#ifdef SK_BUILD_FOR_ANDROID
    overwrite_mem_buffer_size(cinfo);
#endif

    cinfo->src = sk_stream;
    status = jpeg_read_header(cinfo,true);
    if (status != JPEG_HEADER_OK) {
        return false;
    }
    cinfo->out_color_space = JCS_RGBA_8888;
    cinfo->do_fancy_upsampling = 0;
    cinfo->do_block_smoothing = 0;
    //jpeg_start_decompress(cinfo);
    jpeg_start_tile_decompress(cinfo);

    cinfo->scale_num = 1;
    index->cinfo = cinfo;
    *height = cinfo->output_height;
    *width = cinfo->output_width;
    this->imageWidth = *width;
    this->imageHeight = *height;
    this->index = index;
    return true;
}
示例#20
0
void mexFunction(int nlhs, Matrix *plhs[],
                 int nrhs, Matrix *prhs[]) { 
  FILE * infile;
  JSAMPARRAY buffer;
  Matrix *mp_red, *mp_green, *mp_blue;
  double *pr_red, *pr_green, *pr_blue;
  long i,j,k,row_stride;
  char filename[64];
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;

  if (nrhs < 1 || mxIsNumeric(prhs[0]))
    mexErrMsgTxt("Not enough input arguments, or first argument is not a string");

  mxGetString(prhs[0],filename,64);  /* First argument is the filename */

/*
 * Initialize the jpeg library
 */

  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_decompress(&cinfo);

/*
 * Open jpg file
 */

  if ((infile = fopen(filename, "rb")) == NULL) {
    mexErrMsgTxt("Couldn't open file");
  }

/*
 * Read the jpg header to get info about size and color depth
 */

  jpeg_stdio_src(&cinfo, infile);
  jpeg_read_header(&cinfo, TRUE);
  jpeg_start_decompress(&cinfo);
  if (cinfo.output_components == 1) { /* Grayscale */
    jpeg_destroy_decompress(&cinfo);
    mexErrMsgTxt("Grayscale jpegs not supported");
  }

/*
 * Allocate buffer for one scan line
 */

  row_stride = cinfo.output_width * cinfo.output_components;
  buffer = (*cinfo.mem->alloc_sarray)
                ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

/*
 * Create 3 matrices, One each for the Red, Green, and Blue componenet of the image.
 */

  mp_red = mxCreateFull(cinfo.output_height,cinfo.output_width, REAL);
  mp_green = mxCreateFull(cinfo.output_height,cinfo.output_width, REAL);
  mp_blue = mxCreateFull(cinfo.output_height,cinfo.output_width, REAL);

/*
 * Get pointers to the real part of each matrix (data is stored in a 1 dimensional
 * double array).
 */

  pr_red = mxGetPr(mp_red);pr_green = mxGetPr(mp_green);pr_blue = mxGetPr(mp_blue);

/*
 * Now, loop thru each of the scanlines. For each, copy the image
 * data from the buffer, convert to double, rescale from
 * [0 255] to [0 1] and store in the RGB matrices.
 */

  while (cinfo.output_scanline < cinfo.output_height) {
     jpeg_read_scanlines(&cinfo, buffer,1);
     for (i=0;i<cinfo.output_width;i++) {
       j=(i)*cinfo.output_height+cinfo.output_scanline-1;
       pr_red[j]   = ((double)buffer[0][i*3+0])/255;
       pr_green[j] = ((double)buffer[0][i*3+1])/255;
       pr_blue[j]  = ((double)buffer[0][i*3+2])/255;
     }
  }

/*
 * Clean up
 */

  jpeg_finish_decompress(&cinfo); fclose(infile);
  jpeg_destroy_decompress(&cinfo);

/*
 * Give the mexfile output arguments by making the
 * pointer to left hand side point to the RGB matrices.
 */

  plhs[0]=mp_red; plhs[1]=mp_green; plhs[2]=mp_blue;
  return;		
}
示例#21
0
jas_image_t *jpg_decode(jas_stream_t *in, char *optstr)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	FILE *input_file;
	jpg_dest_t dest_mgr_buf;
	jpg_dest_t *dest_mgr = &dest_mgr_buf;
	int num_scanlines;
	jas_image_t *image;

	/* Avoid compiler warnings about unused parameters. */
	optstr = 0;

	image = 0;
	input_file = 0;
	if (!(input_file = tmpfile())) {
		goto error;
	}
	if (jpg_copystreamtofile(input_file, in)) {
		goto error;
	}
	rewind(input_file);

	/* Allocate and initialize a JPEG decompression object. */
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	/* Specify the data source for decompression. */
	jpeg_stdio_src(&cinfo, input_file);

	/* Read the file header to obtain the image information. */
	jpeg_read_header(&cinfo, TRUE);

	/* Start the decompressor. */
	jpeg_start_decompress(&cinfo);

	/* Create an image object to hold the decoded data. */
	if (!(image = jpg_mkimage(&cinfo))) {
		goto error;
	}

	/* Initialize the data sink object. */
	dest_mgr->image = image;
	dest_mgr->data = jas_matrix_create(1, cinfo.output_width);
	dest_mgr->start_output = jpg_start_output;
	dest_mgr->put_pixel_rows = jpg_put_pixel_rows;
	dest_mgr->finish_output = jpg_finish_output;
    dest_mgr->buffer = (*cinfo.mem->alloc_sarray)
      ((j_common_ptr) &cinfo, JPOOL_IMAGE,
       cinfo.output_width * cinfo.output_components, (JDIMENSION) 1);
	dest_mgr->buffer_height = 1;
	dest_mgr->error = 0;

	/* Process the compressed data. */
	(*dest_mgr->start_output)(&cinfo, dest_mgr);
	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);
	}
	(*dest_mgr->finish_output)(&cinfo, dest_mgr);

	/* Complete the decompression process. */
	jpeg_finish_decompress(&cinfo);

	/* Destroy the JPEG decompression object. */
	jpeg_destroy_decompress(&cinfo);

	jas_matrix_destroy(dest_mgr->data);

	fclose(input_file);

	if (dest_mgr->error) {
		goto error;
	}

	return image;

error:
	if (image) {
		jas_image_destroy(image);
	}
	if (input_file) {
		fclose(input_file);
	}
	return 0;
}
示例#22
0
read_JPEG_file (char * filename)
{
  /* 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 buffer;		/* Output row buffer */
  int 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.
   */

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

  /* 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);
    fclose(infile);
    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);

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

/*  if(DebugIt2)
  {
    printf("Source Image Stats\n");
    printf("  Width=%d\n",cinfo.image_width);
    printf("  height=%d\n",cinfo.image_height);
    printf("  num_components=%d\n",cinfo.num_components);
    if(cinfo.out_color_space==JCS_RGB)
    {
      sourceColorSpace=RGB;      
      printf("  JPEG color space==RGB\n");
    }
    else if(cinfo.out_color_space==JCS_GRAYSCALE)
    {
      sourceColorSpace=GRAY;      
      printf("  JPEG color space==RGB\n");
    }
    else
    {
      sourceColorSpace=unknown;      
      printf("  JPEG color space==RGB\n");
    }
  }*/
  /* 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 */
  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. */
    put_scanline_someplace(&cinfo, (char *)buffer[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! */
  return 1;
}
示例#23
0
文件: jpeg.c 项目: cleure/ImageKit2
API
ImageKit_Image *
ImageKit_Image_FromJPEG(const char *filepath)
{
    ImageKit_Image *self;
    FILE *fp;
    
    /* libjpeg variables */
    struct _jpeg_error_handler error_handler;
    struct jpeg_decompress_struct cinfo;
    int pitch, res;
    JSAMPARRAY buffer;
    
    REAL *ptr_out;
    REAL input_scale = 1.0;
//    int colorspace = CS(RGB);
//    int colorspace_format = CS_FMT(RGB24);
    //REAL *format;

    size_t x;
    uint32_t width, height, channels, depth;
    //uint32_t depth;
    
    fp = fopen(filepath, "rb");
    if (!fp) {
        #ifdef DEBUG
            fprintf(stderr, "unable to open file %s\n", filepath);
        #endif
        
        return NULL;
    }
    
    /* Setup JPEG Errors */
    cinfo.err = jpeg_std_error(&error_handler.err);
    error_handler.err.error_exit = &_jpeg_error_exit;
    error_handler.err.emit_message = &_jpeg_emit_message;
    error_handler.err.output_message = &_jpeg_output_message;

    /* Exception style error handling */
    if (setjmp(error_handler.jmpbuf)) {
        #ifdef DEBUG
            fprintf(stderr, "%s\n", (char *)(&error_handler.error_msg));
        #endif
    
        jpeg_destroy_decompress(&cinfo);
        fclose(fp);
        return NULL;
    }
    
    /* JPEG Stuff */
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, fp);
    jpeg_read_header(&cinfo, 1);
    
    /* Set decompress options */
    cinfo.dct_method = JDCT_FLOAT;
    cinfo.dither_mode = JDITHER_NONE;
    cinfo.out_color_space = JCS_RGB;
    
    jpeg_start_decompress(&cinfo);
    
    width = cinfo.output_width;
    height = cinfo.output_height;
    depth = cinfo.data_precision;
    channels = cinfo.output_components;
    input_scale = 1.0 / (double)MaxNumberForNBits(depth);
    
    /* Create image instance */
    self = ImageKit_Image_New(width, height);
    
    if (!self) {
        jpeg_finish_decompress(&cinfo);
        jpeg_destroy_decompress(&cinfo);
        fclose(fp);
        return NULL;
    }

    pitch = cinfo.output_width * cinfo.output_components;
    buffer = (*cinfo.mem->alloc_sarray)
        ((j_common_ptr) &cinfo, JPOOL_IMAGE, pitch, 1);

    ptr_out = &(self->data1[0]);
    while (cinfo.output_scanline < cinfo.output_height) {
        res = jpeg_read_scanlines(&cinfo, buffer, 1);
        if (res < 1) {
            #ifdef DEBUG
                fprintf(stderr, "jpeg_read_scanlines() < 1, exiting loop\n");
            #endif
            
            break;
        }
        
        for (x = 0; x < self->pitch; x++) {
            ptr_out[x] = (REAL)(buffer[0][x]) * input_scale;
        }
        
        ptr_out += self->pitch;
    }
    
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(fp);

    return self;
}
res_gltex_cache_t * Res_CacheInGLTEX_jpg( res_gltex_register_t *reg )
{
	struct jpeg_decompress_struct cinfo;

	ib_file_t	*h;
	unsigned char *buffer;
	int row_stride;
	struct my_error_mgr jerr;
// 	FILE	*b;

	int	pixels;
	unsigned char	*image, *ptr;
	res_gltex_cache_t		*gltex;
	

	h = IB_Open( reg->path );
//	b = fopen( "test.jpg", "rb" );

	if( !h )
	{
		__error( "load of '%s' failed\n", reg->path );
	}

//	memset( &cinfo, 0, sizeof( struct jpeg_decompress_struct ));

	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = jpeg_error_exit;
	
	if (setjmp (jerr.setjmp_buffer))                                              
	{

		jpeg_destroy_decompress (&cinfo);
		if( h )
			IB_Close( h );
		__error( "XJT: JPEG load error\n");
	       
	}



	printf( "%p\n", cinfo.err );


	// step 1

	jpeg_create_decompress(&cinfo);	
//	cinfo.err = jpeg_std_error (&jerr.pub);                                       
//	printf( "%p\n", cinfo.err );

	// step 2
	jpeg_ibase_src(&cinfo, h);
//	jpeg_stdio_src( &cinfo, b );

//	printf( "back\n" );
	
	// step 3
	jpeg_read_header(&cinfo, TRUE);


/*
	if( cinfo.jpeg_color_space != JCS_RGB )
	{
		__error( "colorspace is not RGB\n" );
	}
*/


	jpeg_start_decompress( &cinfo );
//	printf( "jpeg: %d %d %d\n", cinfo.image_width, cinfo.image_height, cinfo.output_components );
	if( cinfo.output_components != 3 )
	{
		__error( "jpeg file '%s' is not RGB\n", reg->path );
	}

	pixels = cinfo.output_width * cinfo.output_height;
	image = (unsigned char *)MM_Malloc( pixels * 3 );
       


	row_stride = cinfo.output_width * 3;

	ptr = image + ( row_stride * (cinfo.output_height - 1) );

	std::vector<unsigned char>buffer_data( row_stride );
	buffer = buffer_data.data();
	//buffer = (unsigned char *)alloca( row_stride );

//	printf( "row_stride: %d\n", row_stride );

       

	while( cinfo.output_scanline < cinfo.output_height )
	{
//		__named_message( "%d\n", cinfo.output_scanline );
		jpeg_read_scanlines( &cinfo, &buffer, 1 ); 
	
		memcpy( ptr, buffer, row_stride );
		
		ptr -= row_stride;

	}

//	memset( image, 0, pixels *3 );

	jpeg_finish_decompress( &cinfo );
	jpeg_destroy_decompress( &cinfo );
	IB_Close( h );

	gltex = NEWTYPE( res_gltex_cache_t );
	gltex->width = cinfo.output_width;
	gltex->height = cinfo.output_height;

	__message( "%s: %d %d\n", reg->path, gltex->width, gltex->height );

	gltex->comp = resGltexComponents_rgb;
	Res_CreateGLTEX_rgb( cinfo.output_width, cinfo.output_height, image );
//	__error( "good\n" );

	return gltex;
}
示例#25
0
G_MODULE_EXPORT gboolean
tracker_extract_get_metadata (TrackerExtractInfo *info)
{
	struct jpeg_decompress_struct cinfo;
	struct tej_error_mgr tejerr;
	struct jpeg_marker_struct *marker;
	TrackerSparqlBuilder *preupdate, *metadata;
	TrackerXmpData *xd = NULL;
	TrackerExifData *ed = NULL;
	TrackerIptcData *id = NULL;
	MergeData md = { 0 };
	GFile *file;
	FILE *f;
	goffset size;
	gchar *filename, *uri;
	gchar *comment = NULL;
	const gchar *dlna_profile, *dlna_mimetype, *graph;
	GPtrArray *keywords;
	gboolean success = TRUE;
	GString *where;
	guint i;

	metadata = tracker_extract_info_get_metadata_builder (info);
	preupdate = tracker_extract_info_get_preupdate_builder (info);
	graph = tracker_extract_info_get_graph (info);

	file = tracker_extract_info_get_file (info);
	filename = g_file_get_path (file);

	size = tracker_file_get_size (filename);

	if (size < 18) {
		g_free (filename);
		return FALSE;
	}

	f = tracker_file_open (filename);
	g_free (filename);

	if (!f) {
		return FALSE;
	}

	uri = g_file_get_uri (file);

	tracker_sparql_builder_predicate (metadata, "a");
	tracker_sparql_builder_object (metadata, "nfo:Image");
	tracker_sparql_builder_predicate (metadata, "a");
	tracker_sparql_builder_object (metadata, "nmm:Photo");

	cinfo.err = jpeg_std_error (&tejerr.jpeg);
	tejerr.jpeg.error_exit = extract_jpeg_error_exit;
	if (setjmp (tejerr.setjmp_buffer)) {
		success = FALSE;
		goto fail;
	}

	jpeg_create_decompress (&cinfo);

	jpeg_save_markers (&cinfo, JPEG_COM, 0xFFFF);
	jpeg_save_markers (&cinfo, JPEG_APP0 + 1, 0xFFFF);
	jpeg_save_markers (&cinfo, JPEG_APP0 + 13, 0xFFFF);

	jpeg_stdio_src (&cinfo, f);

	jpeg_read_header (&cinfo, TRUE);

	/* FIXME? It is possible that there are markers after SOS,
	 * but there shouldn't be. Should we decompress the whole file?
	 *
	 * jpeg_start_decompress(&cinfo);
	 * jpeg_finish_decompress(&cinfo);
	 *
	 * jpeg_calc_output_dimensions(&cinfo);
	 */

	marker = (struct jpeg_marker_struct *) &cinfo.marker_list;

	while (marker) {
		gchar *str;
		gsize len;
#ifdef HAVE_LIBIPTCDATA
		gsize offset;
		guint sublen;
#endif /* HAVE_LIBIPTCDATA */

		switch (marker->marker) {
		case JPEG_COM:
			g_free (comment);
			comment = g_strndup ((gchar*) marker->data, marker->data_length);
			break;

		case JPEG_APP0 + 1:
			str = (gchar*) marker->data;
			len = marker->data_length;

#ifdef HAVE_LIBEXIF
			if (strncmp (EXIF_NAMESPACE, str, EXIF_NAMESPACE_LENGTH) == 0) {
				ed = tracker_exif_new ((guchar *) marker->data, len, uri);
			}
#endif /* HAVE_LIBEXIF */

#ifdef HAVE_EXEMPI
			if (strncmp (XMP_NAMESPACE, str, XMP_NAMESPACE_LENGTH) == 0) {
				xd = tracker_xmp_new (str + XMP_NAMESPACE_LENGTH,
				                      len - XMP_NAMESPACE_LENGTH,
				                      uri);
			}
#endif /* HAVE_EXEMPI */

			break;

		case JPEG_APP0 + 13:
			str = (gchar*) marker->data;
			len = marker->data_length;
#ifdef HAVE_LIBIPTCDATA
			if (len > 0 && strncmp (PS3_NAMESPACE, str, PS3_NAMESPACE_LENGTH) == 0) {
				offset = iptc_jpeg_ps3_find_iptc (str, len, &sublen);
				if (offset > 0 && sublen > 0) {
					id = tracker_iptc_new (str + offset, sublen, uri);
				}
			}
#endif /* HAVE_LIBIPTCDATA */

			break;

		default:
			marker = marker->next;
			continue;
		}

		marker = marker->next;
	}

	if (!ed) {
		ed = g_new0 (TrackerExifData, 1);
	}

	if (!xd) {
		xd = g_new0 (TrackerXmpData, 1);
	}

	if (!id) {
		id = g_new0 (TrackerIptcData, 1);
	}

	md.title = tracker_coalesce_strip (4, xd->title, ed->document_name, xd->title2, xd->pdf_title);
	md.orientation = tracker_coalesce_strip (3, xd->orientation, ed->orientation, id->image_orientation);
	md.copyright = tracker_coalesce_strip (4, xd->copyright, xd->rights, ed->copyright, id->copyright_notice);
	md.white_balance = tracker_coalesce_strip (2, xd->white_balance, ed->white_balance);
	md.fnumber = tracker_coalesce_strip (2, xd->fnumber, ed->fnumber);
	md.flash = tracker_coalesce_strip (2, xd->flash, ed->flash);
	md.focal_length =  tracker_coalesce_strip (2, xd->focal_length, ed->focal_length);
	md.artist = tracker_coalesce_strip (3, xd->artist, ed->artist, xd->contributor);
	md.exposure_time = tracker_coalesce_strip (2, xd->exposure_time, ed->exposure_time);
	md.iso_speed_ratings = tracker_coalesce_strip (2, xd->iso_speed_ratings, ed->iso_speed_ratings);
	md.date = tracker_coalesce_strip (5, xd->date, xd->time_original, ed->time, id->date_created, ed->time_original);
	md.description = tracker_coalesce_strip (2, xd->description, ed->description);
	md.metering_mode = tracker_coalesce_strip (2, xd->metering_mode, ed->metering_mode);
	md.city = tracker_coalesce_strip (2, xd->city, id->city);
	md.state = tracker_coalesce_strip (2, xd->state, id->state);
	md.address = tracker_coalesce_strip (2, xd->address, id->sublocation);
	md.country = tracker_coalesce_strip (2, xd->country, id->country_name);

	/* FIXME We are not handling the altitude ref here for xmp */
	md.gps_altitude = tracker_coalesce_strip (2, xd->gps_altitude, ed->gps_altitude);
	md.gps_latitude = tracker_coalesce_strip (2, xd->gps_latitude, ed->gps_latitude);
	md.gps_longitude = tracker_coalesce_strip (2, xd->gps_longitude, ed->gps_longitude);
	md.gps_direction = tracker_coalesce_strip (2, xd->gps_direction, ed->gps_direction);
	md.creator = tracker_coalesce_strip (3, xd->creator, id->byline, id->credit);
	md.comment = tracker_coalesce_strip (2, comment, ed->user_comment);
	md.make = tracker_coalesce_strip (2, xd->make, ed->make);
	md.model = tracker_coalesce_strip (2, xd->model, ed->model);

	/* Prioritize on native dimention in all cases */
	tracker_sparql_builder_predicate (metadata, "nfo:width");
	tracker_sparql_builder_object_int64 (metadata, cinfo.image_width);

	/* TODO: add ontology and store ed->software */

	tracker_sparql_builder_predicate (metadata, "nfo:height");
	tracker_sparql_builder_object_int64 (metadata, cinfo.image_height);

	if (guess_dlna_profile (cinfo.image_width, cinfo.image_height, &dlna_profile, &dlna_mimetype)) {
		tracker_sparql_builder_predicate (metadata, "nmm:dlnaProfile");
		tracker_sparql_builder_object_string (metadata, dlna_profile);
		tracker_sparql_builder_predicate (metadata, "nmm:dlnaMime");
		tracker_sparql_builder_object_string (metadata, dlna_mimetype);
	}

	if (id->contact) {
		gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", id->contact);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nco:Contact");
		tracker_sparql_builder_predicate (preupdate, "nco:fullname");
		tracker_sparql_builder_object_unvalidated (preupdate, id->contact);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nco:representative");
		tracker_sparql_builder_object_iri (metadata, uri);
		g_free (uri);
	}

	keywords = g_ptr_array_new ();

	if (xd->keywords) {
		tracker_keywords_parse (keywords, xd->keywords);
	}

	if (xd->pdf_keywords) {
		tracker_keywords_parse (keywords, xd->pdf_keywords);
	}

	if (xd->subject) {
		tracker_keywords_parse (keywords, xd->subject);
	}

	if (xd->publisher) {
		gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", xd->publisher);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nco:Contact");
		tracker_sparql_builder_predicate (preupdate, "nco:fullname");
		tracker_sparql_builder_object_unvalidated (preupdate, xd->publisher);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nco:publisher");
		tracker_sparql_builder_object_iri (metadata, uri);
		g_free (uri);
	}

	if (xd->type) {
		tracker_sparql_builder_predicate (metadata, "dc:type");
		tracker_sparql_builder_object_unvalidated (metadata, xd->type);
	}

	if (xd->rating) {
		tracker_sparql_builder_predicate (metadata, "nao:numericRating");
		tracker_sparql_builder_object_unvalidated (metadata, xd->rating);
	}

	if (xd->format) {
		tracker_sparql_builder_predicate (metadata, "dc:format");
		tracker_sparql_builder_object_unvalidated (metadata, xd->format);
	}

	if (xd->identifier) {
		tracker_sparql_builder_predicate (metadata, "dc:indentifier");
		tracker_sparql_builder_object_unvalidated (metadata, xd->identifier);
	}

	if (xd->source) {
		tracker_sparql_builder_predicate (metadata, "dc:source");
		tracker_sparql_builder_object_unvalidated (metadata, xd->source);
	}

	if (xd->language) {
		tracker_sparql_builder_predicate (metadata, "dc:language");
		tracker_sparql_builder_object_unvalidated (metadata, xd->language);
	}

	if (xd->relation) {
		tracker_sparql_builder_predicate (metadata, "dc:relation");
		tracker_sparql_builder_object_unvalidated (metadata, xd->relation);
	}

	if (xd->coverage) {
		tracker_sparql_builder_predicate (metadata, "dc:coverage");
		tracker_sparql_builder_object_unvalidated (metadata, xd->coverage);
	}

	if (xd->license) {
		tracker_sparql_builder_predicate (metadata, "nie:license");
		tracker_sparql_builder_object_unvalidated (metadata, xd->license);
	}

        if (xd->regions) {
	        tracker_xmp_apply_regions (preupdate, metadata, graph, xd);
        }

	if (id->keywords) {
		tracker_keywords_parse (keywords, id->keywords);
	}

	where = g_string_new ("");

	for (i = 0; i < keywords->len; i++) {
		gchar *p, *escaped, *var;

		p = g_ptr_array_index (keywords, i);
		escaped = tracker_sparql_escape_string (p);
		var = g_strdup_printf ("tag%d", i + 1);

		/* ensure tag with specified label exists */
		tracker_sparql_builder_append (preupdate, "INSERT { ");

		if (graph) {
			tracker_sparql_builder_append (preupdate, "GRAPH <");
			tracker_sparql_builder_append (preupdate, graph);
			tracker_sparql_builder_append (preupdate, "> { ");
		}

		tracker_sparql_builder_append (preupdate,
		                               "_:tag a nao:Tag ; nao:prefLabel \"");
		tracker_sparql_builder_append (preupdate, escaped);
		tracker_sparql_builder_append (preupdate, "\"");

		if (graph) {
			tracker_sparql_builder_append (preupdate, " } ");
		}

		tracker_sparql_builder_append (preupdate, " }\n");
		tracker_sparql_builder_append (preupdate,
		                               "WHERE { FILTER (NOT EXISTS { "
		                               "?tag a nao:Tag ; nao:prefLabel \"");
		tracker_sparql_builder_append (preupdate, escaped);
		tracker_sparql_builder_append (preupdate,
		                               "\" }) }\n");

		/* associate file with tag */
		tracker_sparql_builder_predicate (metadata, "nao:hasTag");
		tracker_sparql_builder_object_variable (metadata, var);

		g_string_append_printf (where, "?%s a nao:Tag ; nao:prefLabel \"%s\" .\n", var, escaped);

		g_free (var);
		g_free (escaped);
		g_free (p);
	}
	g_ptr_array_free (keywords, TRUE);

	tracker_extract_info_set_where_clause (info, where->str);
	g_string_free (where, TRUE);

	if (md.make || md.model) {
		gchar *equip_uri;

		equip_uri = tracker_sparql_escape_uri_printf ("urn:equipment:%s:%s:",
		                                              md.make ? md.make : "",
		                                              md.model ? md.model : "");

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, equip_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nfo:Equipment");

		if (md.make) {
			tracker_sparql_builder_predicate (preupdate, "nfo:manufacturer");
			tracker_sparql_builder_object_unvalidated (preupdate, md.make);
		}
		if (md.model) {
			tracker_sparql_builder_predicate (preupdate, "nfo:model");
			tracker_sparql_builder_object_unvalidated (preupdate, md.model);
		}

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nfo:equipment");
		tracker_sparql_builder_object_iri (metadata, equip_uri);
		g_free (equip_uri);
	}

	tracker_guarantee_title_from_file (metadata,
	                                   "nie:title",
	                                   md.title,
	                                   uri,
	                                   NULL);

	if (md.orientation) {
		tracker_sparql_builder_predicate (metadata, "nfo:orientation");
		tracker_sparql_builder_object (metadata, md.orientation);
	}

	if (md.copyright) {
		tracker_sparql_builder_predicate (metadata, "nie:copyright");
		tracker_sparql_builder_object_unvalidated (metadata, md.copyright);
	}

	if (md.white_balance) {
		tracker_sparql_builder_predicate (metadata, "nmm:whiteBalance");
		tracker_sparql_builder_object (metadata, md.white_balance);
	}

	if (md.fnumber) {
		gdouble value;

		value = g_strtod (md.fnumber, NULL);
		tracker_sparql_builder_predicate (metadata, "nmm:fnumber");
		tracker_sparql_builder_object_double (metadata, value);
	}

	if (md.flash) {
		tracker_sparql_builder_predicate (metadata, "nmm:flash");
		tracker_sparql_builder_object (metadata, md.flash);
	}

	if (md.focal_length) {
		gdouble value;

		value = g_strtod (md.focal_length, NULL);
		tracker_sparql_builder_predicate (metadata, "nmm:focalLength");
		tracker_sparql_builder_object_double (metadata, value);
	}

	if (md.artist) {
		gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.artist);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nco:Contact");
		tracker_sparql_builder_predicate (preupdate, "nco:fullname");
		tracker_sparql_builder_object_unvalidated (preupdate, md.artist);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nco:contributor");
		tracker_sparql_builder_object_iri (metadata, uri);
		g_free (uri);
	}

	if (md.exposure_time) {
		gdouble value;

		value = g_strtod (md.exposure_time, NULL);
		tracker_sparql_builder_predicate (metadata, "nmm:exposureTime");
		tracker_sparql_builder_object_double (metadata, value);
	}

	if (md.iso_speed_ratings) {
		gdouble value;

		value = g_strtod (md.iso_speed_ratings, NULL);
		tracker_sparql_builder_predicate (metadata, "nmm:isoSpeed");
		tracker_sparql_builder_object_double (metadata, value);
	}

	tracker_guarantee_date_from_file_mtime (metadata,
	                                        "nie:contentCreated",
	                                        md.date,
	                                        uri);

	if (md.description) {
		tracker_sparql_builder_predicate (metadata, "nie:description");
		tracker_sparql_builder_object_unvalidated (metadata, md.description);
	}

	if (md.metering_mode) {
		tracker_sparql_builder_predicate (metadata, "nmm:meteringMode");
		tracker_sparql_builder_object (metadata, md.metering_mode);
	}

	if (md.creator) {
		gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.creator);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nco:Contact");
		tracker_sparql_builder_predicate (preupdate, "nco:fullname");
		tracker_sparql_builder_object_unvalidated (preupdate, md.creator);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		/* NOTE: We only have affiliation with
		 * nco:PersonContact and we are using
		 * nco:Contact here.
		 */

		/* if (id->byline_title) { */
		/* 	tracker_sparql_builder_insert_open (preupdate, NULL); */

		/* 	tracker_sparql_builder_subject (preupdate, "_:affiliation_by_line"); */
		/* 	tracker_sparql_builder_predicate (preupdate, "a"); */
		/* 	tracker_sparql_builder_object (preupdate, "nco:Affiliation"); */

		/* 	tracker_sparql_builder_predicate (preupdate, "nco:title"); */
		/* 	tracker_sparql_builder_object_unvalidated (preupdate, id->byline_title); */

		/* 	tracker_sparql_builder_insert_close (preupdate); */

		/*      tracker_sparql_builder_predicate (preupdate, "a"); */
		/*      tracker_sparql_builder_object (preupdate, "nco:Contact"); */
		/*      tracker_sparql_builder_predicate (preupdate, "nco:hasAffiliation"); */
		/*      tracker_sparql_builder_object (preupdate, "_:affiliation_by_line"); */
		/* } */

		tracker_sparql_builder_predicate (metadata, "nco:creator");
		tracker_sparql_builder_object_iri (metadata, uri);
		g_free (uri);
	}

	if (md.comment) {
		tracker_sparql_builder_predicate (metadata, "nie:comment");
		tracker_sparql_builder_object_unvalidated (metadata, md.comment);
	}

	if (md.address || md.state || md.country || md.city ||
	    md.gps_altitude || md.gps_latitude || md.gps_longitude) {

		tracker_sparql_builder_predicate (metadata, "slo:location");

		tracker_sparql_builder_object_blank_open (metadata); /* GeoPoint */
		tracker_sparql_builder_predicate (metadata, "a");
		tracker_sparql_builder_object (metadata, "slo:GeoLocation");

		if (md.address || md.state || md.country || md.city) {
			gchar *addruri;

			addruri = tracker_sparql_get_uuid_urn ();

			tracker_sparql_builder_predicate (metadata, "slo:postalAddress");
			tracker_sparql_builder_object_iri (metadata, addruri);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, addruri);

			g_free (addruri);

			tracker_sparql_builder_predicate (preupdate, "a");
			tracker_sparql_builder_object (preupdate, "nco:PostalAddress");

			if (md.address) {
				tracker_sparql_builder_predicate (preupdate, "nco:streetAddress");
				tracker_sparql_builder_object_unvalidated (preupdate, md.address);
			}

			if (md.state) {
				tracker_sparql_builder_predicate (preupdate, "nco:region");
				tracker_sparql_builder_object_unvalidated (preupdate, md.state);
			}

			if (md.city) {
				tracker_sparql_builder_predicate (preupdate, "nco:locality");
				tracker_sparql_builder_object_unvalidated (preupdate, md.city);
			}

			if (md.country) {
				tracker_sparql_builder_predicate (preupdate, "nco:country");
				tracker_sparql_builder_object_unvalidated (preupdate, md.country);
			}

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		if (md.gps_altitude) {
			tracker_sparql_builder_predicate (metadata, "slo:altitude");
			tracker_sparql_builder_object_unvalidated (metadata, md.gps_altitude);
		}

		if (md.gps_latitude) {
			tracker_sparql_builder_predicate (metadata, "slo:latitude");
			tracker_sparql_builder_object_unvalidated (metadata, md.gps_latitude);
		}

		if (md.gps_longitude) {
			tracker_sparql_builder_predicate (metadata, "slo:longitude");
			tracker_sparql_builder_object_unvalidated (metadata, md.gps_longitude);
		}

		tracker_sparql_builder_object_blank_close (metadata); /* GeoLocation */
	}

	if (md.gps_direction) {
		tracker_sparql_builder_predicate (metadata, "nfo:heading");
		tracker_sparql_builder_object_unvalidated (metadata, md.gps_direction);
	}

	if (cinfo.density_unit != 0 || ed->x_resolution) {
		gdouble value;

		if (cinfo.density_unit == 0) {
			if (ed->resolution_unit != 3)
				value = g_strtod (ed->x_resolution, NULL);
			else
				value = g_strtod (ed->x_resolution, NULL) * CM_TO_INCH;
		} else {
			if (cinfo.density_unit == 1)
				value = cinfo.X_density;
			else
				value = cinfo.X_density * CM_TO_INCH;
		}

		tracker_sparql_builder_predicate (metadata, "nfo:horizontalResolution");
		tracker_sparql_builder_object_double (metadata, value);
	}

	if (cinfo.density_unit != 0 || ed->y_resolution) {
		gdouble value;

		if (cinfo.density_unit == 0) {
			if (ed->resolution_unit != 3)
				value = g_strtod (ed->y_resolution, NULL);
			else
				value = g_strtod (ed->y_resolution, NULL) * CM_TO_INCH;
		} else {
			if (cinfo.density_unit == 1)
				value = cinfo.Y_density;
			else
				value = cinfo.Y_density * CM_TO_INCH;
		}

		tracker_sparql_builder_predicate (metadata, "nfo:verticalResolution");
		tracker_sparql_builder_object_double (metadata, value);
	}

	jpeg_destroy_decompress (&cinfo);

	tracker_exif_free (ed);
	tracker_xmp_free (xd);
	tracker_iptc_free (id);
	g_free (comment);

fail:
	tracker_file_close (f, FALSE);
	g_free (uri);

	return success;
}
示例#26
0
void processimage (const void *p, int l)
{

    struct jpeg_decompress_struct mycinfo;
    struct my_error_mgr myjerr;
    JSAMPARRAY jpegbuffer=NULL;
    int row_stride;

    mycinfo.err = jpeg_std_error(&myjerr.pub);
    myjerr.pub.error_exit = my_error_exit;
    if (setjmp(myjerr.setjmp_buffer)) {
        jpeg_destroy_decompress(&mycinfo);
        return ;/*exit(0);*/
    }
    jpeg_create_decompress(&mycinfo);

    jpeg_memory_src(&mycinfo, p, l) ;

    ((memory_source_mgr *)mycinfo.src)->pub.next_input_byte = (JOCTET*)p;
    ((memory_source_mgr *)mycinfo.src)->pub.bytes_in_buffer = l;

    jpeg_read_header(&mycinfo, TRUE);

    mycinfo.out_color_space = JCS_RGB;
    mycinfo.dct_method = JDCT_IFAST;
    mycinfo.jpeg_color_space = JCS_YCbCr;

    my_jpeg_load_dht( &mycinfo,
                      my_jpeg_odml_dht,
                      mycinfo.ac_huff_tbl_ptrs,
                      mycinfo.dc_huff_tbl_ptrs );

    jpeg_start_decompress(&mycinfo);

    row_stride = mycinfo.image_width * mycinfo.num_components;

    if(rgb == NULL) {
        IMG_WIDTH=mycinfo.image_width;
        IMG_HEIGHT=mycinfo.image_height;
        rgb = (int *)malloc(sizeof(int) * (IMG_WIDTH*IMG_HEIGHT));
    }

    if(jpegbuffer==NULL) {
        jpegbuffer = (*mycinfo.mem->alloc_sarray)
                     ((j_common_ptr) &mycinfo, JPOOL_IMAGE, row_stride, 1);
    }

    int y = 0;
    int *outp=rgb;
    while ( mycinfo.output_scanline < mycinfo.image_height) {

        jpeg_read_scanlines(&mycinfo, jpegbuffer, 1);

        int xx;
        int x3;

        for(xx = 0, x3 = 0; xx < IMG_WIDTH && x3 < row_stride; xx++, x3 += 3)
        {
            outp[y+xx] = 0xff000000 | jpegbuffer[0][x3 + 2]<<16
                         | jpegbuffer[0][x3 + 1]<<8 | jpegbuffer[0][x3 + 0];
        }

        y+=IMG_WIDTH;
    }

    jpeg_finish_decompress(&mycinfo);
    jpeg_destroy_decompress(&mycinfo);

}
示例#27
0
int decompress_jpeg(unsigned char *jpeg, int jpegsize, decompressed_image *image)
{
    struct jpeg_decompress_struct cinfo;
    JSAMPROW rowptr[1];
    struct jpeg_error_mgr jerr;

    /* create an error handler that does not terminate MJPEG-streamer */
    cinfo.err = jpeg_std_error(&jerr);
    jerr.error_exit = my_error_exit;
    jerr.output_message = my_error_output_message;

    /* create the decompressor structures */
    jpeg_create_decompress(&cinfo);

    /* initalize the structures of decompressor */
    jpeg_init_src(&cinfo, jpeg, jpegsize);

    /* read the JPEG header data */
    if(jpeg_read_header(&cinfo, TRUE) < 0) {
        jpeg_destroy_decompress(&cinfo);
        DBG("could not read the header\n");
        return 1;
    }

    /*
     * I just expect RGB colored JPEGs, so the num_components must be three
     */
    if(cinfo.num_components != 3) {
        jpeg_destroy_decompress(&cinfo);
        DBG("unsupported number of components (~colorspace)\n");
        return 1;
    }

    /* just use RGB output and adjust decompression parameters */
    cinfo.out_color_space = JCS_RGB;
    cinfo.quantize_colors = FALSE;
    /* to scale the decompressed image, the fraction could be changed here */
    cinfo.scale_num   = 1;
    cinfo.scale_denom = 1;
    cinfo.dct_method = JDCT_FASTEST;
    cinfo.do_fancy_upsampling = FALSE;

    jpeg_calc_output_dimensions(&cinfo);

    /* store the image information */
    image->width = cinfo.output_width;
    image->height = cinfo.output_height;

    /*
     * just allocate a new buffer if not already allocated
     * pay a lot attention, that the calling function has to ensure, that the buffer
     * must be large enough
     */
    if(image->buffer == NULL) {
        image->buffersize = image->width * image->height * cinfo.num_components;
        /* the calling function has to ensure that this buffer will become freed after use! */
        image->buffer = malloc(image->buffersize);
        if(image->buffer == NULL) {
            jpeg_destroy_decompress(&cinfo);
            DBG("allocating memory failed\n");
            return 1;
        }
    }

    /* start to decompress */
    if(jpeg_start_decompress(&cinfo) < 0) {
        jpeg_destroy_decompress(&cinfo);
        DBG("could not start decompression\n");
        return 1;
    }

    while(cinfo.output_scanline < cinfo.output_height) {
        rowptr[0] = (JSAMPROW)(Uint8 *)image->buffer + cinfo.output_scanline * image->width * cinfo.num_components;

        if(jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1) < 0) {
            jpeg_destroy_decompress(&cinfo);
            DBG("could not decompress this line\n");
            return 1;
        }
    }

    if(jpeg_finish_decompress(&cinfo) < 0) {
        jpeg_destroy_decompress(&cinfo);
        DBG("could not finish compression\n");
        return 1;
    }

    /* all is done */
    jpeg_destroy_decompress(&cinfo);

    return 0;
}
示例#28
0
文件: jpeg.c 项目: fshunj/LCUI
/* 载入jpeg图片文件 */
LCUI_API int Graph_LoadJPEG( const char *filepath, LCUI_Graph *out )
{
#ifdef USE_LIBJPEG
	FILE *fp;
	int row_stride,jaka;
	int x,y, m, n, k;
	short int JPsyg;
	
	struct jpeg_decompress_struct cinfo;
	struct my_error_mgr jerr;
	JSAMPARRAY buffer;

	fp = fopen(filepath,"r");
	if(fp == NULL) {
		return FILE_ERROR_OPEN_ERROR;
	}
	
	if( fread( &JPsyg, sizeof(short int), 1, fp ) ) {
		if ( JPsyg != -9985 ) {  /* 如果不是jpg图片 */
			return  FILE_ERROR_UNKNOWN_FORMAT; 
		}
	}
	rewind(fp);
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
	if (setjmp(jerr.setjmp_buffer)) {
		jpeg_destroy_decompress(&cinfo);
		return 2;
	}
	
	jpeg_create_decompress(&cinfo);
	jpeg_stdio_src(&cinfo,fp);
	(void) jpeg_read_header(&cinfo,TRUE);
	(void) jpeg_start_decompress(&cinfo);    
	
	jaka = cinfo.num_components;
	
	//if (jaka==3) printf("color\n"); else printf("grayscale\n");
	out->color_type = COLOR_TYPE_RGB;
	n = Graph_Create(out, cinfo.output_width, cinfo.output_height);
	if( n != 0 ){
		printf("%s (): error: %s",__FUNCTION__, MALLOC_ERROR);
		exit(-1);
	}
	
	row_stride = cinfo.output_width * cinfo.output_components;
	buffer = (*cinfo.mem->alloc_sarray)(
			(j_common_ptr) &cinfo,JPOOL_IMAGE,row_stride,1);
	
	for(y=0; cinfo.output_scanline <cinfo.output_height; ++y) {
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
		m = y*out->w;
		if ( jaka == 3 ) {
			for (x=0;x<out->w;x++) {
				n = x+m;
				k=x*3;
				out->rgba[0][n]=buffer[0][k++];
				out->rgba[1][n]=buffer[0][k++];
				out->rgba[2][n]=buffer[0][k++];
			}
		} else {
			for (x=0;x<out->w;x++) {
				n = x+m;
				out->rgba[0][n]=buffer[0][x];
				out->rgba[1][n]=buffer[0][x];
				out->rgba[2][n]=buffer[0][x];
			}
		} 
	}
	(void) jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	fclose(fp);
#else
	printf("warning: not JPEG support!"); 
#endif
	return 0;
}
示例#29
0
bool UrlValue::loadJpeg(UrlValue_Img &img) const {
#ifdef WITH_LIBJPEG
  struct jpeg_decompress_struct cinfo;
  
  struct urlvalue_jpeg_error_mgr jerr;
  /* More stuff */
  FILE * infile;
  JSAMPARRAY buffer;	/* Output row buffer */
  int row_stride;	/* physical row width in output buffer */
  std::string path = getRelativePath();
  
  if ((infile = fopen(path.c_str(), "rb")) == NULL) {
    return false;
  }

  /* 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 = urlvalue_jpeg_error_exit;
  /* Establish the setjmp return context for urlvalue_jpeg_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(infile);
    return false;
  }
  /* 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.txt 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.
   */

  img.width = cinfo.output_width;
  img.height = cinfo.output_height;
  
  /* 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 */
  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. */
    //put_scanline_someplace(buffer[0], row_stride);
    if (cinfo.out_color_space == JCS_RGB && 
        (cinfo.output_scanline == 1 ||
         cinfo.output_scanline == cinfo.output_height)) {

      if (cinfo.output_scanline == 1) {
        img.background.setRGB(buffer[0][0], buffer[0][1], buffer[0][2]);
      }
      if (img.background.getRed() != buffer[0][0] ||
          img.background.getGreen() != buffer[0][1] ||
          img.background.getBlue() != buffer[0][2] ||

          img.background.getRed() != buffer[0][row_stride - cinfo.output_components] ||
          img.background.getGreen() != buffer[0][row_stride - cinfo.output_components + 1] ||
          img.background.getBlue() != buffer[0][row_stride - cinfo.output_components + 2]) {
        img.background.setRGB(0,0,0);
      }
    }
  }

  /* 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);
  return true;
#else
  return false;
#endif
}
示例#30
0
void GImage::decodeJPEG(
    BinaryInput&                input) {

	struct jpeg_decompress_struct   cinfo;
	struct jpeg_error_mgr           jerr;
    int                             loc = 0;

    channels = 3;
    // We have to set up the error handler, in case initialization fails.
	cinfo.err = jpeg_std_error(&jerr);

    // Initialize the JPEG decompression object.
	jpeg_create_decompress(&cinfo);

	// Specify data source (eg, a file, for us, memory)
	jpeg_memory_src(&cinfo, const_cast<uint8*>(input.getCArray()), input.size());

	// Read the parameters with jpeg_read_header()
	jpeg_read_header(&cinfo, TRUE);

	// Set parameters for decompression
	// (We do nothing here since the defaults are fine)

	// Start decompressor
	jpeg_start_decompress(&cinfo);

	// Get and set the values of interest to this object
	this->width     = cinfo.output_width;
	this->height    = cinfo.output_height;

	// Prepare the pointer object for the pixel data
    _byte = (uint8*)System::malloc(width * height * 3);

 	// JSAMPLEs per row in output buffer
    int bpp         = cinfo.output_components;
    int row_stride  = cinfo.output_width * bpp;

	// Make a one-row-high sample array that will go away when done with image
    JSAMPARRAY temp = (*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

    // Read data on a scanline by scanline basis
	while (cinfo.output_scanline < cinfo.output_height) {

        // We may need to adjust the output based on the
        // number of channels it has.
        switch (bpp) {
	    case 1:
            // Grayscale; decompress to temp.
    		jpeg_read_scanlines(&cinfo, temp, 1);

            // Expand to three channels
            {
                uint8* scan     = &(_byte[loc * 3]);
                uint8* endScan  = scan + (width * 3);
                uint8* t        = *temp;

                while (scan < endScan) {
                    uint8 value = t[0];

                    // Spread the value 3x.
                    scan[0] = value;
                    scan[1] = value;
                    scan[2] = value;

                    scan    += 3;
                    t       += 1;
                }
            }
		    break;

	    case 3:
            // Read directly into the array
            {
                // Need one extra level of indirection.
                uint8*     scan = _byte + loc;
                JSAMPARRAY ptr  = &scan;
    		    jpeg_read_scanlines(&cinfo, ptr, 1);
            }
		    break;

	    case 4:
            // RGBA; decompress to temp.
    		jpeg_read_scanlines(&cinfo, temp, 1);

            // Drop the 3rd channel
            {
                uint8* scan     = &(_byte[loc * 3]);
                uint8* endScan  = scan + width * 3;
                uint8* t        = *temp;

                while (scan < endScan) {
                    scan[0] = t[0];
                    scan[1] = t[1];
                    scan[2] = t[2];
                    
                    scan    += 3;
                    t       += 4;
                }
            }
		    break;

	    default:
		    throw Error("Unexpected number6 of channels.", input.getFilename());
	    }

		loc += row_stride;
	}

	// Finish decompression
	jpeg_finish_decompress(&cinfo);

	// Release JPEG decompression object
	jpeg_destroy_decompress(&cinfo);
}