Exemple #1
0
/**
 * Call CoalesceImages.
 *
 * Ruby usage:
 *   - @verbatim ImageList#coalesce @endverbatim
 *
 * Notes:
 *   - Respects the delay, matte, and start_loop fields in each image.
 *
 * @param self this object
 * @return a new Image with the coalesced image sequence return stored in the
 * images array
 */
VALUE
ImageList_coalesce(VALUE self)
{
    Image *images, *new_images;
    ExceptionInfo *exception;

    // Convert the image array to an image sequence.
    images = images_from_imagelist(self);

    exception = AcquireExceptionInfo();
    new_images = CoalesceImages(images, exception);
    rm_split(images);
    rm_check_exception(exception, new_images, DestroyOnError);
    (void) DestroyExceptionInfo(exception);

    rm_ensure_result(new_images);

    return rm_imagelist_from_images(new_images);
}
Exemple #2
0
/**
 * Equivalent to -layers option in ImageMagick 6.2.6.
 *
 * Ruby usage:
 *   - @verbatim ImageList#optimize_layers(method) @endverbatim
 *
 * @param self this object
 * @param method the method to use
 * @return a new imagelist
 */
VALUE
ImageList_optimize_layers(VALUE self, VALUE method)
{
    Image *images, *new_images, *new_images2;
    LAYERMETHODTYPE mthd;
    ExceptionInfo *exception;
    QuantizeInfo quantize_info;

    new_images2 = NULL;     // defeat "unused variable" message

    exception = AcquireExceptionInfo();
#if defined(HAVE_TYPE_IMAGELAYERMETHOD)
    VALUE_TO_ENUM(method, mthd, ImageLayerMethod);
#else
    VALUE_TO_ENUM(method, mthd, MagickLayerMethod);
#endif
    images = images_from_imagelist(self);

    switch (mthd)
    {
        case CoalesceLayer:
            new_images = CoalesceImages(images, exception);
            break;
        case DisposeLayer:
            new_images = DisposeImages(images, exception);
            break;
        case OptimizeTransLayer:
            new_images = clone_imagelist(images);
            OptimizeImageTransparency(new_images, exception);
            break;
        case RemoveDupsLayer:
            new_images = clone_imagelist(images);
            RemoveDuplicateLayers(&new_images, exception);
            break;
        case RemoveZeroLayer:
            new_images = clone_imagelist(images);
            RemoveZeroDelayLayers(&new_images, exception);
            break;
        case CompositeLayer:
            rm_split(images);
            rb_raise(rb_eNotImpError, "Magick::CompositeLayer is not supported. Use the composite_layers method instead.");
            break;
            // In 6.3.4-ish, OptimizeImageLayer replaced OptimizeLayer
        case OptimizeImageLayer:
            new_images = OptimizeImageLayers(images, exception);
            break;
            // and OptimizeLayer became a "General Purpose, GIF Animation Optimizer" (ref. mogrify.c)
        case OptimizeLayer:
            new_images = CoalesceImages(images, exception);
            rm_split(images);
            rm_check_exception(exception, new_images, DestroyOnError);
            new_images2 = OptimizeImageLayers(new_images, exception);
            DestroyImageList(new_images);
            rm_check_exception(exception, new_images2, DestroyOnError);
            new_images = new_images2;
            OptimizeImageTransparency(new_images, exception);
            rm_check_exception(exception, new_images, DestroyOnError);
            // mogrify supports -dither here. We don't.
#if defined(HAVE_REMAPIMAGE)
            GetQuantizeInfo(&quantize_info);
            (void) RemapImages(&quantize_info, new_images, NULL);
#else
            (void) MapImages(new_images, NULL, 0);
#endif
            break;
        case OptimizePlusLayer:
            new_images = OptimizePlusImageLayers(images, exception);
            break;
        case CompareAnyLayer:
        case CompareClearLayer:
        case CompareOverlayLayer:
            new_images = CompareImageLayers(images, mthd, exception);
            break;
#if defined(HAVE_ENUM_MOSAICLAYER)
        case MosaicLayer:
            new_images = MergeImageLayers(images, mthd, exception);
            break;
#endif
#if defined(HAVE_ENUM_FLATTENLAYER)
        case FlattenLayer:
            new_images = MergeImageLayers(images, mthd, exception);
            break;
#endif
#if defined(HAVE_ENUM_MERGELAYER)
        case MergeLayer:
            new_images = MergeImageLayers(images, mthd, exception);
            break;
#endif
#if defined(HAVE_ENUM_TRIMBOUNDSLAYER)
        case TrimBoundsLayer:
            new_images = MergeImageLayers(images, mthd, exception);
            break;
#endif
        default:
            rm_split(images);
            rb_raise(rb_eArgError, "undefined layer method");
            break;
    }

    rm_split(images);
    rm_check_exception(exception, new_images, DestroyOnError);
    (void) DestroyExceptionInfo(exception);

    rm_ensure_result(new_images);

    return rm_imagelist_from_images(new_images);
}
Exemple #3
0
static MagickBooleanType WriteMPEGImage(const ImageInfo *image_info,
  Image *image)
{
  char
    basename[MaxTextExtent],
    filename[MaxTextExtent];

  Image
    *coalesce_image,
    *next_image;

  ImageInfo
    *write_info;

  int
    file;

  MagickBooleanType
    status;

  register Image
    *p;

  register long
    i;

  size_t
    length;

  unsigned char
    *blob;

  unsigned long
    count,
    delay,
    scene;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
  if (status == MagickFalse)
    return(status);
  CloseBlob(image);
  /*
    Determine if the sequence of images have identical page info.
  */
  coalesce_image=image;
  for (next_image=image; next_image != (Image *) NULL; )
  {
    if ((image->columns != next_image->columns) ||
        (image->rows != next_image->rows))
      break;
    if ((image->page.x != next_image->page.x) ||
        (image->page.y != next_image->page.y))
      break;
    next_image=GetNextImageInList(next_image);
  }
  if (next_image != (Image *) NULL)
    {
      coalesce_image=CoalesceImages(image,&image->exception);
      if (coalesce_image == (Image *) NULL)
        return(MagickFalse);
    }
  /*
    Write YUV files.
  */
  file=AcquireUniqueFileResource(basename);
  if (file != -1)
    file=close(file)-1;
  (void) FormatMagickString(coalesce_image->filename,MaxTextExtent,"%s",
    basename);
  write_info=CloneImageInfo(image_info);
  status=WriteMPEGParameterFiles(write_info,coalesce_image,basename);
  if (status == MagickFalse)
    {
      if (coalesce_image != image)
        coalesce_image=DestroyImage(coalesce_image);
      (void) remove(basename);
      if (image->quality != UndefinedCompressionQuality)
        {
          (void) FormatMagickString(filename,MaxTextExtent,"%s.iqm",
            basename);
          (void) remove(filename);
          (void) FormatMagickString(filename,MaxTextExtent,"%s.niq",
            basename);
          (void) remove(filename);
        }
      ThrowWriterException(CoderError,"UnableToWriteMPEGParameters");
    }
  count=0;
  write_info->interlace=PlaneInterlace;
  for (p=coalesce_image; p != (Image *) NULL; p=GetNextImageInList(p))
  {
    char
      previous_image[MaxTextExtent];

    blob=(unsigned char *) NULL;
    length=0;
    scene=p->scene;
    delay=100*p->delay/Max(p->ticks_per_second,1);
    for (i=0; i < (long) Max((delay+1)/3,1); i++)
    {
      p->scene=count;
      count++;
      status=MagickFalse;
      switch (i)
      {
        case 0:
        {
          Image
            *frame;

          (void) FormatMagickString(p->filename,MaxTextExtent,"%s.%lu.yuv",
            basename,p->scene);
          (void) FormatMagickString(filename,MaxTextExtent,"%s.%lu.yuv",
            basename,p->scene);
          (void) FormatMagickString(previous_image,MaxTextExtent,
            "%s.%lu.yuv",basename,p->scene);
          frame=CloneImage(p,0,0,MagickTrue,&p->exception);
          if (frame == (Image *) NULL)
            break;
          status=WriteImage(write_info,frame);
          frame=DestroyImage(frame);
          break;
        }
        case 1:
        {
          blob=(unsigned char *)
            FileToBlob(previous_image,~0,&length,&image->exception);
        }
        default:
        {
          (void) FormatMagickString(filename,MaxTextExtent,"%s.%lu.yuv",
            basename,p->scene);
          if (length > 0)
            status=BlobToFile(filename,blob,length,&image->exception);
          break;
        }
      }
      if (image->debug != MagickFalse)
        {
          if (status != MagickFalse)
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
              "%lu. Wrote YUV file for scene %lu:",i,p->scene);
          else
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
              "%lu. Failed to write YUV file for scene %lu:",i,p->scene);
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",
            filename);
        }
    }
    p->scene=scene;
    if (blob != (unsigned char *) NULL)
      blob=(unsigned char *) RelinquishMagickMemory(blob);
    if (status == MagickFalse)
      break;
  }
  /*
    Convert YUV to MPEG.
  */
  (void) CopyMagickString(coalesce_image->filename,basename,MaxTextExtent);
  status=InvokeDelegate(write_info,coalesce_image,(char *) NULL,"mpeg-encode",
    &image->exception);
  write_info=DestroyImageInfo(write_info);
  /*
    Free resources.
  */
  count=0;
  for (p=coalesce_image; p != (Image *) NULL; p=GetNextImageInList(p))
  {
    delay=100*p->delay/Max(p->ticks_per_second,1);
    for (i=0; i < (long) Max((delay+1)/3,1); i++)
    {
      (void) FormatMagickString(p->filename,MaxTextExtent,"%s.%lu.yuv",
        basename,count++);
      (void) remove(p->filename);
    }
    (void) CopyMagickString(p->filename,image_info->filename,MaxTextExtent);
  }
  (void) RelinquishUniqueFileResource(basename);
  (void) FormatMagickString(filename,MaxTextExtent,"%s.iqm",basename);
  (void) remove(filename);
  (void) FormatMagickString(filename,MaxTextExtent,"%s.niq",basename);
  (void) remove(filename);
  (void) FormatMagickString(filename,MaxTextExtent,"%s.log",basename);
  (void) remove(filename);
  if (coalesce_image != image)
    coalesce_image=DestroyImage(coalesce_image);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit");
  return(status);
}
Exemple #4
0
static MagickBooleanType WriteMPEGImage(const ImageInfo *image_info,
  Image *image,ExceptionInfo *exception)
{
#define WriteMPEGIntermediateFormat "jpg"

  char
    basename[MagickPathExtent],
    filename[MagickPathExtent];

  double
    delay;

  Image
    *coalesce_image;

  ImageInfo
    *write_info;

  int
    file;

  MagickBooleanType
    status;

  register Image
    *p;

  register ssize_t
    i;

  size_t
    count,
    length,
    scene;

  unsigned char
    *blob;

  /*
    Open output image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(status);
  (void) CloseBlob(image);
  /*
    Write intermediate files.
  */
  coalesce_image=CoalesceImages(image,exception);
  if (coalesce_image == (Image *) NULL)
    return(MagickFalse);
  file=AcquireUniqueFileResource(basename);
  if (file != -1)
    file=close(file)-1;
  (void) FormatLocaleString(coalesce_image->filename,MagickPathExtent,"%s",
    basename);
  count=0;
  write_info=CloneImageInfo(image_info);
  *write_info->magick='\0';
  for (p=coalesce_image; p != (Image *) NULL; p=GetNextImageInList(p))
  {
    char
      previous_image[MagickPathExtent];

    blob=(unsigned char *) NULL;
    length=0;
    scene=p->scene;
    delay=100.0*p->delay/MagickMax(1.0*p->ticks_per_second,1.0);
    for (i=0; i < (ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0); i++)
    {
      p->scene=count;
      count++;
      status=MagickFalse;
      switch (i)
      {
        case 0:
        {
          Image
            *frame;

          (void) FormatLocaleString(p->filename,MagickPathExtent,"%s%.20g.%s",
            basename,(double) p->scene,WriteMPEGIntermediateFormat);
          (void) FormatLocaleString(filename,MagickPathExtent,"%s%.20g.%s",
            basename,(double) p->scene,WriteMPEGIntermediateFormat);
          (void) FormatLocaleString(previous_image,MagickPathExtent,
            "%s%.20g.%s",basename,(double) p->scene,
            WriteMPEGIntermediateFormat);
          frame=CloneImage(p,0,0,MagickTrue,exception);
          if (frame == (Image *) NULL)
            break;
          status=WriteImage(write_info,frame,exception);
          frame=DestroyImage(frame);
          break;
        }
        case 1:
        {
          blob=(unsigned char *) FileToBlob(previous_image,~0UL,&length,
            exception);
        }
        default:
        {
          (void) FormatLocaleString(filename,MagickPathExtent,"%s%.20g.%s",
            basename,(double) p->scene,WriteMPEGIntermediateFormat);
          if (length > 0)
            status=BlobToFile(filename,blob,length,exception);
          break;
        }
      }
      if (image->debug != MagickFalse)
        {
          if (status != MagickFalse)
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
              "%.20g. Wrote %s file for scene %.20g:",(double) i,
              WriteMPEGIntermediateFormat,(double) p->scene);
          else
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
              "%.20g. Failed to write %s file for scene %.20g:",(double) i,
              WriteMPEGIntermediateFormat,(double) p->scene);
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",filename);
        }
    }
    p->scene=scene;
    if (blob != (unsigned char *) NULL)
      blob=(unsigned char *) RelinquishMagickMemory(blob);
    if (status == MagickFalse)
      break;
  }
  /*
    Convert JPEG to MPEG.
  */
  (void) CopyMagickString(coalesce_image->magick_filename,basename,
    MagickPathExtent);
  (void) CopyMagickString(coalesce_image->filename,basename,MagickPathExtent);
  GetPathComponent(image_info->filename,ExtensionPath,coalesce_image->magick);
  if (*coalesce_image->magick == '\0')
    (void) CopyMagickString(coalesce_image->magick,image->magick,
      MagickPathExtent);
  status=InvokeDelegate(write_info,coalesce_image,(char *) NULL,"mpeg:encode",
    exception);
  (void) FormatLocaleString(write_info->filename,MagickPathExtent,"%s.%s",
    write_info->unique,coalesce_image->magick);
  status=CopyDelegateFile(write_info->filename,image->filename);
  (void) RelinquishUniqueFileResource(write_info->filename);
  write_info=DestroyImageInfo(write_info);
  /*
    Relinquish resources.
  */
  count=0;
  for (p=coalesce_image; p != (Image *) NULL; p=GetNextImageInList(p))
  {
    delay=100.0*p->delay/MagickMax(1.0*p->ticks_per_second,1.0);
    for (i=0; i < (ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0); i++)
    {
      (void) FormatLocaleString(p->filename,MagickPathExtent,"%s%.20g.%s",
        basename,(double) count++,WriteMPEGIntermediateFormat);
      (void) RelinquishUniqueFileResource(p->filename);
    }
    (void) CopyMagickString(p->filename,image_info->filename,MagickPathExtent);
  }
  (void) RelinquishUniqueFileResource(basename);
  coalesce_image=DestroyImageList(coalesce_image);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit");
  return(status);
}
Exemple #5
0
/*
    Method:     ImageList#optimize_layers
    Purpose:    Equivalent to -layers option in 6.2.6
    Returns:    a new imagelist
*/
VALUE
ImageList_optimize_layers(VALUE self, VALUE method)
{
    Image *images, *new_images, *new_images2;
    LAYERMETHODTYPE mthd;
    ExceptionInfo exception;

    new_images2 = NULL;     // defeat "unused variable" message

    GetExceptionInfo(&exception);
#if defined(HAVE_TYPE_IMAGELAYERMETHOD)
    VALUE_TO_ENUM(method, mthd, ImageLayerMethod);
#else
    VALUE_TO_ENUM(method, mthd, MagickLayerMethod);
#endif
    images = images_from_imagelist(self);

    switch (mthd)
    {
        case CoalesceLayer:
            new_images = CoalesceImages(images, &exception);
            break;
        case DisposeLayer:
            new_images = DisposeImages(images, &exception);
            break;
#if defined(HAVE_ENUM_OPTIMIZETRANSLAYER)
        case OptimizeTransLayer:
            new_images = clone_imagelist(images);
            OptimizeImageTransparency(new_images, &exception);
            break;
#endif
#if defined(HAVE_ENUM_REMOVEDUPSLAYER)
        case RemoveDupsLayer:
            new_images = clone_imagelist(images);
            RemoveDuplicateLayers(&new_images, &exception);
            break;
#endif
#if defined(HAVE_ENUM_REMOVEZEROLAYER)
        case RemoveZeroLayer:
            new_images = clone_imagelist(images);
            RemoveZeroDelayLayers(&new_images, &exception);
            break;
#endif
#if defined(HAVE_ENUM_COMPOSITELAYER)
        case CompositeLayer:
            rb_raise(rb_eNotImpError, "Magick::CompositeLayer is not yet supported.");
            break;
#endif
#if defined(HAVE_ENUM_OPTIMIZEIMAGELAYER)
            // In 6.3.4-ish, OptimizeImageLayer replaced OptimizeLayer
        case OptimizeImageLayer:
            new_images = OptimizeImageLayers(images, &exception);
            break;
            // and OptimizeLayer became a "General Purpose, GIF Animation Optimizer" (ref. mogrify.c)
        case OptimizeLayer:
            new_images = CoalesceImages(images, &exception);
            rm_split(images);
            rm_check_exception(&exception, new_images, DestroyOnError);
            new_images2 = OptimizeImageLayers(new_images, &exception);
            DestroyImageList(new_images);
            rm_check_exception(&exception, new_images2, DestroyOnError);
            new_images = new_images2;
            OptimizeImageTransparency(new_images, &exception);
            rm_check_exception(&exception, new_images, DestroyOnError);
            // mogrify supports -dither here. We don't.
            (void) MapImages(new_images, NULL, 0);
            break;
#else
        case OptimizeLayer:
            new_images = OptimizeImageLayers(images, &exception);
            break;
#endif
        case OptimizePlusLayer:
            new_images = OptimizePlusImageLayers(images, &exception);
            break;
        case CompareAnyLayer:
        case CompareClearLayer:
        case CompareOverlayLayer:
            new_images = CompareImageLayers(images, mthd, &exception);
            break;
        default:
            rb_raise(rb_eArgError, "undefined layer method");
            break;
    }

    rm_split(images);
    rm_check_exception(&exception, new_images, DestroyOnError);
    (void) DestroyExceptionInfo(&exception);

    rm_ensure_result(new_images);

    return rm_imagelist_from_images(new_images);
}