iPhone ImageMagick 库 - 使用 MagickWand API 将批处理文件脚本转换为 Objective-C

发布于 2024-12-05 14:08:45 字数 3340 浏览 0 评论 0原文

我决定使用以下 ImageMagick 库进行 iPhone 开发:

https://github.com/marforic/imagemagick_lib_iphone

效果很好。示例项目编译得很好,但没有任何意义。

通常,我会使用 ImageMagick for Windows 附带的“convert.exe”通过命令行转换图像。因此,我将编写一个如下所示的小批处理文件:

@echo off

set SOURCE=image_to_convert.jpg

del result.jpg
del source_copy.jpg

convert.exe %SOURCE% -fill "#fff8f2" -colorize 100%% fill.jpg

copy %SOURCE% source_copy.jpg

convert.exe %SOURCE% -modulate 100,0,100 -|^
convert.exe - source_copy.jpg -compose overlay -composite -|^
convert.exe source_copy.jpg - -compose dissolve -define compose:args=37,100 -composite -|^
convert.exe - -modulate 100,70,100 +level 3.5%%,100%% -|^
convert.exe - -channel red -level 0%%,89%% +level 9%%,100%% -|^
convert.exe - -channel green +level 3.5%%,100%% -|^
convert.exe - -channel blue -level 0%%,93%% +level 4.7%%,100%% -|^
convert.exe - -brightness-contrast -5x3 -|^
convert.exe fill.jpg - -compose multiply -gravity center -composite -|^
convert.exe - -level 3.5%%,100%%,0.91 +level 2.7%%,100%% -|^
convert.exe - -channel red +level 3.5%%,100%% -|^
convert.exe - -channel green -level 0%%,87%% +level 1%%,100%% -|^
convert.exe - -channel blue -level 0%%,100%%,0.94 +level 7%%,100%% -|^
convert.exe - -brightness-contrast -1x0 final_converted_image.jpg

del source_copy.jpg
del fill.jpg

问题是将上述批处理文件转换为与该特定库一起使用。

- (void)convertImage {
    MagickWandGenesis();
    magick_wand = NewMagickWand();
    //UIImageJPEGRepresentation([imageViewButton imageForState:UIControlStateNormal], 90);
    NSData * dataObject = UIImagePNGRepresentation([UIImage imageNamed:@"iphone.png"]);
    MagickBooleanType status;
    status = MagickReadImageBlob(magick_wand, [dataObject bytes], [dataObject length]);
    if (status == MagickFalse) {
        ThrowWandException(magick_wand);
    }

    // Resize image.
    ImageInfo *imageInfo = AcquireImageInfo();
    ExceptionInfo *exceptionInfo = AcquireExceptionInfo();

    // Get image from bundle.
    char *input_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *output_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *argv[] = { "convert", input_image, "-resize", "100x100", output_image, NULL };

    // ConvertImageCommand(ImageInfo *, int, char **, char **, MagickExceptionInfo *);
    status = ConvertImageCommand(imageInfo, 5, argv, NULL, exceptionInfo);

    free(input_image);
    free(output_image);

    if (status == MagickFalse) {
        ThrowWandException(magick_wand); // Always throws an exception here...
    }

    size_t my_size;
    unsigned char * my_image = MagickGetImageBlob(magick_wand, &my_size);
    NSData * data = [[NSData alloc] initWithBytes:my_image length:my_size];
    free(my_image);
    magick_wand = DestroyMagickWand(magick_wand);
    MagickWandTerminus();
    UIImage * image = [[UIImage alloc] initWithData:data];
    [data release];

    [imageViewButton setImage:image forState:UIControlStateNormal];
    [image release];
}

问题是 status 始终为 MagickFalse,这意味着它会引发异常。我也不确定我是否以正确的方式使用 ConvertImageCommand()

任何帮助将不胜感激。提前致谢。

I've decided to use the following ImageMagick library for iPhone development:

https://github.com/marforic/imagemagick_lib_iphone

It works quite well. The sample project compiles just fine, but doesn't make any sense whatsoever.

Usually, I'll use the "convert.exe" that comes with ImageMagick for Windows to convert images via the command line. So I'll write a little batch file like the following:

@echo off

set SOURCE=image_to_convert.jpg

del result.jpg
del source_copy.jpg

convert.exe %SOURCE% -fill "#fff8f2" -colorize 100%% fill.jpg

copy %SOURCE% source_copy.jpg

convert.exe %SOURCE% -modulate 100,0,100 -|^
convert.exe - source_copy.jpg -compose overlay -composite -|^
convert.exe source_copy.jpg - -compose dissolve -define compose:args=37,100 -composite -|^
convert.exe - -modulate 100,70,100 +level 3.5%%,100%% -|^
convert.exe - -channel red -level 0%%,89%% +level 9%%,100%% -|^
convert.exe - -channel green +level 3.5%%,100%% -|^
convert.exe - -channel blue -level 0%%,93%% +level 4.7%%,100%% -|^
convert.exe - -brightness-contrast -5x3 -|^
convert.exe fill.jpg - -compose multiply -gravity center -composite -|^
convert.exe - -level 3.5%%,100%%,0.91 +level 2.7%%,100%% -|^
convert.exe - -channel red +level 3.5%%,100%% -|^
convert.exe - -channel green -level 0%%,87%% +level 1%%,100%% -|^
convert.exe - -channel blue -level 0%%,100%%,0.94 +level 7%%,100%% -|^
convert.exe - -brightness-contrast -1x0 final_converted_image.jpg

del source_copy.jpg
del fill.jpg

The problem is converting the above batch file to be used alongside that particular library.

- (void)convertImage {
    MagickWandGenesis();
    magick_wand = NewMagickWand();
    //UIImageJPEGRepresentation([imageViewButton imageForState:UIControlStateNormal], 90);
    NSData * dataObject = UIImagePNGRepresentation([UIImage imageNamed:@"iphone.png"]);
    MagickBooleanType status;
    status = MagickReadImageBlob(magick_wand, [dataObject bytes], [dataObject length]);
    if (status == MagickFalse) {
        ThrowWandException(magick_wand);
    }

    // Resize image.
    ImageInfo *imageInfo = AcquireImageInfo();
    ExceptionInfo *exceptionInfo = AcquireExceptionInfo();

    // Get image from bundle.
    char *input_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *output_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *argv[] = { "convert", input_image, "-resize", "100x100", output_image, NULL };

    // ConvertImageCommand(ImageInfo *, int, char **, char **, MagickExceptionInfo *);
    status = ConvertImageCommand(imageInfo, 5, argv, NULL, exceptionInfo);

    free(input_image);
    free(output_image);

    if (status == MagickFalse) {
        ThrowWandException(magick_wand); // Always throws an exception here...
    }

    size_t my_size;
    unsigned char * my_image = MagickGetImageBlob(magick_wand, &my_size);
    NSData * data = [[NSData alloc] initWithBytes:my_image length:my_size];
    free(my_image);
    magick_wand = DestroyMagickWand(magick_wand);
    MagickWandTerminus();
    UIImage * image = [[UIImage alloc] initWithData:data];
    [data release];

    [imageViewButton setImage:image forState:UIControlStateNormal];
    [image release];
}

The problem is that status is always MagickFalse, which means it throws an exception. I'm also not sure whether I'm using ConvertImageCommand() in the correct way either.

Any help would be greatly appreciated. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤单情人 2024-12-12 14:08:45

我最终使用 MagickCommandGenesis() 来达到预期的结果。

I ended up using MagickCommandGenesis() to achieve the desired result.

旧伤还要旧人安 2024-12-12 14:08:45

这些都不是正确的答案。上面的代码完全是错误的,并且已以某种形式或其他

http://www.imagemagick.org/discourse-server/viewtopic.php?t=19504
http://www.imagemagick.org/discourse-server/viewtopic.php ?t=25430
iPhone ImageMagick 库 - 从批处理文件转换使用 MagickWand API 编写 Objective-C 脚本
http://www.imagemagick.org/discourse-server /viewtopic.php?f=6&t=20527

等等

MagicWand 是使用 imagemagick API 进行图像操作的框架,而ConvertImageCommand 直接调用 convert 命令的命令行界面。如果您希望通过 imagemagick 的 api 执行操作,请使用 MagicWand 等,但如果您希望简单地调用从命令行使用的相同方法,则调用 ConvertImageCommand

它返回 MagickFalse 的事实是正确的。虽然我并不声称已经阅读了整个方法并知道它在做什么或为什么,但如果您查看 convert.c http://www.imagemagick.org/api/MagickWand/convert_8c_source.html,该函数的最后几行是

3217   status&=WriteImages(image_info,image,argv[argc-1],exception);
 3218   if (metadata != (char **) NULL)
 3219     {
 3220       char
 3221         *text;
 3222 
 3223       text=InterpretImageProperties(image_info,image,format);
 3224       if (text == (char *) NULL)
 3225         ThrowConvertException(ResourceLimitError,"MemoryAllocationFailed",
 3226           GetExceptionMessage(errno));
 3227       (void) ConcatenateString(&(*metadata),text);
 3228       text=DestroyString(text);
 3229     }
 3230   DestroyConvert();
 3231   return(status != 0 ? MagickTrue : MagickFalse);
 3232 }

什么呢说是从命令行调用时成功返回 0 (MagickFalse),这是相当合理的。

上面的代码在没有所有 MagicWand 的情况下也能正常工作 -

// Resize image.
    ImageInfo *imageInfo = AcquireImageInfo();
    ExceptionInfo *exceptionInfo = AcquireExceptionInfo();

    // Get image from bundle.
    char *input_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *output_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *argv[] = { "convert", input_image, "-resize", "100x100", output_image, NULL };

    // ConvertImageCommand(ImageInfo *, int, char **, char **, MagickExceptionInfo *);
    status = ConvertImageCommand(imageInfo, 5, argv, NULL, exceptionInfo);

或者,如果您想直接使用 API,那么网上有大量示例提供了如何使用 MagicWand 的示例。

上面的代码试图混合和匹配两种不同的方法。上面的 MagicWand 实例化没有执行任何操作,如果您查看上面代码片段末尾的 NSData 中的图像,它与您开始时使用的图像相同。不过,ConvertImageCommand 的输出应该是您所期望的。

None of these are the right answer. The code above is just plain wrong and has been copied and pasted all over the internet in some form or another

http://www.imagemagick.org/discourse-server/viewtopic.php?t=19504
http://www.imagemagick.org/discourse-server/viewtopic.php?t=25430
iPhone ImageMagick Library - converting from batch file script to Objective-C using MagickWand API
http://www.imagemagick.org/discourse-server/viewtopic.php?f=6&t=20527

the list goes on

MagicWand is the framework to do image manipulations using the imagemagick API, whereas ConvertImageCommand calls directly into the commandline interface for the convert command. If you wish to do things through imagemagick's api, then use MagicWand etc, but if you wish to simply call into the same method that is used from the commandline, then call ConvertImageCommand.

The fact that it is returning MagickFalse is correct. While I don't claim to have read the whole method and know everything it's doing or why, if you look at convert.c http://www.imagemagick.org/api/MagickWand/convert_8c_source.html, the last few lines of the function are

3217   status&=WriteImages(image_info,image,argv[argc-1],exception);
 3218   if (metadata != (char **) NULL)
 3219     {
 3220       char
 3221         *text;
 3222 
 3223       text=InterpretImageProperties(image_info,image,format);
 3224       if (text == (char *) NULL)
 3225         ThrowConvertException(ResourceLimitError,"MemoryAllocationFailed",
 3226           GetExceptionMessage(errno));
 3227       (void) ConcatenateString(&(*metadata),text);
 3228       text=DestroyString(text);
 3229     }
 3230   DestroyConvert();
 3231   return(status != 0 ? MagickTrue : MagickFalse);
 3232 }

What it says is to return 0 (MagickFalse) on success when called from the commandline, which is fairly reasonable.

The above code will work fine without all the MagicWand stuff as so -

// Resize image.
    ImageInfo *imageInfo = AcquireImageInfo();
    ExceptionInfo *exceptionInfo = AcquireExceptionInfo();

    // Get image from bundle.
    char *input_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *output_image = strdup([[[NSBundle mainBundle] pathForResource:@"iphone" ofType:@"png"] UTF8String]);
    char *argv[] = { "convert", input_image, "-resize", "100x100", output_image, NULL };

    // ConvertImageCommand(ImageInfo *, int, char **, char **, MagickExceptionInfo *);
    status = ConvertImageCommand(imageInfo, 5, argv, NULL, exceptionInfo);

Alternatively, if you want to use the API directly, then there are plenty of samples online that provide examples of how to use MagicWand.

The above code is attempting to mix and match two different methodologies. The MagicWand instantiation above is not doing anything, and if you will look at the image in the NSData at the end of the above code snippet, it is the same image you started with. The output of the ConvertImageCommand ought to be what you're expecting though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文