【问题标题】:AS3/AIR - Saving an extremely large image to PNGAS3/AIR - 将超大图像保存为 PNG
【发布时间】:2012-08-16 18:36:09
【问题描述】:

我正在为自己制作一个程序,它可以打开未排列的精灵表,根据 XML 文件排列它们,然后将它们保存为 PNG。它的作用是加载未排列的工作表并将其放入BitmapData,然后根据特定的 XML 文件抓取工作表上的每一帧(使用BitmapData.copypixels()),并将生成的Bitmap 添加到命令。然后通过将这些Bitmaps 添加到Sprite 对象来排列它们,相应地创建新行。本质上,我最终得到的是一个包含BitmapsSprite,它们按照我想要的方式排列。

现在我通常从这里做的是使用BitmapData.draw()Sprite 绘制到BitmapData 上,这可行,然后我继续将其编码为PNG 并保存它。这一切都有效,除了一种情况。 有时我会从多个无组织的 spritesheet 中制作一个排列好的 spritesheet,这会导致一张相当大的表格。在一种情况下,生成的表格非常大,出于某种原因,我想绘制的BitmapData 不会接受那么大。也就是说,我创建了一个新的BitmapData,其尺寸等于Sprite,但是当我尝试这样做时,我得到了这个错误:

ArgumentError: Error #2015: Invalid BitmapData.

据我所知,只有当我创建一个宽度和/或高度为 0 的 BitmapData,或者我超过了最大尺寸时,才会发生这种情况。如果不是因为 Flash 11 和 AIR 3 没有限制,我认为是后者。

无论如何我都没有找到解决办法,所以基本上这是我的问题:有什么不同的方法吗?例如,我可以在不制作BitmapData 的情况下获取Sprite 的像素数据吗?或者,我可以以某种方式将数据存储在BitmapData 中,而不必为其提供与图像相同的尺寸吗?或者有什么不同的方法可以做到这一点?

我意识到我可以将图像拆分为 2 个单独的 BitmapDatas,但我想知道在求助之前是否有其他选择。

顺便说一句,如果重要的话,它是使用 FlashDevelop 和 Flex 4 SDK 制作的 Adob​​e AIR 应用程序。我正在使用PNGEncoder2 对我保存的最终精灵表进行编码。

编辑:我发现问题似乎是我的电脑根本无法处理所需大小的BitmapData。我尝试将其拆分为两个单独的 BitmapDatas,但不幸的是,在创建第二个 BitmapData 时,我收到了同样的错误。因此,我的 PC 内存中似乎无法同时包含 BitmapDatas 的数据量。不幸的是,这意味着我什至不能使用 g10 的解决方案,即使用他链接到的 PNG 编码器将两个 BitmapDatas 合并到一个 PNG 中。 到目前为止,我的解决方案是将图像的一半存储到BitmapData 中,对其进行编码,然后将dispose() BitmapData 存储在其中并对其进行编码。然后我将ByteArrays(编码的结果)保存为单独的图像,我可以使用外部程序将其重建为一个。

所以现在,我的问题更多是“我可以以某种方式将其保存为单个 PNG”而不是“我可以将其保存为单个 BitmapData”。

【问题讨论】:

  • 这是否意味着您不需要显示很大,您只是为上传/保存过程组装图像?
  • @r.bitter 没错,完全不需要显示。

标签: actionscript-3 air png sprite bitmapdata


【解决方案1】:

我也遇到了这个问题,发现 19,000 x 19,000 像素之间存在限制。那是在带有 Flash Player 11.3 的 Windows 7 上,当然 Flash Player 10 的限制要低得多,请查看page for the details

这是我用于测试的代码:

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageAlign;

    public class PNGTest extends Sprite
    {

        static var IMAGE_DIM = 18000;
        public function PNGTest()
        {
            this.stage.align = StageAlign.TOP_LEFT;
            var bmData = new BitmapData(IMAGE_DIM, IMAGE_DIM, false, 0xFF0000);
            var image:Bitmap = new Bitmap(bmData);
            this.addChild(image);
        }
    }
}

如果您需要的图片大于您定位的 Flash Player 版本所支持的图片,只需拆分图片即可。您也可以将图像数据复制到 ByteArray 中,不知道最大大小是多少。示例代码见How to convert bytearray to image or image to bytearray?

【讨论】:

    【解决方案2】:

    检查来自 inspirit.ru 的异步 PNGencoder:http://blog.inspirit.ru/?p=378
    提供了PNGencoder.swc,以及使用示例。
    图像大小没有限制,只需要一些时间来编码(可能显示进度条)。

    编辑:
    BitmapData 对象的尺寸(像素数量)有上限,但 PNG 没有,请查看 http://code.google.com/p/in-spirit/wiki/PNGEncoder 的使用信息,尤其是 getNextBitmapsRow 回调

    专门针对您的情况,而不是在 1 个大的 BitmapData 对象中绘制您的 Sprite,此 PNGEncoder 允许您将您的大 Sprite 拆分为几个小的 BitmapData 对象(例如,从 35,000 x 60,000 像素的 Sprite 中,您可以制作 35 列 x 60 行 = 2100 个 1000x1000 像素的 BitmapData 对象),它通过回调机制实现:创建并传递第一个 BitmapData 对象,lib 对其进行编码,并在完成时调用回调,此时您创建并传递下一个 BitmapData进行编码。

    【讨论】:

    • 问题不在于 PNG 的编码,而在于制作该大小的 BitmapData。到目前为止,我目前的 PNG 编码器没有任何问题。
    • @puggsoy 请检查编辑和使用信息示例。您的需求似乎是:拥有一个最终应该作为 PNG 图像的巨大 Sprite。您的问题:您无法制作该大小的 BitmapData 对象。解决方案:有几个较小的 BitmapData 对象一起形成大的结果图像。我提到的 PNGEncoder 使这成为可能。
    • 啊,我明白了,您是指将多个图像合并为一个 PNG 的功能。这很好,我必须承认,但它并不能完全回答我的问题。我想知道的是是否有办法避免完全使用多个 BitmapData。我是否可以将它们导出为单个或多个 PNG 与我无关。不过,它非常好,所以谢谢。
    • @puggsoy 所以你想要 1 个大 Sprite 生成 1 个大 PNG,而不需要先将 Sprite 转换为(一个或多个)位图(数据)?我想如果没有中间步骤,这将不容易完成。虽然您的 Sprite 由多个位图组成,但定位也需要翻译。
    • 好吧,我不介意将 Sprite 转换为单个 BitmapData,但正如您所见,它不允许我制作具有所需尺寸的图像。更重要的是,如果我制作两个 BitmapData,每个大小的一半,它也不允许我这样做。唯一的方法是将工作表的一半保存在 BitmapData 中,对其进行编码,然后处理 BitmapData 并使用与工作表的后半部分相同的 BitmapData。然后我将两半保存为单独的图像。这就是我现在正在做的事情,已经足够了,但我只是想知道是否有一种解决方法可以将它作为一个 BitmapData 获取。
    猜你喜欢
    • 2012-10-16
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    • 2011-01-19
    • 1970-01-01
    • 2018-07-25
    相关资源
    最近更新 更多