// Compress the data from i->_pixbuf to i->data.
// Uses libjpeg-turbo if available (JCS_EXTENSIONS) for better performance
int image_jpeg_compress(MediaScanImage *i, MediaScanThumbSpec *spec) {
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  struct buf_dst_mgr dst;
  int quality = spec->jpeg_quality;
  int x;
#ifdef JCS_EXTENSIONS
  JSAMPROW *data = NULL;
#else
  volatile unsigned char *data = NULL;  // volatile = won't be rolled back if longjmp is called
  JSAMPROW row_pointer[1];
  int y, row_stride;
#endif

  if (!i->_pixbuf_size) {
    LOG_WARN("JPEG compression requires pixbuf data (%s)\n", i->path);
    exit(-1);
    return 0;
  }

  if (!quality)
    quality = DEFAULT_JPEG_QUALITY;

  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);
  image_jpeg_buf_dest(&cinfo, &dst);

  cinfo.image_width = i->width;
  cinfo.image_height = i->height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB; // output is always RGB even if source was grayscale

  if (setjmp(setjmp_buffer)) {
    if (data != NULL) {
      LOG_MEM("destroy JPEG data row @ %p\n", data);
      free((void *)data);
    }
    return 0;
  }

#ifdef JCS_EXTENSIONS
  // Use libjpeg-turbo support for direct reading from source buffer
  cinfo.input_components = 4;
  cinfo.in_color_space = JCS_EXT_XBGR;
#endif

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

#ifdef JCS_EXTENSIONS
  data = (JSAMPROW *)malloc(i->height * sizeof(JSAMPROW));
  LOG_MEM("new JPEG data row @ %p\n", data);

  for (x = 0; x < i->height; x++)
    data[x] = (JSAMPROW)&i->_pixbuf[x * i->width];

  while (cinfo.next_scanline < cinfo.image_height) {
    jpeg_write_scanlines(&cinfo, &data[cinfo.next_scanline], cinfo.image_height - cinfo.next_scanline);
  }

#else
  // Normal libjpeg
  row_stride = cinfo.image_width * 3;
  data = (unsigned char *)malloc(row_stride);
  LOG_MEM("new JPEG data row @ %p\n", data);

  y = 0;
  while (cinfo.next_scanline < cinfo.image_height) {
    for (x = 0; x < cinfo.image_width; x++) {
      data[x + x + x] = COL_RED(i->_pixbuf[y]);
      data[x + x + x + 1] = COL_GREEN(i->_pixbuf[y]);
      data[x + x + x + 2] = COL_BLUE(i->_pixbuf[y]);
      y++;
    }
    row_pointer[0] = (unsigned char *)data;
    jpeg_write_scanlines(&cinfo, row_pointer, 1);
  }
#endif

  jpeg_finish_compress(&cinfo);

  LOG_MEM("destroy JPEG data row @ %p\n", data);
  free((void *)data);

  jpeg_destroy_compress(&cinfo);

  // Attach compressed buffer to image
  i->_dbuf = (void *)dst.dbuf;

  return 1;
}
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);
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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 */
Beispiel #6
0
static bool write_jpeg_image(const QImage &image, QIODevice *device, int sourceQuality)
{
    bool success = false;
    const QVector<QRgb> cmap = image.colorTable();

    struct jpeg_compress_struct cinfo;
    JSAMPROW row_pointer[1];
    row_pointer[0] = 0;

    struct my_jpeg_destination_mgr *iod_dest = new my_jpeg_destination_mgr(device);
    struct my_error_mgr jerr;

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

    if (!setjmp(jerr.setjmp_buffer)) {
        // WARNING:
        // this if loop is inside a setjmp/longjmp branch
        // do not create C++ temporaries here because the destructor may never be called
        // if you allocate memory, make sure that you can free it (row_pointer[0])
        jpeg_create_compress(&cinfo);

        cinfo.dest = iod_dest;

        cinfo.image_width = image.width();
        cinfo.image_height = image.height();

        bool gray=false;
        switch (image.format()) {
        case QImage::Format_Mono:
        case QImage::Format_MonoLSB:
        case QImage::Format_Indexed8:
            gray = true;
            for (int i = image.colorCount(); gray && i--;) {
                gray = gray & (qRed(cmap[i]) == qGreen(cmap[i]) &&
                               qRed(cmap[i]) == qBlue(cmap[i]));
            }
            cinfo.input_components = gray ? 1 : 3;
            cinfo.in_color_space = gray ? JCS_GRAYSCALE : JCS_RGB;
            break;
        default:
            cinfo.input_components = 3;
            cinfo.in_color_space = JCS_RGB;
        }

        jpeg_set_defaults(&cinfo);

        qreal diffInch = qAbs(image.dotsPerMeterX()*2.54/100. - qRound(image.dotsPerMeterX()*2.54/100.))
                         + qAbs(image.dotsPerMeterY()*2.54/100. - qRound(image.dotsPerMeterY()*2.54/100.));
        qreal diffCm = (qAbs(image.dotsPerMeterX()/100. - qRound(image.dotsPerMeterX()/100.))
                        + qAbs(image.dotsPerMeterY()/100. - qRound(image.dotsPerMeterY()/100.)))*2.54;
        if (diffInch < diffCm) {
            cinfo.density_unit = 1; // dots/inch
            cinfo.X_density = qRound(image.dotsPerMeterX()*2.54/100.);
            cinfo.Y_density = qRound(image.dotsPerMeterY()*2.54/100.);
        } else {
            cinfo.density_unit = 2; // dots/cm
            cinfo.X_density = (image.dotsPerMeterX()+50) / 100;
            cinfo.Y_density = (image.dotsPerMeterY()+50) / 100;
        }


        int quality = sourceQuality >= 0 ? qMin(sourceQuality,100) : 75;
        jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
        jpeg_start_compress(&cinfo, TRUE);

        row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components];
        int w = cinfo.image_width;
        while (cinfo.next_scanline < cinfo.image_height) {
            uchar *row = row_pointer[0];
            switch (image.format()) {
            case QImage::Format_Mono:
            case QImage::Format_MonoLSB:
                if (gray) {
                    const uchar* data = image.constScanLine(cinfo.next_scanline);
                    if (image.format() == QImage::Format_MonoLSB) {
                        for (int i=0; i<w; i++) {
                            bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7)));
                            row[i] = qRed(cmap[bit]);
                        }
                    } else {
                        for (int i=0; i<w; i++) {
                            bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7))));
                            row[i] = qRed(cmap[bit]);
                        }
                    }
                } else {
                    const uchar* data = image.constScanLine(cinfo.next_scanline);
                    if (image.format() == QImage::Format_MonoLSB) {
                        for (int i=0; i<w; i++) {
                            bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7)));
                            *row++ = qRed(cmap[bit]);
                            *row++ = qGreen(cmap[bit]);
                            *row++ = qBlue(cmap[bit]);
                        }
                    } else {
                        for (int i=0; i<w; i++) {
                            bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7))));
                            *row++ = qRed(cmap[bit]);
                            *row++ = qGreen(cmap[bit]);
                            *row++ = qBlue(cmap[bit]);
                        }
                    }
                }
Beispiel #7
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;
}
Beispiel #8
0
/******************************************************************************
Description.: yuv2jpeg function is based on compress_yuyv_to_jpeg written by
              Gabriel A. Devenyi.
              It uses the destination manager implemented above to compress
              YUYV data to JPEG. Most other implementations use the
              "jpeg_stdio_dest" from libjpeg, which can not store compressed
              pictures to memory instead of a file.
Input Value.: video structure from v4l2uvc.c/h, destination buffer and buffersize
              the buffer must be large enough, no error/size checking is done!
Return Value: the buffer will contain the compressed data
******************************************************************************/
int compress_yuyv_to_jpeg(struct vdIn *vd, unsigned char *buffer, int size, int quality,uint32_t format)
{
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_pointer[1];
    unsigned char *line_buffer, *yuyv;
    int z;
    static int written;

    line_buffer = calloc(vd->width * 3, 1);
    yuyv = vd->framebuffer;

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

    cinfo.image_width = vd->width;
    cinfo.image_height = vd->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 < vd->height) {
        int x;
        unsigned char *ptr = line_buffer;
        
        /*TODO: make sure you are dealing with V4L2_PIX_FMT_YUYV here */
        for(x = 0; x < vd->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);
    jpeg_destroy_compress(&cinfo);

    free(line_buffer);

    return (written);
}
//=============================================================================
// Bitmap2JPG  - Enregistre un BITMAP dans un fichier JPEG
//
// Parametres
//   HBITMAP hBitmap    : Bitmap a convertir (DDB)
//   LPCTSTR pszFileJPG : Fichier de sortie  (.JPG)
//   int     nQualite   : Qualite de l'image [0-100]
// 
// Retour
//   TRUE si ok, FALSE si erreur  
//=============================================================================
BOOL Bitmap2JPG(HBITMAP hBitmap, LPCTSTR pszFileJPG, int nQualite)
{
  struct jpeg_compress_struct  cinfo;
  struct jpeg_error_mgr        jerr;
  struct WIN32_destination_mgr dest;
  BITMAP                       bm;
  BITMAPINFO                   bi;
  HANDLE                       hFile;
  HDC                          hdcScr, hdcMem1, hdcMem2;
  HBITMAP                      hbmMem, hbmOld1, hbmOld2;
  JSAMPROW                     jrows[1], jrow;
  LPBYTE                       pPixels;
  UINT                         nRowLen;

  if(!hBitmap)
    return FALSE;

  if(!GetObject(hBitmap, sizeof(bm), &bm))
    return FALSE;

  // Creation DIB -------------------------------------
  ZeroMemory(&bi, sizeof(bi));
  bi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
  bi.bmiHeader.biWidth       = bm.bmWidth;
  bi.bmiHeader.biHeight      = bm.bmHeight;
  bi.bmiHeader.biPlanes      = 1;
  bi.bmiHeader.biBitCount    = 24;
  bi.bmiHeader.biCompression = BI_RGB;

  hdcScr  = GetDC(NULL);
  hdcMem1 = CreateCompatibleDC(hdcScr);
  //Asi estaban originalmente  v2.9  hbmOld1 = SelectObject(hdcMem1, hBitmap);
  hbmOld1 = (HBITMAP)::SelectObject(hdcMem1, hBitmap);
  hdcMem2 = CreateCompatibleDC(hdcScr);
  hbmMem  = CreateDIBSection(hdcScr, &bi, DIB_RGB_COLORS, (LPVOID *)&pPixels, 0, 0);
  //Asi estaban originalmente  v2.9  hbmOld2 = SelectObject(hdcMem2, hbmMem);
  hbmOld2 = (HBITMAP)::SelectObject(hdcMem2, hbmMem);

  BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY);

  SelectObject(hdcMem1, hbmOld1);
  SelectObject(hdcMem2, hbmOld2);
  ReleaseDC(NULL, hdcScr);
  DeleteDC(hdcMem1);
  DeleteDC(hdcMem2);


  // Creation fichier JPG -----------------------------
  hFile = CreateFile(pszFileJPG, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	
  if(hFile == INVALID_HANDLE_VALUE)
    return FALSE;  
	
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);
  cinfo.dest = WIN32_jpeg_dest(&dest, hFile);
  
  cinfo.image_width      = bm.bmWidth;  
  cinfo.image_height     = bm.bmHeight;
  cinfo.input_components = 3;
  cinfo.in_color_space   = JCS_RGB;
  
  jpeg_set_defaults(&cinfo);
  jpeg_set_quality(&cinfo, (nQualite < 0 || nQualite > 100) ? 100 : nQualite, TRUE);
  jpeg_start_compress(&cinfo, TRUE);
		
  nRowLen = (((bm.bmWidth * 24) + 31) / 32) * 4;
		
  while(cinfo.next_scanline < cinfo.image_height)
  {
    int i, j, tmp;
			
    jrow = &pPixels[(cinfo.image_height - cinfo.next_scanline - 1) * nRowLen];
			
    for(i = 0; i < cinfo.image_width; i++)
    {
      j           = i * 3;
      tmp         = jrow[j];
      jrow[j]     = jrow[j + 2];
      jrow[j + 2] = tmp;
    }
    jrows[0] = jrow;
    jpeg_write_scanlines(&cinfo, jrows, 1);
  }
		
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);

  CloseHandle(hFile);
  // v2.9
  //Las tres siguientes lineas! son IMPORTANTISIMAS!!!!
  //Libera la memoria que ocupan esos bitmaps!!!
  DeleteObject(hbmOld1);
  DeleteObject(hbmOld2);
  DeleteObject(hbmMem);
  return TRUE; 
}
int main(int argc, char **argv) {
    struct jpeg_decompress_struct dinfo;
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;

    char *file1;   /* input filename */
    char *file2;   /* output filename */
    FILE *fh1;     /* input file handle */
    FILE *fh2;     /* output file handle */
    float *data;   /* partially-convolved rows in 4-tuples: r, g, b, sum */
    float **ptrs;  /* pointers into input buffer, one for each scanline */
    JSAMPLE *line; /* input/output buffer */
    float *fx,*fy; /* convolution kernel cache */
    int mode;      /* resize mode (see M_SET_SIZE, etc.) */
    int quality;   /* jpeg quality: 0 to 100 */
    int len;       /* length of one line in data */
    int w1, h1, z1; /* size of input image */
    int w2, h2;    /* size of output image */
    int w3, h3;    /* size of convolution kernel */
    int xo, yo;    /* number of cols/rows to side of center of kernel */
    int y1, n1;    /* first row and number of rows loaded into input buffer */
    int yc;        /* last row loaded from input file */
    int x2, y2;    /* current location in output image */
    float ox, oy;  /* offset of origin in input image */
    float sx, sy;  /* amount to scale horizontal and vertical */
    float xf, yf;  /* corresponding location in input image */
    float ax, ay;  /* constants needed for Lanczos kernel */
    float extra;   /* multiply kernel radius by this to get extra lobes */
    int kernel;    /* boolean: dump convolution kernel and abort? */
    int verbose;   /* boolean: verbose mode? */

    /* Temporary variables. */
    float *ptr1, *ptr2, *ptr3;
    JSAMPLE *ptr4;
    int x, y, i, j, k, c;
    float f, r, g, b, s, *accum;

    /* Print help message. */
    if (argc <= 1 || get_flag(argv, &argc, "-h", "--help")) {
        printf("\n");
        printf("USAGE\n");
        printf("    %s\n", USAGE);
        printf("\n");
        printf("OPTIONS\n");
        printf("    <w>x<h>             Width and height of output image, e.g., '200x200'.\n");
        printf("    <input.jpg>         Input image.  Must be 'normal' RGB color JPEG.\n");
        printf("    <output.jpg>        Output image.  Clobbers any existing file.\n");
        printf("\n");
        printf("    --set-size          Default mode: set to given size, ignoring aspect ratio.\n");
        printf("    --set-area          Keep aspect ratio, reducing/enlarging to area of given box.\n");
        printf("    --max-size          Keep aspect ratio, reducing to within given box.\n");
        printf("    --max-area          Keep aspect ratio, reducing to area of given box.\n");
        printf("    --min-size          Keep aspect ratio, enlarging to contain given box.\n");
        printf("    --min-area          Keep aspect ratio, enlarging to area of given box.\n");
        printf("    --crop              Reduce/enlarge, cropping to get correct ratio.\n");
        printf("\n");
        printf("    -q --quality <pct>  JPEG quality of output image; default depends on size.\n");
        printf("    -r --radius <n>     Radius of convolution kernel, > 0; default is 1.0.\n");
        printf("    -s --sharp <n>      Amount to sharpen output, >= 0; default is 0.2.\n");
        printf("\n");
        printf("    --flat              Average pixels within box of given radius.\n");
        printf("    --linear            Weight pixels within box linearly by closeness.\n");
        printf("    --hermite           Hermite cubic spline filter; similar to Gaussian.\n");
        printf("    --catrom [<M>]      Catmull-Rom cubic spline; default is M = 0.5 at R = 1.\n");
        printf("    --mitchell          Mitchell-Netravali filter (see Keys filter).\n");
        printf("    --keys [<B> <C>]    Keys family filters; default is B = C = 1/3 (Mitchell).\n");
        printf("    --lanczos [<N>]     Lanczos windowed sinc filter; default is N = 3 lobes.\n");
        printf("\n");
        printf("    -h --help           Print this message.\n");
        printf("    -v --verbose        Verbose / debug mode.\n");
        printf("    -k --kernel         Dump convolution kernel without processing image.\n");
        printf("\n");
        exit(1);
    }

    /* Get command line args. */
    get_size(argv, &argc, &w2, &h2);
    quality = get_value(argv, &argc, "-q", "--quality", default_quality(w2, h2));
    radius  = get_value(argv, &argc, "-r", "--radius", 1.0);
    sharp   = get_value(argv, &argc, "-s", "--sharp", 0.2);
    verbose = get_flag(argv, &argc, "-v", "--verbose");
    kernel  = get_flag(argv, &argc, "-k", "--kernel");

    /* Only allowed one mode flag. */
    mode = get_flag(argv, &argc, "--set-size", 0) ? M_SET_SIZE :
           get_flag(argv, &argc, "--max-size", 0) ? M_MAX_SIZE :
           get_flag(argv, &argc, "--min-size", 0) ? M_MIN_SIZE :
           get_flag(argv, &argc, "--set-area", 0) ? M_SET_AREA :
           get_flag(argv, &argc, "--max-area", 0) ? M_MAX_AREA :
           get_flag(argv, &argc, "--min-area", 0) ? M_MIN_AREA :
           get_flag(argv, &argc, "--crop",     0) ? M_CROP     : M_SET_SIZE;

    /* Each filter type takes different arguments. */
    if (get_filter(argv, &argc, "--flat", 0, 0, 0)) {
        filter = F_FLAT;
        extra  = 1.0;
    } else if (get_filter(argv, &argc, "--linear", 0, 0, 0)) {
        filter = F_LINEAR;
        extra  = 1.0;
    } else if (get_filter(argv, &argc, "--hermite", 0, 0, 0)) {
        filter = F_HERMITE;
        extra  = 1.0;
    } else if (get_filter(argv, &argc, "--catrom",   1, 1.0, 0.0)) {
        filter = F_CATROM;
        extra  = 2.0;
    } else if (get_filter(argv, &argc, "--mitchell", 0, 0.0, 0.0)) {
        filter = F_KEYS;
        extra  = 2.0;
        arg1   = 1.0 / 3.0;
        arg2   = 1.0 / 3.0;
    } else if (get_filter(argv, &argc, "--keys",     2, 1.0/3.0, 1.0/3.0)) {
        filter = F_KEYS;
        extra  = 2.0;
    } else if (get_filter(argv, &argc, "--lanczos",  1, 3.0, 0.0)) {
        filter = F_LANCZOS;
        extra  = arg1;
    } else {
        filter = F_LANCZOS;
        arg1   = 3.0;
        extra  = arg1;
    }

    /* Get files last because they complain if there are any flags left. */
    file1 = get_file(argv, &argc);
    file2 = get_file(argv, &argc);
    if (argc > 1) bad_usage("unexpected argument: %s", argv[1]);

    /* Create and initialize decompress object. */
    dinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&dinfo);
    if ((fh1 = fopen(file1, "rb")) == NULL) {
        fprintf(stderr, "can't open %s for reading\n", file1);
        exit(1);
    }
    jpeg_stdio_src(&dinfo, fh1);

    /* Get dimensions and format of input image. */
    jpeg_read_header(&dinfo, TRUE);
    jpeg_start_decompress(&dinfo);
    w1 = dinfo.output_width;
    h1 = dinfo.output_height;
    z1 = dinfo.output_components;

    /* Choose output size. */
    if (mode == M_SET_SIZE) {
        /* leave as is */
        sx = (double)w2 / w1;
        sy = (double)h2 / h1;
        ox = oy = 0.0;
    } else if (mode == M_MAX_SIZE) {
        if (w1 > w2 && h1 * w2 / w1 < h2) {
            sx = sy = (double)w2 / w1;
            h2 = sy * h1 + 0.5;
        } else if (h1 > h2) {
            sx = sy = (double)h2 / h1;
            w2 = sx * w1 + 0.5;
        } else {
            sx = sy = 1.0;
            w2 = w1;
            h2 = h1;
        }
        ox = oy = 0.0;
    } else if (mode == M_MIN_SIZE) {
        if (w1 < w2 && h1 * w2 / w1 > h2) {
            sx = sy = (double)w2 / w1;
            h2 = sy * h1 + 0.5;
        } else if (h1 < h2) {
            sx = sy = (double)h2 / h1;
            w2 = sx * w1 + 0.5;
        } else {
            sx = sy = 1.0;
            w2 = w1;
            h2 = h1;
        }
        ox = oy = 0.0;
    } else if (mode == M_SET_AREA) {
        sx = sy = sqrt(((double)w2) * h2 / w1 / h1);
        w2 = sx * w1 + 0.5;
        h2 = sy * h1 + 0.5;
        ox = oy = 0.0;
    } else if (mode == M_MAX_AREA) {
        if (w1 * h1 > w2 * h2) {
            sx = sy = sqrt(((double)w2) * h2 / w1 / h1);
            w2 = sx * w1 + 0.5;
            h2 = sy * h1 + 0.5;
        } else {
            sx = sy = 1.0;
            w2 = w1;
            h2 = h1;
        }
        ox = oy = 0.0;
    } else if (mode == M_MIN_AREA) {
        if (w1 * h1 < w2 * h2) {
            sx = sy = sqrt(((double)w2) * h2 / w1 / h1);
            w2 = sx * w1 + 0.5;
            h2 = sy * h1 + 0.5;
        } else {
            sx = sy = 1.0;
            w2 = w1;
            h2 = h1;
        }
        ox = oy = 0.0;
    } else if (mode == M_CROP) {
        sx = (double)w2 / w1;
        sy = (double)h2 / h1;
        sx = sy = sx > sy ? sx : sy;
        ox = ((double)w1 - (double)w2 / sx) * 0.5;
        oy = ((double)h1 - (double)h2 / sy) * 0.5;
    } else {
        fprintf(stderr, "invalid mode: %d!", mode);
        exit(1);
    }

    if (verbose) {
        fprintf(stderr, "input:   %dx%d (%d) %s\n", w1, h1, z1, file1);
        fprintf(stderr, "output:  %dx%d (%d) %s\n", w2, h2, z1, file2);
        if (sx > 1.0 && sy > 1.0)
            fprintf(stderr, "enlarge: %.2f %.2f\n", sx*1.0, sy*1.0);
        else
            fprintf(stderr, "reduce:  %.2f %.2f\n", 1.0/sx, 1.0/sy);
        fprintf(stderr, "origin:  %.2f %.2f\n", ox, oy);
        fprintf(stderr, "quality: %d\n", quality);
        fprintf(stderr, "radius:  %f\n", radius);
        fprintf(stderr, "sharp:   %f\n", sharp);
        if (filter == F_FLAT)    fprintf(stderr, "filter:  flat\n");
        if (filter == F_LINEAR)  fprintf(stderr, "filter:  bilinear\n");
        if (filter == F_HERMITE) fprintf(stderr, "filter:  hermite\n");
        if (filter == F_CATROM)  fprintf(stderr, "filter:  Catmull-Rom (M=%f)\n", arg1);
        if (filter == F_KEYS)    fprintf(stderr, "filter:  Keys-family (B=%f, C=%f)\n", arg1, arg2);
        if (filter == F_LANCZOS) fprintf(stderr, "filter:  Lanczos (N=%f)\n", arg1);
    }

    /* Calculate size of convolution kernel. */
    ax = sx < 1 ? radius / sx : radius;
    ay = sy < 1 ? radius / sy : radius;
    xo = (int)(ax * extra + 0.5);
    yo = (int)(ay * extra + 0.5);
    w3 = xo + xo + 1;
    h3 = yo + yo + 1;

    /* Pre-calculate coefficients for Keys-family filters. */
    if (filter == F_CATROM) {
        filter = F_KEYS;
        c1 = 2.0 - arg1;
        c2 = -3.0 + arg1;
        c3 = 0.0;
        c4 = 1.0;
        c5 = -arg1;
        c6 = 2.0 * arg1;
        c7 = -arg1;
        c8 = 0.0;
    } else if (filter == F_KEYS) {
        c1 = ( 12.0 + -9.0 * arg1 +  -6.0 * arg2) / 6.0;
        c2 = (-18.0 + 12.0 * arg1 +   6.0 * arg2) / 6.0;
        c3 = (  0.0 +  0.0 * arg1 +   0.0 * arg2) / 6.0;
        c4 = (  6.0 + -2.0 * arg1 +   0.0 * arg2) / 6.0;
        c5 = (  0.0 + -1.0 * arg1 +  -6.0 * arg2) / 6.0;
        c6 = (  0.0 +  3.0 * arg1 +  12.0 * arg2) / 6.0;
        c7 = (  0.0 + -3.0 * arg1 +  -6.0 * arg2) / 6.0;
        c8 = (  0.0 +  1.0 * arg1 +   0.0 * arg2) / 6.0;
    }

    if (verbose) {
        fprintf(stderr, "w1-h1:   %d %d\n", w1, h1);
        fprintf(stderr, "xo-yo:   %d %d\n", xo, yo);
        fprintf(stderr, "w3-h3:   %d %d\n", w3, h3);
        fprintf(stderr, "ax-ay:  %8.5f %8.5f\n", ax, ay);
        fprintf(stderr, "c1-4:   %8.5f %8.5f %8.5f %8.5f\n", c1, c2, c3, c4);
        fprintf(stderr, "c5-8:   %8.5f %8.5f %8.5f %8.5f\n", c5, c6, c7, c8);
    }

    /* Debug convolution kernel. */
    if (kernel) {
        f = -1;
        for (xf=0; xf<10.0; xf+=0.1) {
            s = calc_factor(xf);
            fprintf(stderr, "%5.2f %7.4f\n", xf, s);
            if (s == 0.0 && f == 0.0)
                break;
            f = s;
        }
        exit(0);
    }

    /* Allocate buffers. */
    len   = w2 * (z1 + 1);
    data  = (float*)malloc(h3 * len * sizeof(float));
    ptrs  = (float**)malloc(h3 * sizeof(float*));
    line  = (JSAMPLE*)malloc((w1 > w2 ? w1 : w2) * z1 * sizeof(JSAMPLE));
    fx    = (float*)malloc(w2 * w3 * sizeof(float));
    fy    = (float*)malloc(h2 * h3 * sizeof(float));
    accum = (float*)malloc(z1 * sizeof(float));

    /* Cache horizontal and vertical components of kernel. */
    for (x2=0, ptr3=fx; x2<w2; x2++) {
        xf = ((float)x2) / sx + ox;
        for (i=0, x=(int)xf-xo; i<w3; i++, x++) {
            *ptr3++ = calc_factor(fabs(xf-x) / ax);
        }
    }
    for (y2=0, ptr3=fy; y2<h2; y2++) {
        yf = ((float)y2) / sy + oy;
        for (i=0, y=(int)yf-yo; i<h3; i++, y++) {
            *ptr3++ = calc_factor(fabs(yf-y) / ay);
        }
    }

    /* Create and initialize compress object. */
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    if ((fh2 = fopen(file2, "wb")) == NULL) {
        fprintf(stderr, "can't open %s for writing\n", file2);
        exit(1);
    }
    jpeg_stdio_dest(&cinfo, fh2);
    cinfo.image_width = w2;
    cinfo.image_height = h2;
    cinfo.input_components = z1;
    switch (z1) {
    case 1:
        cinfo.in_color_space = JCS_GRAYSCALE;
        break;
    case 3:
        cinfo.in_color_space = JCS_RGB;
        break;
    case 4:
        cinfo.in_color_space = JCS_CMYK;
        break;
    default:
        fprintf(stderr, "Not sure what colorspace to make output for input file with %d components.\n", z1);
        exit(1);
    }
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, quality, TRUE);
    jpeg_start_compress(&cinfo, TRUE);

    /* Loop through output rows. */
    n1 = 0;  /* (num lines in buffer) */
    yc = -1; /* (last line loaded) */
    for (y2=0; y2<h2; y2++) {
        yf = ((float)y2) / sy + oy;

        /* Make sure we have the 'yo' rows above and below this row. */
        y = (int)yf - yo;
        if (y - y1 >= h3) n1 = 0;
        ptr1 = n1 ? ptrs[y - y1] : data;
        if (n1) n1 -= y - y1;
        for (i=0; i<h3; i++, y++) {

            /* Move already-loaded lines into place until run out. */
            ptrs[i] = ptr1;
            ptr1 += len;
            if (ptr1 >= data + len * h3) ptr1 = data;

            /* Need to load this line into next available slot. */
            /* It's okay to leave junk in lines outside input image. */
            if (n1-- <= 0 && y >= 0 && y < h1) {

                /* Read lines until get the one we want. */
                for (; yc<y; yc++) {
                    if (!jpeg_read_scanlines(&dinfo, &line, 1)) {
                        fprintf(stderr, "JPEG image corrupted at line %d.\n", yc);
                        exit(1);
                    }
                }

                /* Do horizontal part of convolution now.  Stores a partial
                /* result for each output column for this input row. */
/* ------------------------- start switch 1 on z1 ------------------------- */
                switch (z1) {
                case 1:
                    for (x2=0, ptr2=ptrs[i], ptr3=fx; x2<w2; x2++) {
                        xf = ((float)x2) / sx + ox;
                        r = s = 0;
                        for (j=0, x=(int)xf-xo; j<w3; j++, x++) {
                            f = *ptr3++;
                            if (x >= 0 && x < w1 && fabs(f) > 1e-8) {
                                ptr4 = line + x;
                                r += f * *ptr4++;
                                s += f;
                            }
                        }
                        if (fabs(s) > 1e-3) {
                            *ptr2++ = r;
                            *ptr2++ = s;
                        } else {
                            fprintf(stderr, "x factor near zero -- shouldn't happen!\n");
                            ptr4 = line + (int)xf;
                            *ptr2++ = *ptr4++;
                            *ptr2++ = 1.0;
                        }
                    }
                    break;

                case 3:
                    for (x2=0, ptr2=ptrs[i], ptr3=fx; x2<w2; x2++) {
                        xf = ((float)x2) / sx + ox;
                        r = g = b = s = 0;
                        for (j=0, x=(int)xf-xo; j<w3; j++, x++) {
                            f = *ptr3++;
                            if (x >= 0 && x < w1 && fabs(f) > 1e-8) {
                                ptr4 = line + x + x + x;
                                r += f * *ptr4++;
                                g += f * *ptr4++;
                                b += f * *ptr4++;
                                s += f;
                            }
                        }
                        if (fabs(s) > 1e-3) {
                            *ptr2++ = r;
                            *ptr2++ = g;
                            *ptr2++ = b;
                            *ptr2++ = s;
                        } else {
                            fprintf(stderr, "x factor near zero -- shouldn't happen!\n");
                            ptr4 = line + (int)xf * 3;
                            *ptr2++ = *ptr4++;
                            *ptr2++ = *ptr4++;
                            *ptr2++ = *ptr4++;
                            *ptr2++ = 1.0;
                        }
                    }
                    break;

                default:
                    for (x2=0, ptr2=ptrs[i], ptr3=fx; x2<w2; x2++) {
                        xf = ((float)x2) / sx + ox;
                        for (s=k=0; k<z1; k++)
                            accum[k] = 0;
                        for (j=0, x=(int)xf-xo; j<w3; j++, x++) {
                            f = *ptr3++;
                            if (x >= 0 && x < w1 && fabs(f) > 1e-8) {
                                ptr4 = line + x * z1;
                                for (k=0; k<z1; k++)
                                    accum[k] += f * *ptr4++;
                                s += f;
                            }
                        }
                        if (fabs(s) > 1e-3) {
                            for (k=0; k<z1; k++)
                                *ptr2++ = accum[k];
                            *ptr2++ = s;
                        } else {
                            fprintf(stderr, "x factor near zero -- shouldn't happen!\n");
                            ptr4 = line + (int)xf * z1;
                            for (k=0; k<z1; k++)
                                *ptr2++ = *ptr4++;
                            *ptr2++ = 1.0;
                        }
                    }
                }
/* ------------------------- end switch 1 on z1 ------------------------- */

            }
/* printf("i=%d y2=%d yc=%d y1=%d n1=%d ptrs[i]=%d\n", i, y2, yc, y1, n1, (ptrs[i]-data)/len); */
        }

        /* Now have h3 lines in buffer, starting at y - yo. */
        y1 = (int)yf - yo;
        n1 = h3;

        /* Do vertical part of convolution now.  Finish off calculation for
        /* each output column in this output row by iterating over partial
        /* results for each corresponding input row we calculated above. */
/* ------------------------- start switch 2 on z1 ------------------------- */
        switch (z1) {
        case 1:
            for (x2=0, ptr4=line; x2<w2; x2++) {
                xf = ((float)x2) / sx + ox;
                r = s = 0;
                ptr3 = fy + y2 * h3;
                for (i=0, y=(int)yf-yo; i<h3; i++, y++) {
                    f = *ptr3++;
                    if (y >= 0 && y < h1 && fabs(f) > 1e-8) {
                        ptr1 = ptrs[i] + x2 + x2;
                        r += f * *ptr1++;
                        s += f * *ptr1++;
                    }
/* printf("x2=%d y2=%d i=%d f=%f s=%f (y=%d ptr1=%d)\n", x2, y2, i, f, s, y, (ptr1-data)/len); */
                }
                if (fabs(s) > 1e-3) {
                    *ptr4++ = (c = r / s) > 255 ? 255 : c < 0 ? 0 : c;
                } else {
                    fprintf(stderr, "y factor near zero -- shouldn't happen!\n");
                    ptr1 = ptrs[h3/2] + ((int)xf) * 4;
                    *ptr4++ = *ptr1++;
                }
            }
            break;

        case 3:
            for (x2=0, ptr4=line; x2<w2; x2++) {
                xf = ((float)x2) / sx + ox;
                r = g = b = s = 0;
                ptr3 = fy + y2 * h3;
                for (i=0, y=(int)yf-yo; i<h3; i++, y++) {
                    f = *ptr3++;
                    if (y >= 0 && y < h1 && fabs(f) > 1e-8) {
                        ptr1 = ptrs[i] + x2 * 4;
                        r += f * *ptr1++;
                        g += f * *ptr1++;
                        b += f * *ptr1++;
                        s += f * *ptr1++;
                    }
/* printf("x2=%d y2=%d i=%d f=%f s=%f (y=%d ptr1=%d)\n", x2, y2, i, f, s, y, (ptr1-data)/len); */
                }
                if (fabs(s) > 1e-3) {
                    *ptr4++ = (c = r / s) > 255 ? 255 : c < 0 ? 0 : c;
                    *ptr4++ = (c = g / s) > 255 ? 255 : c < 0 ? 0 : c;
                    *ptr4++ = (c = b / s) > 255 ? 255 : c < 0 ? 0 : c;
                } else {
                    fprintf(stderr, "y factor near zero -- shouldn't happen!\n");
                    ptr1 = ptrs[h3/2] + ((int)xf) * 4;
                    *ptr4++ = *ptr1++;
                    *ptr4++ = *ptr1++;
                    *ptr4++ = *ptr1++;
                }
            }
            break;

        default:
            for (x2=0, ptr4=line; x2<w2; x2++) {
                xf = ((float)x2) / sx + ox;
                for (s=k=0; k<z1; k++)
                    accum[k] = 0;
                ptr3 = fy + y2 * h3;
                for (i=0, y=(int)yf-yo; i<h3; i++, y++) {
                    f = *ptr3++;
                    if (y >= 0 && y < h1 && fabs(f) > 1e-8) {
                        ptr1 = ptrs[i] + x2 * (z1 + 1);
                        for (k=0; k<z1; k++)
                            accum[k] += f * *ptr1++;
                        s += f * *ptr1++;
                    }
/* printf("x2=%d y2=%d i=%d f=%f s=%f (y=%d ptr1=%d)\n", x2, y2, i, f, s, y, (ptr1-data)/len); */
                }
                if (fabs(s) > 1e-3) {
                    for (k=0; k<z1; k++)
                        *ptr4++ = (c = accum[k] / s) > 255 ? 255 : c < 0 ? 0 : c;
                } else {
                    fprintf(stderr, "y factor near zero -- shouldn't happen!\n");
                    ptr1 = ptrs[h3/2] + ((int)xf) * 4;
                    for (k=0; k<z1; k++)
                        *ptr4++ = *ptr1++;
                }
            }
        }
/* ------------------------- end switch 2 on z1 ------------------------- */

        /* Write this output line. */
        jpeg_write_scanlines(&cinfo, &line, 1);
    }

    /* Finish off compression. */
    jpeg_finish_compress(&cinfo);

    /* Clean up. */
    jpeg_destroy_decompress(&dinfo);
    jpeg_destroy_compress(&cinfo);
    free(data);
    free(line);
    free(ptrs);
    free(fx);
    free(accum);
    exit(0);
}
Beispiel #11
0
int compress_yuyv_to_jpeg (struct vdIn *vd, 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;

    fprintf (stderr, "Compressing YUYV frame to JPEG image.\n");

    line_buffer = calloc (vd->width * 3, 1);
    yuyv = vd->framebuffer;

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

    cinfo.image_width = vd->width;
    cinfo.image_height = vd->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 < vd->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);
    jpeg_destroy_compress (&cinfo);

    free (line_buffer);

    return (0);
}
Beispiel #12
0
Datei: jpeg.c Projekt: katakk/vlc
/*
 * EncodeBlock
 */
static block_t *EncodeBlock(encoder_t *p_enc, picture_t *p_pic)
{
    encoder_sys_t *p_sys = p_enc->p_sys;

    block_t *p_block = block_Alloc(p_sys->i_blocksize);
    if (p_block == NULL)
    {
        return NULL;
    }

    JSAMPIMAGE p_row_pointers = NULL;

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

    jpeg_create_compress(&p_sys->p_jpeg);
    jpeg_mem_dest(&p_sys->p_jpeg, &p_block->p_buffer, &p_block->i_buffer);

    p_sys->p_jpeg.image_width = p_enc->fmt_in.video.i_visible_width;
    p_sys->p_jpeg.image_height = p_enc->fmt_in.video.i_visible_height;
    p_sys->p_jpeg.input_components = 3;
    p_sys->p_jpeg.in_color_space = JCS_YCbCr;

    jpeg_set_defaults(&p_sys->p_jpeg);
    jpeg_set_colorspace(&p_sys->p_jpeg, JCS_YCbCr);

    p_sys->p_jpeg.raw_data_in = TRUE;
    p_sys->p_jpeg.do_fancy_downsampling = FALSE;

    jpeg_set_quality(&p_sys->p_jpeg, p_sys->i_quality, TRUE);

    jpeg_start_compress(&p_sys->p_jpeg, TRUE);

    /* Encode picture */
    p_row_pointers = malloc(sizeof(JSAMPARRAY) * p_pic->i_planes);
    if (p_row_pointers == NULL)
    {
        goto error;
    }

    for (int i = 0; i < p_pic->i_planes; i++)
    {
        p_row_pointers[i] = malloc(sizeof(JSAMPROW) * p_sys->p_jpeg.comp_info[i].v_samp_factor * DCTSIZE);
    }

    while (p_sys->p_jpeg.next_scanline < p_sys->p_jpeg.image_height)
    {
        for (int i = 0; i < p_pic->i_planes; i++)
        {
            int i_offset = p_sys->p_jpeg.next_scanline * p_sys->p_jpeg.comp_info[i].v_samp_factor / p_sys->p_jpeg.max_v_samp_factor;

            for (int j = 0; j < p_sys->p_jpeg.comp_info[i].v_samp_factor * DCTSIZE; j++)
            {
                p_row_pointers[i][j] = p_pic->p[i].p_pixels + p_pic->p[i].i_pitch * (i_offset + j);
            }
        }
        jpeg_write_raw_data(&p_sys->p_jpeg, p_row_pointers, p_sys->p_jpeg.max_v_samp_factor * DCTSIZE);
    }

    jpeg_finish_compress(&p_sys->p_jpeg);
    jpeg_destroy_compress(&p_sys->p_jpeg);

    for (int i = 0; i < p_pic->i_planes; i++)
    {
        free(p_row_pointers[i]);
    }
    free(p_row_pointers);

    return p_block;

error:
    jpeg_destroy_compress(&p_sys->p_jpeg);

    if (p_row_pointers != NULL)
    {
        for (int i = 0; i < p_pic->i_planes; i++)
        {
            free(p_row_pointers[i]);
        }
    }
    free(p_row_pointers);

    block_Release(p_block);

    return NULL;
}
Beispiel #13
0
/****************************************************************************
DESCRIPTION:
Save a portion of a device context to JPEG on disk.

HEADER:
mgraph.h

PARAMETERS:
dc			- Device context to save
JPEGName	- Name of bitmap file to save
left		- Left coordinate of bitmap to save
top			- Top coordinate of bitmap to save
right		- Right coordinate of bitmap to save
bottom		- Bottom coordinate of bitmap to save
quality		- Quality factor for compression (1-100)

RETURNS:
True on success, false on error.

REMARKS:
This function saves a portion of a device context as a JPEG format bitmap file to
disk. If this function fails for some reason, it will return false and you can get the
error code from the MGL_result function.

Note that the source rectangle for the bitmap to be saved is not clipped to the
current clipping rectangle for the device context, but it is mapped to the current
viewport. If you specify dimensions that are larger than the current device context,
you will get garbage in the bitmap file as a result.

Note that MGL currently only supports saving bitmap data to JPEG files from 8 bits
per pixel device contexts.

SEE ALSO:
MGL_LoadJPEG,MGL_loadJPEGIntoDC
****************************************************************************/
ibool MGLAPI MGL_saveJPEGFromDC(
	MGLDC *dc,
	const char *JPEGName,
	int left,
	int top,
	int right,
	int bottom,
	int quality)
{
	FILE			*f;
	jpeg_compress	cinfo;		/* Main JPEG compressor object			*/
	my_error_mgr	jerr;		/* Error handling object				*/
	palette_t		pal[256];
	MGLDC			*memDC;
	uchar			*p;

	/* Attempt to open the file for writing */
	if ((f = __MGL_fopen(JPEGName,"wb")) == NULL)
		return false;

	/* Allocate a temporary buffer in the correct format for compression */
	if ((memDC = MGL_createMemoryDC(right-left,1,24,&_MGL_pixelFormats[pfBGR24])) == NULL) {
		fclose(f);
		return false;
		}
	/* Set palette for 24-bit memory DC the same as input DC */
	MGL_getPalette(dc,pal,256,0);
	MGL_setPalette(memDC,pal,256,0);
	MGL_realizePalette(memDC,256,0,false);

	/* We set up the normal JPEG error routines, then override error_exit */
	if ((cinfo.err = jpeg_std_error(&jerr.pub)) == NULL)
		MGL_fatalError("Unable to load JPEG library!");
	jerr.pub.error_exit = my_error_exit;
	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 output file, and
		 * return.
		 */
		fclose(f);
		MGL_destroyDC(memDC);
		jpeg_destroy_compress(&cinfo);
		return false;
		}

	/* Initialize the JPEG decompression object and read header */
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, f);

	/* Set parameters for compression. Input data is always 24-bit RGB */
	cinfo.image_width = right-left;
	cinfo.image_height = bottom-top;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality, true);

	/* Loop around passing one scanline at a time to the compressor */
	jpeg_start_compress(&cinfo, true);
	p = memDC->surface;
	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.
		 */
		MGL_bitBltCoord(memDC,dc,
			left,top+cinfo.next_scanline,
			right,top+cinfo.next_scanline+1,
			0,0,MGL_REPLACE_MODE);
		jpeg_write_scanlines(&cinfo, &p, 1);
		}

	/* Finish compression and clean up */
	jpeg_finish_compress(&cinfo);
	fclose(f);
	jpeg_destroy_compress(&cinfo);
	MGL_destroyDC(memDC);
	return true;
}
Beispiel #14
0
static void _JpegEncode(const CFX_DIBSource* pSource,
                        uint8_t*& dest_buf,
                        FX_STRSIZE& dest_size,
                        int quality,
                        const uint8_t* icc_buf,
                        FX_DWORD icc_length) {
  struct jpeg_error_mgr jerr;
  jerr.error_exit = _error_do_nothing;
  jerr.emit_message = _error_do_nothing1;
  jerr.output_message = _error_do_nothing;
  jerr.format_message = _error_do_nothing2;
  jerr.reset_error_mgr = _error_do_nothing;

  struct jpeg_compress_struct cinfo;
  memset(&cinfo, 0, sizeof(cinfo));
  cinfo.err = &jerr;
  jpeg_create_compress(&cinfo);
  int Bpp = pSource->GetBPP() / 8;
  FX_DWORD nComponents = Bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1;
  FX_DWORD pitch = pSource->GetPitch();
  FX_DWORD width = pdfium::base::checked_cast<FX_DWORD>(pSource->GetWidth());
  FX_DWORD height = pdfium::base::checked_cast<FX_DWORD>(pSource->GetHeight());
  FX_SAFE_DWORD safe_buf_len = width;
  safe_buf_len *= height;
  safe_buf_len *= nComponents;
  safe_buf_len += 1024;
  if (icc_length) {
    safe_buf_len += 255 * 18;
    safe_buf_len += icc_length;
  }
  FX_DWORD dest_buf_length = 0;
  if (!safe_buf_len.IsValid()) {
    dest_buf = nullptr;
  } else {
    dest_buf_length = safe_buf_len.ValueOrDie();
    dest_buf = FX_TryAlloc(uint8_t, dest_buf_length);
    const int MIN_TRY_BUF_LEN = 1024;
    while (!dest_buf && dest_buf_length > MIN_TRY_BUF_LEN) {
      dest_buf_length >>= 1;
      dest_buf = FX_TryAlloc(uint8_t, dest_buf_length);
    }
  }
  if (!dest_buf) {
    FX_OutOfMemoryTerminate();
  }
  struct jpeg_destination_mgr dest;
  dest.init_destination = _dest_do_nothing;
  dest.term_destination = _dest_do_nothing;
  dest.empty_output_buffer = _dest_empty;
  dest.next_output_byte = dest_buf;
  dest.free_in_buffer = dest_buf_length;
  cinfo.dest = &dest;
  cinfo.image_width = width;
  cinfo.image_height = height;
  cinfo.input_components = nComponents;
  if (nComponents == 1) {
    cinfo.in_color_space = JCS_GRAYSCALE;
  } else if (nComponents == 3) {
    cinfo.in_color_space = JCS_RGB;
  } else {
    cinfo.in_color_space = JCS_CMYK;
  }
  uint8_t* line_buf = NULL;
  if (nComponents > 1) {
    line_buf = FX_Alloc2D(uint8_t, width, nComponents);
  }
  jpeg_set_defaults(&cinfo);
  if (quality != 75) {
    jpeg_set_quality(&cinfo, quality, TRUE);
  }
  jpeg_start_compress(&cinfo, TRUE);
  _JpegEmbedIccProfile(&cinfo, icc_buf, icc_length);
  JSAMPROW row_pointer[1];
  JDIMENSION row;
  while (cinfo.next_scanline < cinfo.image_height) {
    const uint8_t* src_scan = pSource->GetScanline(cinfo.next_scanline);
    if (nComponents > 1) {
      uint8_t* dest_scan = line_buf;
      if (nComponents == 3) {
        for (int i = 0; i < width; i++) {
          dest_scan[0] = src_scan[2];
          dest_scan[1] = src_scan[1];
          dest_scan[2] = src_scan[0];
          dest_scan += 3;
          src_scan += Bpp;
        }
      } else {
        for (int i = 0; i < pitch; i++) {
          *dest_scan++ = ~*src_scan++;
        }
      }
      row_pointer[0] = line_buf;
    } else {
      row_pointer[0] = (uint8_t*)src_scan;
    }
    row = cinfo.next_scanline;
    jpeg_write_scanlines(&cinfo, row_pointer, 1);
    if (cinfo.next_scanline == row) {
      dest_buf =
          FX_Realloc(uint8_t, dest_buf, dest_buf_length + JPEG_BLOCK_SIZE);
      dest.next_output_byte = dest_buf + dest_buf_length - dest.free_in_buffer;
      dest_buf_length += JPEG_BLOCK_SIZE;
      dest.free_in_buffer += JPEG_BLOCK_SIZE;
    }
  }
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);
  FX_Free(line_buf);
  dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer;
}
Beispiel #15
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);
}
Beispiel #16
0
void jpeg_write(char *jpegFilename, unsigned char* yuv, int width, int height)
{
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;

    unsigned char *img = (unsigned char *)malloc(width*height*3*sizeof(char));

    JSAMPROW row_pointer[1];
    FILE *outfile = fopen( jpegFilename, "wb" );

    /* Open file for saving output */
    if (!outfile) {
		printf("Can't open file!\n");
    }

    /* Create jpeg data */
    cinfo.err = jpeg_std_error( &jerr );
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);

    /* Set image parameters */
    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_YCbCr;

    /* Set jpeg compression parameters to default */
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 90, TRUE);

    /* Start compression */
    jpeg_start_compress(&cinfo, TRUE);

    /* Feed in data. YUV422 is converted to YUV444 */
    row_pointer[0] = img;
    while (cinfo.next_scanline < cinfo.image_height) {
        unsigned i, j;
        unsigned offset = cinfo.next_scanline * cinfo.image_width * 2;
        for (i = 0, j = 0; i < cinfo.image_width*2; i += 4, j += 6) {
            img[j + 0] = yuv[offset + i + 0]; // Y
            img[j + 1] = yuv[offset + i + 1]; // U
            img[j + 2] = yuv[offset + i + 3]; // V
            img[j + 3] = yuv[offset + i + 2]; // Y
            img[j + 4] = yuv[offset + i + 1]; // U
            img[j + 5] = yuv[offset + i + 3]; // V
        }
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    /* Finish compression */
    jpeg_finish_compress(&cinfo);

    /* Destroy jpeg data */
    jpeg_destroy_compress(&cinfo);

    /* Close output file */
    fclose(outfile);

    munmap(img, width*height*3*sizeof(char));

    return;
}
Beispiel #17
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);
}
Beispiel #18
0
int main(int argc, char *argv[]) {
  long quality;
  const char *metric;
  const char *size;
  char *x;
  int luma_width;
  int luma_height;
  int chroma_width;
  int chroma_height;
  int frame_width;
  int frame_height;
  const char *yuv_path;
  const char *jpg_path;
  FILE *yuv_fd;
  size_t yuv_size;
  unsigned char *yuv_buffer;
  JSAMPLE *image_buffer;
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  FILE *jpg_fd;
  JSAMPROW yrow_pointer[16];
  JSAMPROW cbrow_pointer[8];
  JSAMPROW crrow_pointer[8];
  JSAMPROW *plane_pointer[3];
  int y;

  if (argc != 6) {
    fprintf(stderr, "Required arguments:\n");
    fprintf(stderr, "1. JPEG quality value, 0-100\n");
    fprintf(stderr, "2. Metric to tune for: psnr, hvspsnr, ssim, or msssim\n");
    fprintf(stderr, "3. Image size (e.g. '512x512')\n");
    fprintf(stderr, "4. Path to YUV input file\n");
    fprintf(stderr, "5. Path to JPG output file\n");
    return 1;
  }

  errno = 0;

  quality = strtol(argv[1], NULL, 10);
  if (errno != 0 || quality < 0 || quality > 100) {
    fprintf(stderr, "Invalid JPEG quality value!\n");
    return 1;
  }

  metric = argv[2];

  size = argv[3];
  x = strchr(size, 'x');
  if (!x && x != size && x != (x + strlen(x) - 1)) {
    fprintf(stderr, "Invalid image size input!\n");
    return 1;
  }
  luma_width = (int)strtol(size, NULL, 10);
  if (errno != 0) {
    fprintf(stderr, "Invalid image size input!\n");
    return 1;
  }
  luma_height = (int)strtol(x + 1, NULL, 10);
  if (errno != 0) {
    fprintf(stderr, "Invalid image size input!\n");
    return 1;
  }
  if (luma_width <= 0 || luma_height <= 0) {
    fprintf(stderr, "Invalid image size input!\n");
    return 1;
  }

  chroma_width = (luma_width + 1) >> 1;
  chroma_height = (luma_height + 1) >> 1;

  /* Will check these for validity when opening via 'fopen'. */
  yuv_path = argv[4];
  jpg_path = argv[5];

  yuv_fd = fopen(yuv_path, "r");
  if (!yuv_fd) {
    fprintf(stderr, "Invalid path to YUV file!\n");
    return 1;
  }

  fseek(yuv_fd, 0, SEEK_END);
  yuv_size = ftell(yuv_fd);
  fseek(yuv_fd, 0, SEEK_SET);

  /* Check that the file size matches 4:2:0 yuv. */
  if (yuv_size !=
   (size_t)luma_width*luma_height + 2*chroma_width*chroma_height) {
    fprintf(stderr, "Unexpected input format!\n");
    return 1;
  }

  yuv_buffer = malloc(yuv_size);
  if (fread(yuv_buffer, yuv_size, 1, yuv_fd) != 1) {
    fprintf(stderr, "Error reading yuv file\n");
  };

  fclose(yuv_fd);

  frame_width = (luma_width + (16 - 1)) & ~(16 - 1);
  frame_height = (luma_height + (16 - 1)) & ~(16 - 1);

  image_buffer =
   malloc(frame_width*frame_height + 2*(frame_width/2)*(frame_height/2));

  extend_edge(image_buffer, frame_width, frame_height,
   yuv_buffer, luma_width, luma_height, chroma_width, chroma_height);

  free(yuv_buffer);

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

  jpg_fd = fopen(jpg_path, "wb");
  if (!jpg_fd) {
    fprintf(stderr, "Invalid path to JPEG file!\n");
    return 1;
  }

  jpeg_stdio_dest(&cinfo, jpg_fd);

  cinfo.use_moz_defaults = TRUE;

  cinfo.image_width = luma_width;
  cinfo.image_height = luma_height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_YCbCr;
  jpeg_set_defaults(&cinfo);

  cinfo.raw_data_in = TRUE;

  cinfo.comp_info[0].h_samp_factor = 2;
  cinfo.comp_info[0].v_samp_factor = 2;
  cinfo.comp_info[0].dc_tbl_no = 0;
  cinfo.comp_info[0].ac_tbl_no = 0;
  cinfo.comp_info[0].quant_tbl_no = 0;

  cinfo.comp_info[1].h_samp_factor = 1;
  cinfo.comp_info[1].v_samp_factor = 1;
  cinfo.comp_info[1].dc_tbl_no = 1;
  cinfo.comp_info[1].ac_tbl_no = 1;
  cinfo.comp_info[1].quant_tbl_no = 1;

  cinfo.comp_info[2].h_samp_factor = 1;
  cinfo.comp_info[2].v_samp_factor = 1;
  cinfo.comp_info[2].dc_tbl_no = 1;
  cinfo.comp_info[2].ac_tbl_no = 1;
  cinfo.comp_info[2].quant_tbl_no = 1;

  if (strcmp("psnr", metric) == 0) {
    cinfo.use_flat_quant_tbl = TRUE;
    cinfo.lambda_log_scale1 = 9.0;
    cinfo.lambda_log_scale2 = 0.0;
    cinfo.use_lambda_weight_tbl = FALSE;
  } else if (strcmp("ssim", metric) == 0) {
    cinfo.use_flat_quant_tbl = TRUE;
    cinfo.lambda_log_scale1 = 12.0;
    cinfo.lambda_log_scale2 = 13.5;
    cinfo.use_lambda_weight_tbl = FALSE;
  } else if (strcmp("msssim", metric) == 0) {
    cinfo.use_flat_quant_tbl = TRUE;
    cinfo.lambda_log_scale1 = 10.5;
    cinfo.lambda_log_scale2 = 13.0;
    cinfo.use_lambda_weight_tbl = TRUE;
  } else if (strcmp("hvspsnr", metric) == 0) {
    cinfo.use_flat_quant_tbl = FALSE;
    cinfo.lambda_log_scale1 = 16.0;
    cinfo.lambda_log_scale2 = 15.5;
    cinfo.use_lambda_weight_tbl = TRUE;
  } else {
    fprintf(stderr, "Bad metric choice!\n");
    return 1;
  }

  jpeg_set_quality(&cinfo, quality, TRUE);
  cinfo.optimize_coding = TRUE;

  jpeg_start_compress(&cinfo, TRUE);

  plane_pointer[0] = yrow_pointer;
  plane_pointer[1] = cbrow_pointer;
  plane_pointer[2] = crrow_pointer;

  while (cinfo.next_scanline < cinfo.image_height) {
    int scanline;
    scanline = cinfo.next_scanline;

    for (y = 0; y < 16; y++) {
      yrow_pointer[y] = &image_buffer[frame_width*(scanline + y)];
    }
    for (y = 0; y < 8; y++) {
      cbrow_pointer[y] = &image_buffer[frame_width*frame_height +
       (frame_width/2)*((scanline/2) + y)];
      crrow_pointer[y] = &image_buffer[frame_width*frame_height +
       (frame_width/2)*(frame_height/2) + (frame_width/2)*((scanline/2) + y)];
    }
    jpeg_write_raw_data(&cinfo, plane_pointer, 16);
  }

  jpeg_finish_compress(&cinfo);

  jpeg_destroy_compress(&cinfo);

  free(image_buffer);

  fclose(jpg_fd);

  return 0;
}
Beispiel #19
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;
}
Beispiel #20
0
/*
 * Borrowed with very minor modifications from JPEG6 sample code. Error handling
 * remains as default (i.e. exit on errors).
 */
void
write_JPEG_file (char * filename, int quality, int width, int height)
{
  /* 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 */

  /* 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 (strcmp(filename, "-") == 0) {
      outfile = stdout;
  } else {
      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 = width; 	/* image width and height, in pixels */
  cinfo.image_height = height;
  cinfo.input_components = RAW_BYTES_PER_PIXEL;		/* # 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:
   */

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

    /* VNCSNAPSHOT: Set file colourspace to RGB.
     *   If it is not set to RGB, colour distortions occur.
     */
  jpeg_set_colorspace(&cinfo, JCS_RGB);

  /* 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 = width * 3;	/* 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] = & rawBuffer[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. */
  if (strcmp(filename, "-") != 0) {
      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! */
}
Beispiel #21
0
void GImage::encodeJPEG(
    BinaryOutput&           out) const {

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

    debugAssert(m_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 = m_width * m_height * 3 + 200;
    JOCTET* compressed_data = (JOCTET*)System::malloc(buffer_size);
	jpeg_memory_dest(&cinfo, compressed_data, buffer_size);


    cinfo.image_width       = m_width;
    cinfo.image_height      = m_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] = &(m_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;
}
Beispiel #22
0
int
main (int argc, char **argv)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
#ifdef PROGRESS_REPORT
  struct cdjpeg_progress_mgr progress;
#endif
  int file_index;
  cjpeg_source_ptr src_mgr;
  FILE * input_file;
  FILE * output_file;
  JDIMENSION num_scanlines;

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

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

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

  /* Now safe to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
  enable_signal_catcher((j_common_ptr) &cinfo);
#endif

  /* Initialize JPEG parameters.
   * Much of this may be overridden later.
   * In particular, we don't yet know the input file's color space,
   * but we need to provide some value for jpeg_set_defaults() to work.
   */

  cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
  jpeg_set_defaults(&cinfo);

  /* Scan command line to find file names.
   * It is convenient to use just one switch-parsing routine, but the switch
   * values read here are ignored; we will rescan the switches after opening
   * the input file.
   */

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

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

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

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

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

  /* Figure out the input file format, and set up to read it. */
  src_mgr = select_file_type(&cinfo, input_file);
  src_mgr->input_file = input_file;

  /* Read the input file header to obtain file size & colorspace. */
  (*src_mgr->start_input) (&cinfo, src_mgr);

  /* Now that we know input colorspace, fix colorspace-dependent defaults */
  jpeg_default_colorspace(&cinfo);

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

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

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

  /* Process data */
  while (cinfo.next_scanline < cinfo.image_height) {
    num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
    (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
  }

  /* Finish compression and release memory */
  (*src_mgr->finish_input) (&cinfo, src_mgr);
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);

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

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

  /* All done. */
  exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  return 0;			/* suppress no-return-value warnings */
}
Beispiel #23
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;
}
JPG_BOOL JpegFile::RGBToJpegFile(JPG_CString fileName, 
							unsigned char *dataBuf,
							JPG_UINT widthPix,
							JPG_UINT height,
							JPG_BOOL color, 
							int quality)
{
	if (dataBuf==NULL)
		return FALSE;
	if (widthPix==0)
		return FALSE;
	if (height==0)
		return FALSE;

	unsigned char * tmp;
	if (!color) {
		tmp = (unsigned char*)new unsigned char[widthPix*height];
		if (tmp==NULL) {
			fprintf(stderr, "Memory error\n");
			return FALSE;
		}

		JPG_UINT row,col;
		for (row=0;row<height;row++) {
			for (col=0;col<widthPix;col++) {
				unsigned char *pRed, *pGrn, *pBlu;
				pRed = dataBuf + row * widthPix * 3 + col * 3;
				pGrn = dataBuf + row * widthPix * 3 + col * 3 + 1;
				pBlu = dataBuf + row * widthPix * 3 + col * 3 + 2;

				// luminance
				int lum = (int)(.299 * (double)(*pRed) + .587 * (double)(*pGrn) + .114 * (double)(*pBlu));
				unsigned char *pGray;
				pGray = tmp + row * widthPix + col;
				*pGray = (unsigned char)lum;
			}
		}
	}

	struct jpeg_compress_struct cinfo;
	/* More stuff */
	FILE * outfile=NULL;			/* target file */
	//int row_stride;			/* physical row widthPix in image buffer */

	struct my_error_mgr jerr;

	/* Step 1: allocate and initialize JPEG compression object */
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;

	/* Establish the setjmp return context for my_error_exit to use. */
	if (setjmp(jerr.setjmp_buffer)) {
		/* If we get here, the JPEG code has signaled an error.
		 * We need to clean up the JPEG object, close the input file, and return.
		 */

		jpeg_destroy_compress(&cinfo);

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

		if (!color) {
			delete [] tmp;
		}
		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. */

	if ((outfile = fopen(fileName, "wb")) == NULL) {
		fprintf(stderr, "JpegFile :\nCan't open %s\n", fileName);
		return FALSE;
	}

	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 = widthPix; 	/* image widthPix and height, in pixels */
	cinfo.image_height = height;
	if (color) {
		cinfo.input_components = 3;		/* # of color components per pixel */
		cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
	} else {
		cinfo.input_components = 1;		/* # of color components per pixel */
		cinfo.in_color_space = JCS_GRAYSCALE; 	/* 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:
   */
  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 = widthPix * 3;	/* 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.
     */
	unsigned char *outRow;
	if (color) {
		outRow = dataBuf + (cinfo.next_scanline * widthPix * 3);
	} else {
		outRow = tmp + (cinfo.next_scanline * widthPix);
	}

    (void) jpeg_write_scanlines(&cinfo, &outRow, 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);

  if (!color)
	  delete [] tmp;
  /* And we're done! */

  return TRUE;
}
Beispiel #25
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;
}
static void write_rgb_JPEG_file (char * filename, int quality, int width, int height)
{
  struct jpeg_compress_struct cinfo;
  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 */

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

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

  if ((outfile = fopen(filename, "wb")) == NULL) {
    tc_log_error(MOD_NAME, "can't open %s", filename);
  }
  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 = 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 */

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

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

  while (cinfo.next_scanline < cinfo.image_height) {
    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);

}
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;
}
// native YUV jpeg encoder code based on encode_JPEG of the quicktime4linux lib
//
static void write_yuv_JPEG_file(char *filename, int quality,
		       unsigned char **input,
		       int _width, int _height)
{
  int i, j, k;
  int width 	= _width;
  int height 	= _height;
  unsigned char *base[3];
  struct jpeg_compress_struct encinfo;
  struct jpeg_error_mgr jerr;
  FILE * outfile;		/* target file */

  jpeg_create_compress(&encinfo);

  encinfo.err = jpeg_std_error(&jerr);

  if ((outfile = fopen(filename, "wb")) == NULL) {
    tc_log_error(MOD_NAME, "can't open %s", filename);
  }
  jpeg_stdio_dest(&encinfo, outfile);

  encinfo.image_width = width;
  encinfo.image_height = height;
  encinfo.input_components = 3;

  jpeg_set_defaults(&encinfo);
  encinfo.dct_method = JDCT_FASTEST;

  jpeg_set_quality(&encinfo, quality, TRUE);
  encinfo.raw_data_in = TRUE;
  encinfo.in_color_space = JCS_YCbCr;

  encinfo.comp_info[0].h_samp_factor = 2;
  encinfo.comp_info[0].v_samp_factor = 2;
  encinfo.comp_info[1].h_samp_factor = 1;
  encinfo.comp_info[1].v_samp_factor = 1;
  encinfo.comp_info[2].h_samp_factor = 1;
  encinfo.comp_info[2].v_samp_factor = 1;

  jpeg_start_compress(&encinfo, TRUE);

  base[0] = input[0];
  base[1] = input[1];
  base[2] = input[2];

  for (i = 0; i < height; i += 2*DCTSIZE) {
    for (j=0, k=0; j<2*DCTSIZE;j+=2, k++) {

      line[0][j]   = base[0]; base[0] += width;
      line[0][j+1] = base[0]; base[0] += width;
      line[1][k]   = base[1]; base[1] += width/2;
      line[2][k]   = base[2]; base[2] += width/2;
    }
    jpeg_write_raw_data(&encinfo, line, 2*DCTSIZE);
  }
  jpeg_finish_compress(&encinfo);

  fclose(outfile);

  jpeg_destroy_compress(&encinfo);

}
Beispiel #29
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;
}
Beispiel #30
0
bool JpegEncoder::write( const Mat& img, const std::vector<int>& params )
{
    m_last_error.clear();

    struct fileWrapper
    {
        FILE* f;

        fileWrapper() : f(0) {}
        ~fileWrapper() { if(f) fclose(f); }
    };
    volatile bool result = false;
    fileWrapper fw;
    int width = img.cols, height = img.rows;

    std::vector<uchar> out_buf(1 << 12);
    AutoBuffer<uchar> _buffer;
    uchar* buffer;

    struct jpeg_compress_struct cinfo;
    JpegErrorMgr jerr;
    JpegDestination dest;

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

    if( !m_buf )
    {
        fw.f = fopen( m_filename.c_str(), "wb" );
        if( !fw.f )
            goto _exit_;
        jpeg_stdio_dest( &cinfo, fw.f );
    }
    else
    {
        dest.dst = m_buf;
        dest.buf = &out_buf;

        jpeg_buffer_dest( &cinfo, &dest );

        dest.pub.next_output_byte = &out_buf[0];
        dest.pub.free_in_buffer = out_buf.size();
    }

    if( setjmp( jerr.setjmp_buffer ) == 0 )
    {
        cinfo.image_width = width;
        cinfo.image_height = height;

        int _channels = img.channels();
        int channels = _channels > 1 ? 3 : 1;
        cinfo.input_components = channels;
        cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;

        int quality = 95;
        int progressive = 0;
        int optimize = 0;
        int rst_interval = 0;
        int luma_quality = -1;
        int chroma_quality = -1;

        for( size_t i = 0; i < params.size(); i += 2 )
        {
            if( params[i] == CV_IMWRITE_JPEG_QUALITY )
            {
                quality = params[i+1];
                quality = MIN(MAX(quality, 0), 100);
            }

            if( params[i] == CV_IMWRITE_JPEG_PROGRESSIVE )
            {
                progressive = params[i+1];
            }

            if( params[i] == CV_IMWRITE_JPEG_OPTIMIZE )
            {
                optimize = params[i+1];
            }

            if( params[i] == CV_IMWRITE_JPEG_LUMA_QUALITY )
            {
                if (params[i+1] >= 0)
                {
                    luma_quality = MIN(MAX(params[i+1], 0), 100);

                    quality = luma_quality;

                    if (chroma_quality < 0)
                    {
                        chroma_quality = luma_quality;
                    }
                }
            }

            if( params[i] == CV_IMWRITE_JPEG_CHROMA_QUALITY )
            {
                if (params[i+1] >= 0)
                {
                    chroma_quality = MIN(MAX(params[i+1], 0), 100);
                }
            }

            if( params[i] == CV_IMWRITE_JPEG_RST_INTERVAL )
            {
                rst_interval = params[i+1];
                rst_interval = MIN(MAX(rst_interval, 0), 65535L);
            }
        }

        jpeg_set_defaults( &cinfo );
        cinfo.restart_interval = rst_interval;

        jpeg_set_quality( &cinfo, quality,
                          TRUE /* limit to baseline-JPEG values */ );
        if( progressive )
            jpeg_simple_progression( &cinfo );
        if( optimize )
            cinfo.optimize_coding = TRUE;

#if JPEG_LIB_VERSION >= 70
        if (luma_quality >= 0 && chroma_quality >= 0)
        {
            cinfo.q_scale_factor[0] = jpeg_quality_scaling(luma_quality);
            cinfo.q_scale_factor[1] = jpeg_quality_scaling(chroma_quality);
            if ( luma_quality != chroma_quality )
            {
                /* disable subsampling - ref. Libjpeg.txt */
                cinfo.comp_info[0].v_samp_factor = 1;
                cinfo.comp_info[0].h_samp_factor = 1;
                cinfo.comp_info[1].v_samp_factor = 1;
                cinfo.comp_info[1].h_samp_factor = 1;
            }
            jpeg_default_qtables( &cinfo, TRUE );
        }
#endif // #if JPEG_LIB_VERSION >= 70

        jpeg_start_compress( &cinfo, TRUE );

        if( channels > 1 )
            _buffer.allocate(width*channels);
        buffer = _buffer;

        for( int y = 0; y < height; y++ )
        {
            uchar *data = img.data + img.step*y, *ptr = data;

            if( _channels == 3 )
            {
                icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, cvSize(width,1) );
                ptr = buffer;
            }
            else if( _channels == 4 )
            {
                icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, cvSize(width,1), 2 );
                ptr = buffer;
            }

            jpeg_write_scanlines( &cinfo, &ptr, 1 );
        }

        jpeg_finish_compress( &cinfo );
        result = true;
    }

_exit_:

    if(!result)
    {
        char jmsg_buf[JMSG_LENGTH_MAX];
        jerr.pub.format_message((j_common_ptr)&cinfo, jmsg_buf);
        m_last_error = jmsg_buf;
    }

    jpeg_destroy_compress( &cinfo );

    return result;
}