/* Method: ImageList#append(stack) Purpose: Append all the images by calling ImageAppend Returns: an Frame object for the result */ VALUE ImageList_append(VALUE self, VALUE stack_arg) { Image *images, *new_image; unsigned int stack; ExceptionInfo exception; // Convert the image array to an image sequence. images = images_from_imagelist(self); // If stack == true, stack rectangular images top-to-bottom, // otherwise left-to-right. stack = RTEST(stack_arg); GetExceptionInfo(&exception); new_image = AppendImages(images, stack, &exception); rm_split(images); rm_check_exception(&exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(&exception); rm_ensure_result(new_image); return rm_image_new(new_image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % M a g i c k Q u e r y C o n f i g u r e O p t i o n % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % MagickQueryConfigureOption() returns the value associated with the specified % configure option. % % The format of the MagickQueryConfigureOption function is: % % char *MagickQueryConfigureOption(const char *option) % % A description of each parameter follows: % % o option: The option name. % */ WandExport char *MagickQueryConfigureOption(const char *option) { char *value; const ConfigureInfo **configure_info; ExceptionInfo exception; unsigned long number_options; GetExceptionInfo(&exception); configure_info=GetConfigureInfoList(option,&number_options,&exception); DestroyExceptionInfo(&exception); if (configure_info == (const ConfigureInfo **) NULL) return((char *) NULL); value=AcquireString(configure_info[0]->value); configure_info=(const ConfigureInfo **) RelinquishMagickMemory((void *) configure_info); return(value); }
ngx_int_t convert_image(ngx_http_request_t *r, convert_options_t *option_info, Image **image) { ngx_uint_t i; ngx_http_gm_convert_option_t *options; ngx_http_gm_convert_option_t *option; RectangleInfo geometry; RectangleInfo geometry_info; ExceptionInfo exception; Image *resize_image = NULL; u_char *resize_geometry = NULL; u_char *need_crop_resize = NULL; Image *rotate_image = NULL; u_char *rotate_degrees = NULL; ngx_int_t degrees; ngx_int_t degrees_suffix_len = 0; dd("entering"); options = option_info->options->elts; for (i = 0; i < option_info->options->nelts; ++i) { option = &options[i]; if (option->type == NGX_HTTP_GM_RESIZE_OPTION) { dd("starting resize"); resize_geometry = ngx_http_gm_get_str_value(r, option->resize_geometry_cv, &option->resize_geometry); need_crop_resize = (u_char *)ngx_strchr(resize_geometry, 'c'); if (need_crop_resize != NULL) { *need_crop_resize = '^'; } if (resize_geometry == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gm filter: resize image, get resize geometry failed"); return NGX_ERROR; } if (ngx_strncmp(resize_geometry, "no", 2) == 0) { continue; } (void) GetImageGeometry(*image, (char *)resize_geometry, 1, &geometry); if ((geometry.width == (*image)->columns) && (geometry.height == (*image)->rows)) continue; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "resize image geometry: \"%s\"", resize_geometry); GetExceptionInfo(&exception); resize_image = ResizeImage(*image, geometry.width, geometry.height, (*image)->filter,(*image)->blur, &exception); if (resize_image == (Image *) NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gm filter: resize image failed, " "arg: \"%s\" severity: \"%O\" " "reason: \"%s\", description: \"%s\"", resize_geometry, exception.severity, exception.reason, exception.description); DestroyExceptionInfo(&exception); return NGX_ERROR; } DestroyImage(*image); *image = resize_image; DestroyExceptionInfo(&exception); if (need_crop_resize != NULL) { GetGeometry((char *)resize_geometry, &geometry_info.x, &geometry_info.y, (unsigned long *)(&geometry_info.width), (unsigned long *)(&geometry_info.height)); if (geometry_info.width > (*image)->columns || geometry_info.height > (*image)->rows) { continue; } geometry_info.x = ((*image)->columns - geometry_info.width) / 2; geometry_info.y = ((*image)->rows - geometry_info.height) / 2; GetExceptionInfo(&exception); resize_image = CropImage(*image, &geometry_info, &exception); if (resize_image == (Image *) NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gm filter: resize croping image failed, " "arg: \"%s\" severity: \"%O\" " "reason: \"%s\", description: \"%s\"", resize_geometry, exception.severity, exception.reason, exception.description); DestroyExceptionInfo(&exception); return NGX_ERROR; } DestroyImage(*image); *image = resize_image; DestroyExceptionInfo(&exception); } } else if (option->type == NGX_HTTP_GM_ROTATE_OPTION) { dd("starting rotate"); rotate_degrees = ngx_http_gm_get_str_value(r, option->rotate_degrees_cv, &option->rotate_degrees); if (rotate_degrees == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gm filter: rotate image, get rotate degrees failed"); return NGX_ERROR; } if (ngx_strchr(rotate_degrees,'>') != (char *) NULL) { if ((*image)->columns <= (*image)->rows) continue; degrees_suffix_len = 1; } if (ngx_strchr(rotate_degrees,'<') != (char *) NULL) { if ((*image)->columns >= (*image)->rows) continue; degrees_suffix_len = 1; } degrees = 0; degrees = ngx_atoi(rotate_degrees, ngx_strlen(rotate_degrees) - degrees_suffix_len); if (degrees == 0) { continue; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "rotate image degrees: \"%O\"", degrees); GetExceptionInfo(&exception); rotate_image=RotateImage(*image, degrees, &exception); if (rotate_image == (Image *) NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gm filter: rotate image failed, " "degrees: \"%s\" severity: \"%O\" " "reason: \"%s\", description: \"%s\"", option->rotate_degrees, exception.severity, exception.reason, exception.description); DestroyExceptionInfo(&exception); return NGX_ERROR; } DestroyImage(*image); *image = rotate_image; DestroyExceptionInfo(&exception); } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gm filter: convert command, unkonwn option"); return NGX_ERROR; } } return NGX_OK; }
CAMLprim value magick_loader(value input) { CAMLparam1(input); CAMLlocal2(pixel_matrix, res); Image *image_bloc; int image_type_code; int components; GLenum format; ExceptionInfo exception; GetExceptionInfo(&exception); { if (IsMagickInstantiated() == MagickFalse) { InitializeMagick(getenv("PWD")); } { ImageInfo *image_info; image_info = CloneImageInfo((ImageInfo *) NULL); switch (Tag_val(input)) { /* given a filename of an image */ case 0: (void) strcpy(image_info->filename, String_val(Field(input,0))); image_bloc = ReadImage(image_info, &exception); break; /* given the image data in a buffer */ case 1: image_bloc = BlobToImage( image_info, (void *)String_val(Field(input,0)), caml_string_length(Field(input,0)), &exception); break; } DestroyImageInfo(image_info); } if (exception.severity != UndefinedException) { if (image_bloc != (Image *) NULL) { DestroyImage(image_bloc); } DestroyExceptionInfo(&exception); caml_failwith( exception.reason ); /* @TODO exception.description */ } if (image_bloc == (Image *) NULL) { DestroyExceptionInfo(&exception); caml_failwith("read image failed"); } } { ImageType image_type; image_type = GetImageType( image_bloc, &exception ); if (exception.severity != UndefinedException) caml_failwith( exception.reason ); image_type_code = Val_ImageType(image_type, &components); if ( image_type_code == 11 ) caml_failwith("getting image type failed"); } { unsigned long x, y; unsigned long columns, rows; PixelPacket pixel; columns = image_bloc->columns; rows = image_bloc->rows; const PixelPacket * pixel_packet_array; pixel_packet_array = AcquireImagePixels( image_bloc, 0, 0, columns, rows, &exception ); if (exception.severity != UndefinedException) { caml_failwith(exception.reason); } { unsigned char *image; long ndx; long dims[3]; dims[0] = columns; dims[1] = rows; dims[2] = components; pixel_matrix = alloc_bigarray(BIGARRAY_UINT8 | BIGARRAY_C_LAYOUT, 3, NULL, dims); image = Data_bigarray_val(pixel_matrix); for (x=0; x < columns; ++x) { for (y=0; y < rows; ++y) { pixel = pixel_packet_array[(columns * y) + x]; ndx = (columns * y * components) + (x * components); switch (components) { case 1: image[ndx + 0] = pixel.red / SCALE; break; case 2: image[ndx + 0] = pixel.red / SCALE; image[ndx + 1] = ( MaxMap - pixel.opacity ) / SCALE; break; case 3: image[ndx + 0] = pixel.red / SCALE; image[ndx + 1] = pixel.green / SCALE; image[ndx + 2] = pixel.blue / SCALE; break; case 4: image[ndx + 0] = pixel.red / SCALE; image[ndx + 1] = pixel.green / SCALE; image[ndx + 2] = pixel.blue / SCALE; image[ndx + 3] = ( MaxMap - pixel.opacity ) / SCALE; break; } } } } switch (components) { case 1: format = GL_LUMINANCE; break; case 2: format = GL_LUMINANCE_ALPHA; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; } res = alloc_tuple(5); Store_field(res, 0, pixel_matrix ); Store_field(res, 1, Val_long(columns) ); Store_field(res, 2, Val_long(rows) ); Store_field(res, 3, Val_internal_format(components) ); Store_field(res, 4, Val_pixel_data_format(format) ); } DestroyExceptionInfo(&exception); DestroyImage(image_bloc); CAMLreturn(res); }
int main(int argc, char **argv) { char *xml; const char *acronym, *data_type, *description, *endian, *mask, *mime_type, *offset, *pattern, *priority, *match_type, *value; ExceptionInfo *exception; size_t length; static char *doc_type = { "<!DOCTYPE mimemap [\n" " <!ELEMENT mimemap (mime+)>\n" " <!ELEMENT mime (#PCDATA)>\n" " <!ATTLIST mime type CDATA #REQUIRED>\n" " <!ATTLIST mime acronym CDATA #IMPLIED>\n" " <!ATTLIST mime description CDATA #IMPLIED>\n" " <!ATTLIST mime pattern CDATA #IMPLIED>\n" " <!ATTLIST mime offset CDATA #IMPLIED>\n" " <!ATTLIST mime data-type (string|byte|short|ssize_t) #IMPLIED>\n" " <!ATTLIST mime endian (lsb|msb) #IMPLIED>\n" " <!ATTLIST mime magic CDATA #IMPLIED>\n" " <!ATTLIST mime mask CDATA #IMPLIED>\n" " <!ATTLIST mime priority CDATA #IMPLIED>\n" "]>" }; XMLTreeInfo *comment, *expanded_acronym, *glob, *magic, *match, *type, *xml_info; if (argc != 2) return(fprintf(stderr,"usage: %s xml-file\n", argv[0])); exception=AcquireExceptionInfo(); xml=(char *) FileToBlob(argv[1],~0UL,&length,exception); if (xml == (char *) NULL) return(fprintf(stderr,"%s: unable to read file\n",argv[1])); xml_info=NewXMLTree(xml,exception); xml=(char *) RelinquishWizardMemory(xml); if (xml_info == (XMLTreeInfo *) NULL) return(fprintf(stderr,"%s: unable to parse xml-file\n",argv[1])); (void) printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); (void) printf("%s\n",doc_type); (void) printf("<mimemap>\n"); type=GetXMLTreeChild(xml_info,"mime-type"); while (type != (XMLTreeInfo *) NULL) { mime_type=GetXMLTreeAttribute(type,"type"); acronym=(const char *) NULL; expanded_acronym=GetXMLTreeChild(type,"acronym"); if (expanded_acronym != (XMLTreeInfo *) NULL) acronym=GetXMLTreeContent(expanded_acronym); expanded_acronym=GetXMLTreeChild(type,"expanded-acronym"); description=(const char *) NULL; comment=GetXMLTreeChild(type,"comment"); if (comment != (XMLTreeInfo *) NULL) description=GetXMLTreeContent(comment); if (expanded_acronym != (XMLTreeInfo *) NULL) description=GetXMLTreeContent(expanded_acronym); magic=GetXMLTreeChild(type,"magic"); priority=(char *) NULL; match=(XMLTreeInfo *) NULL; if (magic != (XMLTreeInfo *) NULL) { priority=GetXMLTreeAttribute(magic,"priority"); match=GetXMLTreeChild(magic,"match"); } while (match != (XMLTreeInfo *) NULL) { value=(char *) NULL; match_type=(char *) NULL; mask=(char *) NULL; offset=(char *) NULL; if (match != (XMLTreeInfo *) NULL) { value=GetXMLTreeAttribute(match,"value"); match_type=GetXMLTreeAttribute(match,"type"); offset=GetXMLTreeAttribute(match,"offset"); mask=GetXMLTreeAttribute(match,"mask"); } (void) printf(" <mime"); if (mime_type != (const char *) NULL) (void) printf(" type=\"%s\"",mime_type); if (description != (const char *) NULL) (void) printf(" description=\"%s\"",description); if (match_type != (const char *) NULL) { data_type="string"; endian="undefined"; if (strncmp(match_type,"little",6) == 0) endian="LSB"; if (strncmp(match_type,"big",3) == 0) endian="MSB"; if (strcmp(match_type,"byte") == 0) data_type="byte"; if (strcmp(match_type+strlen(match_type)-2,"16") == 0) data_type="short"; if (strcmp(match_type+strlen(match_type)-2,"32") == 0) data_type="ssize_t"; (void) printf(" data-type=\"%s\"",data_type); if (strcmp(endian,"undefined") != 0) (void) printf(" endian=\"%s\"",endian); } if (offset != (const char *) NULL) (void) printf(" offset=\"%s\"",offset); if (mask != (const char *) NULL) (void) printf(" mask=\"%s\"",mask); if (value != (const char *) NULL) { char *magic; magic=AcquireString(value); SubstituteString(&magic,"<","<"); SubstituteString(&magic,">",">"); SubstituteString(&magic,"\"","""); (void) printf(" magic=\"%s\"",magic); magic=(char *) RelinquishWizardMemory(magic); } if (priority != (const char *) NULL) (void) printf(" priority=\"%s\"",priority); (void) printf(" />\n"); match=GetNextXMLTreeTag(match); } glob=GetXMLTreeChild(type,"glob"); while (glob != (XMLTreeInfo *) NULL) { pattern=GetXMLTreeAttribute(glob,"pattern"); value=(char *) NULL; if (match) value=GetXMLTreeAttribute(match,"value"); (void) printf(" <mime"); if (mime_type != (const char *) NULL) (void) printf(" type=\"%s\"",mime_type); if (acronym != (const char *) NULL) (void) printf(" acronym=\"%s\"",acronym); if (description != (const char *) NULL) (void) printf(" description=\"%s\"",description); (void) printf(" priority=\"100\""); if (pattern != (const char *) NULL) (void) printf(" pattern=\"%s\"",pattern); (void) printf(" />\n"); glob=GetNextXMLTreeTag(glob); } type=GetNextXMLTreeTag(type); } (void) printf("</mimemap>\n"); xml=XMLTreeInfoToXML(xml_info); (void) fprintf(stderr,"%s\n",xml); xml=(char *) RelinquishWizardMemory(xml); DestroyXMLTree(xml_info); exception=DestroyExceptionInfo(exception); return(0); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteImage() writes an image or an image sequence to a file or file handle. % If writing to a file is on disk, the name is defined by the filename member % of the image structure. WriteImage() returns MagickFalse is there is a % memory shortage or if the image cannot be written. Check the exception % member of image to determine the cause for any failure. % % The format of the WriteImage method is: % % MagickBooleanType WriteImage(const ImageInfo *image_info,Image *image, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o image: the image. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info, Image *image,ExceptionInfo *exception) { char filename[MaxTextExtent]; const char *option; const DelegateInfo *delegate_info; const MagickInfo *magick_info; ExceptionInfo *sans_exception; ImageInfo *write_info; MagickBooleanType status, temporary; MagickStatusType thread_support; PolicyDomain domain; PolicyRights rights; /* Determine image type from filename prefix or suffix (e.g. image.jpg). */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); sans_exception=AcquireExceptionInfo(); write_info=CloneImageInfo(image_info); (void) CopyMagickString(write_info->filename,image->filename,MaxTextExtent); if (*write_info->magick == '\0') (void) CopyMagickString(write_info->magick,image->magick,MaxTextExtent); (void) SetImageInfo(write_info,1,sans_exception); if (LocaleCompare(write_info->magick,"clipmask") == 0) { if (image->clip_mask == (Image *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), OptionError,"NoClipPathDefined","`%s'",image->filename); return(MagickFalse); } image=image->clip_mask; (void) SetImageInfo(write_info,1,sans_exception); } (void) CopyMagickString(filename,image->filename,MaxTextExtent); (void) CopyMagickString(image->filename,write_info->filename,MaxTextExtent); domain=CoderPolicyDomain; rights=WritePolicyRights; if (IsRightsAuthorized(domain,rights,write_info->magick) == MagickFalse) { sans_exception=DestroyExceptionInfo(sans_exception); errno=EPERM; ThrowBinaryException(PolicyError,"NotAuthorized",filename); } magick_info=GetMagickInfo(write_info->magick,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); if (magick_info != (const MagickInfo *) NULL) { if (GetMagickEndianSupport(magick_info) == MagickFalse) image->endian=UndefinedEndian; else if ((image_info->endian == UndefinedEndian) && (GetMagickRawSupport(magick_info) != MagickFalse)) { size_t lsb_first; lsb_first=1; image->endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian; } } (void) SyncImageProfiles(image); option=GetImageOption(image_info,"delegate:bimodal"); if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse) && (write_info->page == (char *) NULL) && (GetPreviousImageInList(image) == (Image *) NULL) && (GetNextImageInList(image) == (Image *) NULL) && (IsTaintImage(image) == MagickFalse)) { delegate_info=GetDelegateInfo(image->magick,write_info->magick,exception); if ((delegate_info != (const DelegateInfo *) NULL) && (GetDelegateMode(delegate_info) == 0) && (IsPathAccessible(image->magick_filename) != MagickFalse)) { /* Process image with bi-modal delegate. */ (void) CopyMagickString(image->filename,image->magick_filename, MaxTextExtent); status=InvokeDelegate(write_info,image,image->magick, write_info->magick,exception); write_info=DestroyImageInfo(write_info); (void) CopyMagickString(image->filename,filename,MaxTextExtent); return(status); } } status=MagickFalse; temporary=MagickFalse; if ((magick_info != (const MagickInfo *) NULL) && (GetMagickSeekableStream(magick_info) != MagickFalse)) { char filename[MaxTextExtent]; (void) CopyMagickString(filename,image->filename,MaxTextExtent); status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); (void) CopyMagickString(image->filename,filename,MaxTextExtent); if (status != MagickFalse) { if (IsBlobSeekable(image) == MagickFalse) { /* A seekable stream is required by the encoder. */ write_info->adjoin=MagickTrue; (void) CopyMagickString(write_info->filename,image->filename, MaxTextExtent); (void) AcquireUniqueFilename(image->filename); temporary=MagickTrue; } (void) CloseBlob(image); } } if (constitute_semaphore == (SemaphoreInfo *) NULL) AcquireSemaphoreInfo(&constitute_semaphore); if ((magick_info != (const MagickInfo *) NULL) && (GetImageEncoder(magick_info) != (EncodeImageHandler *) NULL)) { /* Call appropriate image writer based on image type. */ thread_support=GetMagickThreadSupport(magick_info); if ((thread_support & EncoderThreadSupport) == 0) LockSemaphoreInfo(constitute_semaphore); status=GetImageEncoder(magick_info)(write_info,image,exception); if ((thread_support & EncoderThreadSupport) == 0) UnlockSemaphoreInfo(constitute_semaphore); } else { delegate_info=GetDelegateInfo((char *) NULL,write_info->magick,exception); if (delegate_info != (DelegateInfo *) NULL) { /* Process the image with delegate. */ *write_info->filename='\0'; if (GetDelegateThreadSupport(delegate_info) == MagickFalse) LockSemaphoreInfo(constitute_semaphore); status=InvokeDelegate(write_info,image,(char *) NULL, write_info->magick,exception); if (GetDelegateThreadSupport(delegate_info) == MagickFalse) UnlockSemaphoreInfo(constitute_semaphore); (void) CopyMagickString(image->filename,filename,MaxTextExtent); } else { sans_exception=AcquireExceptionInfo(); magick_info=GetMagickInfo(write_info->magick,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); if ((write_info->affirm == MagickFalse) && (magick_info == (const MagickInfo *) NULL)) { (void) CopyMagickString(write_info->magick,image->magick, MaxTextExtent); magick_info=GetMagickInfo(write_info->magick,exception); } if ((magick_info == (const MagickInfo *) NULL) || (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL)) { char extension[MaxTextExtent]; GetPathComponent(image->filename,ExtensionPath,extension); if (*extension != '\0') magick_info=GetMagickInfo(extension,exception); else magick_info=GetMagickInfo(image->magick,exception); (void) CopyMagickString(image->filename,filename,MaxTextExtent); } if ((magick_info == (const MagickInfo *) NULL) || (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL)) (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'", image->filename); else { /* Call appropriate image writer based on image type. */ thread_support=GetMagickThreadSupport(magick_info); if ((thread_support & EncoderThreadSupport) == 0) LockSemaphoreInfo(constitute_semaphore); status=GetImageEncoder(magick_info)(write_info,image,exception); if ((thread_support & EncoderThreadSupport) == 0) UnlockSemaphoreInfo(constitute_semaphore); } } } if (GetBlobError(image) != MagickFalse) ThrowFileException(exception,FileOpenError, "AnErrorHasOccurredWritingToFile",image->filename); if (temporary == MagickTrue) { /* Copy temporary image file to permanent. */ status=OpenBlob(write_info,image,ReadBinaryBlobMode,exception); if (status != MagickFalse) status=ImageToFile(image,write_info->filename,exception); (void) CloseBlob(image); (void) RelinquishUniqueFileResource(image->filename); (void) CopyMagickString(image->filename,write_info->filename, MaxTextExtent); } if ((LocaleCompare(write_info->magick,"info") != 0) && (write_info->verbose != MagickFalse)) (void) IdentifyImage(image,stdout,MagickFalse,exception); write_info=DestroyImageInfo(write_info); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadImage() reads an image or image sequence from a file or file handle. % The method returns a NULL if there is a memory shortage or if the image % cannot be read. On failure, a NULL image is returned and exception % describes the reason for the failure. % % The format of the ReadImage method is: % % Image *ReadImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: Read the image defined by the file or filename members of % this structure. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *ReadImage(const ImageInfo *image_info, ExceptionInfo *exception) { char filename[MaxTextExtent], magick[MaxTextExtent], magick_filename[MaxTextExtent]; const char *value; const DelegateInfo *delegate_info; const MagickInfo *magick_info; ExceptionInfo *sans_exception; GeometryInfo geometry_info; Image *image, *next; ImageInfo *read_info; MagickStatusType flags, thread_support; PolicyDomain domain; PolicyRights rights; /* Determine image type from filename prefix or suffix (e.g. image.jpg). */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image_info->filename != (char *) NULL); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); read_info=CloneImageInfo(image_info); (void) CopyMagickString(magick_filename,read_info->filename,MaxTextExtent); (void) SetImageInfo(read_info,0,exception); (void) CopyMagickString(filename,read_info->filename,MaxTextExtent); (void) CopyMagickString(magick,read_info->magick,MaxTextExtent); domain=CoderPolicyDomain; rights=ReadPolicyRights; if (IsRightsAuthorized(domain,rights,read_info->magick) == MagickFalse) { errno=EPERM; (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, "NotAuthorized","`%s'",read_info->filename); return((Image *) NULL); } /* Call appropriate image reader based on image type. */ sans_exception=AcquireExceptionInfo(); magick_info=GetMagickInfo(read_info->magick,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); if (magick_info != (const MagickInfo *) NULL) { if (GetMagickEndianSupport(magick_info) == MagickFalse) read_info->endian=UndefinedEndian; else if ((image_info->endian == UndefinedEndian) && (GetMagickRawSupport(magick_info) != MagickFalse)) { size_t lsb_first; lsb_first=1; read_info->endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian; } } if ((magick_info != (const MagickInfo *) NULL) && (GetMagickSeekableStream(magick_info) != MagickFalse)) { MagickBooleanType status; image=AcquireImage(read_info,exception); (void) CopyMagickString(image->filename,read_info->filename, MaxTextExtent); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { read_info=DestroyImageInfo(read_info); image=DestroyImage(image); return((Image *) NULL); } if (IsBlobSeekable(image) == MagickFalse) { /* Coder requires a seekable stream. */ *read_info->filename='\0'; status=ImageToFile(image,read_info->filename,exception); if (status == MagickFalse) { (void) CloseBlob(image); read_info=DestroyImageInfo(read_info); image=DestroyImage(image); return((Image *) NULL); } read_info->temporary=MagickTrue; } (void) CloseBlob(image); image=DestroyImage(image); } image=NewImageList(); if (constitute_semaphore == (SemaphoreInfo *) NULL) AcquireSemaphoreInfo(&constitute_semaphore); if ((magick_info != (const MagickInfo *) NULL) && (GetImageDecoder(magick_info) != (DecodeImageHandler *) NULL)) { thread_support=GetMagickThreadSupport(magick_info); if ((thread_support & DecoderThreadSupport) == 0) LockSemaphoreInfo(constitute_semaphore); image=GetImageDecoder(magick_info)(read_info,exception); if ((thread_support & DecoderThreadSupport) == 0) UnlockSemaphoreInfo(constitute_semaphore); } else { delegate_info=GetDelegateInfo(read_info->magick,(char *) NULL,exception); if (delegate_info == (const DelegateInfo *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'", read_info->filename); if (read_info->temporary != MagickFalse) (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); return((Image *) NULL); } /* Let our decoding delegate process the image. */ image=AcquireImage(read_info,exception); if (image == (Image *) NULL) { read_info=DestroyImageInfo(read_info); return((Image *) NULL); } (void) CopyMagickString(image->filename,read_info->filename, MaxTextExtent); *read_info->filename='\0'; if (GetDelegateThreadSupport(delegate_info) == MagickFalse) LockSemaphoreInfo(constitute_semaphore); (void) InvokeDelegate(read_info,image,read_info->magick,(char *) NULL, exception); if (GetDelegateThreadSupport(delegate_info) == MagickFalse) UnlockSemaphoreInfo(constitute_semaphore); image=DestroyImageList(image); read_info->temporary=MagickTrue; (void) SetImageInfo(read_info,0,exception); magick_info=GetMagickInfo(read_info->magick,exception); if ((magick_info == (const MagickInfo *) NULL) || (GetImageDecoder(magick_info) == (DecodeImageHandler *) NULL)) { if (IsPathAccessible(read_info->filename) != MagickFalse) (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'", read_info->filename); else ThrowFileException(exception,FileOpenError,"UnableToOpenFile", read_info->filename); read_info=DestroyImageInfo(read_info); return((Image *) NULL); } thread_support=GetMagickThreadSupport(magick_info); if ((thread_support & DecoderThreadSupport) == 0) LockSemaphoreInfo(constitute_semaphore); image=(Image *) (GetImageDecoder(magick_info))(read_info,exception); if ((thread_support & DecoderThreadSupport) == 0) UnlockSemaphoreInfo(constitute_semaphore); } if (read_info->temporary != MagickFalse) { (void) RelinquishUniqueFileResource(read_info->filename); read_info->temporary=MagickFalse; if (image != (Image *) NULL) (void) CopyMagickString(image->filename,filename,MaxTextExtent); } if (image == (Image *) NULL) { read_info=DestroyImageInfo(read_info); return(image); } if (exception->severity >= ErrorException) (void) LogMagickEvent(ExceptionEvent,GetMagickModule(), "Coder (%s) generated an image despite an error (%d), " "notify the developers",image->magick,exception->severity); if (IsBlobTemporary(image) != MagickFalse) (void) RelinquishUniqueFileResource(read_info->filename); if ((GetNextImageInList(image) != (Image *) NULL) && (IsSceneGeometry(read_info->scenes,MagickFalse) != MagickFalse)) { Image *clones; clones=CloneImages(image,read_info->scenes,exception); if (clones == (Image *) NULL) (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "SubimageSpecificationReturnsNoImages","`%s'",read_info->filename); else { image=DestroyImageList(image); image=GetFirstImageInList(clones); } } if (GetBlobError(image) != MagickFalse) { ThrowFileException(exception,FileOpenError, "AnErrorHasOccurredReadingFromFile",read_info->filename); image=DestroyImageList(image); read_info=DestroyImageInfo(read_info); return((Image *) NULL); } for (next=image; next != (Image *) NULL; next=GetNextImageInList(next)) { char magick_path[MaxTextExtent], *property, timestamp[MaxTextExtent]; const char *option; const StringInfo *profile; next->taint=MagickFalse; GetPathComponent(magick_filename,MagickPath,magick_path); if (*magick_path == '\0') (void) CopyMagickString(next->magick,magick,MaxTextExtent); (void) CopyMagickString(next->magick_filename,magick_filename, MaxTextExtent); if (IsBlobTemporary(image) != MagickFalse) (void) CopyMagickString(next->filename,filename,MaxTextExtent); if (next->magick_columns == 0) next->magick_columns=next->columns; if (next->magick_rows == 0) next->magick_rows=next->rows; value=GetImageProperty(next,"tiff:Orientation",exception); if (value == (char *) NULL) value=GetImageProperty(next,"exif:Orientation",exception); if (value != (char *) NULL) { next->orientation=(OrientationType) StringToLong(value); (void) DeleteImageProperty(next,"tiff:Orientation"); (void) DeleteImageProperty(next,"exif:Orientation"); } value=GetImageProperty(next,"exif:XResolution",exception); if (value != (char *) NULL) { geometry_info.rho=next->resolution.x; geometry_info.sigma=1.0; flags=ParseGeometry(value,&geometry_info); if (geometry_info.sigma != 0) next->resolution.x=geometry_info.rho/geometry_info.sigma; (void) DeleteImageProperty(next,"exif:XResolution"); } value=GetImageProperty(next,"exif:YResolution",exception); if (value != (char *) NULL) { geometry_info.rho=next->resolution.y; geometry_info.sigma=1.0; flags=ParseGeometry(value,&geometry_info); if (geometry_info.sigma != 0) next->resolution.y=geometry_info.rho/geometry_info.sigma; (void) DeleteImageProperty(next,"exif:YResolution"); } value=GetImageProperty(next,"tiff:ResolutionUnit",exception); if (value == (char *) NULL) value=GetImageProperty(next,"exif:ResolutionUnit",exception); if (value != (char *) NULL) { next->units=(ResolutionType) (StringToLong(value)-1); (void) DeleteImageProperty(next,"exif:ResolutionUnit"); (void) DeleteImageProperty(next,"tiff:ResolutionUnit"); } if (next->page.width == 0) next->page.width=next->columns; if (next->page.height == 0) next->page.height=next->rows; option=GetImageOption(read_info,"caption"); if (option != (const char *) NULL) { property=InterpretImageProperties(read_info,next,option,exception); (void) SetImageProperty(next,"caption",property,exception); property=DestroyString(property); } option=GetImageOption(read_info,"comment"); if (option != (const char *) NULL) { property=InterpretImageProperties(read_info,next,option,exception); (void) SetImageProperty(next,"comment",property,exception); property=DestroyString(property); } option=GetImageOption(read_info,"label"); if (option != (const char *) NULL) { property=InterpretImageProperties(read_info,next,option,exception); (void) SetImageProperty(next,"label",property,exception); property=DestroyString(property); } if (LocaleCompare(next->magick,"TEXT") == 0) (void) ParseAbsoluteGeometry("0x0+0+0",&next->page); if ((read_info->extract != (char *) NULL) && (read_info->stream == (StreamHandler) NULL)) { RectangleInfo geometry; flags=ParseAbsoluteGeometry(read_info->extract,&geometry); if ((next->columns != geometry.width) || (next->rows != geometry.height)) { if (((flags & XValue) != 0) || ((flags & YValue) != 0)) { Image *crop_image; crop_image=CropImage(next,&geometry,exception); if (crop_image != (Image *) NULL) ReplaceImageInList(&next,crop_image); } else if (((flags & WidthValue) != 0) || ((flags & HeightValue) != 0)) { Image *size_image; flags=ParseRegionGeometry(next,read_info->extract,&geometry, exception); size_image=ResizeImage(next,geometry.width,geometry.height, next->filter,next->blur,exception); if (size_image != (Image *) NULL) ReplaceImageInList(&next,size_image); } } } profile=GetImageProfile(next,"icc"); if (profile == (const StringInfo *) NULL) profile=GetImageProfile(next,"icm"); profile=GetImageProfile(next,"iptc"); if (profile == (const StringInfo *) NULL) profile=GetImageProfile(next,"8bim"); (void) FormatMagickTime(GetBlobProperties(next)->st_mtime,MaxTextExtent, timestamp); (void) SetImageProperty(next,"date:modify",timestamp,exception); (void) FormatMagickTime(GetBlobProperties(next)->st_ctime,MaxTextExtent, timestamp); (void) SetImageProperty(next,"date:create",timestamp,exception); option=GetImageOption(image_info,"delay"); if (option != (const char *) NULL) { GeometryInfo geometry_info; flags=ParseGeometry(option,&geometry_info); if ((flags & GreaterValue) != 0) { if (next->delay > (size_t) floor(geometry_info.rho+0.5)) next->delay=(size_t) floor(geometry_info.rho+0.5); } else if ((flags & LessValue) != 0) { if (next->delay < (size_t) floor(geometry_info.rho+0.5)) next->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5); } else next->delay=(size_t) floor(geometry_info.rho+0.5); if ((flags & SigmaValue) != 0) next->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5); } option=GetImageOption(image_info,"dispose"); if (option != (const char *) NULL) next->dispose=(DisposeType) ParseCommandOption(MagickDisposeOptions, MagickFalse,option); if (read_info->verbose != MagickFalse) (void) IdentifyImage(next,stderr,MagickFalse,exception); image=next; } read_info=DestroyImageInfo(read_info); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G l o b E x p r e s s i o n % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GlobExpression() returns MagickTrue if the expression matches the pattern. % % The format of the GlobExpression function is: % % MagickBooleanType GlobExpression(const char *expression, % const char *pattern,const MagickBooleanType case_insensitive) % % A description of each parameter follows: % % o expression: Specifies a pointer to a text string containing a file name. % % o pattern: Specifies a pointer to a text string containing a pattern. % % o case_insensitive: set to MagickTrue to ignore the case when matching % an expression. % */ MagickExport MagickBooleanType GlobExpression(const char *expression, const char *pattern,const MagickBooleanType case_insensitive) { MagickBooleanType done, match; register const char *p; /* Return on empty pattern or '*'. */ if (pattern == (char *) NULL) return(MagickTrue); if (GetUTFCode(pattern) == 0) return(MagickTrue); if (LocaleCompare(pattern,"*") == 0) return(MagickTrue); p=pattern+strlen(pattern)-1; if ((GetUTFCode(p) == ']') && (strchr(pattern,'[') != (char *) NULL)) { ExceptionInfo *exception; ImageInfo *image_info; /* Determine if pattern is a scene, i.e. img0001.pcd[2]. */ image_info=AcquireImageInfo(); (void) CopyMagickString(image_info->filename,pattern,MaxTextExtent); exception=AcquireExceptionInfo(); (void) SetImageInfo(image_info,MagickTrue,exception); exception=DestroyExceptionInfo(exception); if (LocaleCompare(image_info->filename,pattern) != 0) { image_info=DestroyImageInfo(image_info); return(MagickFalse); } image_info=DestroyImageInfo(image_info); } /* Evaluate glob expression. */ done=MagickFalse; while ((GetUTFCode(pattern) != 0) && (done == MagickFalse)) { if (GetUTFCode(expression) == 0) if ((GetUTFCode(pattern) != '{') && (GetUTFCode(pattern) != '*')) break; switch (GetUTFCode(pattern)) { case '\\': { pattern+=GetUTFOctets(pattern); if (GetUTFCode(pattern) != 0) pattern+=GetUTFOctets(pattern); break; } case '*': { MagickBooleanType status; status=MagickFalse; pattern+=GetUTFOctets(pattern); while ((GetUTFCode(expression) != 0) && (status == MagickFalse)) { status=GlobExpression(expression,pattern,case_insensitive); expression+=GetUTFOctets(expression); } if (status != MagickFalse) { while (GetUTFCode(expression) != 0) expression+=GetUTFOctets(expression); while (GetUTFCode(pattern) != 0) pattern+=GetUTFOctets(pattern); } break; } case '[': { long c; pattern+=GetUTFOctets(pattern); for ( ; ; ) { if ((GetUTFCode(pattern) == 0) || (GetUTFCode(pattern) == ']')) { done=MagickTrue; break; } if (GetUTFCode(pattern) == '\\') { pattern+=GetUTFOctets(pattern); if (GetUTFCode(pattern) == 0) { done=MagickTrue; break; } } if (GetUTFCode(pattern+GetUTFOctets(pattern)) == '-') { c=GetUTFCode(pattern); pattern+=GetUTFOctets(pattern); pattern+=GetUTFOctets(pattern); if (GetUTFCode(pattern) == ']') { done=MagickTrue; break; } if (GetUTFCode(pattern) == '\\') { pattern+=GetUTFOctets(pattern); if (GetUTFCode(pattern) == 0) { done=MagickTrue; break; } } if ((GetUTFCode(expression) < c) || (GetUTFCode(expression) > GetUTFCode(pattern))) { pattern+=GetUTFOctets(pattern); continue; } } else if (GetUTFCode(pattern) != GetUTFCode(expression)) { pattern+=GetUTFOctets(pattern); continue; } pattern+=GetUTFOctets(pattern); while ((GetUTFCode(pattern) != ']') && (GetUTFCode(pattern) != 0)) { if ((GetUTFCode(pattern) == '\\') && (GetUTFCode(pattern+GetUTFOctets(pattern)) > 0)) pattern+=GetUTFOctets(pattern); pattern+=GetUTFOctets(pattern); } if (GetUTFCode(pattern) != 0) { pattern+=GetUTFOctets(pattern); expression+=GetUTFOctets(expression); } break; } break; } case '?': { pattern+=GetUTFOctets(pattern); expression+=GetUTFOctets(expression); break; } case '{': { register const char *p; pattern+=GetUTFOctets(pattern); while ((GetUTFCode(pattern) != '}') && (GetUTFCode(pattern) != 0)) { p=expression; match=MagickTrue; while ((GetUTFCode(p) != 0) && (GetUTFCode(pattern) != 0) && (GetUTFCode(pattern) != ',') && (GetUTFCode(pattern) != '}') && (match != MagickFalse)) { if (GetUTFCode(pattern) == '\\') pattern+=GetUTFOctets(pattern); match=(GetUTFCode(pattern) == GetUTFCode(p)) ? MagickTrue : MagickFalse; p+=GetUTFOctets(p); pattern+=GetUTFOctets(pattern); } if (GetUTFCode(pattern) == 0) { match=MagickFalse; done=MagickTrue; break; } else if (match != MagickFalse) { expression=p; while ((GetUTFCode(pattern) != '}') && (GetUTFCode(pattern) != 0)) { pattern+=GetUTFOctets(pattern); if (GetUTFCode(pattern) == '\\') { pattern+=GetUTFOctets(pattern); if (GetUTFCode(pattern) == '}') pattern+=GetUTFOctets(pattern); } } } else { while ((GetUTFCode(pattern) != '}') && (GetUTFCode(pattern) != ',') && (GetUTFCode(pattern) != 0)) { pattern+=GetUTFOctets(pattern); if (GetUTFCode(pattern) == '\\') { pattern+=GetUTFOctets(pattern); if ((GetUTFCode(pattern) == '}') || (GetUTFCode(pattern) == ',')) pattern+=GetUTFOctets(pattern); } } } if (GetUTFCode(pattern) != 0) pattern+=GetUTFOctets(pattern); } break; } default: { if (case_insensitive != MagickFalse) { if (tolower((int) GetUTFCode(expression)) != tolower((int) GetUTFCode(pattern))) { done=MagickTrue; break; } } else if (GetUTFCode(expression) != GetUTFCode(pattern)) { done=MagickTrue; break; } expression+=GetUTFOctets(expression); pattern+=GetUTFOctets(pattern); } } } while (GetUTFCode(pattern) == '*') pattern+=GetUTFOctets(pattern); match=(GetUTFCode(expression) == 0) && (GetUTFCode(pattern) == 0) ? MagickTrue : MagickFalse; return(match); }
/** * Call QuantizeImages. * * Ruby usage: * - @verbatim ImageList#quantize @endverbatim * - @verbatim ImageList#quantize(number_colors) @endverbatim * - @verbatim ImageList#quantize(number_colors, colorspace) @endverbatim * - @verbatim ImageList#quantize(number_colors, colorspace, dither) @endverbatim * - @verbatim ImageList#quantize(number_colors, colorspace, dither, tree_depth) @endverbatim * - @verbatim ImageList#quantize(number_colors, colorspace, dither, tree_depth, measure_error) @endverbatim * * Notes: * - Default number_colors is 256 * - Default coorspace is Magick::RGBColorsapce * - Default dither is true * - Default tree_depth is 0 * - Default measure_error is false * - Sets \@scene to the same value as self.scene * * @param argc number of input arguments * @param argv array of input arguments * @param self this object * @return a new ImageList with quantized images */ VALUE ImageList_quantize(int argc, VALUE *argv, VALUE self) { Image *images, *new_images; Image *new_image; QuantizeInfo quantize_info; ExceptionInfo *exception; VALUE new_imagelist, scene; GetQuantizeInfo(&quantize_info); switch (argc) { case 5: quantize_info.measure_error = (MagickBooleanType) RTEST(argv[4]); case 4: quantize_info.tree_depth = (unsigned long)NUM2INT(argv[3]); case 3: #if defined(HAVE_TYPE_DITHERMETHOD) && defined(HAVE_ENUM_NODITHERMETHOD) if (rb_obj_is_kind_of(argv[2], Class_DitherMethod)) { VALUE_TO_ENUM(argv[2], quantize_info.dither_method, DitherMethod); quantize_info.dither = quantize_info.dither_method != NoDitherMethod; } #else quantize_info.dither = (MagickBooleanType) RTEST(argv[2]); #endif case 2: VALUE_TO_ENUM(argv[1], quantize_info.colorspace, ColorspaceType); case 1: quantize_info.number_colors = NUM2ULONG(argv[0]); case 0: break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 5)", 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); rm_ensure_result(new_images); (void) QuantizeImages(&quantize_info, new_images); rm_check_exception(exception, new_images, DestroyOnError); (void) DestroyExceptionInfo(exception); // Create new ImageList object, convert mapped image sequence to images, // append to images array. new_imagelist = ImageList_new(); while ((new_image = RemoveFirstImageFromList(&new_images))) { imagelist_push(new_imagelist, rm_image_new(new_image)); } // Set @scene in new ImageList object to same value as in self. scene = rb_iv_get(self, "@scene"); (void) rb_iv_set(new_imagelist, "@scene", scene); RB_GC_GUARD(new_imagelist); RB_GC_GUARD(scene); return new_imagelist; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % M a i n % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % */ int main(int argc,char **argv) { char *option; double elapsed_time, user_time; ExceptionInfo *exception; ImageInfo *image_info; MagickBooleanType regard_warnings, status; register long i; TimerInfo timer; unsigned long iterations; MagickCoreGenesis(*argv,MagickTrue); exception=AcquireExceptionInfo(); iterations=1; status=MagickFalse; regard_warnings=MagickFalse; for (i=1; i < (long) (argc-1); i++) { option=argv[i]; if ((strlen(option) == 1) || ((*option != '-') && (*option != '+'))) continue; if (LocaleCompare("bench",option+1) == 0) iterations=(unsigned long) atol(argv[++i]); if (LocaleCompare("debug",option+1) == 0) (void) SetLogEventMask(argv[++i]); if (LocaleCompare("regard-warnings",option+1) == 0) regard_warnings=MagickTrue; } GetTimerInfo(&timer); for (i=0; i < (long) iterations; i++) { image_info=AcquireImageInfo(); status=ConvertImageCommand(image_info,argc,argv,(char **) NULL,exception); if (exception->severity != UndefinedException) { if ((exception->severity > ErrorException) || (regard_warnings != MagickFalse)) status=MagickTrue; CatchException(exception); } image_info=DestroyImageInfo(image_info); } if (iterations > 1) { elapsed_time=GetElapsedTime(&timer); user_time=GetUserTime(&timer); (void) fprintf(stderr,"Performance: %lui %gips %0.3fu %ld:%02ld\n", iterations,1.0*iterations/elapsed_time,user_time,(long) (elapsed_time/60.0+0.5),(long) ceil(fmod(elapsed_time,60.0))); } exception=DestroyExceptionInfo(exception); MagickCoreTerminus(); return(status == MagickFalse ? 0 : 1); }
// GP: mode = -1 will be automatically guessed from the file SEXP lib_readImages (SEXP files, SEXP mode) { SEXP res; int _mode, i, nappends; Image * image, * images; ImageInfo * image_info; ExceptionInfo exception; const char * file; ImageType it; if ( LENGTH(files) < 1 ) error ( "please supply at least one file name or URL" ); _mode = INTEGER (mode)[0]; if ( _mode < -1 || _mode > MODE_MAX) error ( "requested mode is not supported" ); // Special call for reading Cellomics image if (LENGTH(files)==1) { file = CHAR(STRING_ELT(files, 0)); i = strlen(file); if (i>4 && (strncmp(&file[i-4], ".c01", 4)==0 || strncmp(&file[i-4], ".C01", 4)==0)) { return (readCellomics(file)); } } image_info = (ImageInfo *) NULL; /* images loaded into image and moved into this list */ images = NewImageList (); GetExceptionInfo (&exception); image_info = CloneImageInfo ( (ImageInfo *)NULL ); nappends = 0; for ( i = 0; i < LENGTH (files); i++ ) { if ( LENGTH (files) > 1 ) file = CHAR ( STRING_ELT(files, i) ); else file = CHAR ( asChar(files) ); strcpy (image_info->filename, file); // Prevent an ImageMagick bug when file is an empty string or NULL if (file==NULL) image=NULL; else if (strlen(file)==0) image=NULL; else { image = ReadImage (image_info, &exception); CatchException (&exception); } if ( image == (Image *)NULL ) { warning ("requested image not found or could not be loaded" ); continue; } // Automatic color mode guess if (_mode==-1) { it = GetImageType(image,&exception); // Rprintf("it=%d G=%d P=%d PM=%d\n",it, GrayscaleType, PaletteType, PaletteMatteType); if (it==BilevelType || it==GrayscaleType || it==GrayscaleMatteType) _mode=MODE_GRAYSCALE; else _mode=MODE_COLOR; } /* do not destroy image here */ AppendImageToList (&images, image); if ( nappends == 0 ) { /* set all attributes from the first image */ strcpy (images->filename, image->filename); images->compression = image->compression; images->x_resolution = image->x_resolution; images->y_resolution = image->y_resolution; } nappends++; } /* do not update image properties here because if no image was added to the list it will cause segfault, or use GetImageListLength first to check size */ image_info = DestroyImageInfo (image_info); /* convert image list into R object */ res = PROTECT(magick2SEXP (images, _mode)); images = DestroyImageList (images); DestroyExceptionInfo(&exception); UNPROTECT(1); return res; }
void draw_tiger_map (Widget w, char *filenm, int destination_pixmap, int nocache) { // For future implementation of a "refresh cached map" option char file[MAX_FILENAME]; // Complete path/name of image file char short_filenm[MAX_FILENAME]; FILE *f; // Filehandle of image file char fileimg[MAX_FILENAME]; // Ascii name of image file, read from GEO file char tigertmp[MAX_FILENAME*2]; // Used for putting together the tigermap query int width, height; tiepoint tp[2]; // Calibration points for map, read in from .geo file register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences unsigned long c_x_min, c_y_min;// top left coordinates of map inside screen unsigned long c_y_max; // bottom right coordinates of map inside screen double c_x; // Xastir coordinates 1/100 sec, 0 = 180°W double c_y; // Xastir coordinates 1/100 sec, 0 = 90°N long map_y_0; // map pixel pointer prior to TM adjustment register long map_x, map_y; // map pixel pointers, DNN: this was a float, chg to long long map_x_min, map_x_max; // map boundaries for in screen part of map long map_y_min, map_y_max; // long map_x_ctr; // half map width in pixel long map_y_ctr; // half map height in pixel int map_seen = 0; int map_act; int map_done; long map_c_yc; // map center, vert coordinate long map_c_xc; // map center, hor coordinate double map_c_dx, map_c_dy; // map coordinates increment (pixel width) double c_dx; // adjusted map pixel width long scr_x, scr_y; // screen pixel plot positions long scr_xp, scr_yp; // previous screen plot positions int scr_dx, scr_dy; // increments in screen plot positions long scr_x_mc; // map center in screen units long scr_c_xr; long scale_xa; // adjusted for topo maps double scale_x_nm; // nm per Xastir coordinate unit long scale_x0; // at widest map area char local_filename[MAX_FILENAME]; ExceptionInfo exception; Image *image; ImageInfo *image_info; PixelPacket *pixel_pack; PixelPacket temp_pack; IndexPacket *index_pack; int l; XColor my_colors[256]; double left, right, top, bottom, map_width, map_height; double lat_center = 0; double long_center = 0; char map_it[MAX_FILENAME]; char tmpstr[100]; int geo_image_width; // Image width from GEO file int geo_image_height; // Image height from GEO file // initialize this local_filename[0]='\0'; // Create a shorter filename for display (one that fits the // status line more closely). Subtract the length of the // "Indexing " and/or "Loading " strings as well. if (strlen(filenm) > (41 - 9)) { int avail = 41 - 11; int new_len = strlen(filenm) - avail; xastir_snprintf(short_filenm, sizeof(short_filenm), "..%s", &filenm[new_len]); } else { xastir_snprintf(short_filenm, sizeof(short_filenm), "%s", filenm); } xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA028"), short_filenm); statusline(map_it,0); // Loading ... // Check whether we're indexing or drawing the map if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS) || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) { // We're indexing only. Save the extents in the index. // Force the extents to the edges of the earth for the // index file. index_update_xastir(filenm, // Filename only 64800000l, // Bottom 0l, // Top 0l, // Left 129600000l, // Right 0); // Default Map Level // Update statusline xastir_snprintf(map_it, sizeof(map_it), langcode ("BBARSTA039"), short_filenm); statusline(map_it,0); // Loading/Indexing ... return; // Done indexing this file } // Tiepoint for upper left screen corner // tp[0].img_x = 0; // Pixel Coordinates tp[0].img_y = 0; // Pixel Coordinates tp[0].x_long = NW_corner_longitude; // Xastir Coordinates tp[0].y_lat = NW_corner_latitude; // Xastir Coordinates // Tiepoint for lower right screen corner // tp[1].img_x = screen_width - 1; // Pixel Coordinates tp[1].img_y = screen_height - 1; // Pixel Coordinates tp[1].x_long = SE_corner_longitude; // Xastir Coordinates tp[1].y_lat = SE_corner_latitude; // Xastir Coordinates left = (double)((NW_corner_longitude - 64800000l )/360000.0); // Lat/long Coordinates top = (double)(-((NW_corner_latitude - 32400000l )/360000.0)); // Lat/long Coordinates right = (double)((SE_corner_longitude - 64800000l)/360000.0);//Lat/long Coordinates bottom = (double)(-((SE_corner_latitude - 32400000l)/360000.0));//Lat/long Coordinates map_width = right - left; // Lat/long Coordinates map_height = top - bottom; // Lat/long Coordinates geo_image_width = screen_width; geo_image_height = screen_height; long_center = (left + right)/2.0l; lat_center = (top + bottom)/2.0l; // Example query to the census map server.... /* xastir_snprintf(fileimg, sizeof(fileimg), "\'http://tiger.census.gov/cgi-bin/mapper/map.gif?on=CITIES&on=GRID&on=counties&on=majroads&on=places&&on=interstate&on=states&on=ushwy&on=statehwy&lat=%f\046lon=%f\046wid=%f\046ht=%f\046iwd=%i\046iht=%i\'",\ lat_center, long_center, map_width, map_height, tp[1].img_x + 1, tp[1].img_y + 1); */ xastir_snprintf(tigertmp, sizeof(tigertmp), "http://tiger.census.gov/cgi-bin/mapper/map.gif?"); if (tiger_show_grid) strncat(tigertmp, "&on=GRID", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=GRID", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_counties) strncat(tigertmp, "&on=counties", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=counties", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_cities) strncat(tigertmp, "&on=CITIES", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=CITIES", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_places) strncat(tigertmp, "&on=places", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=places", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_majroads) strncat(tigertmp, "&on=majroads", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=majroads", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_streets) strncat(tigertmp, "&on=streets", sizeof(tigertmp) - 1 - strlen(tigertmp)); // Don't turn streets off since this will automagically show up as you zoom in. if (tiger_show_railroad) strncat(tigertmp, "&on=railroad", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=railroad", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_states) strncat(tigertmp, "&on=states", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=states", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_interstate) strncat(tigertmp, "&on=interstate", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=interstate", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_ushwy) strncat(tigertmp, "&on=ushwy", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=ushwy", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_statehwy) strncat(tigertmp, "&on=statehwy", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=statehwy", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_water) strncat(tigertmp, "&on=water", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=water", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_lakes) strncat(tigertmp, "&on=shorelin", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=shorelin", sizeof(tigertmp) - 1 - strlen(tigertmp)); if (tiger_show_misc) strncat(tigertmp, "&on=miscell", sizeof(tigertmp) - 1 - strlen(tigertmp)); else strncat(tigertmp, "&off=miscell", sizeof(tigertmp) - 1 - strlen(tigertmp)); xastir_snprintf(tmpstr, sizeof(tmpstr), "&lat=%f\046lon=%f\046", lat_center, long_center); strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp)); xastir_snprintf(tmpstr, sizeof(tmpstr), "wid=%f\046ht=%f\046", map_width, map_height); strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp)); xastir_snprintf(tmpstr, sizeof(tmpstr), "iwd=%i\046iht=%i", tp[1].img_x + 1, tp[1].img_y + 1); strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp)); xastir_snprintf(fileimg, sizeof(fileimg), "%s", tigertmp); if (debug_level & 512) { fprintf(stderr,"left side is %f\n", left); fprintf(stderr,"right side is %f\n", right); fprintf(stderr,"top is %f\n", top); fprintf(stderr,"bottom is %f\n", bottom); fprintf(stderr,"lat center is %f\n", lat_center); fprintf(stderr,"long center is %f\n", long_center); fprintf(stderr,"screen width is %li\n", screen_width); fprintf(stderr,"screen height is %li\n", screen_height); fprintf(stderr,"map width is %f\n", map_width); fprintf(stderr,"map height is %f\n", map_height); fprintf(stderr,"fileimg is %s\n", fileimg); fprintf(stderr,"ftp or http file: %s\n", fileimg); } // Hopefully this will eventually allow us to get maps in the background // while (sometimeout !=0 && local_filename[0]==NULL){ if (local_filename[0]=='\0' ){ if (debug_level & 512 ) { fprintf(stderr,"tiger_local_file=<%s>\n",local_filename); } HandlePendingEvents(app_context); if (interrupt_drawing_now) { // Update to screen (void)XCopyArea(XtDisplay(da), pixmap, XtWindow(da), gc, 0, 0, (unsigned int)screen_width, (unsigned int)screen_height, 0, 0); return; } get_tiger_local_file(local_filename,fileimg); } // whackadoodle // Tell ImageMagick where to find it xastir_snprintf(file, sizeof(file), "%s", local_filename); GetExceptionInfo(&exception); image_info=CloneImageInfo((ImageInfo *) NULL); xastir_snprintf(image_info->filename, sizeof(image_info->filename), "%s", file); if (debug_level & 512) { fprintf(stderr,"Copied %s into image info.\n", file); fprintf(stderr,"image_info got: %s\n", image_info->filename); fprintf(stderr,"Entered ImageMagick code.\n"); fprintf(stderr,"Attempting to open: %s\n", image_info->filename); } // We do a test read first to see if the file exists, so we // don't kill Xastir in the ReadImage routine. f = fopen (image_info->filename, "r"); if (f == NULL) { if (debug_level & 512) fprintf(stderr,"File could not be read\n"); #ifdef USE_MAP_CACHE // clear from cache if bad if (map_cache_del(fileimg)) { if (debug_level & 512) { fprintf(stderr,"Couldn't delete unreadable map from cache\n"); } } #endif if (image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); return; } (void)fclose (f); image = ReadImage(image_info, &exception); if (image == (Image *) NULL) { MagickWarning(exception.severity, exception.reason, exception.description); //fprintf(stderr,"MagickWarning\n"); #ifdef USE_MAP_CACHE // clear from cache if bad if (map_cache_del(fileimg)) { if (debug_level & 512) { fprintf(stderr,"Couldn't delete map from cache\n"); } } #endif if (image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); return; } if (debug_level & 512) fprintf(stderr,"Color depth is %i \n", (int)image->depth); if (image->colorspace != RGBColorspace) { fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB"); if (image) DestroyImage(image); if (image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); return; } width = image->columns; height = image->rows; // Code to mute the image so it's not as bright. /* if (raster_map_intensity < 1.0) { char tempstr[30]; if (debug_level & 512) fprintf(stderr,"level=%s\n", tempstr); xastir_snprintf(tempstr, sizeof(tempstr), "%d, 100, 100", (int)(raster_map_intensity * 100.0)); ModulateImage(image, tempstr); } */ // If were are drawing to a low bpp display (typically < 8bpp) // try to reduce the number of colors in an image. // This may take some time, so it would be best to do ahead of // time if it is a static image. #if (MagickLibVersion < 0x0540) if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) { #else // MagickLib >= 540 if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) { #endif // MagickLib Version if (image->storage_class == PseudoClass) { #if (MagickLibVersion < 0x0549) CompressColormap(image); // Remove duplicate colors #else // MagickLib >= 0x0549 CompressImageColormap(image); // Remove duplicate colors #endif // MagickLibVersion < 0x0549 } // Quantize down to 128 will go here... } pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows); if (!pixel_pack) { fprintf(stderr,"pixel_pack == NULL!!!"); if (image) DestroyImage(image); if (image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); return; } index_pack = GetIndexes(image); if (image->storage_class == PseudoClass && !index_pack) { fprintf(stderr,"PseudoClass && index_pack == NULL!!!"); if (image) DestroyImage(image); if (image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); return; } if (image->storage_class == PseudoClass && image->colors <= 256) { for (l = 0; l < (int)image->colors; l++) { // Need to check how to do this for ANY image, as ImageMagick can read in all sorts // of image files temp_pack = image->colormap[l]; if (debug_level & 512) fprintf(stderr,"Colormap color is %i %i %i \n", temp_pack.red, temp_pack.green, temp_pack.blue); // Here's a tricky bit: PixelPacket entries are defined as Quantum's. Quantum // is defined in /usr/include/magick/image.h as either an unsigned short or an // unsigned char, depending on what "configure" decided when ImageMagick was installed. // We can determine which by looking at MaxRGB or QuantumDepth. // if (QuantumDepth == 16) { // Defined in /usr/include/magick/image.h if (debug_level & 512) fprintf(stderr,"Color quantum is [0..65535]\n"); my_colors[l].red = temp_pack.red * raster_map_intensity; my_colors[l].green = temp_pack.green * raster_map_intensity; my_colors[l].blue = temp_pack.blue * raster_map_intensity; } else { // QuantumDepth = 8 if (debug_level & 512) fprintf(stderr,"Color quantum is [0..255]\n"); my_colors[l].red = (temp_pack.red << 8) * raster_map_intensity; my_colors[l].green = (temp_pack.green << 8) * raster_map_intensity; my_colors[l].blue = (temp_pack.blue << 8) * raster_map_intensity; } // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel if (visual_type == NOT_TRUE_NOR_DIRECT) { // XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0); XAllocColor(XtDisplay(w), cmap, &my_colors[l]); } else { pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue, &my_colors[l].pixel); } if (debug_level & 512) fprintf(stderr,"Color allocated is %li %i %i %i \n", my_colors[l].pixel, my_colors[l].red, my_colors[l].blue, my_colors[l].green); } } /* * Here are the corners of our viewport, using the Xastir * coordinate system. Notice that Y is upside down: * * left edge of view = NW_corner_longitude * right edge of view = SE_corner_longitude * top edge of view = NW_corner_latitude * bottom edge of view = SE_corner_latitude * * The corners of our map will soon be (after translating the * tiepoints to the corners if they're not already there): * * left edge of map = tp[0].x_long in Xastir format * right edge of map = tp[1].x_long * top edge of map = tp[0].y_lat * bottom edge of map = tp[1].y_lat * */ map_c_L = tp[0].x_long - NW_corner_longitude; // map left coordinate map_c_T = tp[0].y_lat - NW_corner_latitude; // map top coordinate tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);// Width between tiepoints tp_c_dy = (long)(tp[1].y_lat - tp[0].y_lat); // Height between tiepoints // Check for tiepoints being in wrong relation to one another if (tp_c_dx < 0) tp_c_dx = -tp_c_dx; // New width between tiepoints if (tp_c_dy < 0) tp_c_dy = -tp_c_dy; // New height between tiepoints // Calculate step size per pixel map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x)); map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y)); // Scaled screen step size for use with XFillRectangle below scr_dx = (int) (map_c_dx / scale_x) + 1; scr_dy = (int) (map_c_dy / scale_y) + 1; // calculate top left map corner from tiepoints if (tp[0].img_x != 0) { tp[0].x_long -= (tp[0].img_x * map_c_dx); // map left edge longitude map_c_L = tp[0].x_long - NW_corner_longitude; // delta ?? tp[0].img_x = 0; if (debug_level & 512) fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long); } if (tp[0].img_y != 0) { tp[0].y_lat -= (tp[0].img_y * map_c_dy); // map top edge latitude map_c_T = tp[0].y_lat - NW_corner_latitude; tp[0].img_y = 0; if (debug_level & 512) fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat); } // calculate bottom right map corner from tiepoints // map size is geo_image_width / geo_image_height if (tp[1].img_x != (geo_image_width - 1) ) { tp[1].img_x = geo_image_width - 1; tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right if (debug_level & 512) fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long); } if (tp[1].img_y != (geo_image_height - 1) ) { tp[1].img_y = geo_image_height - 1; tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy); // bottom if (debug_level & 512) fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat); } if (debug_level & 512) { fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx); fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy); fprintf(stderr,"Loading imagemap: %s\n", file); fprintf(stderr,"\nImage: %s\n", file); fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height); fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); fprintf(stderr,"Image size %d %d\n", width, height); #if (MagickLibVersion < 0x0540) fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL)); #else // MagickLib < 540 fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception)); #endif // MagickLib < 540 fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y)); fprintf(stderr,"image matte is %i\n", image->matte); } // debug_level & 512 // draw the image from the file out to the map screen // Get the border values for the X and Y for loops used // for the XFillRectangle call later. map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2; // vert center of map as reference map_y_ctr = (long)(height / 2 +0.499); scale_x0 = get_x_scale(0,map_c_yc,scale_y); // reference scaling at vert map center map_c_xc = (tp[0].x_long + tp[1].x_long) / 2; // hor center of map as reference map_x_ctr = (long)(width / 2 +0.499); scr_x_mc = (map_c_xc - NW_corner_longitude) / scale_x; // screen coordinates of map center // calculate map pixel range in y direction that falls into screen area c_y_max = 0ul; map_y_min = map_y_max = 0l; for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)height; map_y_0++, c_y += map_c_dy) { scr_y = (c_y - NW_corner_latitude) / scale_y; // current screen position if (scr_y > 0) { if (scr_y < screen_height) { map_y_max = map_y_0; // update last map pixel in y c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate } else break; // done, reached bottom screen border } else { // pixel is above screen map_y_min = map_y_0; // update first map pixel in y } } c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy); // top map inside screen coordinate map_x_min = map_x_max = 0l; for (map_x = 0, c_x = tp[0].x_long; map_x < (long)width; map_x++, c_x += map_c_dx) { scr_x = (c_x - NW_corner_longitude)/ scale_x; // current screen position if (scr_x > 0) { if (scr_x < screen_width) map_x_max = map_x; // update last map pixel in x else break; // done, reached right screen border } else { // pixel is left from screen map_x_min = map_x; // update first map pixel in x } } c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx); // left map inside screen coordinate scr_yp = -1; scr_c_xr = SE_corner_longitude; c_dx = map_c_dx; // map pixel width scale_xa = scale_x0; // the compiler likes it ;-) map_done = 0; map_act = 0; map_seen = 0; scr_y = screen_height - 1; // loop over map pixel rows for (map_y_0 = map_y_min, c_y = (double)c_y_min; (map_y_0 <= map_y_max); map_y_0++, c_y += map_c_dy) { HandlePendingEvents(app_context); if (interrupt_drawing_now) { if (image) DestroyImage(image); if (image_info) DestroyImageInfo(image_info); // Update to screen (void)XCopyArea(XtDisplay(da), pixmap, XtWindow(da), gc, 0, 0, (unsigned int)screen_width, (unsigned int)screen_height, 0, 0); DestroyExceptionInfo(&exception); return; } scr_y = (c_y - NW_corner_latitude) / scale_y; if (scr_y != scr_yp) { // don't do a row twice scr_yp = scr_y; // remember as previous y scr_xp = -1; // loop over map pixel columns map_act = 0; scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0; // nm per Xastir coordinate for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) { scr_x = (c_x - NW_corner_longitude) / scale_x; if (scr_x != scr_xp) { // don't do a pixel twice scr_xp = scr_x; // remember as previous x map_y = map_y_0; if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction map_seen = 1; map_act = 1; // detects blank screen rows (end of map) // now copy a pixel from the map image to the screen l = map_x + map_y * image->columns; if (image->storage_class == PseudoClass) { XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel); } else { // It is not safe to assume that the red/green/blue // elements of pixel_pack of type Quantum are the // same as the red/green/blue of an XColor! if (QuantumDepth==16) { my_colors[0].red=pixel_pack[l].red; my_colors[0].green=pixel_pack[l].green; my_colors[0].blue=pixel_pack[l].blue; } else { // QuantumDepth=8 // shift the bits of the 8-bit quantity so that // they become the high bigs of my_colors.* my_colors[0].red=pixel_pack[l].red<<8; my_colors[0].green=pixel_pack[l].green<<8; my_colors[0].blue=pixel_pack[l].blue<<8; } // NOW my_colors has the right r,g,b range for // pack_pixel_bits pack_pixel_bits(my_colors[0].red * raster_map_intensity, my_colors[0].green * raster_map_intensity, my_colors[0].blue * raster_map_intensity, &my_colors[0].pixel); XSetForeground(XtDisplay(w), gc, my_colors[0].pixel); } (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy); } // check map boundaries in y direction } } // loop over map pixel columns if (map_seen && !map_act) map_done = 1; } } // loop over map pixel rows if (image) DestroyImage(image); if (image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); }
MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file, const MagickBooleanType verbose) { char color[MaxTextExtent], format[MaxTextExtent], key[MaxTextExtent]; ChannelFeatures *channel_features; ChannelStatistics *channel_statistics; ColorspaceType colorspace; const char *artifact, *name, *property, *registry, *value; const MagickInfo *magick_info; const PixelPacket *pixels; double elapsed_time, user_time; ExceptionInfo *exception; ImageType type; ssize_t y; MagickBooleanType ping; register ssize_t i, x; size_t distance, scale; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if (file == (FILE *) NULL) file=stdout; *format='\0'; elapsed_time=GetElapsedTime(&image->timer); user_time=GetUserTime(&image->timer); GetTimerInfo(&image->timer); if (verbose == MagickFalse) { /* Display summary info about the image. */ if (*image->magick_filename != '\0') if (LocaleCompare(image->magick_filename,image->filename) != 0) (void) fprintf(file,"%s=>",image->magick_filename); if ((GetPreviousImageInList(image) == (Image *) NULL) && (GetNextImageInList(image) == (Image *) NULL) && (image->scene == 0)) (void) fprintf(file,"%s ",image->filename); else (void) fprintf(file,"%s[%.20g] ",image->filename,(double) image->scene); (void) fprintf(file,"%s ",image->magick); if ((image->magick_columns != 0) || (image->magick_rows != 0)) if ((image->magick_columns != image->columns) || (image->magick_rows != image->rows)) (void) fprintf(file,"%.20gx%.20g=>",(double) image->magick_columns, (double) image->magick_rows); (void) fprintf(file,"%.20gx%.20g ",(double) image->columns,(double) image->rows); if ((image->page.width != 0) || (image->page.height != 0) || (image->page.x != 0) || (image->page.y != 0)) (void) fprintf(file,"%.20gx%.20g%+.20g%+.20g ",(double) image->page.width,(double) image->page.height,(double) image->page.x, (double) image->page.y); (void) fprintf(file,"%.20g-bit ",(double) image->depth); if (image->type != UndefinedType) (void) fprintf(file,"%s ",MagickOptionToMnemonic(MagickTypeOptions, (ssize_t) image->type)); if (image->storage_class == DirectClass) { (void) fprintf(file,"DirectClass "); if (image->total_colors != 0) { (void) FormatMagickSize(image->total_colors,MagickFalse,format); (void) fprintf(file,"%s ",format); } } else if (image->total_colors <= image->colors) (void) fprintf(file,"PseudoClass %.20gc ",(double) image->colors); else (void) fprintf(file,"PseudoClass %.20g=>%.20gc ",(double) image->total_colors,(double) image->colors); if (image->error.mean_error_per_pixel != 0.0) (void) fprintf(file,"%.20g/%f/%fdb ",(double) (image->error.mean_error_per_pixel+0.5), image->error.normalized_mean_error, image->error.normalized_maximum_error); if (GetBlobSize(image) != 0) { (void) FormatMagickSize(GetBlobSize(image),MagickFalse,format); (void) fprintf(file,"%sB ",format); } (void) fprintf(file,"%0.3fu %lu:%02lu.%03lu",user_time,(unsigned long) (elapsed_time/60.0),(unsigned long) floor(fmod(elapsed_time,60.0)), (unsigned long) (1000.0*(elapsed_time-floor(elapsed_time)))); (void) fprintf(file,"\n"); (void) fflush(file); return(ferror(file) != 0 ? MagickFalse : MagickTrue); } /* Display verbose info about the image. */ exception=AcquireExceptionInfo(); pixels=GetVirtualPixels(image,0,0,1,1,exception); exception=DestroyExceptionInfo(exception); ping=pixels == (const PixelPacket *) NULL ? MagickTrue : MagickFalse; type=GetImageType(image,&image->exception); (void) SignatureImage(image); (void) fprintf(file,"Image: %s\n",image->filename); if (*image->magick_filename != '\0') if (LocaleCompare(image->magick_filename,image->filename) != 0) { char filename[MaxTextExtent]; GetPathComponent(image->magick_filename,TailPath,filename); (void) fprintf(file," Base filename: %s\n",filename); } magick_info=GetMagickInfo(image->magick,&image->exception); if ((magick_info == (const MagickInfo *) NULL) || (*GetMagickDescription(magick_info) == '\0')) (void) fprintf(file," Format: %s\n",image->magick); else (void) fprintf(file," Format: %s (%s)\n",image->magick, GetMagickDescription(magick_info)); (void) fprintf(file," Class: %s\n",MagickOptionToMnemonic(MagickClassOptions, (ssize_t) image->storage_class)); (void) fprintf(file," Geometry: %.20gx%.20g%+.20g%+.20g\n",(double) image->columns,(double) image->rows,(double) image->tile_offset.x,(double) image->tile_offset.y); if ((image->magick_columns != 0) || (image->magick_rows != 0)) if ((image->magick_columns != image->columns) || (image->magick_rows != image->rows)) (void) fprintf(file," Base geometry: %.20gx%.20g\n",(double) image->magick_columns,(double) image->magick_rows); if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0)) { (void) fprintf(file," Resolution: %gx%g\n",image->x_resolution, image->y_resolution); (void) fprintf(file," Print size: %gx%g\n",(double) image->columns/ image->x_resolution,(double) image->rows/image->y_resolution); } (void) fprintf(file," Units: %s\n",MagickOptionToMnemonic( MagickResolutionOptions,(ssize_t) image->units)); (void) fprintf(file," Type: %s\n",MagickOptionToMnemonic(MagickTypeOptions, (ssize_t) type)); if (image->type != UndefinedType) (void) fprintf(file," Base type: %s\n",MagickOptionToMnemonic( MagickTypeOptions,(ssize_t) image->type)); (void) fprintf(file," Endianess: %s\n",MagickOptionToMnemonic( MagickEndianOptions,(ssize_t) image->endian)); /* Detail channel depth and extrema. */ (void) fprintf(file," Colorspace: %s\n",MagickOptionToMnemonic( MagickColorspaceOptions,(ssize_t) image->colorspace)); channel_statistics=(ChannelStatistics *) NULL; channel_features=(ChannelFeatures *) NULL; colorspace=image->colorspace; if (ping == MagickFalse) { size_t depth; channel_statistics=GetImageChannelStatistics(image,&image->exception); artifact=GetImageArtifact(image,"identify:features"); if (artifact != (const char *) NULL) { distance=StringToUnsignedLong(artifact); channel_features=GetImageChannelFeatures(image,distance, &image->exception); } depth=GetImageDepth(image,&image->exception); if (image->depth == depth) (void) fprintf(file," Depth: %.20g-bit\n",(double) image->depth); else (void) fprintf(file," Depth: %.20g/%.20g-bit\n",(double) image->depth,(double) depth); (void) fprintf(file," Channel depth:\n"); if (IsGrayImage(image,&image->exception) != MagickFalse) colorspace=GRAYColorspace; switch (colorspace) { case RGBColorspace: default: { (void) fprintf(file," red: %.20g-bit\n",(double) channel_statistics[RedChannel].depth); (void) fprintf(file," green: %.20g-bit\n",(double) channel_statistics[GreenChannel].depth); (void) fprintf(file," blue: %.20g-bit\n",(double) channel_statistics[BlueChannel].depth); break; } case CMYKColorspace: { (void) fprintf(file," cyan: %.20g-bit\n",(double) channel_statistics[CyanChannel].depth); (void) fprintf(file," magenta: %.20g-bit\n",(double) channel_statistics[MagentaChannel].depth); (void) fprintf(file," yellow: %.20g-bit\n",(double) channel_statistics[YellowChannel].depth); (void) fprintf(file," black: %.20g-bit\n",(double) channel_statistics[BlackChannel].depth); break; } case GRAYColorspace: { (void) fprintf(file," gray: %.20g-bit\n",(double) channel_statistics[GrayChannel].depth); break; } } if (image->matte != MagickFalse) (void) fprintf(file," alpha: %.20g-bit\n",(double) channel_statistics[OpacityChannel].depth); scale=1; if (image->depth <= MAGICKCORE_QUANTUM_DEPTH) scale=QuantumRange/((size_t) QuantumRange >> ((size_t) MAGICKCORE_QUANTUM_DEPTH-image->depth)); }
static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception) { #define MaxBufferExtent 8192 char filename[MaxTextExtent]; FILE *file; Image *image; ImageInfo *read_info; int unique_file; image=(Image *) NULL; read_info=CloneImageInfo(image_info); SetImageInfoBlob(read_info,(void *) NULL,0); file=(FILE *) NULL; unique_file=AcquireUniqueFileResource(read_info->filename); if (unique_file != -1) file=fdopen(unique_file,"wb"); if ((unique_file == -1) || (file == (FILE *) NULL)) { ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", read_info->filename); read_info=DestroyImageInfo(read_info); return((Image *) NULL); } (void) CopyMagickString(filename,image_info->magick,MaxTextExtent); (void) ConcatenateMagickString(filename,":",MaxTextExtent); LocaleLower(filename); (void) ConcatenateMagickString(filename,image_info->filename,MaxTextExtent); if (LocaleCompare(read_info->magick,"file") == 0) { (void) RelinquishUniqueFileResource(read_info->filename); unique_file=(-1); (void) CopyMagickString(read_info->filename,image_info->filename+2, MaxTextExtent); } #if defined(MAGICKCORE_WINDOWS_SUPPORT) && \ !(defined(__MINGW32__) || defined(__MINGW64__)) (void) fclose(file); if (URLDownloadToFile(NULL,filename,read_info->filename,0,NULL) != S_OK) { ThrowFileException(exception,FileOpenError,"UnableToOpenFile", filename); (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); return((Image *) NULL); } #else #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED) if (LocaleCompare(read_info->magick,"ftp") == 0) { void *context; xmlNanoFTPInit(); context=xmlNanoFTPNewCtxt(filename); if (context != (void *) NULL) { if (xmlNanoFTPConnect(context) >= 0) (void) xmlNanoFTPGet(context,GetFTPData,(void *) file, (char *) NULL); (void) xmlNanoFTPClose(context); } } #endif #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED) if (LocaleCompare(read_info->magick,"http") == 0) { char buffer[MaxBufferExtent], *type; int bytes; void *context; type=(char *) NULL; context=xmlNanoHTTPMethod(filename,(const char *) NULL, (const char *) NULL,&type,(const char *) NULL,0); if (context != (void *) NULL) { ssize_t count; while ((bytes=xmlNanoHTTPRead(context,buffer,MaxBufferExtent)) > 0) count=(ssize_t) fwrite(buffer,bytes,1,file); (void) count; xmlNanoHTTPClose(context); xmlFree(type); xmlNanoHTTPCleanup(); } } #endif (void) fclose(file); #endif { ExceptionInfo *sans; ImageInfo *clone_info; /* Guess image format from URL. */ clone_info=CloneImageInfo(image_info); sans=AcquireExceptionInfo(); (void) SetImageInfo(clone_info,0,sans); (void) CopyMagickString(read_info->magick,clone_info->magick,MaxTextExtent); clone_info=DestroyImageInfo(clone_info); sans=DestroyExceptionInfo(sans); } image=ReadImage(read_info,exception); if (unique_file != -1) (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); if (image != (Image *) NULL) GetPathComponent(image_info->filename,TailPath,image->filename); else { (void) ThrowMagickException(exception,GetMagickModule(),CoderError, "NoDataReturned","`%s'",filename); return((Image *) NULL); } return(GetFirstImageInList(image)); }
/* * given a source image, a destination filepath and a set of image metadata thresholds, * search for the lowest-quality version of the source image whose properties fall within our * thresholds. * this will produce an image file that looks the same to the casual observer, but which * contains much less information and results in a smaller file. * typical savings on unoptimized images vary widely from 10-80%, with 25-50% being most common. */ MagickWand * search_quality(MagickWand *mw, const char *dst, const struct imgmin_options *opt) { MagickWand *tmp = NULL; char tmpfile[MAX_PATH] = "/tmp/imgminXXXXXX"; if (0 == strcmp("-", dst)) { if (-1 == mkstemp(tmpfile)) { perror("mkstemp"); return CloneMagickWand(mw); } } else { strcpy(tmpfile, dst); } /* * The overwhelming majority of JPEGs are TrueColorType; it is those types, with a low * unique color count, that we must avoid. */ if (!enough_colors(mw, opt)) { fprintf(stdout, " Color count is too low, skipping...\n"); return CloneMagickWand(mw); } if (quality(mw) < opt->quality_in_min) { fprintf(stdout, " Quality < %u, won't second-guess...\n", opt->quality_in_min); return CloneMagickWand(mw); } size_t width = MagickGetImageWidth(mw); size_t height = MagickGetImageHeight(mw); dssim_info *dssim = dssim_init(1); void *convert_data = convert_row_start(mw); dssim_set_original_float_callback(dssim, width, height, convert_row_callback, convert_data); convert_row_finish(convert_data); { ExceptionInfo *exception = AcquireExceptionInfo(); const double original_density = color_density(mw); unsigned qmax = min(quality(mw), opt->quality_out_max); unsigned qmin = opt->quality_out_min; unsigned steps = 0; /* * binary search of quality space for optimally lowest quality that * produces an acceptable level of distortion */ while (qmax > qmin + 1 && steps < opt->max_steps) { double density_ratio; unsigned q; steps++; q = (qmax + qmin) / 2; /* change quality */ tmp = CloneMagickWand(mw); MagickSetImageCompressionQuality(tmp, q); /* apply quality change */ MagickWriteImages(tmp, tmpfile, MagickTrue); DestroyMagickWand(tmp); tmp = NewMagickWand(); MagickReadImage(tmp, tmpfile); void *convert_data = convert_row_start(tmp); dssim_set_modified_float_callback(dssim, width, height, convert_row_callback, convert_data); convert_row_finish(convert_data); double error = 20.0 * dssim_compare(dssim, NULL); // scaled to threshold of previous implementation density_ratio = fabs(color_density(tmp) - original_density) / original_density; /* color density ratio threshold is an alternative quality measure. If it's exceeded, pretend MSE was higher to increase quality */ if (density_ratio > opt->color_density_ratio) { error *= 1.25 + density_ratio; // fudge factor } /* eliminate half search space based on whether distortion within thresholds */ if (error > opt->error_threshold) { qmin = q; } else { qmax = q; } if (opt->show_progress) { fprintf(stdout, "%.2f/%.2f@%u ", error, density_ratio, q); } /* Stop searching if close enough to the target */ if (fabs(error - opt->error_threshold) < opt->error_threshold * ERROR_THRESHOLD_INACCURACY) { qmax = q; break; } } if (opt->show_progress) { putc('\n', stdout); } MagickSetImageCompressionQuality(mw, qmax); /* "Chroma sub-sampling works because human vision is relatively insensitive to * small areas of colour. It gives a significant reduction in file sizes, with * little loss of perceived quality." [3] */ #if MagickLibVersion >= 0x630 /* FIXME: available in 0x660, not available in 0x628, not sure which version it was introduced in */ (void) MagickSetImageProperty(mw, "jpeg:sampling-factor", "2x2"); #endif /* strip an image of all profiles and comments */ (void) MagickStripImage(mw); MagickWriteImages(mw, tmpfile, MagickTrue); (void) DestroyMagickWand(tmp); tmp = NewMagickWand(); MagickReadImage(tmp, tmpfile); exception = DestroyExceptionInfo(exception); } return tmp; }
/** * 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; }
/** * 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); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G l o b E x p r e s s i o n % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GlobExpression() returns MagickTrue if the expression matches the pattern. % % The format of the GlobExpression function is: % % MagickBooleanType GlobExpression(const char *expression, % const char *pattern) % % A description of each parameter follows: % % o expression: Specifies a pointer to a text string containing a file name. % % o pattern: Specifies a pointer to a text string containing a pattern. % % */ MagickExport MagickBooleanType GlobExpression(const char *expression, const char *pattern) { MagickBooleanType done; register const char *p; /* Return on empty pattern or '*'. */ if (pattern == (char *) NULL) return(MagickTrue); if (*pattern == '\0') return(MagickTrue); if (LocaleCompare(pattern,"*") == 0) return(MagickTrue); p=pattern+strlen(pattern)-1; if ((*p == ']') && (strchr(pattern,'[') != (char *) NULL)) { ExceptionInfo exception; ImageInfo *image_info; /* Determine if pattern is a scene, i.e. img0001.pcd[2]. */ image_info=CloneImageInfo((ImageInfo *) NULL); (void) CopyMagickString(image_info->filename,pattern,MaxTextExtent); GetExceptionInfo(&exception); (void) SetImageInfo(image_info,MagickTrue,&exception); DestroyExceptionInfo(&exception); if (LocaleCompare(image_info->filename,pattern) != 0) { image_info=DestroyImageInfo(image_info); return(MagickFalse); } image_info=DestroyImageInfo(image_info); } /* Evaluate glob expression. */ done=MagickFalse; while ((*pattern != '\0') && (done == MagickFalse)) { if (*expression == '\0') if ((*pattern != '{') && (*pattern != '*')) break; switch (*pattern) { case '\\': { pattern++; if (*pattern != '\0') pattern++; break; } case '*': { MagickBooleanType status; pattern++; status=MagickFalse; while ((*expression != '\0') && (status == MagickFalse)) status=GlobExpression(expression++,pattern); if (status != MagickFalse) { while (*expression != '\0') expression++; while (*pattern != '\0') pattern++; } break; } case '[': { char c; pattern++; for ( ; ; ) { if ((*pattern == '\0') || (*pattern == ']')) { done=MagickTrue; break; } if (*pattern == '\\') { pattern++; if (*pattern == '\0') { done=MagickTrue; break; } } if (*(pattern+1) == '-') { c=(*pattern); pattern+=2; if (*pattern == ']') { done=MagickTrue; break; } if (*pattern == '\\') { pattern++; if (*pattern == '\0') { done=MagickTrue; break; } } if ((*expression < c) || (*expression > *pattern)) { pattern++; continue; } } else if (*pattern != *expression) { pattern++; continue; } pattern++; while ((*pattern != ']') && (*pattern != '\0')) { if ((*pattern == '\\') && (*(pattern+1) != '\0')) pattern++; pattern++; } if (*pattern != '\0') { pattern++; expression++; } break; } break; } case '?': { pattern++; expression++; break; } case '{': { MagickBooleanType match; register const char *p; pattern++; while ((*pattern != '}') && (*pattern != '\0')) { p=expression; match=MagickTrue; while ((*p != '\0') && (*pattern != '\0') && (*pattern != ',') && (*pattern != '}') && (match != MagickFalse)) { if (*pattern == '\\') pattern++; match=(MagickBooleanType) (*pattern == *p); p++; pattern++; } if (*pattern == '\0') { match=MagickFalse; done=MagickTrue; break; } else if (match != MagickFalse) { expression=p; while ((*pattern != '}') && (*pattern != '\0')) { pattern++; if (*pattern == '\\') { pattern++; if (*pattern == '}') pattern++; } } } else { while ((*pattern != '}') && (*pattern != ',') && (*pattern != '\0')) { pattern++; if (*pattern == '\\') { pattern++; if ((*pattern == '}') || (*pattern == ',')) pattern++; } } } if (*pattern != '\0') pattern++; } break; } default: { if (*expression != *pattern) done=MagickTrue; else { expression++; pattern++; } } } } while (*pattern == '*') pattern++; return((MagickBooleanType) ((*expression == '\0') && (*pattern == '\0'))); }
Tagimage::~Tagimage() { DestroyImage(image); DestroyExceptionInfo(&exception); }
// load a full-res thumbnail: int dt_imageio_large_thumbnail(const char *filename, uint8_t **buffer, int32_t *width, int32_t *height, dt_colorspaces_color_profile_type_t *color_space) { int res = 1; uint8_t *buf = NULL; char *mime_type = NULL; size_t bufsize; // get the biggest thumb from exif if(dt_exif_get_thumbnail(filename, &buf, &bufsize, &mime_type)) goto error; if(strcmp(mime_type, "image/jpeg") == 0) { // Decompress the JPG into our own memory format dt_imageio_jpeg_t jpg; if(dt_imageio_jpeg_decompress_header(buf, bufsize, &jpg)) goto error; *buffer = (uint8_t *)malloc((size_t)sizeof(uint8_t) * jpg.width * jpg.height * 4); if(!*buffer) goto error; *width = jpg.width; *height = jpg.height; // TODO: check if the embedded thumbs have a color space set! currently we assume that it's always sRGB *color_space = DT_COLORSPACE_SRGB; if(dt_imageio_jpeg_decompress(&jpg, *buffer)) { free(*buffer); *buffer = NULL; goto error; } res = 0; } else { #ifdef HAVE_GRAPHICSMAGICK ExceptionInfo exception; Image *image = NULL; ImageInfo *image_info = NULL; GetExceptionInfo(&exception); image_info = CloneImageInfo((ImageInfo *)NULL); image = BlobToImage(image_info, buf, bufsize, &exception); if(exception.severity != UndefinedException) CatchException(&exception); if(!image) { fprintf(stderr, "[dt_imageio_large_thumbnail GM] thumbnail not found?\n"); goto error_gm; } *width = image->columns; *height = image->rows; *color_space = DT_COLORSPACE_SRGB; // FIXME: this assumes that embedded thumbnails are always srgb *buffer = (uint8_t *)malloc((size_t)sizeof(uint8_t) * image->columns * image->rows * 4); if(!*buffer) goto error_gm; for(uint32_t row = 0; row < image->rows; row++) { uint8_t *bufprt = *buffer + (size_t)4 * row * image->columns; int gm_ret = DispatchImage(image, 0, row, image->columns, 1, "RGBP", CharPixel, bufprt, &exception); if(exception.severity != UndefinedException) CatchException(&exception); if(gm_ret != MagickPass) { fprintf(stderr, "[dt_imageio_large_thumbnail GM] error_gm reading thumbnail\n"); free(*buffer); *buffer = NULL; goto error_gm; } } // fprintf(stderr, "[dt_imageio_large_thumbnail GM] successfully decoded thumbnail\n"); res = 0; error_gm: if(image) DestroyImage(image); if(image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); if(res) goto error; #else fprintf(stderr, "[dt_imageio_large_thumbnail] error: The thumbnail image is not in JPEG format, but DT " "was built without GraphicsMagick. Please rebuild DT with GraphicsMagick support " "enabled.\n"); #endif } if(res) { fprintf( stderr, "[dt_imageio_large_thumbnail] error: Not a supported thumbnail image format or broken thumbnail: %s\n", mime_type); goto error; } error: free(mime_type); free(buf); return res; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteImages() writes an image sequence into one or more files. While % WriteImage() can write an image sequence, it is limited to writing % the sequence into a single file using a format which supports multiple % frames. WriteImages(), however, does not have this limitation, instead it % generates multiple output files if necessary (or when requested). When % ImageInfo's adjoin flag is set to MagickFalse, the file name is expected % to include a printf-style formatting string for the frame number (e.g. % "image%02d.png"). % % The format of the WriteImages method is: % % MagickBooleanType WriteImages(const ImageInfo *image_info,Image *images, % const char *filename,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o images: the image list. % % o filename: the image filename. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType WriteImages(const ImageInfo *image_info, Image *images,const char *filename,ExceptionInfo *exception) { #define WriteImageTag "Write/Image" BlobInfo *blob; ExceptionInfo *sans_exception; ImageInfo *write_info; MagickBooleanType proceed; MagickOffsetType i; MagickProgressMonitor progress_monitor; MagickSizeType number_images; MagickStatusType status; register Image *p; assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(images != (Image *) NULL); assert(images->signature == MagickSignature); if (images->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); assert(exception != (ExceptionInfo *) NULL); write_info=CloneImageInfo(image_info); images=GetFirstImageInList(images); blob=CloneBlobInfo(images->blob); /* thread specific I/O handler */ DestroyBlob(images); images->blob=blob; if (filename != (const char *) NULL) for (p=images; p != (Image *) NULL; p=GetNextImageInList(p)) (void) CopyMagickString(p->filename,filename,MaxTextExtent); (void) CopyMagickString(write_info->filename,images->filename,MaxTextExtent); if (*write_info->magick == '\0') (void) CopyMagickString(write_info->magick,images->magick,MaxTextExtent); sans_exception=AcquireExceptionInfo(); (void) SetImageInfo(write_info,(unsigned int) GetImageListLength(images), sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); p=images; for ( ; GetNextImageInList(p) != (Image *) NULL; p=GetNextImageInList(p)) if (p->scene >= GetNextImageInList(p)->scene) { register ssize_t i; /* Generate consistent scene numbers. */ i=(ssize_t) images->scene; for (p=images; p != (Image *) NULL; p=GetNextImageInList(p)) p->scene=(size_t) i++; break; } /* Write images. */ status=MagickTrue; progress_monitor=(MagickProgressMonitor) NULL; i=0; number_images=GetImageListLength(images); for (p=images; p != (Image *) NULL; p=GetNextImageInList(p)) { if (number_images != 1) progress_monitor=SetImageProgressMonitor(p,(MagickProgressMonitor) NULL, p->client_data); status&=WriteImage(write_info,p,exception); if (number_images != 1) (void) SetImageProgressMonitor(p,progress_monitor,p->client_data); if (write_info->adjoin != MagickFalse) break; if (number_images != 1) { proceed=SetImageProgress(p,WriteImageTag,i++,number_images); if (proceed == MagickFalse) break; } } write_info=DestroyImageInfo(write_info); return(status != 0 ? MagickTrue : MagickFalse); }
std::string imageproc::ChangeImage(const std::string & inPath, const std::string & tmpDir, Type outputFormat, const bp::List & transformations, int quality, unsigned int & x, unsigned int & y, unsigned int & orig_x, unsigned int & orig_y, std::string & oError) { ExceptionInfo exception; Image *images; ImageInfo *image_info; orig_x = orig_y = x = y = 0; GetExceptionInfo(&exception); image_info = CloneImageInfo((ImageInfo *) NULL); // first we read the image if (exception.severity != UndefinedException) { if (exception.reason) g_bpCoreFunctions->log(BP_ERROR, "after: %s\n", exception.reason); if (exception.description) g_bpCoreFunctions->log(BP_ERROR, "after: %s\n", exception.description); CatchException(&exception); } (void) strcpy(image_info->filename, inPath.c_str()); images = IP_ReadImageFile(image_info, inPath, &exception); if (exception.severity != UndefinedException) { if (exception.reason) g_bpCoreFunctions->log(BP_ERROR, "after: %s\n", exception.reason); if (exception.description) g_bpCoreFunctions->log(BP_ERROR, "after: %s\n", exception.description); CatchException(&exception); } if (!images) { oError.append("couldn't read image"); DestroyImageInfo(image_info); image_info = NULL; DestroyExceptionInfo(&exception); return std::string(); } g_bpCoreFunctions->log( BP_INFO, "Image contains %lu frames, type: %s\n", GetImageListLength(images), images->magick); // set quality if (quality > 100) quality = 100; if (quality < 0) quality = 0; image_info->quality = quality; g_bpCoreFunctions->log( BP_INFO, "Quality set to %d (0-100, worst-best)", quality); // execute 'actions' images = runTransformations(images, transformations, quality, oError); // was all that successful? if (!images) { DestroyImageInfo(image_info); image_info = NULL; DestroyExceptionInfo(&exception); return std::string(); } // set the output size orig_x = images->magick_columns; orig_y = images->magick_rows; x = images->columns; y = images->rows; // let's set the output format correctly (default to input format) std::string name; if (outputFormat == UNKNOWN) name.append(ft::basename(inPath)); else { name.append("img."); name.append(typeToExt(outputFormat)); (void) sprintf(images->magick, outputFormat); g_bpCoreFunctions->log(BP_INFO, "Output to format: %s", outputFormat); } // Now let's go directly from blob to file. We bypass // GM to-file functions so that we can handle wide filenames // safely on win32 systems. A superior solution would // be to use GM stream facilities (if they exist) // upon success, will hold path to output file and will be returned to // client std::string rv; { size_t l = 0; void * blob = NULL; blob = ImageToBlob( image_info, images, &l, &exception ); if (exception.severity != UndefinedException) { oError.append("ImageToBlob failed."); CatchException(&exception); } else { g_bpCoreFunctions->log(BP_INFO, "Writing %lu bytes to %s", l, name.c_str()); if (!ft::mkdir(tmpDir, false)) { oError.append("Couldn't create temp dir"); } else { std::string outpath = ft::getPath(tmpDir, name); FILE * f = ft::fopen_binary_write(outpath); if (f == NULL) { g_bpCoreFunctions->log( BP_ERROR, "Couldn't open '%s' for writing!", outpath.c_str()); oError.append("Error saving output image"); } else { size_t wt; wt = fwrite(blob, sizeof(char), l, f); fclose(f); if (wt != l) { g_bpCoreFunctions->log( BP_ERROR, "Partial write (%lu/%lu) when writing resultant " "image '%s'", wt, l, outpath.c_str()); oError.append("Error saving output image"); } else { // success! rv = outpath; } } } } } DestroyImage(images); DestroyImageInfo(image_info); image_info = NULL; DestroyExceptionInfo(&exception); return rv; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadImages() reads one or more images and returns them as an image list. % % The format of the ReadImage method is: % % Image *ReadImages(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *ReadImages(const ImageInfo *image_info, ExceptionInfo *exception) { char filename[MaxTextExtent]; Image *image, *images; ImageInfo *read_info; /* Read image list from a file. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); (void) InterpretImageFilename(image_info,(Image *) NULL,image_info->filename, (int) image_info->scene,filename,exception); if (LocaleCompare(filename,image_info->filename) != 0) { ExceptionInfo *sans; ssize_t extent, scene; /* Images of the form image-%d.png[1-5]. */ read_info=CloneImageInfo(image_info); sans=AcquireExceptionInfo(); (void) SetImageInfo(read_info,0,sans); sans=DestroyExceptionInfo(sans); if (read_info->number_scenes == 0) { read_info=DestroyImageInfo(read_info); return(ReadImage(image_info,exception)); } (void) CopyMagickString(filename,read_info->filename,MaxTextExtent); images=NewImageList(); extent=(ssize_t) (read_info->scene+read_info->number_scenes); for (scene=(ssize_t) read_info->scene; scene < (ssize_t) extent; scene++) { (void) InterpretImageFilename(image_info,(Image *) NULL,filename,(int) scene,read_info->filename,exception); image=ReadImage(read_info,exception); if (image == (Image *) NULL) continue; AppendImageToList(&images,image); } read_info=DestroyImageInfo(read_info); return(images); } return(ReadImage(image_info,exception)); }
/*---------------------------------------------------------- * int_imread: * interface for imread function. * should provide [RGB]=imread(name) * [Index,Map]=imread(name) at Scilab level * * TO-DO * - return on errors, even if exeption is NULL * * $Revision: 1.2 $ $Date: 2009-03-29 21:34:48 $ *----------------------------------------------------------*/ SipExport int int_imread(char *fname) { /* Interface variables */ HyperMat *Img; int m1, n1,l1, /* for name input argument */ m2, n2, /* for index output argument */ minlhs=1, maxlhs=2, minrhs=1, maxrhs=1, i; double *l2; /* Other variables */ unsigned long imgsize; /* ImageMagick variables */ ExceptionInfo exception; Image *image; ImageInfo *image_info; PixelPacket *pix; ImageType imgtype; bool stat; CheckRhs(minrhs,maxrhs) ; CheckLhs(minlhs,maxlhs) ; /* Get name (#1) */ GetRhsVar(1, "c", &m1, &n1, &l1); /* Initialize the image info structure and read an image. */ InitializeMagick(NULL); GetExceptionInfo(&exception); image_info=CloneImageInfo((ImageInfo *) NULL); (void) strncpy(image_info->filename,cstk(l1),MaxTextExtent); image=ReadImage(image_info,&exception); if (image == (Image *) NULL) { /* clean up */ if(exception.reason != NULL) { char errmsg[50]; for (i=0; i<49; i++) errmsg[i]=' '; errmsg[49]='\0'; strncpy(errmsg,SipGetLocaleExceptionMessage(exception.severity,exception.reason),50); DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); DestroyMagick(); sip_error(errmsg); } DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); DestroyMagick(); sip_error("unknown reason"); } m2 = image->rows; n2 = image->columns; if (sip_verbose == SIP_WORDY) sciprint("Size:\t%ld rows X %ld columns\n\r", m2, n2); imgsize = m2 * n2; pix=GetImagePixels(image, 0, 0, n2, m2); if(pix == (PixelPacket *) NULL) SIP_MAGICK_ERROR; switch(image->storage_class) { case DirectClass: { imgtype = GetImageType(image, &exception); if(imgtype == BilevelType) { stat = magick_binary_image_to_double_array(fname,pix,&l2, m2, n2); if (!stat) return false; CreateVarFromPtr(2, "d",&m2,&n2,&l2); free(l2); } else { stat= magick_truecolor_image_to_double_hypermat(fname,pix,&Img,m2,n2); if (!stat) return false; CreateHMat(2,Img); free_sci_tru_img(&Img); } m1 = n1 = 0; CreateVar(3,"d",&m1,&n1,&l1); break; } case PseudoClass: { stat= magick_index_map_to_sci_dbl(fname,image,2); if (!stat) return false; break; } default: sip_error("unknown color class"); break; } LhsVar(1) = 2; LhsVar(2) = 3; /* Terminate Imagemagick */ DestroyImageInfo(image_info); DestroyImage(image); DestroyExceptionInfo(&exception); DestroyMagick(); return true; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d D N G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadDNGImage() reads an binary file in the Digital Negative format and % returns it. It allocates the memory necessary for the new Image structure % and returns a pointer to the new image. % % The format of the ReadDNGImage method is: % % Image *ReadDNGImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception) { ExceptionInfo *sans_exception; Image *image; ImageInfo *read_info; MagickBooleanType status; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } (void) CloseBlob(image); (void) DestroyImageList(image); /* Convert DNG to PPM with delegate. */ image=AcquireImage(image_info); read_info=CloneImageInfo(image_info); (void) InvokeDelegate(read_info,image,"dng:decode",(char *) NULL,exception); image=DestroyImage(image); (void) FormatMagickString(read_info->filename,MaxTextExtent,"%s.png", read_info->unique); sans_exception=AcquireExceptionInfo(); image=ReadImage(read_info,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); if (image == (Image *) NULL) { (void) FormatMagickString(read_info->filename,MaxTextExtent,"%s.ppm", read_info->unique); image=ReadImage(read_info,exception); } (void) RelinquishUniqueFileResource(read_info->filename); if (image != (Image *) NULL) { char filename[MaxTextExtent], *xml; ExceptionInfo *sans; (void) CopyMagickString(image->magick,read_info->magick,MaxTextExtent); (void) FormatMagickString(filename,MaxTextExtent,"%s.ufraw", read_info->unique); sans=AcquireExceptionInfo(); xml=FileToString(filename,MaxTextExtent,sans); (void) RelinquishUniqueFileResource(filename); if (xml != (char *) NULL) { XMLTreeInfo *ufraw; /* Inject */ ufraw=NewXMLTree(xml,sans); if (ufraw != (XMLTreeInfo *) NULL) { char *content, property[MaxTextExtent]; const char *tag; XMLTreeInfo *next; if (image->properties == (void *) NULL) ((Image *) image)->properties=NewSplayTree( CompareSplayTreeString,RelinquishMagickMemory, RelinquishMagickMemory); next=GetXMLTreeChild(ufraw,(const char *) NULL); while (next != (XMLTreeInfo *) NULL) { tag=GetXMLTreeTag(next); if (tag == (char *) NULL) tag="unknown"; (void) FormatMagickString(property,MaxTextExtent,"dng:%s",tag); content=ConstantString(GetXMLTreeContent(next)); StripString(content); if ((LocaleCompare(tag,"log") != 0) && (LocaleCompare(tag,"InputFilename") != 0) && (LocaleCompare(tag,"OutputFilename") != 0) && (LocaleCompare(tag,"OutputType") != 0) && (strlen(content) != 0)) (void) AddValueToSplayTree((SplayTreeInfo *) ((Image *) image)->properties,ConstantString(property), content); next=GetXMLTreeSibling(next); } ufraw=DestroyXMLTree(ufraw); } xml=DestroyString(xml); } sans=DestroyExceptionInfo(sans); } read_info=DestroyImageInfo(read_info); return(image); }
dt_imageio_retval_t dt_imageio_open_gm( dt_image_t *img, const char *filename, dt_mipmap_cache_allocator_t a) { int err = DT_IMAGEIO_FILE_CORRUPTED; float *buf = NULL; ExceptionInfo exception; Image *image = NULL; ImageInfo *image_info = NULL; uint32_t width, height, orientation; if(!_supported_image(filename)) return DT_IMAGEIO_FILE_CORRUPTED; if(!img->exif_inited) (void) dt_exif_read(img, filename); GetExceptionInfo(&exception); image_info=CloneImageInfo((ImageInfo *) NULL); g_strlcpy(image_info->filename,filename,sizeof(image_info->filename)); image=ReadImage(image_info,&exception); if (exception.severity != UndefinedException) CatchException(&exception); if (!image) { fprintf(stderr, "[GraphicsMagick_open] image `%s' not found\n", img->filename); err = DT_IMAGEIO_FILE_NOT_FOUND; goto error; } width = image->columns; height = image->rows; orientation = image->orientation; if(orientation & 4) { img->width = height; img->height = width; } else { img->width = width; img->height = height; } img->bpp = 4*sizeof(float); float *mipbuf = (float *)dt_mipmap_cache_alloc(img, DT_MIPMAP_FULL, a); if(!mipbuf) { fprintf(stderr, "[GraphicsMagick_open] could not alloc full buffer for image `%s'\n", img->filename); err = DT_IMAGEIO_CACHE_FULL; goto error; } buf = (float *)dt_alloc_align(16, width*img->bpp); if(!buf) goto error; const int ht2 = orientation & 4 ? img->width : img->height; // pretend unrotated, rotate in write_pos const int wd2 = orientation & 4 ? img->height : img->width; for (uint32_t row = 0; row < height; row++) { int ret = DispatchImage(image, 0, row, width, 1, "RGBP", FloatPixel, (void *)buf, &exception); if (exception.severity != UndefinedException) CatchException(&exception); if(ret != MagickPass) { fprintf(stderr, "[GraphicsMagick_open] error reading image `%s'\n", img->filename); err = DT_IMAGEIO_FILE_CORRUPTED; goto error; } for(uint32_t i=0; i<width; i++) for(int k=0; k<4; k++) mipbuf[4*dt_imageio_write_pos(i, row, wd2, ht2, wd2, ht2, orientation) + k] = buf[4*i + k]; } if(buf) dt_free_align(buf); if(image) DestroyImage(image); if(image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); img->filters = 0; img->flags &= ~DT_IMAGE_RAW; img->flags &= ~DT_IMAGE_HDR; img->flags |= DT_IMAGE_LDR; return DT_IMAGEIO_OK; error: if(buf) dt_free_align(buf); if(image) DestroyImage(image); if(image_info) DestroyImageInfo(image_info); DestroyExceptionInfo(&exception); return err; }
static MagickBooleanType LoadTypeList(const char *xml,const char *filename, const size_t depth,ExceptionInfo *exception) { char font_path[MaxTextExtent], keyword[MaxTextExtent], *token; const char *q; MagickBooleanType status; TypeInfo *type_info; /* Load the type map file. */ (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), "Loading type configure file \"%s\" ...",filename); if (xml == (const char *) NULL) return(MagickFalse); if (type_list == (SplayTreeInfo *) NULL) { type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL, DestroyTypeNode); if (type_list == (SplayTreeInfo *) NULL) { ThrowFileException(exception,ResourceLimitError, "MemoryAllocationFailed",filename); return(MagickFalse); } } status=MagickTrue; type_info=(TypeInfo *) NULL; token=AcquireString(xml); #if defined(MAGICKCORE_WINDOWS_SUPPORT) /* Determine the Ghostscript font path. */ *font_path='\0'; if (NTGhostscriptFonts(font_path,MaxTextExtent-2)) (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent); #endif for (q=(char *) xml; *q != '\0'; ) { /* Interpret XML. */ GetMagickToken(q,&q,token); if (*token == '\0') break; (void) CopyMagickString(keyword,token,MaxTextExtent); if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0) { /* Doctype element. */ while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0')) GetMagickToken(q,&q,token); continue; } if (LocaleNCompare(keyword,"<!--",4) == 0) { /* Comment element. */ while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0')) GetMagickToken(q,&q,token); continue; } if (LocaleCompare(keyword,"<include") == 0) { /* Include element. */ while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0')) { (void) CopyMagickString(keyword,token,MaxTextExtent); GetMagickToken(q,&q,token); if (*token != '=') continue; GetMagickToken(q,&q,token); if (LocaleCompare(keyword,"file") == 0) { if (depth > 200) (void) ThrowMagickException(exception,GetMagickModule(), ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token); else { char path[MaxTextExtent], *xml; ExceptionInfo *sans_exception; *path='\0'; GetPathComponent(filename,HeadPath,path); if (*path != '\0') (void) ConcatenateMagickString(path,DirectorySeparator, MaxTextExtent); if (*token == *DirectorySeparator) (void) CopyMagickString(path,token,MaxTextExtent); else (void) ConcatenateMagickString(path,token,MaxTextExtent); sans_exception=AcquireExceptionInfo(); xml=FileToString(path,~0UL,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); if (xml != (char *) NULL) { status=LoadTypeList(xml,path,depth+1,exception); xml=(char *) RelinquishMagickMemory(xml); } } } } continue; } if (LocaleCompare(keyword,"<type") == 0) { /* Type element. */ type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info)); if (type_info == (TypeInfo *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); (void) ResetMagickMemory(type_info,0,sizeof(*type_info)); type_info->path=ConstantString(filename); type_info->signature=MagickSignature; continue; } if (type_info == (TypeInfo *) NULL) continue; if (LocaleCompare(keyword,"/>") == 0) { status=AddValueToSplayTree(type_list,type_info->name,type_info); if (status == MagickFalse) (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name); type_info=(TypeInfo *) NULL; } GetMagickToken(q,(const char **) NULL,token); if (*token != '=') continue; GetMagickToken(q,&q,token); GetMagickToken(q,&q,token); switch (*keyword) { case 'E': case 'e': { if (LocaleCompare((char *) keyword,"encoding") == 0) { type_info->encoding=ConstantString(token); break; } break; } case 'F': case 'f': { if (LocaleCompare((char *) keyword,"face") == 0) { type_info->face=StringToUnsignedLong(token); break; } if (LocaleCompare((char *) keyword,"family") == 0) { type_info->family=ConstantString(token); break; } if (LocaleCompare((char *) keyword,"format") == 0) { type_info->format=ConstantString(token); break; } if (LocaleCompare((char *) keyword,"foundry") == 0) { type_info->foundry=ConstantString(token); break; } if (LocaleCompare((char *) keyword,"fullname") == 0) { type_info->description=ConstantString(token); break; } break; } case 'G': case 'g': { if (LocaleCompare((char *) keyword,"glyphs") == 0) { char *path; path=ConstantString(token); #if defined(MAGICKCORE_WINDOWS_SUPPORT) if (strchr(path,'@') != (char *) NULL) SubstituteString(&path,"@ghostscript_font_path@",font_path); #endif if (IsPathAccessible(path) == MagickFalse) { /* Relative path. */ path=DestroyString(path); GetPathComponent(filename,HeadPath,font_path); (void) ConcatenateMagickString(font_path,DirectorySeparator, MaxTextExtent); (void) ConcatenateMagickString(font_path,token,MaxTextExtent); path=ConstantString(font_path); if (IsPathAccessible(path) == MagickFalse) { path=DestroyString(path); path=ConstantString(token); } } type_info->glyphs=path; break; } break; } case 'M': case 'm': { if (LocaleCompare((char *) keyword,"metrics") == 0) { char *path; path=ConstantString(token); #if defined(MAGICKCORE_WINDOWS_SUPPORT) if (strchr(path,'@') != (char *) NULL) SubstituteString(&path,"@ghostscript_font_path@",font_path); #endif if (IsPathAccessible(path) == MagickFalse) { /* Relative path. */ path=DestroyString(path); GetPathComponent(filename,HeadPath,font_path); (void) ConcatenateMagickString(font_path,DirectorySeparator, MaxTextExtent); (void) ConcatenateMagickString(font_path,token,MaxTextExtent); path=ConstantString(font_path); } type_info->metrics=path; break; } break; } case 'N': case 'n': { if (LocaleCompare((char *) keyword,"name") == 0) { type_info->name=ConstantString(token); break; } break; } case 'S': case 's': { if (LocaleCompare((char *) keyword,"stealth") == 0) { type_info->stealth=IsStringTrue(token); break; } if (LocaleCompare((char *) keyword,"stretch") == 0) { type_info->stretch=(StretchType) ParseCommandOption( MagickStretchOptions,MagickFalse,token); break; } if (LocaleCompare((char *) keyword,"style") == 0) { type_info->style=(StyleType) ParseCommandOption(MagickStyleOptions, MagickFalse,token); break; } break; } case 'W': case 'w': { if (LocaleCompare((char *) keyword,"weight") == 0) { type_info->weight=StringToUnsignedLong(token); if (LocaleCompare(token,"bold") == 0) type_info->weight=700; if (LocaleCompare(token,"normal") == 0) type_info->weight=400; break; } break; } default: break; } } token=(char *) RelinquishMagickMemory(token); return(status); }
MagickExport MagickBooleanType GetPathTemplate(char *path) { char *directory, *value; ExceptionInfo *exception; MagickBooleanType status; struct stat attributes; (void) FormatLocaleString(path,MagickPathExtent,"magick-%.20gXXXXXXXXXXXX", (double) getpid()); exception=AcquireExceptionInfo(); directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path", exception); exception=DestroyExceptionInfo(exception); if (directory == (char *) NULL) directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH"); if (directory == (char *) NULL) directory=GetEnvironmentValue("MAGICK_TMPDIR"); if (directory == (char *) NULL) directory=GetEnvironmentValue("TMPDIR"); #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__) if (directory == (char *) NULL) directory=GetEnvironmentValue("TMP"); if (directory == (char *) NULL) directory=GetEnvironmentValue("TEMP"); #endif #if defined(__VMS) if (directory == (char *) NULL) directory=GetEnvironmentValue("MTMPDIR"); #endif #if defined(P_tmpdir) if (directory == (char *) NULL) directory=ConstantString(P_tmpdir); #endif if (directory == (char *) NULL) return(MagickTrue); value=GetPolicyValue("temporary-path"); if (value != (char *) NULL) (void) CloneString(&directory,value); if (strlen(directory) > (MagickPathExtent-25)) { directory=DestroyString(directory); return(MagickFalse); } status=GetPathAttributes(directory,&attributes); if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode)) { directory=DestroyString(directory); return(MagickFalse); } if (directory[strlen(directory)-1] == *DirectorySeparator) (void) FormatLocaleString(path,MagickPathExtent, "%smagick-%.20gXXXXXXXXXXXX",directory,(double) getpid()); else (void) FormatLocaleString(path,MagickPathExtent, "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,(double) getpid()); directory=DestroyString(directory); #if defined(MAGICKCORE_WINDOWS_SUPPORT) { register char *p; /* Ghostscript does not like backslashes so we need to replace them. The forward slash also works under Windows. */ for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++) if (*p == *DirectorySeparator) *p='/'; } #endif return(MagickTrue); }
static MagickBooleanType GetPathTemplate(char *path) { char *directory; ExceptionInfo *exception; MagickBooleanType status; register char *p; struct stat attributes; (void) CopyMagickString(path,"magick-XXXXXXXX",MaxTextExtent); exception=AcquireExceptionInfo(); directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path", exception); exception=DestroyExceptionInfo(exception); if (directory == (char *) NULL) directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH"); if (directory == (char *) NULL) directory=GetEnvironmentValue("MAGICK_TMPDIR"); if (directory == (char *) NULL) directory=GetPolicyValue("temporary-path"); if (directory == (char *) NULL) directory=GetEnvironmentValue("TMPDIR"); #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) if (directory == (char *) NULL) directory=GetEnvironmentValue("TMP"); if (directory == (char *) NULL) directory=GetEnvironmentValue("TEMP"); #endif #if defined(__VMS) if (directory == (char *) NULL) directory=GetEnvironmentValue("MTMPDIR"); #endif #if defined(P_tmpdir) if (directory == (char *) NULL) directory=ConstantString(P_tmpdir); #endif if (directory == (char *) NULL) return(MagickTrue); if (strlen(directory) > (MaxTextExtent-15)) { directory=DestroyString(directory); return(MagickTrue); } status=GetPathAttributes(directory,&attributes); if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode)) { directory=DestroyString(directory); return(MagickTrue); } if (directory[strlen(directory)-1] == *DirectorySeparator) (void) FormatLocaleString(path,MaxTextExtent,"%smagick-XXXXXXXX",directory); else (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-XXXXXXXX", directory,DirectorySeparator); directory=DestroyString(directory); if (*DirectorySeparator != '/') for (p=path; *p != '\0'; p++) if (*p == *DirectorySeparator) *p='/'; return(MagickTrue); }
/** * Return the imagelist as a blob (a String). * * Ruby usage: * - @verbatim ImageList#to_blob @endverbatim * * Notes: * - Runs an info parm block if present - the user can specify the image * format and depth * * @param self this object * @return the blob */ VALUE ImageList_to_blob(VALUE self) { Image *images, *image; Info *info; VALUE info_obj; 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); exception = AcquireExceptionInfo(); (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); } } for (image = images; image; image = GetNextImageInList(image)) { rm_sync_image_options(image, info); } // 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 (blob && exception->severity >= ErrorException) { magick_free((void*)blob); blob = NULL; length = 0; } 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); RB_GC_GUARD(info_obj); RB_GC_GUARD(blob_str); return blob_str; }