std::optional<ImageData2D> JpegImporter::doImage2D(UnsignedInt) {
    /* Initialize structures */
    jpeg_decompress_struct file;
    JSAMPARRAY rows = nullptr;
    unsigned char* data = nullptr;

    /* Fugly error handling stuff */
    /** @todo Get rid of this crap */
    struct ErrorManager {
        jpeg_error_mgr jpegErrorManager;
        std::jmp_buf setjmpBuffer;
    } errorManager;
    file.err = jpeg_std_error(&errorManager.jpegErrorManager);
    errorManager.jpegErrorManager.error_exit = [](j_common_ptr info) {
        info->err->output_message(info);
        std::longjmp(reinterpret_cast<ErrorManager*>(info->err)->setjmpBuffer, 1);
    };
    if(setjmp(errorManager.setjmpBuffer)) {
        Error() << "Trade::JpegImporter::image2D(): error while reading JPEG file";

        jpeg_destroy_decompress(&file);
        delete[] rows;
        delete[] data;
        return std::nullopt;
    }

    /* Open file */
    jpeg_create_decompress(&file);
    jpeg_mem_src(&file, _in.begin(), _in.size());

    /* Read file header, start decompression */
    jpeg_read_header(&file, true);
    jpeg_start_decompress(&file);

    /* Image size and type */
    const Vector2i size(file.output_width, file.output_height);
    static_assert(BITS_IN_JSAMPLE == 8, "Only 8-bit JPEG is supported");
    constexpr const ImageType type = ImageType::UnsignedByte;

    /* Image format */
    ImageFormat format;
    switch(file.out_color_space) {
        case JCS_GRAYSCALE:
            CORRADE_INTERNAL_ASSERT(file.out_color_components == 1);
            #ifdef MAGNUM_TARGET_GLES
            format = Context::current() && Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>() ?
                ImageFormat::Red : ImageFormat::Luminance;
            #else
            format = ImageFormat::Red;
            #endif
            break;
        case JCS_RGB:
            CORRADE_INTERNAL_ASSERT(file.out_color_components == 3);
            format = ImageFormat::RGB;
            break;

        /** @todo RGBA (only in libjpeg-turbo and probably ignored) */

        default:
            Error() << "Trade::JpegImporter::image2D(): unsupported color space" << file.out_color_space;
    }

    /* Initialize data array */
    data = new unsigned char[size.product()*file.out_color_components*BITS_IN_JSAMPLE/8];

    /* Read image row by row */
    rows = new JSAMPROW[size.y()];
    const Int stride = size.x()*file.out_color_components*BITS_IN_JSAMPLE/8;
    for(Int i = 0; i != size.y(); ++i)
        rows[i] = data + (size.y() - i - 1)*stride;
    while(file.output_scanline < file.output_height)
        jpeg_read_scanlines(&file, rows+file.output_scanline, file.output_height-file.output_scanline);
    delete[] rows;
    rows = nullptr;

    /* Cleanup */
    jpeg_finish_decompress(&file);
    jpeg_destroy_decompress(&file);

    return Trade::ImageData2D(format, type, size, data);
}
GLuint loadTextureFromJPEG(const char* filename, int &width, int &height){
	AAsset* pAsset = NULL;


	struct jpeg_decompress_struct cInfo;
	struct jpeg_error_mgr jError;
	cInfo.err = jpeg_std_error(&jError); // register error handler 1
	jError.error_exit = _JpegError; // register error handler 2
	jpeg_create_decompress(&cInfo); // create a decompresser


	// load from asset
	pAsset = AAssetManager_open(mgr, filename, AASSET_MODE_UNKNOWN);
	if (!pAsset) {
		LOGD("!pAsset");
		return NULL;
	}

	unsigned char* ucharRawData = (unsigned char*)AAsset_getBuffer(pAsset);
	long myAssetLength = (long)AAsset_getLength(pAsset);

	// the jpeg_stdio_src alternative func, which is also included in IJG's lib.
	jpeg_mem_src(&cInfo, ucharRawData, myAssetLength);


	uint32_t* pTexUint;
	int yy;
	int  pixelSize, lineSize;
	char* lpbtBits;
	JSAMPLE tmp;
	int rectHeight, rectWidth;

	jpeg_read_header(&cInfo, TRUE); // read header
	jpeg_start_decompress(&cInfo); // start decompression
	//LOGD("cInfo %i - %i",cInfo.output_width,cInfo.output_height);
	width = cInfo.output_width;
	height = height = cInfo.output_height;
	pixelSize = cInfo.output_components;
	lineSize = width * pixelSize;

	pTexUint = (uint32_t*)calloc(sizeof(uint32_t), width * height);
	if (pTexUint == NULL){
		AAsset_close(pAsset);

		return NULL;
	}

	JSAMPLE* pSample = (JSAMPLE*)calloc(sizeof(JSAMPLE), lineSize + 10);
	if (!pSample){
		LOGE("Jpeg Lib","cannot alloc pSample");
		if (pTexUint) free(pTexUint);

		AAsset_close(pAsset);

		return NULL; //error
	}

	JSAMPROW buffer[1];
	buffer[0] = pSample;

	uint32_t* pPixelsUint = pTexUint;
	yy = 0;
	while(cInfo.output_scanline < cInfo.output_height){
		if(yy >= cInfo.output_height)
			break;

		jpeg_read_scanlines(&cInfo, buffer, 1);

		int xx;
		int x3;
		for(xx = 0, x3 = 0; xx < width; xx++, x3 += 3)
			pPixelsUint[xx] = make8888(buffer[0][x3], buffer[0][x3 + 1], buffer[0][x3 + 2], 0xff);

		pPixelsUint = (uint32_t*)pPixelsUint + width;
		yy++;
	}
	//LOGD("sizeof(*pPixelsUint) = %i", sizeof(*pPixelsUint));
	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pTexUint);


	jpeg_finish_decompress(&cInfo);
	jpeg_destroy_decompress(&cInfo);

	if (pSample) free(pSample);

	AAsset_close(pAsset);
	//free(pTexUint);
	return texture;
	//return (unsigned char*)pTexUint;

}
bool BitmapData::initWithJPGData(const unsigned char *data, ssize_t size) {
    
    struct jpeg_decompress_struct cinfo;
    
    JpgError jerr;
    
    JSAMPROW row_pointer[1] = {0};
    unsigned long location = 0;
    unsigned int  i = 0;
    
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = myErrorExit;
    
    if (setjmp(jerr.setjmp_buffer)) {
        jpeg_destroy_decompress(&cinfo);
        return false;
    }
    
    jpeg_create_decompress(&cinfo);
    
#ifndef CC_TARGET_QT5
    jpeg_mem_src( &cinfo, const_cast<unsigned char*>(data), size);
#endif /* CC_TARGET_QT5 */

#if (JPEG_LIB_VERSION >= 90)
    jpeg_read_header( &cinfo, TRUE );
#else
    jpeg_read_header( &cinfo, true );
#endif
    
    if (cinfo.jpeg_color_space == JCS_GRAYSCALE) {
        _renderFormat = Texture2D::PixelFormat::I8;
    } else {
        cinfo.out_color_space = JCS_RGB;
        _renderFormat = Texture2D::PixelFormat::RGB888;
    }
    
    jpeg_start_decompress(&cinfo);
    
    _width  = cinfo.output_width;
    _height = cinfo.output_height;
    
    row_pointer[0] = static_cast<unsigned char*>(malloc(cinfo.output_width*cinfo.output_components * sizeof(unsigned char)));

    _dataSize = cinfo.output_width*cinfo.output_height*cinfo.output_components;
    _data     = static_cast<unsigned char*>(malloc(_dataSize * sizeof(unsigned char)));
    
    while(cinfo.output_scanline < cinfo.output_height) {
        jpeg_read_scanlines( &cinfo, row_pointer, 1 );
        for(i=0; i<cinfo.output_width*cinfo.output_components;i++) {
            _data[location++] = row_pointer[0][i];
        }
    }
    
    jpeg_destroy_decompress(&cinfo);
    
    if (row_pointer[0] != nullptr) {
        free(row_pointer[0]);
    };
    
    _alpha = false;
    
    return true;
}
Exemple #4
0
bool CJpegIO::Read(unsigned char* buffer, unsigned int bufSize, unsigned int minx, unsigned int miny)
{
  struct my_error_mgr jerr;
  m_cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = jpeg_error_exit;

  if (buffer == NULL || !bufSize )
    return false;

  jpeg_create_decompress(&m_cinfo);
#if JPEG_LIB_VERSION < 80
  x_mem_src(&m_cinfo, buffer, bufSize);
#else
  jpeg_mem_src(&m_cinfo, buffer, bufSize);
#endif

  if (setjmp(jerr.setjmp_buffer))
  {
    jpeg_destroy_decompress(&m_cinfo);
    return false;
  }
  else
  {
    jpeg_save_markers (&m_cinfo, JPEG_APP0 + 1, 0xFFFF);
    jpeg_read_header(&m_cinfo, true);

    /*  libjpeg can scale the image for us if it is too big. It must be in the format
    num/denom, where (for our purposes) that is [1-8]/8 where 8/8 is the unscaled image.
    The only way to know how big a resulting image will be is to try a ratio and
    test its resulting size.
    If the res is greater than the one desired, use that one since there's no need
    to decode a bigger one just to squish it back down. If the res is greater than
    the gpu can hold, use the previous one.*/
    if (minx == 0 || miny == 0)
    {
      miny = g_advancedSettings.m_imageRes;
      if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes)
      { // a separate fanart resolution is specified - check if the image is exactly equal to this res
        if (m_cinfo.image_width == (unsigned int)g_advancedSettings.m_fanartRes * 16/9 &&
            m_cinfo.image_height == (unsigned int)g_advancedSettings.m_fanartRes)
        { // special case for fanart res
          miny = g_advancedSettings.m_fanartRes;
        }
      }
      minx = miny * 16/9;
    }

    m_cinfo.scale_denom = 8;
    m_cinfo.out_color_space = JCS_RGB;
    unsigned int maxtexsize = g_Windowing.GetMaxTextureSize();
    for (unsigned int scale = 1; scale <= 8; scale++)
    {
      m_cinfo.scale_num = scale;
      jpeg_calc_output_dimensions(&m_cinfo);
      if ((m_cinfo.output_width > maxtexsize) || (m_cinfo.output_height > maxtexsize))
      {
        m_cinfo.scale_num--;
        break;
      }
      if (m_cinfo.output_width >= minx && m_cinfo.output_height >= miny)
        break;
    }
    jpeg_calc_output_dimensions(&m_cinfo);
    m_width  = m_cinfo.output_width;
    m_height = m_cinfo.output_height;

    if (m_cinfo.marker_list)
      m_orientation = GetExifOrientation(m_cinfo.marker_list->data, m_cinfo.marker_list->data_length);
    return true;
  }
}
Exemple #5
0
size_t Jpeg::Leanify(size_t size_leanified /*= 0*/) {
  struct jpeg_decompress_struct srcinfo;
  struct jpeg_compress_struct dstinfo;
  struct jpeg_error_mgr jsrcerr, jdsterr;

  srcinfo.err = jpeg_std_error(&jsrcerr);
  jsrcerr.error_exit = mozjpeg_error_handler;
  if (setjmp(setjmp_buffer)) {
    jpeg_destroy_compress(&dstinfo);
    jpeg_destroy_decompress(&srcinfo);

    return Format::Leanify(size_leanified);
  }

  jpeg_create_decompress(&srcinfo);

  dstinfo.err = jpeg_std_error(&jdsterr);
  jdsterr.error_exit = mozjpeg_error_handler;

  jpeg_create_compress(&dstinfo);

  if (is_verbose) {
    dstinfo.err->trace_level++;
  }
  if (is_fast) {
    jpeg_c_set_int_param(&dstinfo, JINT_COMPRESS_PROFILE, JCP_FASTEST);
  }

  /* Specify data source for decompression */
  jpeg_mem_src(&srcinfo, fp_, size_);

  // Always save exif to show warning if orientation might change.
  jpeg_save_markers(&srcinfo, JPEG_APP0 + 1, 0xFFFF);
  if (keep_icc_profile_ || keep_all_metadata_) {
    jpeg_save_markers(&srcinfo, JPEG_APP0 + 2, 0xFFFF);
  }
  if (keep_all_metadata_) {
    // Save the rest APPn markers.
    for (int i = 3; i < 16; i++)
      jpeg_save_markers(&srcinfo, JPEG_APP0 + i, 0xFFFF);
    // Save comments.
    jpeg_save_markers(&srcinfo, JPEG_COM, 0xFFFF);
  }

  (void)jpeg_read_header(&srcinfo, true);

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

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

  // use arithmetic coding if input file is arithmetic coded
  if (srcinfo.arith_code) {
    dstinfo.arith_code = true;
    dstinfo.optimize_coding = false;
  } else {
    dstinfo.optimize_coding = true;
  }

  uint8_t* outbuffer = nullptr;
  unsigned long outsize = 0;
  /* Specify data destination for compression */
  jpeg_mem_dest(&dstinfo, &outbuffer, &outsize);

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

  for (auto marker = srcinfo.marker_list; marker; marker = marker->next) {
    if (marker->marker == JPEG_APP0 + 1 && !keep_exif_ && !keep_all_metadata_) {
      // Tag number: 0x0112, data format: unsigned short(3), number of components: 1
      const uint8_t kExifOrientation[] = { 0x12, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00 };
      const uint8_t kExifOrientationMotorola[] = { 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01 };
      uint8_t* start = marker->data;
      uint8_t* end = start + marker->data_length;
      if (std::search(start, end, kExifOrientation, std::end(kExifOrientation)) != end ||
          std::search(start, end, kExifOrientationMotorola, std::end(kExifOrientationMotorola)) != end) {
        std::cout << "Warning: The Exif being removed contains orientation data, result image might have wrong "
                     "orientation, use --keep-exif to keep Exif."
                  << std::endl;
      }
      continue;
    }
    jpeg_write_marker(&dstinfo, marker->marker, marker->data, marker->data_length);
  }

  /* Finish compression and release memory */
  jpeg_finish_compress(&dstinfo);

  (void)jpeg_finish_decompress(&srcinfo);
  jpeg_destroy_decompress(&srcinfo);

  fp_ -= size_leanified;
  // use mozjpeg result if it's smaller than original
  if (outsize < size_) {
    memcpy(fp_, outbuffer, outsize);
    size_ = outsize;
  } else {
    memmove(fp_, fp_ + size_leanified, size_);
  }

  jpeg_destroy_compress(&dstinfo);

  return size_;
}
Exemple #6
0
int v4lconvert_decode_jpeg_libjpeg(struct v4lconvert_data *data,
	unsigned char *src, int src_size, unsigned char *dest,
	struct v4l2_format *fmt, unsigned int dest_pix_fmt)
{
	unsigned int width  = fmt->fmt.pix.width;
	unsigned int height = fmt->fmt.pix.height;
	int result = 0;

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

	init_libjpeg_cinfo(data);

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

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

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

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

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

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

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

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

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

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

	return result;
}
Exemple #7
0
void LoadJPG( 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! */
}
Exemple #8
0
qbyte *LoadJPG(vfsfile_t *fin)
{
	qbyte *mem=NULL, *in, *out;
	int i;

  /* 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 */  
  JSAMPARRAY buffer;		/* Output row buffer */
  int size_stride;		/* physical row width in output buffer */


	qbyte *infile;
	int length;

	length = VFS_GETLEN(fin);
	infile = malloc(length);
	VFS_READ(fin, infile, length);
	VFS_CLOSE(fin);



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

    jpeg_destroy_decompress(&cinfo);    

	if (mem)
		free(mem);
    return 0;
  }  
  jpeg_create_decompress(&cinfo);

  jpeg_mem_src(&cinfo, infile, length);

  (void) jpeg_read_header(&cinfo, TRUE);

  (void) jpeg_start_decompress(&cinfo);


  if (cinfo.output_components!=3)
	  Sys_Error("Bad number of componants in jpeg");
  size_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, size_stride, 1);

   out=mem=malloc(cinfo.output_height*cinfo.output_width*4);
   memset(out, 0, cinfo.output_height*cinfo.output_width*4);

  while (cinfo.output_scanline < cinfo.output_height) {
    (void) jpeg_read_scanlines(&cinfo, buffer, 1);    

	in = buffer[0];
	for (i = 0; i < cinfo.output_width; i++)
	{//rgb to rgba
		*out++ = *in++;
		*out++ = *in++;
		*out++ = *in++;
		*out++ = 255;	
	}	
  }

  (void) jpeg_finish_decompress(&cinfo);

  jpeg_destroy_decompress(&cinfo);

  image_width      = cinfo.output_width;
  image_height   = cinfo.output_height;

  return mem;

}
Exemple #9
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;
}
Exemple #10
0
RawFrame *Mjpeg422Decoder::decode(void *data, size_t size, int scale_down) {
    JSAMPARRAY planes[3];
    JDIMENSION scanlines_produced = 0;

    jpeg_mem_src(&cinfo, data, size);
    jpeg_save_markers(&cinfo, JPEG_COM, 64);
    jpeg_read_header(&cinfo, TRUE /* require_image */);

    /* search for a JPEG comment */
    jpeg_saved_marker_ptr marker = cinfo.marker_list;

    while (marker != NULL) {
        if (marker->marker == JPEG_COM) {
            comment.assign((char *)marker->data, marker->data_length);
            break;
        }
        marker = marker->next;
    }

    cinfo.dct_method = JDCT_FASTEST;
    cinfo.raw_data_out = TRUE;

    /* less than 20, assume it's a ratio... otherwise, assume a max. width */
    if (scale_down < 20) {
        cinfo.scale_num = 1;
        cinfo.scale_denom = scale_down;
    } else {
        /* crudely fit decompressed results into specified width */
        cinfo.scale_num = 1;
        cinfo.scale_denom = 1;

        while ((int)(cinfo.image_width / cinfo.scale_denom) > scale_down) {
            cinfo.scale_denom++;
        }
    }


    if (cinfo.num_components != 3) {
        throw std::runtime_error("Mjpeg422Decoder: wrong number of components");
    }

    if (cinfo.comp_info[0].v_samp_factor != 1 
            || cinfo.comp_info[0].h_samp_factor != 2) {
        throw std::runtime_error("JPEG not in 4:2:2 format");
    }

    if (cinfo.comp_info[1].v_samp_factor != 1
            || cinfo.comp_info[1].h_samp_factor != 1) {
        throw std::runtime_error("JPEG not in 4:2:2 format");
    }

    if (cinfo.comp_info[2].v_samp_factor != 1
            || cinfo.comp_info[2].h_samp_factor != 1) {
        throw std::runtime_error("JPEG not in 4:2:2 format");
    }

    jpeg_start_decompress(&cinfo);

    if (cinfo.output_width > maxw || cinfo.output_height > maxh) {
        throw std::runtime_error("Mjpeg422Decoder: image too large");
    }

    for (unsigned int i = 0; i < cinfo.output_height; i++) {
        y_scans[i] = y_plane + i * cinfo.output_width;
        cb_scans[i] = cb_plane + i * (cinfo.output_width / 2);
        cr_scans[i] = cr_plane + i * (cinfo.output_width / 2);
    }

    while (cinfo.output_scanline < cinfo.output_height) {
        planes[0] = y_scans + scanlines_produced;
        planes[1] = cb_scans + scanlines_produced;
        planes[2] = cr_scans + scanlines_produced;
        scanlines_produced += jpeg_read_raw_data(&cinfo, planes,
                cinfo.output_height - scanlines_produced);
    }

    jpeg_finish_decompress(&cinfo);

    RawFrame *result = new RawFrame(cinfo.output_width, cinfo.output_height, 
            RawFrame::CbYCrY8422);
    result->pack->YCbCr8P422(y_plane, cb_plane, cr_plane);
    return result;
}
Exemple #11
0
/*
 * This function must be fed with a complete compressed frame.
 */
static picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;
    picture_t *p_pic = 0;

    JSAMPARRAY p_row_pointers = NULL;

    if (!pp_block || !*pp_block)
    {
        return NULL;
    }

    p_block = *pp_block;

    if (p_block->i_flags & BLOCK_FLAG_DISCONTINUITY)
    {
        block_Release(p_block);
        *pp_block = NULL;
        return NULL;
    }

    /* libjpeg longjmp's there in case of error */
    if (setjmp(p_sys->setjmp_buffer))
    {
        goto error;
    }

    jpeg_create_decompress(&p_sys->p_jpeg);
    jpeg_mem_src(&p_sys->p_jpeg, p_block->p_buffer, p_block->i_buffer);
    jpeg_read_header(&p_sys->p_jpeg, TRUE);

    p_sys->p_jpeg.out_color_space = JCS_RGB;

    jpeg_start_decompress(&p_sys->p_jpeg);

    /* Set output properties */
    p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
    p_dec->fmt_out.video.i_width = p_sys->p_jpeg.output_width;
    p_dec->fmt_out.video.i_height = p_sys->p_jpeg.output_height;
    p_dec->fmt_out.video.i_sar_num = 1;
    p_dec->fmt_out.video.i_sar_den = 1;
    p_dec->fmt_out.video.i_rmask = 0x000000ff;
    p_dec->fmt_out.video.i_gmask = 0x0000ff00;
    p_dec->fmt_out.video.i_bmask = 0x00ff0000;

    /* Get a new picture */
    p_pic = decoder_NewPicture(p_dec);
    if (!p_pic)
    {
        goto error;
    }

    /* Decode picture */
    p_row_pointers = malloc(sizeof(JSAMPROW) * p_sys->p_jpeg.output_height);
    if (!p_row_pointers)
    {
        goto error;
    }
    for (unsigned i = 0; i < p_sys->p_jpeg.output_height; i++) {
        p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i;
    }

    while (p_sys->p_jpeg.output_scanline < p_sys->p_jpeg.output_height)
    {
        jpeg_read_scanlines(&p_sys->p_jpeg,
                p_row_pointers + p_sys->p_jpeg.output_scanline,
                p_sys->p_jpeg.output_height - p_sys->p_jpeg.output_scanline);
    }

    jpeg_finish_decompress(&p_sys->p_jpeg);
    jpeg_destroy_decompress(&p_sys->p_jpeg);
    free(p_row_pointers);

    p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;

    block_Release(p_block);
    *pp_block = NULL;

    return p_pic;

error:

    jpeg_destroy_decompress(&p_sys->p_jpeg);
    free(p_row_pointers);

    block_Release(p_block);
    *pp_block = NULL;

    return NULL;
}
///////////////////////////////////////////////////////////////
//
// JpegDecode
//
// jpeg to XRGB
//
///////////////////////////////////////////////////////////////
bool JpegDecode ( const void* pData, uint uiDataSize, CBuffer& outBuffer, uint& uiOutWidth, uint& uiOutHeight )
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    /* Initialize the JPEG decompression object with default error handling. */
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    /* Specify data source for decompression */
    jpeg_mem_src (&cinfo,(uchar*)pData,uiDataSize );

    /* Read file header, set default decompression parameters */
    (void) jpeg_read_header(&cinfo, TRUE);

    /* default decompression parameters */
    // TODO

    /* Start decompressor */
    (void) jpeg_start_decompress(&cinfo);

    /* Write output file header */
    JDIMENSION uiWidth = cinfo.output_width;	/* scaled image width */
    JDIMENSION uiHeight = cinfo.output_height;	/* scaled image height */

    uiOutWidth = uiWidth;
    uiOutHeight = uiHeight;

    outBuffer.SetSize ( uiWidth * uiHeight * 4 );
    char* pOutData = outBuffer.GetData ();

    /* Process data */
    JSAMPROW row_pointer[1];
    CBuffer rowBuffer;
    rowBuffer.SetSize ( uiWidth * 3 );
    char* pRowTemp = rowBuffer.GetData ();

    while (cinfo.output_scanline < cinfo.output_height)
    {
        BYTE* pRowDest = (BYTE*)pOutData + cinfo.output_scanline * uiWidth * 4;
        row_pointer[0] = (JSAMPROW)pRowTemp;

        JDIMENSION num_scanlines = jpeg_read_scanlines(&cinfo, row_pointer, 1);

        for ( uint i = 0 ; i < uiWidth ; i++ )
        {
            pRowDest[i*4+0] = pRowTemp[i*3+2];
            pRowDest[i*4+1] = pRowTemp[i*3+1];
            pRowDest[i*4+2] = pRowTemp[i*3+0];
            pRowDest[i*4+3] = 255;
        }
    }

    // Finish decompression and release memory.
    (void) jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

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

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

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

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

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

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

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

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

	free(filedata);

	return out;
}
Exemple #14
0
int
main (int argc, char **argv)
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
    struct cdjpeg_progress_mgr progress;
#endif
    int file_index;
    djpeg_dest_ptr dest_mgr = NULL;
    FILE * input_file;
    FILE * output_file;
    unsigned char *inbuffer = NULL;
    unsigned long insize = 0;
    JDIMENSION num_scanlines;

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

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

    /* Initialize the JPEG decompression object with default error handling. */
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    /* Add some application-specific error messages (from cderror.h) */
    jerr.addon_message_table = cdjpeg_message_table;
    jerr.first_addon_message = JMSG_FIRSTADDONCODE;
    jerr.last_addon_message = JMSG_LASTADDONCODE;

    /* Insert custom marker processor for COM and APP12.
     * APP12 is used by some digital camera makers for textual info,
     * so we provide the ability to display it as text.
     * If you like, additional APPn marker types can be selected for display,
     * but don't try to override APP0 or APP14 this way (see libjpeg.txt).
     */
    jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
    jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);

    /* Scan command line to find file names. */
    /* It is convenient to use just one switch-parsing routine, but the switch
     * values read here are ignored; we will rescan the switches after opening
     * the input file.
     * (Exception: tracing level set here controls verbosity for COM markers
     * found during jpeg_read_header...)
     */

    file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);

#ifdef TWO_FILE_COMMANDLINE
    /* Must have either -outfile switch or explicit output file name */
    if (outfilename == NULL) {
        if (file_index != argc-2) {
            fprintf(stderr, "%s: must name one input and one output file\n",
                    progname);
            usage();
        }
        outfilename = argv[file_index+1];
    } else {
        if (file_index != argc-1) {
            fprintf(stderr, "%s: must name one input and one output file\n",
                    progname);
            usage();
        }
    }
#else
    /* Unix style: expect zero or one file name */
    if (file_index < argc-1) {
        fprintf(stderr, "%s: only one input file\n", progname);
        usage();
    }
#endif /* TWO_FILE_COMMANDLINE */

    /* Open the input file. */
    if (file_index < argc) {
        if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
            fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
            exit(EXIT_FAILURE);
        }
    } else {
        /* default input file is stdin */
        input_file = read_stdin();
    }

    /* Open the output file. */
    if (outfilename != NULL) {
        if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
            fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
            exit(EXIT_FAILURE);
        }
    } else {
        /* default output file is stdout */
        output_file = write_stdout();
    }

#ifdef PROGRESS_REPORT
    start_progress_monitor((j_common_ptr) &cinfo, &progress);
#endif

    /* Specify data source for decompression */
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
    if (memsrc) {
        size_t nbytes;
        do {
            inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE);
            if (inbuffer == NULL) {
                fprintf(stderr, "%s: memory allocation failure\n", progname);
                exit(EXIT_FAILURE);
            }
            nbytes = JFREAD(input_file, &inbuffer[insize], INPUT_BUF_SIZE);
            if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) {
                if (file_index < argc)
                    fprintf(stderr, "%s: can't read from %s\n", progname,
                            argv[file_index]);
                else
                    fprintf(stderr, "%s: can't read from stdin\n", progname);
            }
            insize += (unsigned long)nbytes;
        } while (nbytes == INPUT_BUF_SIZE);
        fprintf(stderr, "Compressed size:  %lu bytes\n", insize);
        jpeg_mem_src(&cinfo, inbuffer, insize);
    } else
#endif
        jpeg_stdio_src(&cinfo, input_file);

    /* Read file header, set default decompression parameters */
    (void) jpeg_read_header(&cinfo, TRUE);

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

    /* Initialize the output module now to let it override any crucial
     * option settings (for instance, GIF wants to force color quantization).
     */
    switch (requested_fmt) {
#ifdef BMP_SUPPORTED
    case FMT_BMP:
        dest_mgr = jinit_write_bmp(&cinfo, FALSE);
        break;
    case FMT_OS2:
        dest_mgr = jinit_write_bmp(&cinfo, TRUE);
        break;
#endif
#ifdef GIF_SUPPORTED
    case FMT_GIF:
        dest_mgr = jinit_write_gif(&cinfo);
        break;
#endif
#ifdef PPM_SUPPORTED
    case FMT_PPM:
        dest_mgr = jinit_write_ppm(&cinfo);
        break;
#endif
#ifdef RLE_SUPPORTED
    case FMT_RLE:
        dest_mgr = jinit_write_rle(&cinfo);
        break;
#endif
#ifdef TARGA_SUPPORTED
    case FMT_TARGA:
        dest_mgr = jinit_write_targa(&cinfo);
        break;
#endif
    default:
        ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
        break;
    }
    dest_mgr->output_file = output_file;

    /* Start decompressor */
    (void) jpeg_start_decompress(&cinfo);

    /* Strip decode */
    if (strip || skip) {
        JDIMENSION tmp;

        /* Check for valid endY.  We cannot check this value until after
         * jpeg_start_decompress() is called.  Note that we have already verified
         * that startY <= endY.
         */
        if (endY > cinfo.output_height - 1) {
            fprintf(stderr, "%s: strip %d-%d exceeds image height %d\n", progname,
                    startY, endY, cinfo.output_height);
            exit(EXIT_FAILURE);
        }

        /* Write output file header.  This is a hack to ensure that the destination
         * manager creates an image of the proper size for the partial decode.
         */
        tmp = cinfo.output_height;
        cinfo.output_height = endY - startY + 1;
        if (skip)
            cinfo.output_height = tmp - cinfo.output_height;
        (*dest_mgr->start_output) (&cinfo, dest_mgr);
        cinfo.output_height = tmp;

        /* Process data */
        if (skip) {
            while (cinfo.output_scanline < startY) {
                num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
                                                    dest_mgr->buffer_height);
                (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
            }
            jpeg_skip_scanlines(&cinfo, endY - startY + 1);
            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);
            }
        } else {
            jpeg_skip_scanlines(&cinfo, startY);
            while (cinfo.output_scanline <= endY) {
                num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
                                                    dest_mgr->buffer_height);
                (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
            }
            jpeg_skip_scanlines(&cinfo, cinfo.output_height - endY + 1);
        }

        /* Normal full image decode */
    } else {
        /* Write output file header */
        (*dest_mgr->start_output) (&cinfo, dest_mgr);

        /* Process data */
        while (cinfo.output_scanline < cinfo.output_height) {
            num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
                                                dest_mgr->buffer_height);
            (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
        }
    }

#ifdef PROGRESS_REPORT
    /* Hack: count final pass as done in case finish_output does an extra pass.
     * The library won't have updated completed_passes.
     */
    progress.pub.completed_passes = progress.pub.total_passes;
#endif

    /* Finish decompression and release memory.
     * I must do it in this order because output module has allocated memory
     * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
     */
    (*dest_mgr->finish_output) (&cinfo, dest_mgr);
    (void) jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    /* Close files, if we opened them */
    if (input_file != stdin)
        fclose(input_file);
    if (output_file != stdout)
        fclose(output_file);

#ifdef PROGRESS_REPORT
    end_progress_monitor((j_common_ptr) &cinfo);
#endif

    if (memsrc && inbuffer != NULL)
        free(inbuffer);

    /* All done. */
    exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
    return 0;                     /* suppress no-return-value warnings */
}
int JPEG2NV21(Uint8 *yuv, Uint8 *jpegdata, int jpeglen, int sx, int sy, bool needRotation, bool cameraMirrored, int rotationDegree)
{
	int i, y;
	int inlen;

	struct jpeg_decompress_struct cinfo;
	struct my_error_mgr jerr;
	JSAMPARRAY scanline;
	unsigned char  *wline;
	unsigned char *y_buffer;
	unsigned char *cbcr_buffer;

	Uint8* dst;

	if (needRotation || cameraMirrored)
	//if(rotationDegree != 0 || cameraMirrored)
		dst = (unsigned char*)malloc(sx*sy+2*((sx+1)/2)*((sy+1)/2));
	else
		dst = yuv;

	cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    /* Establish the setjmp return context for my_error_exit to use. */
    if (setjmp(jerr.setjmp_buffer))
    {
        jpeg_destroy_decompress(&cinfo);
        return 0;
    }
	jpeg_create_decompress(&cinfo);

	jpeg_mem_src(&cinfo, jpegdata, jpeglen);
	(void) jpeg_read_header(&cinfo, TRUE);
	//cinfo.raw_data_out = TRUE;
    cinfo.out_color_space = JCS_YCbCr;

	(void) jpeg_start_decompress(&cinfo);

	y_buffer = dst;
	cbcr_buffer = y_buffer + cinfo.output_width * cinfo.output_height;
	scanline = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width * cinfo.output_components, 1);
	wline = scanline[0];

	while (cinfo.output_scanline < cinfo.output_height)
	{
		jpeg_read_scanlines(&cinfo, scanline, (JDIMENSION)1);

		for (i = 0; i < cinfo.output_width; i++)
			y_buffer[i] = wline[i*3];

		y_buffer += cinfo.output_width;

		if (y++ & 1)
		{
			for (int i = 0; i < cinfo.output_width; i+=2)
			{
				cbcr_buffer[i] = wline[(i*3) + 2];		// V
				cbcr_buffer[i + 1] = wline[(i*3) + 1];	// U
			}
			cbcr_buffer += cinfo.output_width;
		}
	}

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


	if (needRotation || cameraMirrored)
	{
		int nRotate = 0;
		int flipUD = 0;
		if(rotationDegree == 180 || rotationDegree == 270)
		{
			cameraMirrored = !cameraMirrored; //used to support 4-side rotation
			flipUD = 1; //used to support 4-side rotation
		}
		if(rotationDegree == 90 || rotationDegree == 270)
			nRotate = 1; //used to support 4-side rotation

		// ToDo: not sure if it should be 'cameraMirrored, 0,' or '0, cameraMirrored,'
		TransformNV21(dst, yuv, sx, sy, NULL, cameraMirrored, flipUD, nRotate);
		free(dst);
	}

	return 1;
}
Exemple #16
0
uvc_error_t uvc_mjpeg2yuyv(uvc_frame_t *in, uvc_frame_t *out) {

	out->actual_bytes = 0;	// XXX
	if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
		return UVC_ERROR_INVALID_PARAM;

	if (uvc_ensure_frame_size(out, in->width * in->height * 2) < 0)
		return UVC_ERROR_NO_MEM;

	size_t lines_read = 0;
	int i, j;
	int num_scanlines;
	register uint8_t *yuyv, *ycbcr;

	out->width = in->width;
	out->height = in->height;
	out->frame_format = UVC_FRAME_FORMAT_YUYV;
	out->step = in->width * 2;
	out->sequence = in->sequence;
	out->capture_time = in->capture_time;
	out->source = in->source;

	struct jpeg_decompress_struct dinfo;
	struct error_mgr jerr;
	dinfo.err = jpeg_std_error(&jerr.super);
	jerr.super.error_exit = _error_exit;

	if (setjmp(jerr.jmp)) {
		goto fail;
	}

	jpeg_create_decompress(&dinfo);
	jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/);	// XXX
	jpeg_read_header(&dinfo, TRUE);

	if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
		/* This frame is missing the Huffman tables: fill in the standard ones */
		insert_huff_tables(&dinfo);
	}

	dinfo.out_color_space = JCS_YCbCr;
	dinfo.dct_method = JDCT_IFAST;

	// start decompressor
	jpeg_start_decompress(&dinfo);

	// these dinfo.xxx valiables are only valid after jpeg_start_decompress
	const int row_stride = dinfo.output_width * dinfo.output_components;

	// allocate buffer
	register JSAMPARRAY buffer = (*dinfo.mem->alloc_sarray)
		((j_common_ptr) &dinfo, JPOOL_IMAGE, row_stride, MAX_READLINE);

	// local copy
	uint8_t *data = out->data;
	const int out_step = out->step;

	if (LIKELY(dinfo.output_height == out->height)) {
		for (; dinfo.output_scanline < dinfo.output_height ;) {
			// convert lines of mjpeg data to YCbCr
			num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
			// convert YCbCr to yuyv(YUV422)
			for (j = 0; j < num_scanlines; j++) {
				yuyv = data + (lines_read + j) * out_step;
				ycbcr = buffer[j];
				for (i = 0; i < row_stride; i += 24) {	// step by YCbCr x 8 pixels = 3 x 8 bytes
					YCbCr_YUYV_2(ycbcr + i, yuyv);
					YCbCr_YUYV_2(ycbcr + i + 6, yuyv);
					YCbCr_YUYV_2(ycbcr + i + 12, yuyv);
					YCbCr_YUYV_2(ycbcr + i + 18, yuyv);
				}
			}
			lines_read += num_scanlines;
		}
		out->actual_bytes = in->width * in->height * 2;	// XXX
	}

	jpeg_finish_decompress(&dinfo);
	jpeg_destroy_decompress(&dinfo);
	return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER;

fail:
	jpeg_destroy_decompress(&dinfo);
	return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER+1;
}
Exemple #17
0
/** @brief Convert an MJPEG frame to RGB
 * @ingroup frame
 *
 * @param in MJPEG frame
 * @param out RGB frame
 */
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
	struct jpeg_decompress_struct dinfo;
	struct error_mgr jerr;
	size_t lines_read;
	// local copy
	uint8_t *data = out->data;
	const int out_step = out->step;

	int num_scanlines, i;
	lines_read = 0;
	unsigned char *buffer[MAX_READLINE];

	out->actual_bytes = 0;	// XXX
	if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
		return UVC_ERROR_INVALID_PARAM;

	if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
		return UVC_ERROR_NO_MEM;

	out->width = in->width;
	out->height = in->height;
	out->frame_format = UVC_FRAME_FORMAT_RGB;
	out->step = in->width * 3;
	out->sequence = in->sequence;
	out->capture_time = in->capture_time;
	out->source = in->source;

	dinfo.err = jpeg_std_error(&jerr.super);
	jerr.super.error_exit = _error_exit;

	if (setjmp(jerr.jmp)) {
		goto fail;
	}

	jpeg_create_decompress(&dinfo);
	jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/);
	jpeg_read_header(&dinfo, TRUE);

	if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
		/* This frame is missing the Huffman tables: fill in the standard ones */
		insert_huff_tables(&dinfo);
	}

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

	jpeg_start_decompress(&dinfo);

	if (LIKELY(dinfo.output_height == out->height)) {
		for (; dinfo.output_scanline < dinfo.output_height ;) {
			buffer[0] = data + (lines_read) * out_step;
			for (i = 1; i < MAX_READLINE; i++)
				buffer[i] = buffer[i-1] + out_step;
			num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
			lines_read += num_scanlines;
		}
		out->actual_bytes = in->width * in->height * 3;	// XXX
	}
	jpeg_finish_decompress(&dinfo);
	jpeg_destroy_decompress(&dinfo);
	return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER;	// XXX

fail:
	jpeg_destroy_decompress(&dinfo);
	return UVC_ERROR_OTHER+1;
}
Exemple #18
0
    int jpeg_read(const char* filename,jpeg_datap result){
  
        auto jpegData = D2D::FileUtil::getInstacne()->getDataFromFile(filename,true);
        assert(!jpegData.isNull());
        
        /* these are standard libjpeg structures for reading(decompression) */
        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 MyErrorMgr 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;
        
        /* We set up the normal JPEG error routines, then override error_exit. */
        cinfo.err = jpeg_std_error(&jerr.pub);
        jerr.pub.error_exit = myErrorExit;
        /* Establish the setjmp return context for MyErrorExit 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);
            printf("decompress jpeg : %s error.\n",filename);
            abort();
            return -1;
        }
        
        /* setup decompression process and source, then read JPEG header */
        jpeg_create_decompress( &cinfo );
        
        jpeg_mem_src( &cinfo, const_cast<unsigned char*>(jpegData.getBytes()),jpegData.getSize());
        
        /* reading the image header which contains image information */
#if (JPEG_LIB_VERSION >= 90)
        // libjpeg 0.9 adds stricter types.
        jpeg_read_header( &cinfo, TRUE );
#else
        jpeg_read_header( &cinfo, true );
#endif
        
        // we only support RGB or grayscale
        if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
        {
            result->format = Texture2D::PixelFormat::I8;
        }else
        {
            cinfo.out_color_space = JCS_RGB;
            result->format = Texture2D::PixelFormat::RGB888;
        }
        
        /* Start decompression jpeg here */
        jpeg_start_decompress( &cinfo );
        
        /* init image info */
        result->width  = cinfo.output_width;
        result->height = cinfo.output_height;
        
        row_pointer[0] = static_cast<unsigned char*>(malloc(cinfo.output_width*cinfo.output_components * sizeof(unsigned char)));
        
        ssize_t dataLen = cinfo.output_width * cinfo.output_height*cinfo.output_components;
        result->data = static_cast<unsigned char*>(malloc(dataLen * sizeof(unsigned char)));
        
        /* now actually read the jpeg into the raw buffer */
        /* read one scan line at a time */
        while( cinfo.output_scanline < cinfo.output_height ){
            
            jpeg_read_scanlines( &cinfo, row_pointer, 1 );
            for( i=0; i<cinfo.output_width*cinfo.output_components;i++)
            {
                result->data[location++] = row_pointer[0][i];
            }
        }
        
        /* When read image file with broken data, jpeg_finish_decompress() may cause error.
         * Besides, jpeg_destroy_decompress() shall deallocate and release all memory associated
         * with the decompression object.
         * So it doesn't need to call jpeg_finish_decompress().
         */
        //jpeg_finish_decompress( &cinfo );
        jpeg_destroy_decompress( &cinfo );
        
        if (row_pointer[0] != nullptr)
        {
            free(row_pointer[0]);
        };
        
        return 0;
    }
cairo_surface_t* guacenc_jpeg_decoder(unsigned char* data, int length) {

    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    /* Create decompressor with standard error handling */
    jpeg_create_decompress(&cinfo);
    cinfo.err = jpeg_std_error(&jerr);

    /* Read JPEG directly from memory buffer */
    jpeg_mem_src(&cinfo, data, length);

    /* Read and validate JPEG header */
    if (!jpeg_read_header(&cinfo, TRUE)) {
        guacenc_log(GUAC_LOG_WARNING, "Invalid JPEG data");
        jpeg_destroy_decompress(&cinfo);
        return NULL;
    }

    /* Begin decompression */
    cinfo.out_color_space = JCS_RGB;
    jpeg_start_decompress(&cinfo);

    /* Pull JPEG dimensions from decompressor */
    int width = cinfo.output_width;
    int height = cinfo.output_height;

    /* Allocate sufficient buffer space for one JPEG scanline */
    unsigned char* jpeg_scanline = malloc(width * 3);

    /* Create blank Cairo surface (no transparency in JPEG) */
    cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
            width, height);

    /* Pull underlying buffer and its stride */
    int stride = cairo_image_surface_get_stride(surface);
    unsigned char* row = cairo_image_surface_get_data(surface);

    /* Read JPEG into surface */
    while (cinfo.output_scanline < height) {

        /* Read single scanline */
        unsigned char* buffers[1] = { jpeg_scanline };
        jpeg_read_scanlines(&cinfo, buffers, 1);

        /* Copy scanline to Cairo surface */
        guacenc_jpeg_copy_scanline(row, jpeg_scanline, width);

        /* Advance to next row of Cairo surface */
        row += stride;

    }

    /* Scanline buffer is no longer needed */
    free(jpeg_scanline);

    /* End decompression */
    jpeg_finish_decompress(&cinfo);

    /* Free decompressor */
    jpeg_destroy_decompress(&cinfo);

    /* JPEG was read successfully */
    return surface;

}