/* Method: ImageList#to_blob Purpose: returns the imagelist as a blob (a String) Notes: runs an info parm block if present - the user can specify the image format and depth */ VALUE ImageList_to_blob(VALUE self) { Image *images; Info *info; volatile VALUE info_obj; volatile VALUE blob_str; void *blob = NULL; size_t length = 0; ExceptionInfo exception; info_obj = rm_info_new(); Data_Get_Struct(info_obj, Info, info); // Convert the images array to an images sequence. images = images_from_imagelist(self); GetExceptionInfo(&exception); (void) SetImageInfo(info, MagickTrue, &exception); rm_check_exception(&exception, images, RetainOnError); if (*info->magick != '\0') { Image *img; for (img = images; img; img = GetNextImageInList(img)) { strncpy(img->magick, info->magick, sizeof(info->magick)-1); } } // Unconditionally request multi-images support. The worst that // can happen is that there's only one image or the format // doesn't support multi-image files. info->adjoin = MagickTrue; blob = ImagesToBlob(info, images, &length, &exception); if (exception.severity != UndefinedException) { magick_free((void*)blob); } rm_split(images); CHECK_EXCEPTION() (void) DestroyExceptionInfo(&exception); if (length == 0 || !blob) { return Qnil; } blob_str = rb_str_new(blob, (long)length); magick_free((void*)blob); return blob_str; }
/* Method: ImageList#display Purpose: Display all the images to an X window screen. */ VALUE ImageList_display(VALUE self) { Image *images; Info *info; volatile VALUE info_obj; // Create a new Info object to use with this call info_obj = rm_info_new(); Data_Get_Struct(info_obj, Info, info); // Convert the images array to an images sequence. images = images_from_imagelist(self); (void) DisplayImages(info, images); rm_split(images); rm_check_image_exception(images, RetainOnError); return self; }
VALUE ImageList_animate(int argc, VALUE *argv, VALUE self) { Image *images; Info *info; VALUE info_obj; if (argc > 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc); } // Create a new Info object to use with this call info_obj = rm_info_new(); // Convert the images array to an images sequence. images = images_from_imagelist(self); if (argc == 1) { Image *img; unsigned int delay; delay = NUM2UINT(argv[0]); for (img = images; img; img = GetNextImageInList(img)) { img->delay = delay; } } Data_Get_Struct(info_obj, Info, info); (void) AnimateImages(info, images); rm_check_image_exception(images, RetainOnError); rm_split(images); RB_GC_GUARD(info_obj); return self; }
/** * Write all the images to the specified file. If the file format supports * multi-image files, and the 'images' array contains more than one image, then * the images will be written as a single multi-image file. Otherwise each image * will be written to a separate file. * * Ruby usage: * - @verbatim ImageList#write(file) @endverbatim * * @param self this object * @param file the file * @return self */ VALUE ImageList_write(VALUE self, VALUE file) { Image *images, *img; Info *info; const MagickInfo *m; VALUE info_obj; unsigned long scene; ExceptionInfo *exception; info_obj = rm_info_new(); Data_Get_Struct(info_obj, Info, info); if (TYPE(file) == T_FILE) { OpenFile *fptr; // Ensure file is open - raise error if not GetOpenFile(file, fptr); #if defined(_WIN32) add_format_prefix(info, fptr->pathv); SetImageInfoFile(info, NULL); #else SetImageInfoFile(info, GetReadFile(fptr)); #endif } else { add_format_prefix(info, file); SetImageInfoFile(info, NULL); } // Convert the images array to an images sequence. images = images_from_imagelist(self); // Copy the filename into each image. Set a scene number to be used if // writing multiple files. (Ref: ImageMagick's utilities/convert.c for (scene = 0, img = images; img; img = GetNextImageInList(img)) { img->scene = scene++; strcpy(img->filename, info->filename); } // Find out if the format supports multi-images files. exception = AcquireExceptionInfo(); (void) SetImageInfo(info, MagickTrue, exception); rm_check_exception(exception, images, RetainOnError); m = GetMagickInfo(info->magick, exception); rm_check_exception(exception, images, RetainOnError); (void) DestroyExceptionInfo(exception); // Tell WriteImage if we want a multi-images file. if (imagelist_length(self) > 1L && m->adjoin) { info->adjoin = MagickTrue; } for (img = images; img; img = GetNextImageInList(img)) { rm_sync_image_options(img, info); (void) WriteImage(info, img); // images will be split before raising an exception rm_check_image_exception(images, RetainOnError); if (info->adjoin) { break; } } rm_split(images); RB_GC_GUARD(info_obj); return self; }
/* Method: ImageList#write(file) Purpose: Write all the images to the specified file. If the file format supports multi-image files, and the @images array contains more than one image, then the images will be written as a single multi-image file. Otherwise each image will be written to a separate file. Returns self. */ VALUE ImageList_write(VALUE self, VALUE file) { Image *images, *img; Info *info; const MagickInfo *m; volatile VALUE info_obj; char *filename; long filenameL; unsigned long scene; ExceptionInfo exception; info_obj = rm_info_new(); Data_Get_Struct(info_obj, Info, info); if (TYPE(file) == T_FILE) { OpenFile *fptr; // Ensure file is open - raise error if not GetOpenFile(file, fptr); SetImageInfoFile(info, GetReadFile(fptr)); } else { // Convert arg to string. Catch exceptions. file = rb_rescue(rb_String, file, file_arg_rescue, file); // Copy the filename to the Info and to the Image. filename = rb_str2cstr(file, &filenameL); filenameL = min(filenameL, MaxTextExtent-1); memcpy(info->filename, filename, (size_t)filenameL); info->filename[filenameL] = '\0'; SetImageInfoFile(info, NULL); } // Convert the images array to an images sequence. images = images_from_imagelist(self); // Copy the filename into each images. Set a scene number to be used if // writing multiple files. (Ref: ImageMagick's utilities/convert.c for (scene = 0, img = images; img; img = GetNextImageInList(img)) { img->scene = scene++; strcpy(img->filename, info->filename); } GetExceptionInfo(&exception); (void) SetImageInfo(info, MagickTrue, &exception); rm_check_exception(&exception, images, RetainOnError); (void) DestroyExceptionInfo(&exception); // Find out if the format supports multi-images files. GetExceptionInfo(&exception); m = GetMagickInfo(info->magick, &exception); rm_check_exception(&exception, images, RetainOnError); (void) DestroyExceptionInfo(&exception); // Tell WriteImage if we want a multi-images file. if (imagelist_length(self) > 1L && m->adjoin) { info->adjoin = MagickTrue; } for (img = images; img; img = GetNextImageInList(img)) { (void) WriteImage(info, img); // images will be split before raising an exception rm_check_image_exception(images, RetainOnError); if (info->adjoin) { break; } } rm_split(images); return self; }