Logo Search packages:      
Sourcecode: libjpeg-turbo version File versions  Download package

DLLEXPORT int DLLCALL tjTransform ( tjhandle  handle,
unsigned char *  jpegBuf,
unsigned long  jpegSize,
int  n,
unsigned char **  dstBufs,
unsigned long *  dstSizes,
tjtransform transforms,
int  flags 
)

Losslessly transform a JPEG image into another JPEG image. Lossless transforms work by moving the raw coefficients from one JPEG image structure to another without altering the values of the coefficients. While this is typically faster than decompressing the image, transforming it, and re-compressing it, lossless transforms are not free. Each lossless transform requires reading and Huffman decoding all of the coefficients in the source image, regardless of the size of the destination image. Thus, this function provides a means of generating multiple transformed images from the same source or of applying multiple transformations simultaneously, in order to eliminate the need to read the source coefficients multiple times.

Parameters:
handlea handle to a TurboJPEG transformer instance
jpegBufpointer to a buffer containing the JPEG image to transform
jpegSizesize of the JPEG image (in bytes)
nthe number of transformed JPEG images to generate
dstBufspointer to an array of n image buffers. dstBufs[i] will receive a JPEG image that has been transformed using the parameters in transforms[i]. TurboJPEG has the ability to reallocate the JPEG buffer to accommodate the size of the JPEG image. Thus, you can choose to:

  1. pre-allocate the JPEG buffer with an arbitrary size using tjAlloc() and let TurboJPEG grow the buffer as needed,
  2. set dstBufs[i] to NULL to tell TurboJPEG to allocate the buffer for you, or
  3. pre-allocate the buffer to a "worst case" size determined by calling tjBufSize() with the cropped width and height. This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)

If you choose option 1, dstSizes[i] should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check dstBufs[i] upon return from this function, as it may have changed.

dstSizespointer to an array of n unsigned long variables which will receive the actual sizes (in bytes) of each transformed JPEG image. If dstBufs[i] points to a pre-allocated buffer, then dstSizes[i] should be set to the size of the buffer. Upon return, dstSizes[i] will contain the size of the JPEG image (in bytes.)
transformspointer to an array of n tjtransform structures, each of which specifies the transform parameters and/or cropping region for the corresponding transformed output image.
flagsthe bitwise OR of one or more of the flags.
Returns:
0 if successful, or -1 if an error occurred (see tjGetErrorStr().)

Definition at line 938 of file turbojpeg.c.

References tjtransform::op, tjtransform::r, tjBufSize(), TJFLAG_FORCEMMX, TJFLAG_FORCESSE, TJFLAG_FORCESSE2, TJFLAG_NOREALLOC, TJXOP_HFLIP, TJXOPT_CROP, TJXOPT_GRAY, TJXOPT_PERFECT, TJXOPT_TRIM, and tjregion::y.

{
      jpeg_transform_info *xinfo=NULL;
      jvirt_barray_ptr *srccoefs, *dstcoefs;
      int retval=0, i, jpegSubsamp;

      getinstance(handle);
      if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
            _throw("tjTransform(): Instance has not been initialized for transformation");

      if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
            || t==NULL || flags<0)
            _throw("tjTransform(): Invalid argument");

      if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
      else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
      else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");

      if(setjmp(this->jerr.setjmp_buffer))
      {
            /* If we get here, the JPEG code has signaled an error. */
            retval=-1;
            goto bailout;
      }

      jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);

      if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
            ==NULL)
            _throw("tjTransform(): Memory allocation failure");
      MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);

      for(i=0; i<n; i++)
      {
            xinfo[i].transform=xformtypes[t[i].op];
            xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
            xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
            xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
            xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
            if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
            else xinfo[i].slow_hflip=0;

            if(xinfo[i].crop)
            {
                  xinfo[i].crop_xoffset=t[i].r.x;  xinfo[i].crop_xoffset_set=JCROP_POS;
                  xinfo[i].crop_yoffset=t[i].r.y;  xinfo[i].crop_yoffset_set=JCROP_POS;
                  if(t[i].r.w!=0)
                  {
                        xinfo[i].crop_width=t[i].r.w;  xinfo[i].crop_width_set=JCROP_POS;
                  }
                  else xinfo[i].crop_width=JCROP_UNSET;
                  if(t[i].r.h!=0)
                  {
                        xinfo[i].crop_height=t[i].r.h;  xinfo[i].crop_height_set=JCROP_POS;
                  }
                  else xinfo[i].crop_height=JCROP_UNSET;
            }
      }

      jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
      jpeg_read_header(dinfo, TRUE);
      jpegSubsamp=getSubsamp(dinfo);
      if(jpegSubsamp<0)
            _throw("tjTransform(): Could not determine subsampling type for JPEG image");

      for(i=0; i<n; i++)
      {
            if(!jtransform_request_workspace(dinfo, &xinfo[i]))
                  _throw("tjTransform(): Transform is not perfect");

            if(xinfo[i].crop)
            {
                  if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
                        || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
                  {
                        snprintf(errStr, JMSG_LENGTH_MAX,
                              "To crop this JPEG image, x must be a multiple of %d\n"
                              "and y must be a multiple of %d.\n",
                              xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
                        retval=-1;  goto bailout;
                  }
            }
      }

      srccoefs=jpeg_read_coefficients(dinfo);

      for(i=0; i<n; i++)
      {
            int w, h, alloc=1;
            if(!xinfo[i].crop)
            {
                  w=dinfo->image_width;  h=dinfo->image_height;
            }
            else
            {
                  w=xinfo[i].crop_width;  h=xinfo[i].crop_height;
            }
            if(flags&TJFLAG_NOREALLOC)
            {
                  alloc=0;  dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
            }
            jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
            jpeg_copy_critical_parameters(dinfo, cinfo);
            dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
                  &xinfo[i]);
            jpeg_write_coefficients(cinfo, dstcoefs);
            jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
            jtransform_execute_transformation(dinfo, cinfo, srccoefs,
                  &xinfo[i]);
            jpeg_finish_compress(cinfo);
      }

      jpeg_finish_decompress(dinfo);

      bailout:
      if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
      if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
      if(xinfo) free(xinfo);
      return retval;
}

Here is the call graph for this function:


Generated by  Doxygen 1.6.0   Back to index