2010-11-02 126 views
2

我想在Android应用程序中写入磁盘,我在一个int [](或者一个字节[]如果你喜欢的)中有一些二进制数据(像素值)。我只想使用少量的处理时间,但希望尽可能多地进行压缩。我有什么选择?快速的方法来压缩二进制数据?

在许多情况下,数组将包含很多连续的零,所以像RLE压缩这样简单快速的东西可能会工作得很好。虽然我看不到任何Android API函数。如果我必须在Java中循环访问数组,这将会非常缓慢,因为大多数Android设备上都没有JIT。我可以使用NDK,但如果可以的话,我宁愿避免这种情况。

+1

真正的问题是什么是折衷。一般来说,我认为编写原始字节会更快,因为其他任何方法都会使用处理器时间,例如DeflaterOutputStream或GZipOutputStream,特别是对于大量数据可能需要很长时间。 – Nicholas 2010-11-02 03:28:01

+0

我想RLE的开销会很低,但是我找不到一个API函数来为我做RLE。在非JIT Android手机上使用Java代码执行此操作将非常缓慢。 Deflater和GZip似乎使用更复杂的压缩(即霍夫曼),而且处理起来会慢得多。 – RichardNewton 2010-11-02 04:02:32

+0

对于存在大量相似连续颜色(这似乎是您的情况)的每个像素,可以使用无损PNG格式非常高效地编码像素值(如在“32位ARGB”中的int []中)接受你想要的无损)。用于无损压缩的算法behing PNG称为DEFLATE(根据wiki,基本上是Huffman + LZ77)。不知道如何强大的Android设备,但编码一个微小的(PNG屏幕尺寸真的很小,相比我的1920x1200桌面)使用PNG图片真的不接近数字处理... – SyntaxT3rr0r 2010-11-02 19:07:07

回答

2

DeflatorOutputStream在Java中压缩1 MB大约需要25 ms。它是一种本地方法,所以JIT应该没有太大的区别。

你有0.2s或0.5s太慢的要求吗?

你可以在后台线程中做到这一点,所以用户不会注意到需要多长时间?

GZIP基于Deflator + CRC32,因此可能会大致相同或稍慢。

平滑器有几种模式。在Java中DEFAULT_STRATEGY是最快的,但更简单的压缩比如HUFFMAN_ONLY可能会更快。

2

Android有Java的DeflaterOutputStream。这会起作用吗?

+0

仅供参考:deflate有点慢.... – JimR 2010-11-02 03:10:45

+0

我可以确认它在Android中非常慢。用deflater写入1Mb数组大约需要0.5s,而且只需要0.01s就可以做为原始字节! – RichardNewton 2010-11-02 03:25:00

+0

也许'GZipOutputStream'会提供更好的压缩? – 2010-11-02 03:25:56

0

随机想法:如果是图像数据,请尝试将其保存为png。标准的java有它,我敢肯定android也会,并且可能会使用本机代码进行优化。它具有相当不错的压缩效果,并且无损。

+0

我试过这个,速度很慢。至少比保存原始字节慢10倍左右。 – RichardNewton 2010-11-02 04:00:39

+0

@RichardNewton:在发表评论之后,我意识到DEFLATE已经被提出。 tulskiy:PNG正在使用DEFLATE,因此如果DEF的OPL速度太慢,这里就不会出现奇迹。 – SyntaxT3rr0r 2010-11-02 19:08:48

1

字节数组传递给
http://download.oracle.com/javase/6/docs/api/java/io/FileWriter.html
和链
http://download.oracle.com/javase/1.4.2/docs/api/java/util/zip/GZIPOutputStream.html

那么当你需要做反向读取数据回 http://download.oracle.com/javase/1.4.2/docs/api/java/io/FileReader.html
和链
http://download.oracle.com/javase/1.4.2/docs/api/java/util/zip/GZIPInputStream.html

根据文件的大小,您的sa ving你会看到一些压缩Gzip就是这样,如果你没有看到使用缓冲写入器(这应该是最快的)未压缩的数据的贸易。此外,如果您使用缓冲作家读取器进行gzip,也可以加快速度。

1

我不得不在另一个平台上解决基本相同的问题,我的解决方案是使用修改的LZW压缩。首先,在32bpp图像上进行一些差异过滤(类似于PNG)。如果有大面积的普通颜色,这会使大部分图像变成黑色。然后使用通用的GIF压缩算法处理滤波后的图像,就好像它是8bpp一样。你会得到体面的压缩,它的工作速度非常快。这将需要在本机代码(NDK)中运行。在Android上使用本机代码真的很容易。