Ejemplo n.º 1
0
/* write_JPEG_memory: store JPEG compressed image into memory.
*/
static bool writeJPEGFile(io::IWriteFile* file, IImage* image, u32 quality)
{
	void (*format)(const void*, s32, void*) = 0;
	switch( image->getColorFormat () )
	{
		case ECF_R8G8B8:
			format = CColorConverter::convert_R8G8B8toR8G8B8;
			break;
		case ECF_A8R8G8B8:
			format = CColorConverter::convert_A8R8G8B8toR8G8B8;
			break;
		case ECF_A1R5G5B5:
			format = CColorConverter::convert_A1R5G5B5toB8G8R8;
			break;
		case ECF_R5G6B5:
			format = CColorConverter::convert_R5G6B5toR8G8B8;
			break;
#ifndef _DEBUG
		default:
			break;
#endif
	}

	// couldn't find a color converter
	if ( 0 == format )
		return false;

	const core::dimension2du dim = image->getDimension();

	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	cinfo.err = jpeg_std_error(&jerr);

	jpeg_create_compress(&cinfo);
	jpeg_file_dest(&cinfo, file);
	cinfo.image_width = dim.Width;
	cinfo.image_height = dim.Height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;

	jpeg_set_defaults(&cinfo);

	if ( 0 == quality )
		quality = 75;

	jpeg_set_quality(&cinfo, quality, TRUE);
	jpeg_start_compress(&cinfo, TRUE);

	u8 * dest = new u8[dim.Width*3];

	if (dest)
	{
		const u32 pitch = image->getPitch();
		JSAMPROW row_pointer[1];      /* pointer to JSAMPLE row[s] */
		row_pointer[0] = dest;

		u8* src = (u8*)image->lock();

		while (cinfo.next_scanline < cinfo.image_height)
		{
			// convert next line
			format( src, dim.Width, dest );
			src += pitch;
			jpeg_write_scanlines(&cinfo, row_pointer, 1);
		}
		image->unlock();

		delete [] dest;

		/* Step 6: Finish compression */
		jpeg_finish_compress(&cinfo);
	}

	/* Step 7: Destroy */
	jpeg_destroy_compress(&cinfo);

	return (dest != 0);
}
Ejemplo n.º 2
0
void GImage::encodeJPEG(
    BinaryOutput&           out) const {

	if (channels != 3) {
		// Convert to three channel
		GImage tmp = *this;
		tmp.convertToRGB();
		tmp.encodeJPEG(out);
		return;
	}

    debugAssert(channels == 3);
    out.setEndian(G3D_LITTLE_ENDIAN);

    // Allocate and initialize a compression object
    jpeg_compress_struct    cinfo;
    jpeg_error_mgr          jerr;

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

    // Specify the destination for the compressed data.
    // (Overestimate the size)
    int buffer_size = width * height * 3 + 200;
    JOCTET* compressed_data = (JOCTET*)System::malloc(buffer_size);
	jpeg_memory_dest(&cinfo, compressed_data, buffer_size);


    cinfo.image_width       = width;
    cinfo.image_height      = height;

	// # of color components per pixel
    cinfo.input_components  = 3;

    // colorspace of input image
    cinfo.in_color_space    = JCS_RGB; 
    cinfo.input_gamma       = 1.0;
    
    // Set parameters for compression, including image size & colorspace
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, jpegQuality, false);
    cinfo.smoothing_factor = 0;
    cinfo.optimize_coding = TRUE;
//    cinfo.dct_method = JDCT_FLOAT;
    cinfo.dct_method = JDCT_ISLOW;
    cinfo.jpeg_color_space = JCS_YCbCr;

    // Initialize the compressor
    jpeg_start_compress(&cinfo, TRUE);

    // Iterate over all scanlines from top to bottom
	// pointer to a single row
    JSAMPROW row_pointer[1];
    
    // JSAMPLEs per row in image_buffer
    int row_stride = cinfo.image_width * 3;
    while (cinfo.next_scanline < cinfo.image_height) {
	    row_pointer[0] = &(_byte[cinfo.next_scanline * row_stride]);
	    jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    // Shut down the compressor
    jpeg_finish_compress(&cinfo);
    
    // Figure out how big the result was.
    int outLength = ((mem_dest_ptr)cinfo.dest)->count;

    //	Release the JPEG compression object
    jpeg_destroy_compress(&cinfo);

    // Copy into an appropriately sized output buffer.
    out.writeBytes(compressed_data, outLength);

    // Free the conservative buffer.
    System::free(compressed_data);
    compressed_data = NULL;
}
Ejemplo n.º 3
0
void
image_upsize(image_s * pdest, image_s * psrc, int32_t width, int32_t height)
{
	int32_t vx, vy;
#if !defined __i386__ && !defined __x86_64__
	int32_t rx, ry;
	pix vcol;

	if((pdest == NULL) || (psrc == NULL))
		return;

	for(vy = 0; vy < height; vy++)
	{
		for(vx = 0; vx < width; vx++)
		{
			rx = ((vx * psrc->width) / width);
			ry = ((vy * psrc->height) / height);
			vcol = get_pix(psrc, rx, ry);
#else
	pix   vcol,vcol1,vcol2,vcol3,vcol4;
	float rx,ry;
	float width_scale, height_scale;
	float x_dist, y_dist;

	width_scale  = (float)psrc->width  / (float)width;
	height_scale = (float)psrc->height / (float)height;

	for(vy = 0;vy < height; vy++)
	{
		for(vx = 0;vx < width; vx++)
		{
			rx = vx * width_scale;
			ry = vy * height_scale;
			vcol1 = get_pix(psrc, (int32_t)rx, (int32_t)ry);
			vcol2 = get_pix(psrc, ((int32_t)rx)+1, (int32_t)ry);
			vcol3 = get_pix(psrc, (int32_t)rx, ((int32_t)ry)+1);
			vcol4 = get_pix(psrc, ((int32_t)rx)+1, ((int32_t)ry)+1);

			x_dist = rx - ((float)((int32_t)rx));
			y_dist = ry - ((float)((int32_t)ry));
			vcol = COL_FULL( (uint8_t)((COL_RED(vcol1)*(1.0-x_dist)
			                  + COL_RED(vcol2)*(x_dist))*(1.0-y_dist)
			                  + (COL_RED(vcol3)*(1.0-x_dist)
			                  + COL_RED(vcol4)*(x_dist))*(y_dist)),
			                 (uint8_t)((COL_GREEN(vcol1)*(1.0-x_dist)
			                  + COL_GREEN(vcol2)*(x_dist))*(1.0-y_dist)
			                  + (COL_GREEN(vcol3)*(1.0-x_dist)
			                  + COL_GREEN(vcol4)*(x_dist))*(y_dist)),
			                 (uint8_t)((COL_BLUE(vcol1)*(1.0-x_dist)
			                  + COL_BLUE(vcol2)*(x_dist))*(1.0-y_dist)
			                  + (COL_BLUE(vcol3)*(1.0-x_dist)
			                  + COL_BLUE(vcol4)*(x_dist))*(y_dist)),
			                 (uint8_t)((COL_ALPHA(vcol1)*(1.0-x_dist)
			                  + COL_ALPHA(vcol2)*(x_dist))*(1.0-y_dist)
			                  + (COL_ALPHA(vcol3)*(1.0-x_dist)
			                  + COL_ALPHA(vcol4)*(x_dist))*(y_dist))
			               );
#endif
			put_pix_alpha_replace(pdest, vx, vy, vcol);
		}
	}
}

void
image_downsize(image_s * pdest, image_s * psrc, int32_t width, int32_t height)
{
	int32_t vx, vy;
	pix vcol;
	int32_t i, j;
#if !defined __i386__ && !defined __x86_64__
	int32_t rx, ry, rx_next, ry_next;
	int red, green, blue, alpha;
	int factor;

	if((pdest == NULL) || (psrc == NULL))
		return;

	for(vy = 0; vy < height; vy++)
	{
		for(vx = 0; vx < width; vx++)
		{

			rx = ((vx * psrc->width) / width);
			ry = ((vy * psrc->height) / height);

			red = green = blue = alpha = 0;

			rx_next = rx + (psrc->width / width);
			ry_next = ry + (psrc->width / width);
			factor = 0;

			for( j = rx; j < rx_next; j++)
			{
				for( i = ry; i < ry_next; i++)
				{
					factor += 1;
					vcol = get_pix(psrc, j, i);

					red   += COL_RED(vcol);
					green += COL_GREEN(vcol);
					blue  += COL_BLUE(vcol);
					alpha += COL_ALPHA(vcol);
				}
			}

			red   /= factor;
			green /= factor;
			blue  /= factor;
			alpha /= factor;

			/* on sature les valeurs */
			red   = (red   > 255) ? 255 : ((red   < 0) ? 0 : red  );
			green = (green > 255) ? 255 : ((green < 0) ? 0 : green);
			blue  = (blue  > 255) ? 255 : ((blue  < 0) ? 0 : blue );
			alpha = (alpha > 255) ? 255 : ((alpha < 0) ? 0 : alpha);
#else
	float rx,ry;
	float width_scale, height_scale;
	float red, green, blue, alpha;
	int32_t half_square_width, half_square_height;
	float round_width, round_height;

	if( (pdest == NULL) || (psrc == NULL) )
		return;

	width_scale  = (float)psrc->width  / (float)width;
	height_scale = (float)psrc->height / (float)height;

	half_square_width  = (int32_t)(width_scale  / 2.0);
	half_square_height = (int32_t)(height_scale / 2.0);
	round_width  = (width_scale  / 2.0) - (float)half_square_width;
	round_height = (height_scale / 2.0) - (float)half_square_height;
	if(round_width  > 0.0)
		half_square_width++;
	else
		round_width = 1.0;
	if(round_height > 0.0)
		half_square_height++;
	else
		round_height = 1.0;

	for(vy = 0;vy < height; vy++)  
	{
		for(vx = 0;vx < width; vx++)
		{
			rx = vx * width_scale;
			ry = vy * height_scale;
			vcol = get_pix(psrc, (int32_t)rx, (int32_t)ry);

			red = green = blue = alpha = 0.0;

			for(j=0;j<half_square_height<<1;j++)
			{
				for(i=0;i<half_square_width<<1;i++)
				{
					vcol = get_pix(psrc, ((int32_t)rx)-half_square_width+i,
					                     ((int32_t)ry)-half_square_height+j);
          
					if(((j == 0) || (j == (half_square_height<<1)-1)) && 
					   ((i == 0) || (i == (half_square_width<<1)-1)))
					{
						red   += round_width*round_height*(float)COL_RED  (vcol);
						green += round_width*round_height*(float)COL_GREEN(vcol);
						blue  += round_width*round_height*(float)COL_BLUE (vcol);
						alpha += round_width*round_height*(float)COL_ALPHA(vcol);
					}
					else if((j == 0) || (j == (half_square_height<<1)-1))
					{
						red   += round_height*(float)COL_RED  (vcol);
						green += round_height*(float)COL_GREEN(vcol);
						blue  += round_height*(float)COL_BLUE (vcol);
						alpha += round_height*(float)COL_ALPHA(vcol);
					}
					else if((i == 0) || (i == (half_square_width<<1)-1))
					{
						red   += round_width*(float)COL_RED  (vcol);
						green += round_width*(float)COL_GREEN(vcol);
						blue  += round_width*(float)COL_BLUE (vcol);
						alpha += round_width*(float)COL_ALPHA(vcol);
					}
					else
					{
						red   += (float)COL_RED  (vcol);
						green += (float)COL_GREEN(vcol);
						blue  += (float)COL_BLUE (vcol);
						alpha += (float)COL_ALPHA(vcol);
					}
				}
			}
      
			red   /= width_scale*height_scale;
			green /= width_scale*height_scale;
			blue  /= width_scale*height_scale;
			alpha /= width_scale*height_scale;
      
			/* on sature les valeurs */
			red   = (red   > 255.0)? 255.0 : ((red   < 0.0)? 0.0:red  );
			green = (green > 255.0)? 255.0 : ((green < 0.0)? 0.0:green);
			blue  = (blue  > 255.0)? 255.0 : ((blue  < 0.0)? 0.0:blue );
			alpha = (alpha > 255.0)? 255.0 : ((alpha < 0.0)? 0.0:alpha);
#endif
			put_pix_alpha_replace(pdest, vx, vy,
					      COL_FULL((uint8_t)red, (uint8_t)green, (uint8_t)blue, (uint8_t)alpha));
		}
	}
}

image_s *
image_resize(image_s * src_image, int32_t width, int32_t height)
{
	image_s * dst_image;

	dst_image = image_new(width, height);
	if( !dst_image )
		return NULL;
	if( (src_image->width < width) || (src_image->height < height) )
		image_upsize(dst_image, src_image, width, height);
	else
		image_downsize(dst_image, src_image, width, height);

	return dst_image;
}


unsigned char *
image_save_to_jpeg_buf(image_s * pimage, int * size)
{
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	JSAMPROW row_pointer[1];
	int row_stride;
	char *data;
	int i, x;
	struct my_dst_mgr dst;

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_memory_dest(&cinfo, &dst);
	cinfo.image_width = pimage->width;
	cinfo.image_height = pimage->height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE);
	jpeg_start_compress(&cinfo, TRUE);
	row_stride = cinfo.image_width * 3;
	if((data = malloc(row_stride)) == NULL)
	{
		DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
		free(dst.buf);
		jpeg_destroy_compress(&cinfo);
		return NULL;
	}
	i = 0;
	while(cinfo.next_scanline < cinfo.image_height)
	{
		for(x = 0; x < pimage->width; x++)
		{
			data[x * 3]     = COL_RED(pimage->buf[i]);
			data[x * 3 + 1] = COL_GREEN(pimage->buf[i]);
			data[x * 3 + 2] = COL_BLUE(pimage->buf[i]);
			i++;
		}
		row_pointer[0] = (JSAMPROW )data;
		jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	jpeg_finish_compress(&cinfo);
	*size = dst.used;
	free(data);
	jpeg_destroy_compress(&cinfo);

	return (unsigned char *)dst.buf;
}

char *
image_save_to_jpeg_file(image_s * pimage, char * path)
{
	int nwritten, size = 0;
	unsigned char * buf;
	FILE * dst_file;

	buf = image_save_to_jpeg_buf(pimage, &size);
	if( !buf )
		return NULL;
 	dst_file = fopen(path, "w");
	if( !dst_file )
	{
		free(buf);
		return NULL;
	}
	nwritten = fwrite(buf, 1, size, dst_file);
	fclose(dst_file);
	free(buf);

	return (nwritten == size) ? path : NULL;
}
Ejemplo n.º 4
0
bool CJpegIO::CreateThumbnailFromSurface(unsigned char* bufferin, unsigned int width, unsigned int height, unsigned int format, unsigned int pitch, const std::string& destFile, 
                                         unsigned char* &bufferout, unsigned int &bufferoutSize)
{
  //Encode raw data from buffer, save to destbuffer
  struct jpeg_compress_struct cinfo;
  struct my_error_mgr jerr;
  JSAMPROW row_pointer[1];
  long unsigned int outBufSize = width * height;
  unsigned char* src = bufferin;
  unsigned char* rgbbuf;

  if(bufferin == NULL)
  {
    CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface no buffer");
    return false;
  }

  m_thumbnailbuffer = (unsigned char*) malloc(outBufSize); //Initial buffer. Grows as-needed.
  if (m_thumbnailbuffer == NULL)
  {
    CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface error allocating memory for image buffer");
    return false;
  }

  if(format == XB_FMT_RGB8)
  {
    rgbbuf = bufferin;
  }
  else if(format == XB_FMT_A8R8G8B8)
  {
    // create a copy for bgra -> rgb.
    rgbbuf = new unsigned char [(width * height * 3)];
    unsigned char* dst = rgbbuf;
    for (unsigned int y = 0; y < height; y++)
    {

      unsigned char* dst2 = dst;
      unsigned char* src2 = src;
      for (unsigned int x = 0; x < width; x++, src2 += 4)
      {
        *dst2++ = src2[2];
        *dst2++ = src2[1];
        *dst2++ = src2[0];
      }
      dst += width * 3;
      src += pitch;
    }
  }
  else
  {
    CLog::Log(LOGWARNING, "JpegIO::CreateThumbnailFromSurface Unsupported format");
    free(m_thumbnailbuffer);
    return false;
  }

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

  if (setjmp(jerr.setjmp_buffer))
  {
    jpeg_destroy_compress(&cinfo);
    free(m_thumbnailbuffer);
    if(format != XB_FMT_RGB8)
      delete [] rgbbuf;
    return false;
  }
  else
  {
#if JPEG_LIB_VERSION < 80
    x_jpeg_mem_dest(&cinfo, &m_thumbnailbuffer, &outBufSize);
#else
    jpeg_mem_dest(&cinfo, &m_thumbnailbuffer, &outBufSize);
#endif
    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 90, TRUE);
    jpeg_start_compress(&cinfo, TRUE);

    while (cinfo.next_scanline < cinfo.image_height)
    {
      row_pointer[0] = &rgbbuf[cinfo.next_scanline * width * 3];
      jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
  }
  if(format != XB_FMT_RGB8)
    delete [] rgbbuf;

  bufferout = m_thumbnailbuffer;
  bufferoutSize = outBufSize;

  return true;
}
Ejemplo n.º 5
0
int R2Image::
WriteJPEG(const char *filename) const
{
  // Open file
  FILE *fp = fopen(filename, "wb");
  if (!fp) {
    fprintf(stderr, "Unable to open image file: %s\n", filename);
    return 0;
  }

  // Initialize compression info
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);
  jpeg_stdio_dest(&cinfo, fp);
  cinfo.image_width = width; 	/* image width and height, in pixels */
  cinfo.image_height = height;
  cinfo.input_components = 3;		/* # of color components per pixel */
  cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
  cinfo.dct_method = JDCT_ISLOW;
  jpeg_set_defaults(&cinfo);
  cinfo.optimize_coding = TRUE;
  jpeg_set_quality(&cinfo, 75, TRUE);
  jpeg_start_compress(&cinfo, TRUE);
	
  // Allocate unsigned char buffer for reading image
  int rowsize = 3 * width;
  if ((rowsize % 4) != 0) rowsize = (rowsize / 4 + 1) * 4;
  int nbytes = rowsize * height;
  unsigned char *buffer = new unsigned char [nbytes];
  if (!buffer) {
    fprintf(stderr, "Unable to allocate temporary memory for JPEG file");
    fclose(fp);
    return 0;
  }

  // Fill buffer with pixels
  for (int j = 0; j < height; j++) {
    unsigned char *p = &buffer[j * rowsize];
    for (int i = 0; i < width; i++) {
      int r = (int) (255.0 * Red(i, j));
      int g = (int) (255.0 * Green(i, j));
      int b = (int) (255.0 * Blue(i, j));
      if (r > 255) r = 255;
      if (g > 255) g = 255;
      if (b > 255) b = 255;
      *(p++) = r;
      *(p++) = g;
      *(p++) = b;
    }
  }



  // Output scan lines
  // First jpeg pixel is top-left, so write in opposite scan-line order
  while (cinfo.next_scanline < cinfo.image_height) {
    int scanline = cinfo.image_height - cinfo.next_scanline - 1;
    unsigned char *row_pointer = &buffer[scanline * rowsize];
    jpeg_write_scanlines(&cinfo, &row_pointer, 1);
  }

  // Free everything
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);

  // Close file
  fclose(fp);

  // Free unsigned char buffer for reading pixels
  delete [] buffer;

  // Return number of bytes written
  return 1;
}
Ejemplo n.º 6
0
/*
=================
SaveJPGToBuffer

Encodes JPEG from image in image_buffer and writes to buffer.
Expects RGB input data
=================
*/
size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
	int image_width, int image_height, byte *image_buffer, int padding)
{
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
	my_dest_ptr dest;
	int row_stride;		/* physical row width in image buffer */
	size_t outcount;

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

	cinfo.err = jpeg_std_error(&jerr);
	cinfo.err->error_exit = R_JPGErrorExit;
	cinfo.err->output_message = R_JPGOutputMessage;
	
	/* Now we can initialize the JPEG compression object. */
	jpeg_create_compress(&cinfo);

	/* Step 2: specify data destination (eg, a file) */
	/* Note: steps 2 and 3 can be done in either order. */

	jpegDest(&cinfo, buffer, bufSize);

	/* Step 3: set parameters for compression */
	cinfo.image_width = image_width; 	/* image width and height, in pixels */
	cinfo.image_height = image_height;
	cinfo.input_components = 3;		/* # of color components per pixel */
	cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

	/* If quality is set high, disable chroma subsampling */
	if (quality >= 85) {
		cinfo.comp_info[0].h_samp_factor = 1;
		cinfo.comp_info[0].v_samp_factor = 1;
	}

	/* Step 4: Start compressor */

	jpeg_start_compress(&cinfo, TRUE);

	/* Step 5: while (scan lines remain to be written) */
	/*           jpeg_write_scanlines(...); */

	row_stride = image_width * cinfo.input_components + padding; /* JSAMPLEs per row in image_buffer */

	while (cinfo.next_scanline < cinfo.image_height) {
		/* jpeg_write_scanlines expects an array of pointers to scanlines.
		* Here the array is only one element long, but you could pass
		* more than one scanline at a time if that's more convenient.
		*/
		row_pointer[0] = &image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride];
		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

	/* Step 6: Finish compression */
	jpeg_finish_compress(&cinfo);

	dest = (my_dest_ptr) cinfo.dest;
	outcount = dest->size - dest->pub.free_in_buffer;

	/* Step 7: release JPEG compression object */
	jpeg_destroy_compress(&cinfo);

	/* And we're done! */
	return outcount;
}
Ejemplo n.º 7
0
void export_JPEG_file (const char* filename, const unsigned char* image_chars,
		       int image_height, int image_width, int num_components,
		       int quality)
{
  /* This struct contains the JPEG compression parameters and pointers to
   * working space (which is allocated as needed by the JPEG library).
   * It is possible to have several such structures, representing multiple
   * compression/decompression processes, in existence at once.  We refer
   * to any one struct (and its associated working data) as a "JPEG object".
   */
  struct jpeg_compress_struct cinfo;
  /* 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 */
  FILE * outfile;		/* target file */
  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
  int row_stride;		/* physical row width in image buffer */

  JSAMPLE* image_buffer = (JSAMPLE*) image_chars;

  /* Step 1: allocate and initialize JPEG compression 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);
  /* Now we can initialize the JPEG compression object. */
  jpeg_create_compress(&cinfo);

  /* Step 2: specify data destination (eg, a file) */
  /* Note: steps 2 and 3 can be done in either order. */

  /* Here we use the library-supplied code to send compressed data to a
   * stdio stream.  You can also write your own code to do something else.
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
   * requires it in order to write binary files.
   */
  if ((outfile = fopen(filename, "wb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    exit(1);
  }
  jpeg_stdio_dest(&cinfo, outfile);

  /* Step 3: set parameters for compression */

  /* First we supply a description of the input image.
   * Four fields of the cinfo struct must be filled in:
   */
  cinfo.image_width = image_width; 	/* image width and height, in pixels */
  cinfo.image_height = image_height;
  cinfo.input_components = num_components;/* # of color components per pixel */
  if (num_components==3)
    cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
  else
    cinfo.in_color_space = JCS_GRAYSCALE;
  /* Now use the library's routine to set default compression parameters.
   * (You must set at least cinfo.in_color_space before calling this,
   * since the defaults depend on the source color space.)
   */
  jpeg_set_defaults(&cinfo);
  /* Now you can set any non-default parameters you wish to.
   * Here we just illustrate the use of quality (quantization table) scaling:
   */
  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

  /* Step 4: Start compressor */

  /* TRUE ensures that we will write a complete interchange-JPEG file.
   * Pass TRUE unless you are very sure of what you're doing.
   */
  jpeg_start_compress(&cinfo, TRUE);

  /* Step 5: while (scan lines remain to be written) */
  /*           jpeg_write_scanlines(...); */

  /* Here we use the library's state variable cinfo.next_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   * To keep things simple, we pass one scanline per call; you can pass
   * more if you wish, though.
   */
  row_stride = image_width * num_components;

  while (cinfo.next_scanline < cinfo.image_height) {
    /* jpeg_write_scanlines expects an array of pointers to scanlines.
     * Here the array is only one element long, but you could pass
     * more than one scanline at a time if that's more convenient.
     */
    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
  }

  /* Step 6: Finish compression */

  jpeg_finish_compress(&cinfo);
  /* After finish_compress, we can close the output file. */
  fclose(outfile);

  /* Step 7: release JPEG compression object */

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

  /* And we're done! */
}
Ejemplo n.º 8
0
static bool image_jpeg_save (fs_file_t *f, const image_t *im) {
  struct jpeg_compress_struct cs;
  struct jpeg_error_mgr       em;

  if (unlikely(IMAGE_DATA_FORMAT_BGRA != im->format)) {
    fs_print_error(f, "only BGRA format is supported for JPEG saving %c");
    return false;
  }

  cs.err = jpeg_std_error(&em);

  cs.err->error_exit   = jpeg_error_exit;
  cs.err->emit_message = jpeg_emit_message;

  if (unlikely(0 != setjmp(jpeg_jmpbuf))) {
    return false;
  }

  jpeg_CreateCompress(&cs, JPEG_LIB_VERSION, sizeof(cs));

  if (unlikely(0 != setjmp(jpeg_jmpbuf))) {
    goto error;
  }

  jpeg_dest(&cs, f);

  cs.image_width      = im->width;
  cs.image_height     = im->height;
  cs.input_components = 3;
  cs.in_color_space   = jpeg_bgr ? jpeg_bgr : JCS_RGB;

  jpeg_set_defaults(&cs);
  jpeg_set_quality(&cs, 100, TRUE);

  // 1x1 subsampling
  cs.comp_info[0].v_samp_factor = 1;
  cs.comp_info[0].h_samp_factor = 1;

  jpeg_start_compress(&cs, TRUE);

  uint8_t *data = mem_alloc(image_mem_pool, im->width * 3);

  for (int r = 0, in = 0; r < im->height; r++) {
    JSAMPROW scanlines[1] = { (void *)data };

    for (int i = 0; i < im->width * 3; i += 3, in += 4) {
      if (jpeg_bgr) {
        data[i + 0] = im->data[in + 0];
        data[i + 1] = im->data[in + 1];
        data[i + 2] = im->data[in + 2];
      }
      else {
        data[i + 0] = im->data[in + 2];
        data[i + 1] = im->data[in + 1];
        data[i + 2] = im->data[in + 0];
      }
    }

    jpeg_write_scanlines(&cs, scanlines, 1);
  }

  jpeg_finish_compress(&cs);
  jpeg_destroy_compress(&cs);

  mem_free(data);

  return true;

error:
  jpeg_destroy_compress(&cs);

  return false;
}
Ejemplo n.º 9
0
void
banded_float_image_export_as_jpeg(BandedFloatImage *self, const char *output_name)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  int i;

  assert(self->nbands >= 1);

  float *min, *max, *mean, *stddev, *lin_min, *lin_max;
  min = MALLOC(sizeof(float)*self->nbands);
  max = MALLOC(sizeof(float)*self->nbands);
  mean = MALLOC(sizeof(float)*self->nbands);
  stddev = MALLOC(sizeof(float)*self->nbands);

  for (i=0; i<self->nbands; ++i) {
      float_image_statistics(self->images[i], &min[i], &max[i], &mean[i], &stddev[i], -999);
      lin_min[i] = mean[i] - 2 * stddev[i];
      lin_max[i] = mean[i] + 2 * stddev[i];
  }

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

  FILE *ofp = fopen (output_name, "wb");
  if ( ofp == NULL ) {
    asfPrintError("Open of %s for writing failed: %s",
                  output_name, strerror(errno));
  }

  jpeg_stdio_dest (&cinfo, ofp);

  int nl = banded_float_image_get_size_y(self);
  int ns = banded_float_image_get_size_x(self);

  cinfo.image_width = ns;
  cinfo.image_height = nl;

  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;

  jpeg_set_defaults (&cinfo);
  jpeg_start_compress (&cinfo, TRUE);

  JSAMPLE *jsample_row = MALLOC(sizeof(JSAMPLE)*ns*3);
  JSAMPROW *row_pointer = MALLOC(sizeof(JSAMPROW));

  while (cinfo.next_scanline < cinfo.image_height) {
      for (i=0; i<ns; ++i) {
          int band = 0;
          int r = scale_to_byte(lin_min[band], lin_max[band],
              banded_float_image_get_pixel(self, band, cinfo.next_scanline, i));

          if (band < self->nbands-1) ++band;
          int g = scale_to_byte(lin_min[band], lin_max[band],
              banded_float_image_get_pixel(self, band, cinfo.next_scanline, i));

          if (band < self->nbands-1) ++band;
          int b = scale_to_byte(lin_min[band], lin_max[band],
              banded_float_image_get_pixel(self, band, cinfo.next_scanline, i));

          jsample_row[i*3+0] = (JSAMPLE) r;
          jsample_row[i*3+1] = (JSAMPLE) g;
          jsample_row[i*3+2] = (JSAMPLE) b;
      }
      row_pointer[0] = jsample_row;
      int written = jpeg_write_scanlines(&cinfo, row_pointer, 1);
      if (written != 1)
          asfPrintError("Failed to write the correct number of lines.\n");
      asfLineMeter(cinfo.next_scanline, cinfo.image_height);
  }

  FREE(row_pointer);
  FREE(jsample_row);
  jpeg_finish_compress (&cinfo);
  FCLOSE (ofp);
  jpeg_destroy_compress (&cinfo);
}
Ejemplo n.º 10
0
// Access point for applications wishing to use the jpeg library directly in
// conjunction with DevIL.
//
// The caller must set up the desired parameters by e.g. calling
// jpeg_set_defaults and overriding the parameters the caller wishes
// to change, such as quality, before calling this function. The caller
// is also responsible for calling jpeg_finish_compress in case the
// caller still needs to compressor for something.
// 
ILboolean ILAPIENTRY ilSaveFromJpegStruct(ILvoid *_JpegInfo)
{
#ifndef IL_NO_JPG
#ifndef IL_USE_IJL
	void (*errorHandler)(j_common_ptr);
	JSAMPROW	row_pointer[1];
	ILimage		*TempImage;
	ILubyte		*TempData;
	j_compress_ptr JpegInfo = (j_compress_ptr)_JpegInfo;

	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	//added on 2003-08-31 as explained in sf bug 596793
	jpgErrorOccured = IL_FALSE;

	errorHandler = JpegInfo->err->error_exit;
	JpegInfo->err->error_exit = ExitErrorHandle;


	if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) {
		TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
		if (TempImage == NULL) {
			return IL_FALSE;
		}
	}
	else {
		TempImage = iCurImage;
	}

	if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) {
		TempData = iGetFlipped(TempImage);
		if (TempData == NULL) {
			if (TempImage != iCurImage)
				ilCloseImage(TempImage);
			return IL_FALSE;
		}
	}
	else {
		TempData = TempImage->Data;
	}

	JpegInfo->image_width = TempImage->Width;  // image width and height, in pixels
	JpegInfo->image_height = TempImage->Height;
	JpegInfo->input_components = TempImage->Bpp;  // # of color components per pixel

	jpeg_start_compress(JpegInfo, IL_TRUE);

	//row_stride = image_width * 3;	// JSAMPLEs per row in image_buffer

	while (JpegInfo->next_scanline < JpegInfo->image_height) {
		// jpeg_write_scanlines expects an array of pointers to scanlines.
		// Here the array is only one element long, but you could pass
		// more than one scanline at a time if that's more convenient.
		row_pointer[0] = &TempData[JpegInfo->next_scanline * TempImage->Bps];
		(ILvoid) jpeg_write_scanlines(JpegInfo, row_pointer, 1);
	}

	if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
		ifree(TempData);
	if (TempImage != iCurImage)
		ilCloseImage(TempImage);

	return (!jpgErrorOccured);
#endif
#endif
	return IL_FALSE;
}
Ejemplo n.º 11
0
gint
xjpg_save_drawable (const char     *filename,
                    gint32          image_ID,
                    gint32          drawable_ID,
                    gint            save_mode,
                    t_JpegSaveVals *jsvals)
{
  GimpPixelRgn pixel_rgn;
  GimpDrawable *drawable;
  GimpImageType drawable_type;
  struct jpeg_compress_struct cinfo;
  struct my_error_mgr jerr;
  FILE * volatile outfile;
  guchar *temp, *t;
  guchar *data;
  guchar *src, *s;
  int has_alpha;
  int rowstride, yend;
  int i, j;
  int alpha_offset;
  guchar alpha_byte;
  guchar volatile l_alpha_sum;

  alpha_offset = 0;
  has_alpha = 0;
  src = NULL;
  temp = NULL;
  data = NULL;
  l_alpha_sum = 0xff;

  drawable = gimp_drawable_get (drawable_ID);
  drawable_type = gimp_drawable_type (drawable_ID);
  switch (drawable_type)
  {
    case GIMP_RGB_IMAGE:
    case GIMP_GRAY_IMAGE:
      if(save_mode == JSVM_ALPHA)
        return FALSE;              /* there is no alpha to save */
      break;
    case GIMP_RGBA_IMAGE:
    case GIMP_GRAYA_IMAGE:
      break;

    case GIMP_INDEXED_IMAGE:
      /*g_message ("jpeg: cannot operate on indexed color images");*/
      return FALSE;
      break;
    default:
      /*g_message ("jpeg: cannot operate on unknown image types");*/
      return FALSE;
      break;
  }



  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE);


  /* Step 1: allocate and initialize JPEG compression 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.pub);
  jerr.pub.error_exit = my_error_exit;

  outfile = NULL;
  /* 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_compress (&cinfo);
      if (outfile)
	fclose (outfile);
      if (drawable)
	gimp_drawable_detach (drawable);

      return FALSE;
    }

  /* Now we can initialize the JPEG compression object. */
  jpeg_create_compress (&cinfo);

  /* Step 2: specify data destination (eg, a file) */
  /* Note: steps 2 and 3 can be done in either order. */

  /* Here we use the library-supplied code to send compressed data to a
   * stdio stream.  You can also write your own code to do something else.
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
   * requires it in order to write binary files.
   */
  if ((outfile = g_fopen (filename, "wb")) == NULL)
    {
      g_message ("can't open %s\n", filename);
      return FALSE;
    }
  jpeg_stdio_dest (&cinfo, outfile);

  /* Get the input image and a pointer to its data.
   */
  switch (drawable_type)
  {
    case GIMP_RGB_IMAGE:
    case GIMP_GRAY_IMAGE:
      /* # of color components per pixel */
      cinfo.input_components = drawable->bpp;
      has_alpha = 0;
      alpha_offset = 0;
      break;
    case GIMP_RGBA_IMAGE:
    case GIMP_GRAYA_IMAGE:
      if(save_mode == JSVM_ALPHA)
      {
 	cinfo.input_components = 1;
      }
      else
      {
        /* # of color components per pixel (minus the GIMP alpha channel) */
	cinfo.input_components = drawable->bpp - 1;
      }
      alpha_offset = drawable->bpp -1;
      has_alpha = 1;
      break;
    default:
      return FALSE;
      break;
  }

  /* Step 3: set parameters for compression */

  /* First we supply a description of the input image.
   * Four fields of the cinfo struct must be filled in:
   */
  /* image width and height, in pixels */
  cinfo.image_width = drawable->width;
  cinfo.image_height = drawable->height;
  /* colorspace of input image */
  cinfo.in_color_space = ( (save_mode != JSVM_ALPHA) &&
                          (drawable_type == GIMP_RGB_IMAGE ||
			   drawable_type == GIMP_RGBA_IMAGE))
    ? JCS_RGB : JCS_GRAYSCALE;
  /* Now use the library's routine to set default compression parameters.
   * (You must set at least cinfo.in_color_space before calling this,
   * since the defaults depend on the source color space.)
   */
  jpeg_set_defaults (&cinfo);
  /* Now you can set any non-default parameters you wish to.
   * Here we just illustrate the use of quality (quantization table) scaling:
   */
  jpeg_set_quality (&cinfo, (int) (jsvals->quality * 100), TRUE /* limit to baseline-JPEG values */);
  cinfo.smoothing_factor = (int) (jsvals->smoothing * 100);
  cinfo.optimize_coding = jsvals->optimize;

  /* Step 4: Start compressor */

  /* TRUE ensures that we will write a complete interchange-JPEG file.
   * Pass TRUE unless you are very sure of what you're doing.
   */
  jpeg_start_compress (&cinfo, TRUE);

  /* Step 5: while (scan lines remain to be written) */
  /*           jpeg_write_scanlines(...); */

  /* Here we use the library's state variable cinfo.next_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   * To keep things simple, we pass one scanline per call; you can pass
   * more if you wish, though.
   */
  /* JSAMPLEs per row in image_buffer */
  rowstride = drawable->bpp * drawable->width;
  temp = (guchar *) g_malloc (cinfo.image_width * cinfo.input_components);
  data = (guchar *) g_malloc (rowstride * gimp_tile_height ());
  src = data;

  while (cinfo.next_scanline < cinfo.image_height)
  {
      if ((cinfo.next_scanline % gimp_tile_height ()) == 0)
      {
	  yend = cinfo.next_scanline + gimp_tile_height ();
	  yend = MIN (yend, cinfo.image_height);
	  gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, cinfo.next_scanline, cinfo.image_width,
				   (yend - cinfo.next_scanline));
	  src = data;
      }

      t = temp;
      s = src;
      i = cinfo.image_width;

      switch(save_mode)
      {
	case JSVM_DRAWABLE:
	    if(jsvals->clr_transparent)
	    {
	      /* save drawable (clear pixels where alpha is full transparent) */
	      while (i--)
	      {
	          alpha_byte = s[cinfo.input_components];
		  for (j = 0; j < cinfo.input_components; j++)
		  {
		     if(alpha_byte != 0) { *t++ = *s++;   }
		     else                { *t++ = 0; s++; }
		  }
		  if (has_alpha)  /* ignore alpha channel */
		  {
		    s++;
		  }
	      }
	    }
	    else
	    {
	      /* save the drawable as it is (ignore alpha channel) */
	      while (i--)
	      {
		  for (j = 0; j < cinfo.input_components; j++)
		  {
                    *t++ = *s++;
		  }
		  if (has_alpha)  /* ignore alpha channel */
		  {
		    s++;
		  }
	      }
	    }
	    break;
        case JSVM_ALPHA:
	    /* save the drawable's alpha cahnnel */
	    while (i--)
	    {
		s += alpha_offset;
		l_alpha_sum &= (*s);  /* check all alpha bytes for full opacity */
                *t++ = *s++;
	    }
	    break;
      }

      src += rowstride;
      jpeg_write_scanlines (&cinfo, (JSAMPARRAY) &temp, 1);

      if ((cinfo.next_scanline % 5) == 0)
	gimp_progress_update ((double) cinfo.next_scanline / (double) cinfo.image_height);
  }

  /* Step 6: Finish compression */
  jpeg_finish_compress (&cinfo);
  /* After finish_compress, we can close the output file. */
  fclose (outfile);

  if((save_mode == JSVM_ALPHA) && (l_alpha_sum == 0xff))
  {
    /* all bytes in the alpha channel are set to 0xff
     * == full opaque image. We can remove the file
     * to save diskspace
     */
    g_remove(filename);
  }

  /* Step 7: release JPEG compression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_compress (&cinfo);
  /* free the temporary buffer */
  g_free (temp);
  g_free (data);

  gimp_drawable_detach (drawable);

  return TRUE;
}	/* end xjpg_save_drawable */
Ejemplo n.º 12
0
// Internal function used to save the Jpeg.
ILboolean iSaveJpegInternal()
{
	struct		jpeg_compress_struct JpegInfo;
	struct		jpeg_error_mgr Error;
	JSAMPROW	row_pointer[1];
	ILimage		*TempImage;
	ILubyte		*TempData;
	ILenum		Type = 0;

	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	/*if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION)
		Quality = 85;  // Not sure how low we should dare go...
	else
		Quality = 99;*/

	if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) {
		TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
		if (TempImage == NULL) {
			return IL_FALSE;
		}
	}
	else {
		TempImage = iCurImage;
	}

	if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) {
		TempData = iGetFlipped(TempImage);
		if (TempData == NULL) {
			if (TempImage != iCurImage)
				ilCloseImage(TempImage);
			return IL_FALSE;
		}
	}
	else {
		TempData = TempImage->Data;
	}


	JpegInfo.err = jpeg_std_error(&Error);
	// Now we can initialize the JPEG compression object.
	jpeg_create_compress(&JpegInfo);

	//jpeg_stdio_dest(&JpegInfo, JpegFile);
	devil_jpeg_write_init(&JpegInfo);

	JpegInfo.image_width = TempImage->Width;  // image width and height, in pixels
	JpegInfo.image_height = TempImage->Height;
	JpegInfo.input_components = TempImage->Bpp;  // # of color components per pixel

	// John Villar's addition
	if (TempImage->Bpp == 1)
		JpegInfo.in_color_space = JCS_GRAYSCALE;
	else
		JpegInfo.in_color_space = JCS_RGB;

	jpeg_set_defaults(&JpegInfo);

#ifndef IL_USE_JPEGLIB_UNMODIFIED
	Type = iGetInt(IL_JPG_SAVE_FORMAT);
	if (Type == IL_EXIF) {
		JpegInfo.write_JFIF_header = FALSE;
		JpegInfo.write_EXIF_header = TRUE;
	}
	else if (Type == IL_JFIF) {
		JpegInfo.write_JFIF_header = TRUE;
		JpegInfo.write_EXIF_header = FALSE;
	}
#else
	Type = Type;
	JpegInfo.write_JFIF_header = TRUE;
#endif//IL_USE_JPEGLIB_UNMODIFIED

	jpeg_set_quality(&JpegInfo, iGetInt(IL_JPG_QUALITY), IL_TRUE);

	jpeg_start_compress(&JpegInfo, IL_TRUE);

	//row_stride = image_width * 3;	// JSAMPLEs per row in image_buffer

	while (JpegInfo.next_scanline < JpegInfo.image_height) {
		// jpeg_write_scanlines expects an array of pointers to scanlines.
		// Here the array is only one element long, but you could pass
		// more than one scanline at a time if that's more convenient.
		row_pointer[0] = &TempData[JpegInfo.next_scanline * TempImage->Bps];
		(ILvoid) jpeg_write_scanlines(&JpegInfo, row_pointer, 1);
	}

	// Step 6: Finish compression
	jpeg_finish_compress(&JpegInfo);

	// Step 7: release JPEG compression object

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

	if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
		ifree(TempData);
	if (TempImage != iCurImage)
		ilCloseImage(TempImage);

	return IL_TRUE;
}
Ejemplo n.º 13
0
int JpegCompressor::compressRawImage(const void * image,
                                     int width,
                                     int height,
                                     int quality,
                                     int useEffect = 0)
{
    void * src = const_cast<void *>(image);
    uint8_t *yp = static_cast<uint8_t *>(src);
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_pointer[1];
    uint8_t *line_buffer;
    int bufferlen = width*height<<1;

    line_buffer = (uint8_t*)calloc(width*3,1);
    mJpegBuffer = new uint8_t[bufferlen];
    mJpegSize = 0;

    if(!line_buffer) {
        LOGE("@TEI compress_yuv_to_jpeg: line_buffer calloc failed!" );
        return -1;
    }
    if (!mJpegBuffer)
    {
        free(line_buffer);
        return -1;
    }

    cinfo.err = jpeg_std_error (&jerr);
    jpeg_create_compress (&cinfo);
    jpeg_nf_stdio_dest(&cinfo,(char*)mJpegBuffer,&bufferlen );

    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults (&cinfo);
    jpeg_set_quality (&cinfo, quality, TRUE);

    jpeg_start_compress (&cinfo, TRUE);

    uint8_t *vp, *up,*vpos, *upos;

    getYuvOffsets(width, height, yp, &up, &vp);

    vpos=vp;
    upos=up;

    uint32_t rgb = 0xFFFFFFFF;
    int z = 0;
    while (cinfo.next_scanline < cinfo.image_height) {
        unsigned char *ptr = line_buffer;

        for (int x = 0; x < width; x += 2) {
            rgb = YUVToRGB32WithEffect(*yp, *up, *vp, useEffect);
            *ptr++ = R32(rgb);
            *ptr++ = G32(rgb);
            *ptr++ = B32(rgb);

            //
            yp += mStrides[0];
            rgb = YUVToRGB32WithEffect(*yp, *up, *vp, useEffect);
            *ptr++ = R32(rgb);
            *ptr++ = G32(rgb);
            *ptr++ = B32(rgb);
            //
            yp += mStrides[0];
            up += mStrides[1];
            vp += mStrides[2];
        }

        if (mIs420) {
            if (z == 0) {
                vp = vpos;
                up = upos;
                z++;
            } else {
                vpos = vp;
                upos = up;
                z--;
            }
        }

        row_pointer[0] = line_buffer;
        jpeg_write_scanlines (&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress (&cinfo);
    jpeg_destroy_compress (&cinfo);

    free (line_buffer);
    mJpegSize = bufferlen;
    LOGD("====== Jpeg size: %d ======", mJpegSize);
    return 0;
}
Ejemplo n.º 14
0
bool CCImage::_saveImageToJPG(const char * pszFilePath)
{
	bool bRet = false;
	do 
	{
		CC_BREAK_IF(NULL == pszFilePath);

		struct jpeg_compress_struct cinfo;
		struct jpeg_error_mgr jerr;
		FILE * outfile;                 /* target file */
		JSAMPROW row_pointer[1];        /* pointer to JSAMPLE row[s] */
		int     row_stride;          /* physical row width in image buffer */

		FILE_STANDARD_INFO fileStandardInfo = { 0 };
		HANDLE hFile;
		std::wstring path = CCUtf8ToUnicode(pszFilePath);

		CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0};
		extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
		extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
		extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
		extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
		extendedParams.lpSecurityAttributes = nullptr;
		extendedParams.hTemplateFile = nullptr;

		// read the file from hardware
		hFile = ::CreateFile2(path.c_str(), GENERIC_WRITE, 0, CREATE_ALWAYS, &extendedParams);
		if (INVALID_HANDLE_VALUE == hFile)
		{
			break;
		}

		int CrtFileHandle;
		/* convert OS file handle to CRT file pointer */ 
		if ((CrtFileHandle=_open_osfhandle ((long)hFile,_O_RDONLY))==-1){ 
			//printf( "_open_osfhandle Failed "); 
			break;
		} 
		/* Change handle access to stream access. */ 
		if( (outfile = _fdopen( CrtFileHandle, "wb")) == NULL ) { 
			//printf( "_fdopen Failed "); 
			break;
		} 


		cinfo.err = jpeg_std_error(&jerr);
		/* Now we can initialize the JPEG compression object. */
		jpeg_create_compress(&cinfo);
		
		jpeg_stdio_dest(&cinfo, outfile);

		cinfo.image_width = m_nWidth;    /* image width and height, in pixels */
		cinfo.image_height = m_nHeight;
		cinfo.input_components = 3;       /* # of color components per pixel */
		cinfo.in_color_space = JCS_RGB;       /* colorspace of input image */

		jpeg_set_defaults(&cinfo);

		jpeg_start_compress(&cinfo, TRUE);

		row_stride = m_nWidth * 3; /* JSAMPLEs per row in image_buffer */

		if (m_bHasAlpha)
		{
			unsigned char *pTempData = new unsigned char[m_nWidth * m_nHeight * 3];
			if (NULL == pTempData)
			{
				jpeg_finish_compress(&cinfo);
				jpeg_destroy_compress(&cinfo);
				fclose(outfile);
				break;
			}

			for (int i = 0; i < m_nHeight; ++i)
			{
				for (int j = 0; j < m_nWidth; ++j)

				{
					pTempData[(i * m_nWidth + j) * 3] = m_pData[(i * m_nWidth + j) * 4];
					pTempData[(i * m_nWidth + j) * 3 + 1] = m_pData[(i * m_nWidth + j) * 4 + 1];
					pTempData[(i * m_nWidth + j) * 3 + 2] = m_pData[(i * m_nWidth + j) * 4 + 2];
				}
			}

			while (cinfo.next_scanline < cinfo.image_height) {
				row_pointer[0] = & pTempData[cinfo.next_scanline * row_stride];
				(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
			}

			CC_SAFE_DELETE_ARRAY(pTempData);
		} 
		else
		{
			while (cinfo.next_scanline < cinfo.image_height) {
				row_pointer[0] = & m_pData[cinfo.next_scanline * row_stride];
				(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
			}
		}

		jpeg_finish_compress(&cinfo);
		fclose(outfile);
		jpeg_destroy_compress(&cinfo);
		
		bRet = true;
	} while (0);
	return bRet;
}
Ejemplo n.º 15
0
BGD_DECLARE(void) gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  int i, j, jidx;
  /* volatile so we can gdFree it on return from longjmp */
  volatile JSAMPROW row = 0;
  JSAMPROW rowptr[1];
  jmpbuf_wrapper jmpbufw;
  JDIMENSION nlines;
  char comment[255];

#ifdef JPEG_DEBUG
  printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
  printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
	  JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
  if (!im->trueColor)
    {
      for (i = 0; i < im->colorsTotal; i++)
	{
	  if (!im->open[i])
	    printf ("gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i,
		    im->red[i], im->green[i], im->blue[i]);
	}
    }
#endif /* JPEG_DEBUG */

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

  cinfo.err = jpeg_std_error (&jerr);
  cinfo.client_data = &jmpbufw;
  if (setjmp (jmpbufw.jmpbuf) != 0)
    {
      /* we're here courtesy of longjmp */
      if (row)
	gdFree (row);
      return;
    }

  cinfo.err->error_exit = fatal_jpeg_error;

  jpeg_create_compress (&cinfo);

  cinfo.image_width = im->sx;
  cinfo.image_height = im->sy;
  cinfo.input_components = 3;	/* # of color components per pixel */
  cinfo.in_color_space = JCS_RGB;	/* colorspace of input image */
  jpeg_set_defaults (&cinfo);
  if (quality >= 0)
    jpeg_set_quality (&cinfo, quality, TRUE);

  /* If user requests interlace, translate that to progressive JPEG */
  if (gdImageGetInterlaced (im))
    {
#ifdef JPEG_DEBUG
      printf ("gd-jpeg: interlace set, outputting progressive"
	      " JPEG image\n");
#endif
      jpeg_simple_progression (&cinfo);
    }

  jpeg_gdIOCtx_dest (&cinfo, outfile);

  row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components
			     * sizeof (JSAMPLE));
  if (row == 0)
    {
      fprintf (stderr, "gd-jpeg: error: unable to allocate JPEG row "
	       "structure: gdCalloc returns NULL\n");
      jpeg_destroy_compress (&cinfo);
      return;
    }

  rowptr[0] = row;

  jpeg_start_compress (&cinfo, TRUE);

  sprintf (comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),",
	   GD_JPEG_VERSION, JPEG_LIB_VERSION);
  if (quality >= 0)
    sprintf (comment + strlen (comment), " quality = %d\n", quality);
  else
    strcat (comment + strlen (comment), " default quality\n");
  jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment,
		     (unsigned int) strlen (comment));
  if (im->trueColor)
    {
#if BITS_IN_JSAMPLE == 12
      fprintf (stderr,
	       "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
	       "precision. This is mostly useless, because JPEGs on the web are\n"
	       "8-bit and such versions of the jpeg library won't read or write\n"
	       "them. GD doesn't support these unusual images. Edit your\n"
	       "jmorecfg.h file to specify the correct precision and completely\n"
	       "'make clean' and 'make install' libjpeg again. Sorry.\n");
      goto error;
#endif /* BITS_IN_JSAMPLE == 12 */
      for (i = 0; i < im->sy; i++)
	{
	  for (jidx = 0, j = 0; j < im->sx; j++)
	    {
	      int val = im->tpixels[i][j];
	      row[jidx++] = gdTrueColorGetRed (val);
	      row[jidx++] = gdTrueColorGetGreen (val);
	      row[jidx++] = gdTrueColorGetBlue (val);
	    }

	  nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
	  if (nlines != 1)
	    fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines"
		     " returns %u -- expected 1\n", nlines);
	}
    }
  else
    {
      for (i = 0; i < im->sy; i++)
	{
	  for (jidx = 0, j = 0; j < im->sx; j++)
	    {
	      int idx = im->pixels[i][j];

	      /*
	       * NB: Although gd RGB values are ints, their max value is
	       * 255 (see the documentation for gdImageColorAllocate())
	       * -- perfect for 8-bit JPEG encoding (which is the norm)
	       */
#if BITS_IN_JSAMPLE == 8
	      row[jidx++] = im->red[idx];
	      row[jidx++] = im->green[idx];
	      row[jidx++] = im->blue[idx];
#elif BITS_IN_JSAMPLE == 12
	      row[jidx++] = im->red[idx] << 4;
	      row[jidx++] = im->green[idx] << 4;
	      row[jidx++] = im->blue[idx] << 4;
#else
#error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
#endif
	    }

	  nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
	  if (nlines != 1)
	    fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines"
		     " returns %u -- expected 1\n", nlines);
	}
    }
  jpeg_finish_compress (&cinfo);
  jpeg_destroy_compress (&cinfo);
  gdFree (row);
}
int V4L2Camera::saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int height, FILE *file, int quality)
{
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_pointer[1];
    unsigned char *line_buffer, *yuyv;
    int z;
    int fileSize;

    line_buffer = (unsigned char *) calloc (width * 3, 1);
    yuyv = inputBuffer;

    cinfo.err = jpeg_std_error (&jerr);
    jpeg_create_compress (&cinfo);
    jpeg_stdio_dest (&cinfo, file);

    ALOGI("JPEG PICTURE WIDTH AND HEIGHT: %dx%d", width, height);

    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults (&cinfo);
    jpeg_set_quality (&cinfo, quality, TRUE);

    jpeg_start_compress (&cinfo, TRUE);

    z = 0;
    while (cinfo.next_scanline < cinfo.image_height) {
        int x;
        unsigned char *ptr = line_buffer;

        for (x = 0; x < width; x++) {
            int r, g, b;
            int y, u, v;

            if (!z)
                y = yuyv[0] << 8;
            else
                y = yuyv[2] << 8;

            u = yuyv[1] - 128;
            v = yuyv[3] - 128;

            r = (y + (359 * v)) >> 8;
            g = (y - (88 * u) - (183 * v)) >> 8;
            b = (y + (454 * u)) >> 8;

            *(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
            *(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
            *(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);

            if (z++) {
                z = 0;
                yuyv += 4;
            }
        }

        row_pointer[0] = line_buffer;
        jpeg_write_scanlines (&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress (&cinfo);
    fileSize = ftell(file);
    jpeg_destroy_compress (&cinfo);

    free (line_buffer);

    return fileSize;
}
Ejemplo n.º 17
0
static BOOL SaveBmpToJPGfile(HBITMAP hbmp,LPTSTR file)
{
	LONG i;
	LONG	 bmp_length;
	PVOID	 bmp_data ;
	BITMAP	bmp;
	FILE * fp = NULL;
	
	if(!GetObject(hbmp,sizeof(BITMAP),&bmp))return FALSE;

	bmp_length = bmp.bmWidthBytes * bmp.bmHeight;
	
	fp = _tfopen(file,TEXT("wb"));
	
	if(!fp)
	{
		DeleteObject(hbmp);
		return FALSE;
	}

	jpeg_error_mgr err;

	jpeg_compress_struct cinfo={0};

	jpeg_create_compress(&cinfo);

	jpeg_stdio_dest(&cinfo,fp);

	cinfo.image_width = bmp.bmWidth;
	cinfo.image_height = bmp.bmHeight;

	cinfo.input_components = 3; //rgb only
	cinfo.in_color_space = JCS_RGB;

	jpeg_set_defaults(&cinfo);
	
//cinfo.err = & err;

	cinfo.err = jpeg_std_error(&err);



	jpeg_start_compress(&cinfo, TRUE);

	bmp_data = malloc(bmp_length);
	
	GetBitmapBits(hbmp,bmp_length,bmp_data);

	PBYTE row_pointer;

	if(bmp.bmBitsPixel != 24)
		row_pointer = (PBYTE)malloc(bmp.bmWidth * 3);

	while (cinfo.next_scanline < cinfo.image_height) 
	{
		// 32bit to 24 bit, ro 16 bit to 24 bit

		switch(bmp.bmBitsPixel)
		{
		case 24:
			row_pointer= (PBYTE)bmp_data + bmp.bmWidthBytes * cinfo.next_scanline;
			jpeg_write_scanlines(&cinfo, &row_pointer, 1);
			row_pointer = NULL;
			break;
		case 32:
			for (i=0; i < bmp.bmWidth ; i++)
			{
				row_pointer[i*3+2] = ((PBYTE)bmp_data)[bmp.bmWidthBytes * cinfo.next_scanline + i*4 ];
				row_pointer[i*3+1] = ((PBYTE)bmp_data)[bmp.bmWidthBytes * cinfo.next_scanline +i*4+1];
				row_pointer[i*3] = ((PBYTE)bmp_data)[bmp.bmWidthBytes * cinfo.next_scanline +i*4 + 2];
			}
			jpeg_write_scanlines(&cinfo, &row_pointer, 1);
			break;
		case 16:
			for ( i=0; i < bmp.bmWidth ; i++)
			{
				WORD   Color;//存16bit的颜色 
				
				double   Red,Green,Blue; 
				
				Color = *(PWORD)((PBYTE)bmp_data + cinfo.next_scanline * bmp.bmWidthBytes + i*2 );
								
				Red=(Color&0xF800)>> 11; 
				
				Green=(Color&0x7e0)>> 5; 
				
				Blue=(Color&0x1F);
				
				row_pointer[i*3]= (BYTE)(Red * 256  / 32 +0.5);
				row_pointer[i*3+1] = (BYTE)(Green * 256  / 64 +0.5);
				row_pointer[i*3+2] = (BYTE)(Blue * 256  / 32 +0.5);
			}
			jpeg_write_scanlines(&cinfo, &row_pointer, 1);			
		}		
	}

	if(row_pointer)
		free(row_pointer);

	jpeg_finish_compress(&cinfo);
	jpeg_destroy_compress(&cinfo);

	fclose(fp);
	DeleteObject(hbmp);
	return FALSE;
}
Ejemplo n.º 18
0
bool CxImageJPG::Encode(CxFile * hFile)
{
	if (EncodeSafeCheck(hFile)) return false;

	if (head.biClrUsed!=0 && !IsGrayScale()){
		strcpy(info.szLastError,"JPEG can save only RGB or GreyScale images");
		return false;
	}	

	// necessary for EXIF, and for roll backs
	long pos=hFile->Tell();

	/* This struct contains the JPEG compression parameters and pointers to
	* working space (which is allocated as needed by the JPEG library).
	* It is possible to have several such structures, representing multiple
	* compression/decompression processes, in existence at once.  We refer
	* to any one struct (and its associated working data) as a "JPEG object".
	*/
	struct jpeg_compress_struct cinfo;
	/* 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;
	/* We use our private extension JPEG error handler. <CSC> */
	struct jpg_error_mgr jerr;
	jerr.buffer=info.szLastError;
	/* More stuff */
	int row_stride;		/* physical row width in image buffer */
	JSAMPARRAY buffer;		/* Output row buffer */

	/* Step 1: allocate and initialize JPEG compression 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); <CSC>
	/* We set up the normal JPEG error routines, then override error_exit. */
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = ima_jpeg_error_exit;

	/* 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.
		*/
		strcpy(info.szLastError, jerr.buffer); //<CSC>
		jpeg_destroy_compress(&cinfo);
		return 0;
	}
	
	/* Now we can initialize the JPEG compression object. */
	jpeg_create_compress(&cinfo);
	/* Step 2: specify data destination (eg, a file) */
	/* Note: steps 2 and 3 can be done in either order. */
	/* Here we use the library-supplied code to send compressed data to a
	* stdio stream.  You can also write your own code to do something else.
	* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
	* requires it in order to write binary files.
	*/

	//jpeg_stdio_dest(&cinfo, outfile);
	CxFileJpg dest(hFile);
    cinfo.dest = &dest;

	/* Step 3: set parameters for compression */
	/* First we supply a description of the input image.
	* Four fields of the cinfo struct must be filled in:
	*/
	cinfo.image_width = GetWidth(); 	// image width and height, in pixels
	cinfo.image_height = GetHeight();

	if (IsGrayScale()){
		cinfo.input_components = 1;			// # of color components per pixel
		cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
	} else {
		cinfo.input_components = 3; 	// # of color components per pixel
		cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
	}

	/* Now use the library's routine to set default compression parameters.
	* (You must set at least cinfo.in_color_space before calling this,
	* since the defaults depend on the source color space.)
	*/
	jpeg_set_defaults(&cinfo);
	/* Now you can set any non-default parameters you wish to.
	* Here we just illustrate the use of quality (quantization table) scaling:
	*/

//#ifdef C_ARITH_CODING_SUPPORTED
	if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_ARITHMETIC) != 0)
		cinfo.arith_code = TRUE;
//#endif

//#ifdef ENTROPY_OPT_SUPPORTED
	if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_OPTIMIZE) != 0)
		cinfo.optimize_coding = TRUE;
//#endif

	if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_GRAYSCALE) != 0)
		jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);

	if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_SMOOTHING) != 0)
		cinfo.smoothing_factor = m_nSmoothing;

	jpeg_set_quality(&cinfo, GetJpegQuality(), (GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_BASELINE) != 0);

//#ifdef C_PROGRESSIVE_SUPPORTED
	if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_PROGRESSIVE) != 0)
		jpeg_simple_progression(&cinfo);
//#endif

#ifdef C_LOSSLESS_SUPPORTED
	if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_LOSSLESS) != 0)
		jpeg_simple_lossless(&cinfo, m_nPredictor, m_nPointTransform);
#endif

	cinfo.density_unit=1;
	cinfo.X_density=(unsigned short)GetXDPI();
	cinfo.Y_density=(unsigned short)GetYDPI();

	/* Step 4: Start compressor */
	/* TRUE ensures that we will write a complete interchange-JPEG file.
	* Pass TRUE unless you are very sure of what you're doing.
	*/
	jpeg_start_compress(&cinfo, TRUE);

	/* Step 5: while (scan lines remain to be written) */
	/*           jpeg_write_scanlines(...); */
	/* Here we use the library's state variable cinfo.next_scanline as the
	* loop counter, so that we don't have to keep track ourselves.
	* To keep things simple, we pass one scanline per call; you can pass
	* more if you wish, though.
	*/
	row_stride = info.dwEffWidth;	/* JSAMPLEs per row in image_buffer */

	//<DP> "8+row_stride" fix heap deallocation problem during debug???
	buffer = (*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo, JPOOL_IMAGE, 8+row_stride, 1);

	CImageIterator iter(this);

	iter.Upset();
	while (cinfo.next_scanline < cinfo.image_height) {
		// info.nProgress = (long)(100*cinfo.next_scanline/cinfo.image_height);
		iter.GetRow(buffer[0], row_stride);
		// not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>
		if (head.biClrUsed==0){				 // swap R & B for RGB images
			RGBtoBGR(buffer[0], row_stride); // Lance : 1998/09/01 : Bug ID: EXP-2.1.1-9
		}
		iter.PrevRow();
		(void) jpeg_write_scanlines(&cinfo, buffer, 1);
	}

	/* Step 6: Finish compression */
	jpeg_finish_compress(&cinfo);

	/* Step 7: release JPEG compression object */
	/* This is an important step since it will release a good deal of memory. */
	jpeg_destroy_compress(&cinfo);


#if CXIMAGEJPG_SUPPORT_EXIF
	if (m_exif && m_exif->m_exifinfo->IsExif){
		// discard useless sections (if any) read from original image
		m_exif->DiscardAllButExif();
		// read new created image, to split the sections
		hFile->Seek(pos,SEEK_SET);
		m_exif->DecodeExif(hFile,EXIF_READ_IMAGE);
		// save back the image, adding EXIF section
		hFile->Seek(pos,SEEK_SET);
		m_exif->EncodeExif(hFile);
	}
#endif


	/* And we're done! */
	return true;
}
Ejemplo n.º 19
0
void save_jpg(const char* filename, uchar* body, int h, int w, int ch, int quality)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;

  FILE * outfile;		/* target file */
  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
  int row_stride;		/* physical row width in image buffer */

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

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

  /* Step 2: specify data destination (eg, a file) */
  /* Note: steps 2 and 3 can be done in either order. */

  if ((outfile = fopen(filename, "wb")) == NULL) {
     fprintf(stderr, "can't open %s\n", filename);
    exit(1);
  }
  jpeg_stdio_dest(&cinfo, outfile);

  /* Step 3: set parameters for compression */

  cinfo.image_width = w;
  cinfo.image_height = h;
  cinfo.input_components = ch; /* # of color components per pixel */

  if( ch == 3 )
     cinfo.in_color_space = JCS_RGB;  /* colorspace of input image */
  else
     cinfo.in_color_space = JCS_GRAYSCALE;  /* colorspace of input image */

  jpeg_set_defaults(&cinfo);

  /* Now you can set any non-default parameters you wish to.
   * Here we just illustrate the use of quality (quantization table) scaling:
   */
  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

  /* Step 4: Start compressor */
  jpeg_start_compress(&cinfo, TRUE);

  /* Step 5: while (scan lines remain to be written) */
  /*           jpeg_write_scanlines(...); */

  /* Here we use the library's state variable cinfo.next_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   * To keep things simple, we pass one scanline per call; you can pass
   * more if you wish, though.
   */
  row_stride = w * ch; /* JSAMPLEs per row in image_buffer */

  while (cinfo.next_scanline < cinfo.image_height) {
    /* jpeg_write_scanlines expects an array of pointers to scanlines.
     * Here the array is only one element long, but you could pass
     * more than one scanline at a time if that's more convenient.
     */
    row_pointer[0] = & body[cinfo.next_scanline * row_stride];
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
  }

  /* Step 6: Finish compression */

  jpeg_finish_compress(&cinfo);
  fclose(outfile);

  /* Step 7: release JPEG compression object */

  jpeg_destroy_compress(&cinfo);

  /* And we're done! */
}
Ejemplo n.º 20
0
int
write_image (dt_imageio_jpeg_t *jpg, const char *filename, const uint8_t *in, void *exif, int exif_len, int imgid)
{
    struct dt_imageio_jpeg_error_mgr jerr;

    jpg->cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = dt_imageio_jpeg_error_exit;
    if (setjmp(jerr.setjmp_buffer))
    {
        jpeg_destroy_compress(&(jpg->cinfo));
        return 1;
    }
    jpeg_create_compress(&(jpg->cinfo));
    FILE *f = fopen(filename, "wb");
    if(!f) return 1;
    jpeg_stdio_dest(&(jpg->cinfo), f);

    jpg->cinfo.image_width = jpg->width;
    jpg->cinfo.image_height = jpg->height;
    jpg->cinfo.input_components = 3;
    jpg->cinfo.in_color_space = JCS_RGB;
    jpeg_set_defaults(&(jpg->cinfo));
    jpeg_set_quality(&(jpg->cinfo), jpg->quality, TRUE);
    if(jpg->quality > 90) jpg->cinfo.comp_info[0].v_samp_factor = 1;
    if(jpg->quality > 92) jpg->cinfo.comp_info[0].h_samp_factor = 1;
    if(jpg->quality > 95) jpg->cinfo.dct_method = JDCT_FLOAT;
    if(jpg->quality < 50) jpg->cinfo.dct_method = JDCT_IFAST;
    if(jpg->quality < 80) jpg->cinfo.smoothing_factor = 20;
    if(jpg->quality < 60) jpg->cinfo.smoothing_factor = 40;
    if(jpg->quality < 40) jpg->cinfo.smoothing_factor = 60;
    jpg->cinfo.optimize_coding = 1;

    jpeg_start_compress(&(jpg->cinfo), TRUE);

    if(imgid > 0)
    {
        cmsHPROFILE out_profile = dt_colorspaces_create_output_profile(imgid);
        uint32_t len = 0;
        cmsSaveProfileToMem(out_profile, 0, &len);
        if (len > 0)
        {
            unsigned char buf[len];
            cmsSaveProfileToMem(out_profile, buf, &len);
            write_icc_profile(&(jpg->cinfo), buf, len);
        }
        dt_colorspaces_cleanup_profile(out_profile);
    }

    if(exif && exif_len > 0 && exif_len < 65534)
        jpeg_write_marker(&(jpg->cinfo), JPEG_APP0+1, exif, exif_len);

    uint8_t row[3*jpg->width];
    const uint8_t *buf;
    while(jpg->cinfo.next_scanline < jpg->cinfo.image_height)
    {
        JSAMPROW tmp[1];
        buf = in + jpg->cinfo.next_scanline * jpg->cinfo.image_width * 4;
        for(int i=0; i<jpg->width; i++) for(int k=0; k<3; k++) row[3*i+k] = buf[4*i+k];
        tmp[0] = row;
        jpeg_write_scanlines(&(jpg->cinfo), tmp, 1);
    }
    jpeg_finish_compress (&(jpg->cinfo));
    jpeg_destroy_compress(&(jpg->cinfo));
    fclose(f);
    return 0;
}
Ejemplo n.º 21
0
Archivo: JPEG.cpp Proyecto: fserb/lime
	bool JPEG::Encode (ImageBuffer *imageBuffer, ByteArray *bytes, int quality) {
		
		struct jpeg_compress_struct cinfo;
		
		struct ErrorData jpegError;
		cinfo.err = jpeg_std_error (&jpegError.base);
		jpegError.base.error_exit = OnError;
		jpegError.base.output_message = OnOutput;
		
		MyDestManager dest;
		
		int w = imageBuffer->width;
		int h = imageBuffer->height;
		QuickVec<uint8> row_buf (w * 3);
		
		jpeg_create_compress (&cinfo);
		
		if (setjmp (jpegError.on_error)) {
			
			jpeg_destroy_compress (&cinfo);
			return false;
			
		}
		
		cinfo.dest = (jpeg_destination_mgr *)&dest;
		
		cinfo.image_width = w;
		cinfo.image_height = h;
		cinfo.input_components = 3;
		cinfo.in_color_space = JCS_RGB;
		
		jpeg_set_defaults (&cinfo);
		jpeg_set_quality (&cinfo, quality, true);
		jpeg_start_compress (&cinfo, true);
		
		JSAMPROW row_pointer = &row_buf[0];
		unsigned char* imageData = imageBuffer->data->Bytes();
		int stride = w * imageBuffer->bpp;
		
		while (cinfo.next_scanline < cinfo.image_height) {
			
			const uint8 *src = (const uint8 *)(imageData + (stride * cinfo.next_scanline));
			uint8 *dest = &row_buf[0];
			
			for(int x = 0; x < w; x++) {
				
				dest[0] = src[0];
				dest[1] = src[1];
				dest[2] = src[2];
				dest += 3;
				src += 4;
				
			}
			
			jpeg_write_scanlines (&cinfo, &row_pointer, 1);
			
		}
		
		jpeg_finish_compress (&cinfo);
		
		*bytes = ByteArray (dest.mOutput);
		
		return true;
		
	}
Ejemplo n.º 22
0
bool ossimPlanetJpegImage::saveFile( std::ostream& stream,
                                   ossimPlanetImage &image,
                                   bool verbose )
{
    struct jpeg_compress_struct cinfo;
    struct ossimPlanet_error_mgr jerr;
    JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
    JSAMPLE *image_buffer;
    int stride;                /* physical row width in image buffer */

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

    if (!verbose) cinfo.err->output_message=NULL;

    /* 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_compress(&cinfo);
         return false;
    }

    jpeg_create_compress(&cinfo);
    ossimPlanet_jpeg_io_dest(&cinfo, stream);

    cinfo.image_width      = image.getWidth();
    cinfo.image_height     = image.getHeight();
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
    jpeg_set_defaults(&cinfo);

    // TODO: 3rd parameter is force_baseline, what value should this be?
    // Code says: "If force_baseline is TRUE, the computed quantization table entries
    // are limited to 1..255 for JPEG baseline compatibility."
    // 'Quality' is a number between 0 (terrible) and 100 (very good).
    // The default (in jcparam.c, jpeg_set_defaults) is 75,
    // and force_baseline is TRUE.
    jpeg_set_quality(&cinfo, 100, TRUE);

    jpeg_start_compress(&cinfo, TRUE);

    stride = cinfo.image_width * 3;    /* JSAMPLEs per row in image_buffer */
    image_buffer = image.data();
    ossim_uint32 scanlineTemp = cinfo.next_scanline;
    while (cinfo.next_scanline < cinfo.image_height)
    {
        row_pointer[0] = &image_buffer[cinfo.next_scanline * stride];
        jpeg_write_scanlines( &cinfo, row_pointer, 1 );
        if(scanlineTemp == cinfo.next_scanline)
        {
           ++cinfo.next_scanline;
        }
        scanlineTemp = cinfo.next_scanline;
    }
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);

    return true;
}
Ejemplo n.º 23
0
TEXLoader::IoStatus TEXLoader::WriteJpeg(const Canvas& canvas) {
	int size_offset = (int)save_file_->Tell();
	unsigned size = 0;
	save_file_->Write(size);	// We will update this data after writing the jpeg image.
	int start_offset = (int)save_file_->Tell();

	jpeg_compress_struct _c_info;
	jpeg_error_mgr j_err;
	_c_info.err = jpeg_std_error(&j_err);
	jpeg_create_compress(&_c_info);

	InitDestinationManager(&_c_info);

	_c_info.image_width = canvas.GetWidth();
	_c_info.image_height = canvas.GetHeight();

	if (canvas.GetBitDepth() == Canvas::kBitdepth8Bit) {
		_c_info.input_components = 1;
		_c_info.in_color_space = JCS_GRAYSCALE;
	} else {
		_c_info.input_components = 3;
		_c_info.in_color_space = JCS_RGB;
	}

	// If the image is in 8-bit mode, it is considered to be a grayscale image.
	// Otherwise, we must make sure that the image is in 24-bit kRgb mode.
	Canvas copy(canvas, true);
	if (copy.GetBitDepth() != Canvas::kBitdepth24Bit &&
	   copy.GetBitDepth() != Canvas::kBitdepth8Bit) {
		copy.ConvertBitDepth(Canvas::kBitdepth24Bit);
	}

	jpeg_set_defaults(&_c_info);
	jpeg_start_compress(&_c_info, TRUE);

	uint8* buffer = (uint8*)copy.GetBuffer();
	int row_stride = copy.GetPitch() * copy.GetPixelByteSize();
	int scan_lines = copy.GetHeight();

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

	for (int i = 0; i < scan_lines; i++) {
		jpeg_write_scanlines(&_c_info, offset, 1);
		offset[0] += row_stride;
	}

	jpeg_finish_compress(&_c_info);
	jpeg_destroy_compress(&_c_info);

	// Calculate and write the size of this jpeg image.
	const int end_offset = (int)save_file_->Tell();
	size = (unsigned)(end_offset - start_offset);
	save_file_->SeekSet(size_offset);
	save_file_->Write(size);

	// Go back to where we were...
	save_file_->SeekEnd(0);

	return kStatusSuccess;
}
int main( int argc, char **argv )
{
	unicap_handle_t handle;
	unicap_device_t device;
	unicap_format_t format_spec;
	unicap_format_t format;
	unicap_data_buffer_t buffer;
	unicap_data_buffer_t *returned_buffer;
	int width, height;
	
	int i;

	SDL_Surface *screen;
	SDL_Overlay *overlay;

	int quit=0;
	int imgcnt = 0;

	printf( "select video device\n" );
	for( i = 0; SUCCESS( unicap_enumerate_devices( NULL, &device, i ) ); i++ )
	{
		printf( "%i: %s\n", i, device.identifier );
	}
	if( --i > 0 )
	{
		printf( "Select video capture device: " );
		scanf( "%d", &i );
	}

	if( !SUCCESS( unicap_enumerate_devices( NULL, &device, i ) ) )
	{
		fprintf( stderr, "Failed to get info for device '%s'\n", device.identifier );
		exit( 1 );
	}

	/*
	  Acquire a handle to this device
	 */
	if( !SUCCESS( unicap_open( &handle, &device ) ) )
	{
		fprintf( stderr, "Failed to open device: %s\n", device.identifier );
		exit( 1 );
	}

	printf( "Opened video capture device: %s\n", device.identifier );

	/*
	  Create a format specification to limit the list of formats returned by 
	  unicap_enumerate_formats to the ones with the color format 'UYVY'
	 */
	unicap_void_format( &format_spec );
	format_spec.fourcc = FOURCC('U','Y','V','Y');
	
	/*
	  Get the list of video formats of the colorformat UYVY
	 */
	for( i = 0; SUCCESS( unicap_enumerate_formats( handle, &format_spec, &format, i ) ); i++ )
	{
		printf( "%d: %s [%dx%d]\n", 
				i,
				format.identifier, 
				format.size.width, 
				format.size.height );
	}
	if( --i > 0 )
	{
		printf( "Select video format: " );
		scanf( "%d", &i );
	}
	if( !SUCCESS( unicap_enumerate_formats( handle, &format_spec, &format, i ) ) )
	{
		fprintf( stderr, "Failed to get video format\n" );
		exit( 1 );
	}
	
   /*
     If a video format has more than one size, ask for which size to use
   */
   if( format.size_count )
   {
      for( i = 0; i < format.size_count; i++ )
      {
	 printf( "%d: %dx%d\n", i, format.sizes[i].width, format.sizes[i].height );
      }
      do
      {
	 printf( "Select video format size: " );
	 scanf( "%d", &i );
      }while( ( i < 0 ) && ( i > format.size_count ) );
      format.size.width = format.sizes[i].width;
      format.size.height = format.sizes[i].height;
   }

	/*
	  Set this video format
	 */
	if( !SUCCESS( unicap_set_format( handle, &format ) ) )
	{
		fprintf( stderr, "Failed to set video format\n" );
		exit( 1 );
	}

	/*
	  Initialize the image buffer
	 */
	memset( &buffer, 0x0, sizeof( unicap_data_buffer_t ) );

	/**
	   Init SDL & SDL_Overlay
	 **/
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
	{
	   fprintf(stderr, "Failed to initialize SDL:  %s\n", SDL_GetError());
	   exit(1);
	}
	
	atexit(SDL_Quit);

	/*
	  Make sure the video window does not get too big. 
	 */
	width = MIN( format.size.width, 800 );
	height = MIN( format.size.height, 600 );

	screen = SDL_SetVideoMode( width, height, 32, SDL_HWSURFACE);
	if ( screen == NULL ) {
	   fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
	   exit(1);
	}
	
	overlay = SDL_CreateYUVOverlay( format.size.width, 
									format.size.height, SDL_UYVY_OVERLAY, screen );
	if( overlay == NULL )
	{
	   fprintf( stderr, "Unable to create overlay: %s\n", SDL_GetError() );
	   exit( 1 );
	}

	/*
	  Pass the pointer to the overlay to the unicap data buffer. 
	 */
	buffer.data = overlay->pixels[0];	
   buffer.buffer_size = format.size.width * format.size.height * format.bpp / 8;
	
	/*
	  Start the capture process on the device
	 */
	if( !SUCCESS( unicap_start_capture( handle ) ) )
	{
		fprintf( stderr, "Failed to start capture on device: %s\n", device.identifier );
		exit( 1 );
	}
	

	while( !quit )
	{
		SDL_Rect rect;
		SDL_Event event;

		rect.x = 0;
		rect.y = 0;
		rect.w = width;
		rect.h = height;
		/*
		  Queue the buffer
		  
		  The buffer now gets filled with image data by the capture device
		*/
		if( !SUCCESS( unicap_queue_buffer( handle, &buffer ) ) )
		{
			fprintf( stderr, "Failed to queue a buffer on device: %s\n", device.identifier );
			exit( 1 );
		}
		
		/*
		  Wait until the image buffer is ready
		*/
		if( !SUCCESS( unicap_wait_buffer( handle, &returned_buffer ) ) )
		{
			fprintf( stderr, "Failed to wait for buffer on device: %s\n", device.identifier );
		}

		/*
		  Display the video data
		 */
		SDL_UnlockYUVOverlay( overlay );
		SDL_DisplayYUVOverlay( overlay, &rect );

		while( SDL_PollEvent( &event ) )
		{
			switch( event.type )
			{
				case SDL_QUIT:
					quit = 1;
					break;
					
				case SDL_MOUSEBUTTONDOWN:
				{
					unsigned char *pixels;
					struct jpeg_compress_struct cinfo;
					struct jpeg_error_mgr jerr;
					FILE *outfile;
					JSAMPROW row_pointer[1];
					int row_stride;
					char filename[128];

					struct timeval t1, t2;
					unsigned long long usecs;
					
					sprintf( filename, "%04d.jpg", imgcnt++ );
					
					cinfo.err = jpeg_std_error(&jerr);
					/* Now we can initialize the JPEG compression object. */
					jpeg_create_compress(&cinfo);
					if ((outfile = fopen( filename, "wb" ) ) == NULL ) 
					{
						fprintf(stderr, "can't open %s\n", "file");
						exit(1);
					}
					jpeg_stdio_dest(&cinfo, outfile);
					
					cinfo.image_width = format.size.width; 	/* image width and height, in pixels */
					cinfo.image_height = format.size.height;
					cinfo.input_components = 3;		/* # of color components per pixel */
					cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
					
					jpeg_set_defaults(&cinfo);
					pixels = malloc( format.size.width * format.size.height * 3 );
					uyvy2rgb24( pixels, returned_buffer->data,
						    format.size.width * format.size.height * 3,
						    format.size.width * format.size.height * 2 );

					gettimeofday( &t1, NULL );
					jpeg_start_compress(&cinfo, TRUE);
					while( cinfo.next_scanline < cinfo.image_height )
					{
						row_pointer[0] = &pixels[cinfo.next_scanline * format.size.width * 3 ];
						(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
					}
					jpeg_finish_compress(&cinfo);
					gettimeofday( &t2, NULL );

					usecs = t2.tv_sec * 1000000LL + t2.tv_usec;
					usecs -= ( t1.tv_sec * 1000000LL + t1.tv_usec );
					
					printf( "Compression took: %lld usec\n", usecs );

					/* After finish_compress, we can close the output file. */
					fclose(outfile);
					jpeg_destroy_compress(&cinfo);
					
					free( pixels );
				}
				
				break;
				
				
				default: 
					break;
			}
		}
		SDL_LockYUVOverlay(overlay);
	}
	
	/*
	  Stop the device
	 */
	if( !SUCCESS( unicap_stop_capture( handle ) ) )
	{
		fprintf( stderr, "Failed to stop capture on device: %s\n", device.identifier );
	}

	/*
	  Close the device 

	  This invalidates the handle
	 */
	if( !SUCCESS( unicap_close( handle ) ) )
	{
		fprintf( stderr, "Failed to close the device: %s\n", device.identifier );
	}

	SDL_Quit();
	
	return 0;
}
Ejemplo n.º 25
0
DistillerStatus
DistillerMain(Argument *args, int nargs,
	      DistillerInput *din,
	      DistillerOutput *dout)
{
  JSAMPROW handoff = NULL;
  JDIMENSION handoff_height, handoff_width, num_scanlines;
  int        max_x=-1, max_y=-1, min_x=-1, min_y=-1, qual=55, i;
  int        expert=0, resize=0, quality=3, nodistill=0, ismap=0;
  double     scale = 0.5;
  cjpeg_source_ptr src_mgr;
  void       *phase1_data;
  INT32       phase1_length;
  int        fin_denom, fin_qual;
  DistillerStatus result = distBadInput;

  SetData(dout, NULL);
  bailout_now = 0;

  if ( (setjmp(jumpbuffer) != 0) ) {
    /*
     *  fatal error occurred, so return immediately.
     */
    MonitorClientSend(monID, "Distiller Errors", 
		      "Resetting distiller...\n", "Log");
    DistillerExit();
    DistillerInit(dType, 0, NULL);

    if (DataPtr(dout) != NULL)
      DataNeedsFree(dout,gm_True);
    else
      DataNeedsFree(dout,gm_False);
    return distFatalError;
  }

  /*
   *  parse distillation arguments.  set default values for some
   *  things, then override them if args are specified.  Default will
   *  be to scale each axis by 0.5, turn quality down to 55%.
   */

  for (i=0; i<nargs; i++) {
    INT32 argval = ARG_INT(args[i]);

    switch(ARG_ID(args[i])) {
    case GJPG_MAX_X:
      max_x = (int) argval;
      break;
    case GJPG_MAX_Y:
      max_y = (int) argval;
      break;
    case GJPG_MIN_X:
      min_x = (int) argval;
      break;
    case GJPG_MIN_Y:
      min_y = (int) argval;
      break;
    case GJPG_SCALE:
      scale = (double) ARG_DOUBLE(args[i]);
      break;
    case GJPG_QUAL:
      qual = (int) argval;
      break;
    case FRONT_RESIZE:
      resize = (int) argval;
      break;
    case FRONT_NO_DISTILL:
      nodistill = (int) argval;
      break;
    case FRONT_QUALITY:
      if (argval >= 1 && argval <= 5)
        quality = (int) argval;
      break;
    case FRONT_EXPERT:
      expert = (int) argval;
      break;
    case FRONT_ISMAP:
      ismap = (int) argval;
      break;
    default:
      break;
    }
  }

  if (nodistill) {
    return gjpg_passthrough(din, dout);
  }

  /* First pass through, we're just going to convert the GIF to JPEG */
  phase1_data = NULL;
  phase1_length = 0;
  dstinfo.in_color_space = JCS_RGB;
  jpeg_set_defaults(&dstinfo);
  src_mgr = jinit_read_gif(&dstinfo, (JOCTET *) DataPtr(din),
			   (INT32) DataLength(din));
  (*src_mgr->start_input)(&dstinfo, src_mgr);
  jpeg_default_colorspace(&dstinfo);
  jpeg_mem_dest(&dstinfo, (void **) &phase1_data, (UINT32 *) &phase1_length);
  jpeg_start_compress(&dstinfo, TRUE);

  while (dstinfo.next_scanline < dstinfo.image_height) {
    num_scanlines = (*src_mgr->get_pixel_rows)(&dstinfo, src_mgr);
    jpeg_write_scanlines(&dstinfo, src_mgr->buffer, num_scanlines);
  }

  (*src_mgr->finish_input)(&dstinfo, src_mgr);
  jpeg_finish_compress(&dstinfo);

  /* early bailout because of animated or transparent gif? */
  if (bailout_now
      &&  DataLength(din) <= bailout_thresh[quality]) {
    result = distBadInput;
    goto JPGMUNGE_RETURN;
  }
    

  /* Now we're into the second pass.  Let's do our JPEG->JPEG
   * distillation. We need to compute the denominator and the quality
   * knob setting. */

  if (expert) {
    /* Do expert-like things here.  Need to work out still. */
    fin_qual = qual;
    fin_denom = compute_scale_denom(max_x, max_y, min_x, min_y,
				    srcinfo.image_width,
				    srcinfo.image_height, scale);
  } else {
    /* We're in beginner mode.  Life is easier. */
    if (ismap) {
      fin_qual = ismap_qual[quality-1];
      fin_denom = ismap_denom[quality-1];
    } else if (resize) {
      fin_qual = noscale_qual[quality-1];
      fin_denom = noscale_denom[quality-1];
    } else {
      fin_qual = norm_qual[quality-1];
      fin_denom = norm_denom[quality-1];
    }
  }

  /* Prep the input decompressor */
  jpeg_mem_src(&srcinfo, phase1_data, phase1_length);
  jpeg_read_header(&srcinfo, TRUE);

  srcinfo.scale_num = 1;
  srcinfo.scale_denom = fin_denom;
  srcinfo.dither_mode = JDITHER_ORDERED;  
  srcinfo.dct_method = JDCT_FASTEST;      
  jpeg_start_decompress(&srcinfo);

  /* Prep the output compressor */
  SetDataLength(dout,0);
  SetData(dout, NULL);
  sprintf(dout->mimeType, "image/jpeg");
  jpeg_mem_dest(&dstinfo, (void **) &(DataPtr(dout)),
                (UINT32 *) &(DataLength(dout)));
  dstinfo.image_width = srcinfo.output_width;
  dstinfo.image_height = srcinfo.output_height;
  dstinfo.input_components = srcinfo.output_components;
  dstinfo.in_color_space = srcinfo.out_color_space;
  jpeg_set_defaults(&dstinfo);
  jpeg_set_quality(&dstinfo, fin_qual, TRUE);
  jpeg_start_compress(&dstinfo, TRUE);

  handoff_height = (JDIMENSION) 1;
  handoff_width = 
    srcinfo.output_width*sizeof(JSAMPLE)*srcinfo.output_components;
  handoff = (JSAMPROW) malloc(handoff_width);

  /* We're going to need some buffer space to hand off data
     from the decompressor to the compressor. */
  while (srcinfo.output_scanline < srcinfo.output_height) {
    num_scanlines = jpeg_read_scanlines(&srcinfo, &handoff, handoff_height);
    jpeg_write_scanlines(&dstinfo, &handoff, num_scanlines);
  }

  jpeg_finish_decompress(&srcinfo);
  jpeg_finish_compress(&dstinfo);

  result = distOk;

JPGMUNGE_RETURN:
  if (handoff)
    free(handoff);
  DataNeedsFree(dout,gm_True);
  if (phase1_data)
    free(phase1_data);
  if (DataLength(dout) > DataLength(din)) {
    SetDataLength(dout, DataLength(din));
    memcpy(DataPtr(dout), DataPtr(din), DataLength(din));
    sprintf(dout->mimeType, "image/gif");
  }
  DEBUG("finished processing\n");
  return result;
}
static gsize
photos_operation_jpg_guess_sizes_count (GeglBuffer *buffer,
                                        gint quality,
                                        gint smoothing,
                                        gboolean optimize,
                                        gboolean progressive,
                                        gboolean sampling,
                                        gboolean grayscale,
                                        gdouble zoom,
                                        gint src_x,
                                        gint src_y,
                                        gint width,
                                        gint height)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  JSAMPROW row_pointer[1];
  const Babl *format;
  gint bpp;
  gsize size;

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

  photos_jpeg_count_dest (&cinfo, &size);

  cinfo.image_width = width;
  cinfo.image_height = height;

  if (!grayscale)
    {
      cinfo.input_components = 3;
      cinfo.in_color_space = JCS_RGB;
      format = babl_format ("R'G'B' u8");
    }
  else
    {
      cinfo.input_components = 1;
      cinfo.in_color_space = JCS_GRAYSCALE;
      format = babl_format ("Y' u8");
    }

  jpeg_set_defaults (&cinfo);
  jpeg_set_quality (&cinfo, quality, TRUE);
  cinfo.smoothing_factor = smoothing;
  cinfo.optimize_coding = optimize;
  if (progressive)
    jpeg_simple_progression (&cinfo);

  if (!sampling)
    {
      /* Use 1x1,1x1,1x1 MCUs and no subsampling */
      cinfo.comp_info[0].h_samp_factor = 1;
      cinfo.comp_info[0].v_samp_factor = 1;

      if (!grayscale)
        {
          cinfo.comp_info[1].h_samp_factor = 1;
          cinfo.comp_info[1].v_samp_factor = 1;
          cinfo.comp_info[2].h_samp_factor = 1;
          cinfo.comp_info[2].v_samp_factor = 1;
        }
    }

  /* No restart markers */
  cinfo.restart_interval = 0;
  cinfo.restart_in_rows = 0;

  jpeg_start_compress (&cinfo, TRUE);

  bpp = babl_format_get_bytes_per_pixel (format);
  row_pointer[0] = g_malloc (width * bpp);

  while (cinfo.next_scanline < cinfo.image_height)
    {
      GeglRectangle rect;

      rect.x = src_x;
      rect.y = src_y + cinfo.next_scanline;
      rect.width = width;
      rect.height = 1;
      gegl_buffer_get (buffer, &rect, zoom, format, row_pointer[0], GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
      jpeg_write_scanlines (&cinfo, row_pointer, 1);
    }

  jpeg_finish_compress (&cinfo);
  jpeg_destroy_compress (&cinfo);
  g_free (row_pointer[0]);

  return size;
}
Ejemplo n.º 27
0
BOOL CPack::JStegWriteImage(const PackHeader * data, const CSBitmap & bmp, LPCTSTR szSrc, LPCTSTR szExt,CString & szError, 
		BOOL * bCancel, CB_SET_PROGRESS fnSetProgress)
{
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	JSAMPROW row_pointer[1];
	int row_stride;
	FILE * outfile = NULL;
	CCorBuffer sbuf;
	JStegParam param;
	struct jpeg_steg_mgr jsteg;
	INT nProgress = 0, nNewProgress;
	LPBYTE pBuffer = NULL;

	/* check ext */

	rc = wc = 0;

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

	if((pBuffer = (LPBYTE)malloc(sizeof(PackHeader) + data->dwCapicity)) == NULL) {
		szError.LoadString(IDS_ERROR_INTERNAL);
		goto error;
	}

	memcpy(pBuffer, data, data->dwDataSize + sizeof(PackHeader));

	if(data->dwCapicity > data->dwDataSize) {
		PadMemory(pBuffer + sizeof(PackHeader) + data->dwDataSize, data->dwCapicity - data->dwDataSize);
	}

	/* progress 50% */
	if(!sbuf.SetData((LPBYTE)pBuffer, (data->dwCapicity + sizeof(PackHeader)), (CCorBuffer::CorFormat)data->dwFormatParam, 
		bCancel, fnSetProgress)) {
		if(bCancel && *bCancel) {
			szError.LoadString(IDS_ERROR_CANCELED);
		} else {
			szError.LoadString(IDS_ERROR_INTERNAL);
		}
		goto error;
	}
	sbuf.Rewind();

	if(NULL != pBuffer) {
		free(pBuffer);
		pBuffer = NULL;
	}

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

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

	jpeg_create_compress(&cinfo);

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

	if((outfile = _tfopen(szSrc, _T("wb"))) == NULL ) {
		INT err = ferror(outfile);
		szError.LoadString(IDS_ERROR_READ_FILE);
		goto error;
	}
	jpeg_stdio_dest(&cinfo, outfile);

	cinfo.image_width = bmp.Columns(); 	/* image width and height, in pixels */
	cinfo.image_height = bmp.Rows();
	cinfo.input_components = 3;         /* # of color components per pixel */
	cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */

	jpeg_set_defaults(&cinfo);

	jpeg_set_quality(&cinfo, 100, TRUE /* limit to baseline-JPEG values */);

	jpeg_start_compress(&cinfo, TRUE);

	row_stride = bmp.Columns() * 3;	/* JSAMPLEs per row in image_buffer */

	while (cinfo.next_scanline < cinfo.image_height) {
		/* row_pointer[0] = (JSAMPROW)& img[cinfo.next_scanline * row_stride]; */
		row_pointer[0] = (JSAMPROW)bmp.GetBufferPointer(cinfo.next_scanline * row_stride);
		if(NULL == row_pointer[0]) {
			param.bError = TRUE;
			break;
		}

		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);

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

		if(fnSetProgress) {
			nNewProgress = 50 + cinfo.next_scanline * 50 / cinfo.image_height;
			if(nNewProgress != nProgress) {
				fnSetProgress(50 + cinfo.next_scanline * 50 / cinfo.image_height);
				nProgress = nNewProgress;
			}
		}
	}

	jpeg_finish_compress(&cinfo);

	jpeg_destroy_compress(&cinfo);

	if(NULL != outfile) {
		fclose(outfile);
		outfile = NULL;
	}

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

	if(!param.buffer->Eof()) {
		szError.LoadString(IDS_ERROR_INTERNAL);
		goto error;
	}

	if(fnSetProgress) {
			fnSetProgress(100);
	}

	return TRUE;

error:
	if(NULL != outfile) {
		fclose(outfile);
		outfile = NULL;
	}
	if(NULL != pBuffer) {
		free(pBuffer);
		pBuffer = NULL;
	}
	return FALSE;
}
size_t MJPEGStreamer::compress_yuyv_to_jpeg(const YUVImage& src, uint8_t* buffer, size_t size, int quality) const {
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_pointer[1];
    uint8_t *line_buffer;
    const uint8_t *yuyv;
    int z;
    static size_t written;

    line_buffer = (uint8_t*)calloc((size_t)(uint32_t)(src.getWidth() * 3), (size_t)1);
    if (line_buffer == NULL) {
    	return 0;
    }
    yuyv = (const uint8_t*)src.getImage();

    cinfo.err = jpeg_std_error (&jerr);
    jpeg_create_compress (&cinfo);
    /* jpeg_stdio_dest (&cinfo, file); */
    dest_buffer(&cinfo, buffer, size, &written);

    cinfo.image_width = (uint32_t)src.getWidth();
    cinfo.image_height = (uint32_t)src.getHeight();
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults (&cinfo);
    jpeg_set_quality (&cinfo, quality, TRUE);

    jpeg_start_compress (&cinfo, TRUE);

    z = 0;
    while (cinfo.next_scanline < (uint32_t)src.getHeight()) {
        int x;
        uint8_t *ptr = line_buffer;

        for (x = 0; x < src.getWidth(); x++) {
            int r, g, b;
            int y, u, v;

            if (!z)
                y = yuyv[0] << 8;
            else
                y = yuyv[2] << 8;
            u = yuyv[1] - 128;
            v = yuyv[3] - 128;

            //lint -e{702}
            r = (y + (359 * v)) >> 8;
            //lint -e{702}
            g = ((y - (88 * u)) - (183 * v)) >> 8;
            //lint -e{702}
            b = (y + (454 * u)) >> 8;

            *(ptr++) = (uint8_t)((r > 255) ? 255 : ((r < 0) ? 0 : r));
            *(ptr++) = (uint8_t)((g > 255) ? 255 : ((g < 0) ? 0 : g));
            *(ptr++) = (uint8_t)((b > 255) ? 255 : ((b < 0) ? 0 : b));

            if (z++) {
                z = 0;
                yuyv += 4;
            }
        }

        row_pointer[0] = line_buffer;
        jpeg_write_scanlines (&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress (&cinfo);
    jpeg_destroy_compress (&cinfo);

    free (line_buffer);

    return (written);
}
Ejemplo n.º 29
0
CPLErr JPEG_Codec::CompressJPEG(buf_mgr &dst, buf_mgr &src)
#endif

{
    // The cinfo should stay open and reside in the DS, since it can be left initialized
    // It saves some time because it has the tables initialized
    struct jpeg_compress_struct cinfo;
    MRFJPEGStruct sJPEGStruct;
    struct jpeg_error_mgr sJErr;
    ILSize sz = img.pagesize;

    jpeg_destination_mgr jmgr;
    jmgr.next_output_byte = (JOCTET *)dst.buffer;
    jmgr.free_in_buffer = dst.size;
    jmgr.init_destination = init_or_terminate_destination;
    jmgr.empty_output_buffer = empty_output_buffer;
    jmgr.term_destination = init_or_terminate_destination;

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

    // Look at the source of this, some interesting tidbits
    cinfo.err = jpeg_std_error(&sJErr);
    sJErr.error_exit = errorExit;
    sJErr.emit_message = emitMessage;
    cinfo.client_data = (void *)&(sJPEGStruct);
    jpeg_create_compress(&cinfo);
    cinfo.dest = &jmgr;

    // The page specific info, size and color spaces
    cinfo.image_width = sz.x;
    cinfo.image_height = sz.y;
    cinfo.input_components = sz.c;
    switch (cinfo.input_components) {
    case 1:cinfo.in_color_space = JCS_GRAYSCALE; break;
    case 3:cinfo.in_color_space = JCS_RGB; break;  // Stored as YCbCr 4:2:0 by default
    default:
        cinfo.in_color_space = JCS_UNKNOWN; // 2, 4-10 bands
    }

    // Set all required fields and overwrite the ones we want to change
    jpeg_set_defaults(&cinfo);

    // Override certain settings
    jpeg_set_quality(&cinfo, img.quality, TRUE);
    cinfo.dct_method = JDCT_FLOAT; // Pretty fast and precise
    cinfo.optimize_coding = optimize; // Set "OPTIMIZE=TRUE" in OPTIONS, default for 12bit

    // Do we explicitly turn off the YCC color and downsampling?

    if (cinfo.in_color_space == JCS_RGB) {
        if (rgb) {  // Stored as RGB
            jpeg_set_colorspace(&cinfo, JCS_RGB);  // Huge files
        }
        else if (sameres) { // YCC, somewhat larger files with improved color spatial detail
            cinfo.comp_info[0].h_samp_factor = 1;
            cinfo.comp_info[0].v_samp_factor = 1;

            // Enabling these lines will make the color components use the same tables as Y, even larger file with slightly better color depth detail
            // cinfo.comp_info[1].quant_tbl_no = 0;
            // cinfo.comp_info[2].quant_tbl_no = 0;

            // cinfo.comp_info[1].dc_tbl_no = 0;
            // cinfo.comp_info[2].dc_tbl_no = 0;

            // cinfo.comp_info[1].ac_tbl_no = 0;
            // cinfo.comp_info[2].ac_tbl_no = 0;
        }
    }

    int linesize = cinfo.image_width * cinfo.input_components * ((cinfo.data_precision == 8) ? 1 : 2);
    JSAMPROW *rowp = (JSAMPROW *)CPLMalloc(sizeof(JSAMPROW)*sz.y);
    if (!rowp) {
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG compression error");
        jpeg_destroy_compress(&cinfo);
        return CE_Failure;
    }

    for (int i = 0; i < sz.y; i++)
        rowp[i] = (JSAMPROW)(src.buffer + i*linesize);

    if (setjmp(sJPEGStruct.setjmpBuffer)) {
        CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG compression error");
        jpeg_destroy_compress(&cinfo);
        CPLFree(rowp);
        return CE_Failure;
    }

    // Build a bitmaps of the black pixels
    // If there are any black pixels, write a compressed mask in APP3 "C3Mask" chunk

    // Mask is initialized to all pixels valid
    BitMask mask(sz.x, sz.y);
    storage_manager mbuffer = { CHUNK_NAME, CHUNK_NAME_SIZE };

    int nzeros = (cinfo.data_precision == 8) ?
        update_mask(mask, reinterpret_cast<GByte *>(src.buffer), sz.c) :
        update_mask(mask, reinterpret_cast<GUInt16 *>(src.buffer), sz.c);

    // In case we need to build a Zen chunk
    char *buffer = nullptr; 

    if (nzeros != 0) { // build the Zen chunk
        mbuffer.size = 2 * mask.size() + CHUNK_NAME_SIZE;
        buffer = reinterpret_cast<char *>(CPLMalloc(mbuffer.size));
        if (!buffer) {
            jpeg_destroy_compress(&cinfo);
            CPLFree(rowp);
            CPLError(CE_Failure, CPLE_OutOfMemory, "MRF: JPEG Zen mask compression");
            return CE_Failure;
        }

        memcpy(buffer, CHUNK_NAME, CHUNK_NAME_SIZE);
        mbuffer.buffer = buffer + CHUNK_NAME_SIZE;
        mbuffer.size -= CHUNK_NAME_SIZE;

        RLEC3Packer c3;
        mask.set_packer(&c3);
        if (!mask.store(&mbuffer)) {
            CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG Zen mask compression");
            CPLFree(rowp);
            CPLFree(buffer);
            return CE_Failure;
        }

        // Change the buffer pointer to include the signature, on output the size is the compressed size
        mbuffer.buffer = buffer;
        mbuffer.size += CHUNK_NAME_SIZE;

        // Check that the size fits in one JPEG chunk
        if (mbuffer.size + 2 + CHUNK_NAME_SIZE > 65535) {
            // Should split it in multiple chunks, for now mark this tile as all data and emit a warning
            CPLError(CE_Warning, CPLE_NotSupported, "MRF: JPEG Zen mask too large");
            mbuffer.size = CHUNK_NAME_SIZE; // Write just the signature
        }
    }

    // Everything is ready
    jpeg_start_compress(&cinfo, TRUE);

    // Always write the Zen app chunk, App3
    jpeg_write_marker(&cinfo, JPEG_APP0 + 3,
      reinterpret_cast<JOCTET *>(mbuffer.buffer),
      static_cast<unsigned int>(mbuffer.size));

    jpeg_write_scanlines(&cinfo, rowp, sz.y);
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);

    CPLFree(rowp);
    CPLFree(buffer);     // Safe to call on null

    // Figure out the size
    dst.size -= jmgr.free_in_buffer;

    return CE_None;
}
Ejemplo n.º 30
0
int compress_yuyv_to_jpeg (const char *basename, int quality, uint16_t width, uint16_t height, void *data)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  JSAMPROW row_pointer[1];
  unsigned char *line_buffer, *yuyv;
  int z;
  struct timeval start, end;
  char outname[1024];

  sprintf(outname, "%s.jpg", basename);
  gettimeofday(&start, NULL);
  FILE *file = fopen (outname, "wb");
  if (!file) {
     perror ("Error opening output file");
     return -1;
  }

  line_buffer = calloc (width * 3, 1);
  yuyv = data;

  cinfo.err = jpeg_std_error (&jerr);
  jpeg_create_compress (&cinfo);
  jpeg_stdio_dest (&cinfo, file);

  cinfo.image_width = width;
  cinfo.image_height = height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;

  jpeg_set_defaults (&cinfo);
  jpeg_set_quality (&cinfo, quality, TRUE);

  jpeg_start_compress (&cinfo, TRUE);

  z = 0;
  while (cinfo.next_scanline < cinfo.image_height) {
    int x;
    unsigned char *ptr = line_buffer;

    for (x = 0; x < width; x++) {
      int r, g, b;
      int y = 0, u = 0, v = 0;

         // Atmel uses this one
         if (!z)
	         y = yuyv[1] << 8;
         else
	         y = yuyv[3] << 8;
         u = yuyv[2] - 128;
         v = yuyv[0] - 128;


      r = (y + (359 * v)) >> 8;
      g = (y - (88 * u) - (183 * v)) >> 8;
      b = (y + (454 * u)) >> 8;
#define CAP(x) ((x) < 0 ? 0 : ((x) > 255 ? 255 : (x)) )

      *(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
      *(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
      *(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);

      if (z++) {
	z = 0;
	yuyv += 4;
      }
    }

    row_pointer[0] = line_buffer;
    jpeg_write_scanlines (&cinfo, row_pointer, 1);
  }

  jpeg_finish_compress (&cinfo);
  jpeg_destroy_compress (&cinfo);

  free (line_buffer);
  fclose(file);

  gettimeofday(&end, NULL);
  end.tv_sec -= start.tv_sec;
  end.tv_usec -= start.tv_usec;
  if (end.tv_usec < 0) {
     end.tv_usec += 1000000;
     end.tv_sec -= 1;
  }

  printf("JPEG Time: %ld.%06ld\n", end.tv_sec, end.tv_usec);

  return (0);
}