我想为我的照片创建预览缩略图,例如 Facebook's preview photo .我的计划:
- 发件人:从原始照片生成缩放缩略图(最大尺寸为 30 像素),去除所有固定标题以发送。
- Receiver:从“缩小的”字节数组,附加固定 header (客户端代码中的硬编码)。然后转换为
Bitmap
显示。
最后我想出了基于 Q42.ImagePreview 的解决方案.
我将这些部分拆分为固定标题:
- 图像开始(
0xFFD8
) - App0(以
0xFFE0
开头) - 定义量化表
- 定义霍夫曼表
动态部分是:
- 帧开始(以
0xFFC0
开始):因为它包含宽度/高度字节。 - 扫描开始(以
0xFFDA
开始)。 - 压缩图像数据。
- 图像结束(
0xFFD9
)
但它只适用于我的一台设备,不适用于其他设备。
那么如何生成可在 Android 和 iOS 设备上使用的固定的、通用的和标准的 JPEG header ?
谢谢。
更多细节:
生成缩小的数据流:
使用
从原始图像创建缩放位图(最大尺寸 30 像素,保持宽高比)BitmapFactory
和Matrix
使用
Bitmap#compress()
压缩质量为64
的缩放位图并存储在byte[] thumbData
中。将上面的
thumbData
从0xFFDA
分列到末尾。 (SOS、图像数据和 EOI)并存储在byte[] body
中。在
body
中加上代表宽度和高度的4个字节,转换为Base64字符串并发送。
在正常工作的设备中,thumbData
的大小比其他不工作的设备长。不同之处在于霍夫曼表、SOS 和图像数据部分,请参见:
Diff check between 2 image photos
最佳答案
恐怕您不能使用每个平台的内置方法来做到这一点。 问题出在压缩阶段。
JPEG 压缩中有许多变量,包括扫描的类型和分割、样本、DHT 选择和 DQT 选择。 如果您使用的编码器中的任何一个不同,您将获得不同的输出。这是野兽的本性。
例如:定义霍夫曼表 (DHT) 定义“图像数据”(在 SoS 段之后)是如何压缩的。而您使用固定的霍夫曼表仅用于解码,这就是导致问题的原因。
所以你可能有一些选择:
- 在缩小到最大尺寸
30px
后发送完整质量的图像(不压缩)作为预览缩略图。 - 编写您自己的压缩算法或使用跨平台库。
- 将整个原始图像上传到您的服务器进行处理,并将“缩小数据”发送回 Android/iOS。
Telegram 也有预览图,他们的做法和你差不多。但他们将整个原始图像(以字节数组形式)传输到服务器,创建缩略图,去除“固定 header ”并将“缩小数据”发回给接收者.
当在移动设备上接收时,他们通过附加“固定 header ”(Bitmaps.java#L111)将“缩小数据”解码为位图,并更新 SoF 段中的图像大小。参见 ImageLoader.java#L750 .
关于java - 使用通用固定标题创建 JPEG 拇指图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56236805/