【问题标题】:Encode / Decode PNGs to base64 strings in JXA/JavaScript在 JXA/JavaScript 中将 PNG 编码/解码为 base64 字符串
【发布时间】:2019-06-12 05:05:18
【问题描述】:

我正在尝试在 Apple 脚本编辑器中编写一个 JXA 脚本,将 PNG 文件转换为 base64 字符串,然后可以将其添加到 JSON 对象中。

我似乎找不到适用于执行 base64 编码/解码部分的 JXA 方法。

我遇到了一个droplet which was written using Shell Script,它将任务外包给openssl,然后输出一个.b64 文件:

for f in "$@"
do
    openssl base64 -in "$f" -out "$f.b64"
done

因此,我正在考虑将科学怪人转化为一种使用 evalASrun inline 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 文件,但这一切似乎相当冗长和笨拙。

知道Cocoa in JXA scripts是可以用的,看到base64 encoding/decoding in Cocoa也有方法……

还有Objective-C:

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

JXA Cookbook 有一个完整的部分覆盖了Syntax for Calling ObjC functions,我正在尝试阅读。 据我了解,它应该类似于:

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

但我只是一个完全的菜鸟,所以我仍然很难理解这一切。

在上面的推测代码中,我不确定我会从哪里获得 image 数据?

我目前正在尝试:

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(图像)', '$.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。我只是下定决心要有所作为。

我希望有某种方法可以在 JXA 脚本中工作的普通旧 JavaScript 中执行此操作?

我期待您提供任何答案和/或建议。提前谢谢大家!

【问题讨论】:

    标签: javascript cocoa base64 applescript javascript-automation


    【解决方案1】:

    很抱歉,我从未使用过 JXA,但经常使用 Objective-C。

    我认为你得到了编译错误,因为你总是试图分配新的对象。

    我认为应该是简单的:

    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 数据(它似乎是某种类型的 obj)......关于这些行的任何想法: NSArray *keys = [NSArray arrayWithObject: @"NSImageCompressionFactor"]; NSArray *objects = [NSArray arrayWithObject:@"1.0"]; NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:[图像 TIFFRepresentation]]; NSData *tiff_data = [imageRep representationUsingType:NSPNGFileType properties:dictionary];谢谢!
    • 所有这些方法都用于获取图像的数据。 NSBitmapImageRep 是代表 PNG、JPG 等的对象。这对您的任务来说是不必要的,因为您拥有该文件并且只想将其作为 Base64 字符串获取。我编辑了答案并添加了var theString = ObjC.unwrap(image_as_base64);似乎没有这些步骤您无权访问该值。这些行应该适用于每种类型的文件。
    • 非常感谢@ivion,我昨天一直在努力写这几行哈哈-“你大爷!”
    【解决方案2】:

    使用下面的代码。使用“readDataAsURL”中的 FileReader 将文件从 jquery 文件输入元素读取到 var 文件。然后你将把你的 png 作为 base64 格式的字符串。

    您可能需要将 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 中正确写出语法。不过我很感激你的努力。
    猜你喜欢
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多