/** * Call MapImages. * * Ruby usage: * - @verbatim ImageList#map(reference) @endverbatim * - @verbatim ImageList#map(reference, dither) @endverbatim * * Notes: * - Default dither is false * - Sets \@scene to self.scene * * @param argc number of input arguments * @param argv array of input arguments * @param self this object * @return a new ImageList with mapped images. */ VALUE ImageList_map(int argc, VALUE *argv, VALUE self) { Image *images, *new_images = NULL; Image *map; unsigned int dither = MagickFalse; VALUE scene, new_imagelist, t; ExceptionInfo *exception; #if defined(HAVE_REMAPIMAGES) QuantizeInfo quantize_info; rb_warning("ImageList#map is deprecated. Use ImageList#remap instead."); #endif switch (argc) { case 2: dither = RTEST(argv[1]); case 1: t = rm_cur_image(argv[0]); map = rm_check_destroyed(t); break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc); break; } // Convert image array to image sequence, clone image sequence. exception = AcquireExceptionInfo(); images = images_from_imagelist(self); new_images = CloneImageList(images, exception); rm_split(images); rm_check_exception(exception, new_images, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_images); // Call ImageMagick #if defined(HAVE_REMAPIMAGES) GetQuantizeInfo(&quantize_info); quantize_info.dither = dither; (void) RemapImages(&quantize_info, new_images, map); #else (void) MapImages(new_images, map, dither); #endif rm_check_image_exception(new_images, DestroyOnError); // Set @scene in new ImageList object to same value as in self. new_imagelist = rm_imagelist_from_images(new_images); scene = rb_iv_get(self, "@scene"); (void) imagelist_scene_eq(new_imagelist, scene); RB_GC_GUARD(scene); RB_GC_GUARD(new_imagelist); RB_GC_GUARD(t); return new_imagelist; }
/** * Requires a minimum of two images. The first image is transformed into the * second by a number of intervening images as specified by "number_images". * * Ruby usage: * - @verbatim ImageList#morph(number_images) @endverbatim * * Notes: * - Sets \@scenes to 0 * * @param self this object * @param nimages the number of images * @return a new image list with the images array set to the morph sequence. */ VALUE ImageList_morph(VALUE self, VALUE nimages) { Image *images, *new_images; ExceptionInfo *exception; long number_images; // Use a signed long so we can test for a negative argument. number_images = NUM2LONG(nimages); if (number_images <= 0) { rb_raise(rb_eArgError, "number of intervening images must be > 0"); } exception = AcquireExceptionInfo(); images = images_from_imagelist(self); new_images = MorphImages(images, (unsigned long)number_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); }
/* Method: ImageList#composite_layers Purpose: Equivalent to convert's -layers composite option Notes: see mogrify.c */ VALUE ImageList_composite_layers(int argc, VALUE *argv, VALUE self) { #if defined(HAVE_COMPOSITELAYERS) volatile VALUE source_images; Image *dest, *source, *new_images; RectangleInfo geometry; CompositeOperator operator = OverCompositeOp; ExceptionInfo exception; switch (argc) { case 2: VALUE_TO_ENUM(argv[1], operator, CompositeOperator); case 1: source_images = argv[0]; break; default: rb_raise(rb_eArgError, "wrong number of arguments (expected 1 or 2, got %d)", argc); break; } // Convert ImageLists to image sequences. dest = images_from_imagelist(self); new_images = clone_imagelist(dest); rm_split(dest); source = images_from_imagelist(source_images); SetGeometry(new_images,&geometry); (void) ParseAbsoluteGeometry(new_images->geometry, &geometry); geometry.width = source->page.width != 0 ? source->page.width : source->columns; geometry.height = source->page.height != 0 ? source->page.height : source->rows; GravityAdjustGeometry(new_images->page.width != 0 ? new_images->page.width : new_images->columns , new_images->page.height != 0 ? new_images->page.height : new_images->rows , new_images->gravity, &geometry); GetExceptionInfo(&exception); CompositeLayers(new_images, operator, source, geometry.x, geometry.y, &exception); rm_split(source); rm_check_exception(&exception, new_images, DestroyOnError); (void) DestroyExceptionInfo(&exception); return rm_imagelist_from_images(new_images); #else self = self; argc = argc; argv = argv; rm_not_implemented(); return (VALUE)0; #endif }
/* Method: ImageList#map(reference, dither=false) Purpose: Call MapImages Returns: a new ImageList with mapped images. @scene is set to self.scene */ VALUE ImageList_map(int argc, VALUE *argv, VALUE self) { Image *images, *new_images = NULL; Image *map; unsigned int dither = False; volatile VALUE scene, new_imagelist, t; ExceptionInfo exception; switch (argc) { case 2: dither = RTEST(argv[1]); case 1: t = ImageList_cur_image(argv[0]); map = rm_check_destroyed(t); break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc); break; } if (imagelist_length(self) == 0L) { rb_raise(rb_eArgError, "no images in this image list"); } // Convert image array to image sequence, clone image sequence. GetExceptionInfo(&exception); images = images_from_imagelist(self); new_images = CloneImageList(images, &exception); rm_split(images); rm_check_exception(&exception, new_images, DestroyOnError); (void) DestroyExceptionInfo(&exception); rm_ensure_result(new_images); // Call ImageMagick (void) MapImages(new_images, map, dither); rm_check_image_exception(new_images, DestroyOnError); // Set @scene in new ImageList object to same value as in self. new_imagelist = rm_imagelist_from_images(new_images); scene = rb_iv_get(self, "@scene"); (void) imagelist_scene_eq(new_imagelist, scene); return new_imagelist; }
/** * Equivalent to convert's -layers composite option. * * Ruby usage: * - @verbatim ImageList#composite_layers(images) @endverbatim * - @verbatim ImageList#composite_layers(images,operator) @endverbatim * * Notes: * - Default operator is OverCompositeOp * * @param argc number of input arguments * @param argv array of input arguments * @param self this object * @return a new imagelist * @see mogrify.c in ImageMagick */ VALUE ImageList_composite_layers(int argc, VALUE *argv, VALUE self) { VALUE source_images; Image *dest, *source, *new_images; RectangleInfo geometry; CompositeOperator operator = OverCompositeOp; ExceptionInfo *exception; switch (argc) { case 2: VALUE_TO_ENUM(argv[1], operator, CompositeOperator); case 1: source_images = argv[0]; break; default: rb_raise(rb_eArgError, "wrong number of arguments (expected 1 or 2, got %d)", argc); break; } // Convert ImageLists to image sequences. dest = images_from_imagelist(self); new_images = clone_imagelist(dest); rm_split(dest); source = images_from_imagelist(source_images); SetGeometry(new_images,&geometry); (void) ParseAbsoluteGeometry(new_images->geometry, &geometry); geometry.width = source->page.width != 0 ? source->page.width : source->columns; geometry.height = source->page.height != 0 ? source->page.height : source->rows; GravityAdjustGeometry(new_images->page.width != 0 ? new_images->page.width : new_images->columns , new_images->page.height != 0 ? new_images->page.height : new_images->rows , new_images->gravity, &geometry); exception = AcquireExceptionInfo(); CompositeLayers(new_images, operator, source, geometry.x, geometry.y, exception); rm_split(source); rm_check_exception(exception, new_images, DestroyOnError); (void) DestroyExceptionInfo(exception); RB_GC_GUARD(source_images); return rm_imagelist_from_images(new_images); }
/** * Compare each image with the next in a sequence and returns the maximum * bounding region of any pixel differences it discovers. * * Ruby usage: * - @verbatim ImageList#deconstruct @endverbatim * * @param self this object * @return a new imagelist */ VALUE ImageList_deconstruct(VALUE self) { Image *new_images, *images; ExceptionInfo *exception; images = images_from_imagelist(self); exception = AcquireExceptionInfo(); new_images = DeconstructImages(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); }
/** * Call MontageImages. * * Ruby usage: * - @verbatim ImageList#montage <{parm block}> @endverbatim * * Notes: * - Creates Montage object, yields to block if present in Montage object's * scope. * * @param self this object * @return a new image list */ VALUE ImageList_montage(VALUE self) { VALUE montage_obj; Montage *montage; Image *new_images, *images; ExceptionInfo *exception; // Create a new instance of the Magick::Montage class montage_obj = rm_montage_new(); if (rb_block_given_p()) { // Run the block in the instance's context, allowing the app to modify the // object's attributes. (void) rb_obj_instance_eval(0, NULL, montage_obj); } Data_Get_Struct(montage_obj, Montage, montage); images = images_from_imagelist(self); // If app specified a non-default composition operator, use it for all images. if (montage->compose != UndefinedCompositeOp) { Image *i; for (i = images; i; i = GetNextImageInList(i)) { i->compose = montage->compose; } } exception = AcquireExceptionInfo(); // MontageImage can return more than one image. new_images = MontageImages(images, montage->info, exception); rm_split(images); rm_check_exception(exception, new_images, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_images); RB_GC_GUARD(montage_obj); return rm_imagelist_from_images(new_images); }
/** * 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); }
/** * 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); }
/* 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); }