我试图在循环中使用dd读取二进制文件中的每对其他字节,但是这太慢了。
我在BusyBox嵌入式设备上有一个二进制文件,其中包含rgb565格式的数据。每个像素为2个字节,我正尝试读取其他每个像素以进行非常基本的图像缩放,以减小文件大小。
整体大小为640x480,通过将dd循环到960字节块大小,我已经能够读取每隔一个“行”像素。但是,即使在我的本地系统上,通过循环2字节的块大小对剩下的所有其他“列”执行相同的操作也是非常慢的。
i=1
while [[ $i -le 307200 ]]
do
dd bs=2 skip=$((i-1)) seek=$((i-1)) count=1 if=./tmpfile >> ./outfile 2>/dev/null
let i=i+2
done
当我得到期望的输出时,此方法不可用。
是否有一些不太明显的方法让dd快速复制每隔一对字节?
可悲的是,对于在BusyBox中编译的内容,我没有太多控制权。我欢迎其他可能的方法,但我可以使用dd / sh解决方案。例如,一个构建省略了head -c ...
感谢所有反馈。我将检查各种建议,然后再返回结果。
答案 0 :(得分:3)
对于不需要使用换行符和空字节的sed或awk之类的工具,跳过其他所有字符都是微不足道的。但是Busybox对sed和awk中的空字节的支持很差,以至于我认为您根本无法应付。可以处理换行符,但这是一个巨大的痛苦,因为根据4字节块中的每个位置是否换行,有16种不同的组合要处理。
由于任意二进制数据很麻烦,所以我们将其转换为十六进制或八进制!我将从bin2hex
and hex2bin
scripts by Stéphane Chazelas中汲取灵感。由于我们不在乎中间格式,因此我将使用八进制,因为它的最后一步使用了仅支持八进制的printf
,因此使用八进制更为简单。 Stéphane的hex2bin
使用awk进行十六进制到八进制的转换; oct2bin
可以使用sed。因此,最后您需要 sh
,od
,sed
和printf
。
我认为您无法避免使用printf
:输出空字节至关重要。尽管od
是必不可少的,但大多数选项不是必需的,因此应该可以对该代码进行调整,以支持精简的od并进行更多的后处理。
od -An -v -t o1 -w4 |
sed 's/^ \([0-7]*\) \([0-7]*\).*/printf \\\\\1\\\\\2/' |
sh
与基于dd的方法相比,它之所以如此之快,是因为BusyBox在父进程中运行printf
,而dd
需要它自己的进程。分叉很慢。如果我没记错的话,有一个编译选项可以使BusyBox分叉成为所有实用程序。在这种情况下,我的方法可能会和您一样慢。这是使用dd
的一种中间方法,它无法避免产生分叉,但至少避免每次都打开和关闭文件。它应该比您的快一点。
i=$(($(wc -c <"$1") / 4))
exec <"$1"
dd ibs=2 count=1 conv=notrunc 2>/dev/null
while [ $i -gt 1 ]; do
dd ibs=2 count=1 skip=1 conv=notrunc 2>/dev/null
i=$((i - 1))
done
答案 1 :(得分:1)
不知道使用BusyBox是否会更快甚至可能,但这是一个想法...
#!/bin/bash
# Empty result file
> result
exec 3< datafile
while true; do
# Read 2 bytes into file "short"
dd bs=2 count=1 <&3 > short 2> /dev/null
[ ! -s short ] && break
# Accumulate result file
cat short >> result
# Read two bytes and discard
dd bs=2 count=1 <&3 > short 2> /dev/null
[ ! -s short ] && break
done
或者这应该更有效:
#!/bin/bash
exec 3< datafile
for ((i=0;i<76800;i++)) ; do
# Skip 2 bytes then read 2 bytes
dd bs=2 count=1 skip=1 <&3 2> /dev/null
done > result
或者,也许您可以使用netcat
或ssh
使用适当的工具将文件发送到明智(功能更强大)的计算机上,以处理并返回文件。例如,如果远程计算机具有 ImageMagick ,则可以非常简单地缩小图像的比例。
答案 2 :(得分:0)
另一种选择是使用 Lua ,它以体积小,速度快并且非常适合嵌入式系统而著称-请参见Lua website。也有预构建的,可下载的二进制文件。也建议在Busybox website here上使用。
我以前从未写过任何Lua,所以可能效率不高,但这似乎工作得很好,并且可以在几毫秒内在桌面上处理640x480 RGB565图像。
magick -depth 16 -size 640x480 gradient: gray:image.bin
我使用 ImageMagick 创建了灰度测试图像,如下所示:
lua scale.lua image.bin smaller.bin
然后我使用以下命令运行上述Lua脚本:
magick -depth 16 -size 320x240 gray:smaller.bin smaller.jpg
然后我制作了JPEG,可以通过以下方式查看进行测试:
image: samueldebruyn/debian-git
pipelines:
default:
- step:
script:
- echo "Pipeline Init"
- apt-get update
- apt-get -qq install git-ftp
- git ftp init --user $FTP_USERNAME --passwd $FTP_PASSWORD ftp://$FTP_HOST