在JXA / JavaScript中将PNG编码/解码为base64字符串

3
我正在尝试在Apple Script Editor中编写JXA脚本,将PNG文件转换为base64字符串,然后添加到JSON对象中。
我似乎找不到适用于执行base64编码/解码的JXA方法。
我发现一个使用Shell脚本编写的滴答程序,它将任务外包给openssl,然后输出.b64文件:
for f in "$@"
do
    openssl base64 -in "$f" -out "$f.b64"
done

所以我在考虑将其改造为一种方法,使用evalAS运行内联AppleScript,就像这个例子:

(() => {
    'use strict';

    // evalAS2 :: String -> IO a
    const evalAS2 = s => {
        const a = Application.currentApplication();
        return (a.includeStandardAdditions = true, a)
            .runScript(s);
    };

    return evalAS2(
        'use scripting additions\n\
         for f in' + '\x22' + file + '\x22\n'
         do
         openssl base64 -in "$f" -out "$f.b64"
         done'
    );
})();

然后在脚本中重新打开.b64文件,但这一切似乎都很冗长和笨拙。

我知道可以在JXA脚本中使用Cocoa,我看到Cocoa中有base64编码/解码方法...

以及Objective-C

NSData *imageData = UIImagePNGRepresentation(myImageView.image);
NSString * base64String = [imageData base64EncodedStringWithOptions:0];

JXA Cookbook有一个完整的章节介绍调用ObjC函数的语法,我正在阅读它。据我理解,它应该像这样:

var image_to_convert = $.NSData.alloc.UIImagePNGRepresentation(image)
var image_as_base64 = $.NSString.alloc.base64EncodedStringWithOptions(image_to_convert) 

但我完全是个新手,所以对于这些内容理解起来仍然很困难。

在上面的推测代码中,我不确定从哪里获取图像数据?

我目前正在尝试:

ObjC.import("Cocoa");
var image = $.NSImage.alloc.initWithContentsOfFile(file)
console.log(image);
var image_to_convert = $.NSData.alloc.UIImagePNGRepresentation(image)
var image_as_base64 = $.NSString.alloc.base64EncodedStringWithOptions(image_to_convert)

但是它导致以下错误: $.NSData.alloc.UIImagePNGRepresentation不是一个函数。(在“$.NSData.alloc.UIImagePNGRepresentation(image)”中,“$.NSData.alloc.UIImagePNGRepresentation”未定义)
我猜这是因为UIImagePNGRepresentation属于UIKit框架,这是iOS的东西而不是OS X?
我发现this post,它建议使用以下内容:
NSArray *keys = [NSArray arrayWithObject:@"NSImageCompressionFactor"];
NSArray *objects = [NSArray arrayWithObject:@"1.0"];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];

NSImage *image = [[NSImage alloc] initWithContentsOfFile:[imageField stringValue]];
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]];
NSData *tiff_data = [imageRep representationUsingType:NSPNGFileType properties:dictionary];

NSString *base64 = [tiff_data encodeBase64WithNewlines:NO];

但是,我不知道这如何转换为JXA。我只是决心让某些东西工作。

我希望有一种方法可以在普通的JavaScript中完成,在JXA脚本中也能运行?

期待您能提供任何答案和/或指针。提前感谢您所有人!

2个回答

2

很抱歉,我从未使用过JXA,但是使用了很多Objective-C。

我认为您遇到了编译错误,因为您正在尝试始终分配新的对象。

我认为应该简单地写成:

Original Answer翻译成"最初的回答"

ObjC.import("Cocoa");
var imageData = $.NSData.alloc.initWithContentsOfFile(file);
console.log(imageData);
var image_as_base64 = imageData.base64EncodedStringWithOptions(0); // Call method of allocated object

0是Base64编码中的常数,用于仅获取base64字符串。

最初的回答

edit:
var theString = ObjC.unwrap(image_as_base64);

最初的回答:为了让JXA能够看到该值,请执行以下操作。

谢谢你,@ivion!你的更正没有出现错误-但是我做错了什么,因为我无法使它返回base64数据(它似乎是某种类型的对象)...对于这些行有任何想法吗:NSArray *keys = [NSArray arrayWithObject:@"NSImageCompressionFactor"]; NSArray *objects = [NSArray arrayWithObject:@"1.0"]; NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]]; NSData *tiff_data = [imageRep representationUsingType:NSPNGFileType properties:dictionary]; 谢谢! - PE B
所有这些方法都用于获取图像的数据。NSBitmapImageRep是表示PNG、JPG等图像的对象。对于您的任务来说,它是不必要的,因为您已经有了文件,只想将其作为Base64字符串获取。我编辑了答案并添加了var theString = ObjC.unwrap(image_as_base64);。似乎没有这些步骤,您无法访问该值。这些代码应该适用于任何类型的文件。 - ivion
非常感谢@ivion,昨天我在那几行代码上苦苦挣扎哈哈 - "你太棒了!" - PE B

0
使用以下代码。使用FileReader在'readDataAsURL'中从jquery文件输入元素读取文件到var文件。然后,您将以base64格式的字符串形式拥有您的png。
您可能需要使用','分割base64字符串以获取字符串的实际数据部分,您可以将其包含在JSON中,并通过API将其发送到后端。
var file = $('#fileUpload').prop('files')[0];
var base64data;
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
  base64data = reader.result;
  var dataUrl = base64data.split(",");
};

通常你会得到这种形式的base64字符串。
'data:image/png;base64,STREAM_OF_SOME_CHARACTERS...'
所以,STREAM_OF_SOME_CHARACTERS...(dataUrl)实际上是图像数据所在的位置。
此外,您可以在HTML页面中打开图像。
<img src=base64data>

感谢@Anjana Senanayake的帮助,不幸的是尽管这段代码在常规JavaScript环境中运行良好,但它在JXA中无法工作-它无法识别FileReader对象。JXA本身已经相当受限,因此我认为解决方案在于使用Objective-C。我只是不能理解如何在JXA中正确地编写语法。非常感谢你的努力。 - PE B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接