24位bmp到RGB565文件转换

时间:2017-06-30 16:26:19

标签: image-processing

我想将24位bmp文件转换为RGB565格式以写入串行TFT彩色显示器。

24位bmp的大小总是320x240像素,因为我的TFT显示器是320x240

有没有人有这方面的经验?它可能是C / C ++,Shell,Python,Java Script等等......

3 个答案:

答案 0 :(得分:1)

我会使用 NetPBM (小得多,重量更轻)或 ImageMagick (更大的安装)将BMP转换为格式解析起来很简单,然后使用 Perl 将其转换为RGB565格式。

我假设您计划将RGB565数据写入帧缓冲区,因此您可以执行以下操作:

./bmp2rgb565 image.bmp > /dev/fb1

因此,将以下内容保存为bmp2rgb565

#!/bin/bash
################################################################################
# bmp2rgb565
# Mark Setchell
################################################################################

if [ $# -ne 1 ]; then 
   echo Usage: $0 image.bmp
   exit 1
fi

file=$1

# Use NetPBM's "bmptopnm" to convert BMP to PNM for easy reading
# You could use ImageMagick: convert "$file" PNM: | perl ...
bmptopnm "$file" 2> /dev/null | 
   perl -e '
      my $debug=0;   # Change to 1 for debugging

      # Discard first 3 lines of PNM header:
      #   P3
      #   320 240
      #   255
      my $line=<STDIN>; $line=<STDIN>; $line=<STDIN>;

      # Read file, 3 RGB bytes at a time
      {
         local $/ = \3;
         while(my $pixel=<STDIN>){
            # Extract 8-bit R,G and B from pixel
            my ($r,$g,$b)=unpack("CCC",$pixel);
            printf("R/G/B: %d/%d/%d\n",$r,$g,$b) if $debug;

            # Convert to RGB565
            my $r5=$r>>3;
            my $g6=$g>>2;
            my $b5=$b>>3;
            my $rgb565 = ($r5<<11) | ($g6<<5) | $b5;

            # Convert to little-endian 16-bit (VAX order) and write 2 bytes
            my $v=pack("v",$rgb565);
            syswrite(STDOUT,$v,2);
         }
      }
   '

我没有方便测试的帧缓冲区,但它应该非常接近。

请注意,您可以通过以下方式使代码更加健壮:

convert "$file" -depth 8 -resize 320x240\! PNM: | perl ...

这将确保图像始终与帧缓冲区大小匹配,并且它是8位而不是16位。如果-flip图片是颠倒的或从前到后,您可能还需要-flopBMP

请注意,如果您使用 ImageMagick convert,该代码将适用于GIF,TIFF,JPEG,PNG以及约150种其他格式以及BMP。

请注意,如果您要测试代码,可以使用 ImageMagick 生成黑色图像,如下所示:

convert -size 320x240 xc:black BMP3:black.bmp

然后在运行时在输出中查找一堆零:

./bmp2rgb565 black.bmp | xxd -g2

同样,您可以生成白色图像并查找一堆ff s:

convert -size 320x240 xc:red BMP3:white.bmp

依旧是红色,绿色和蓝色:

convert -size 320x240 xc:red  BMP3:red.bmp
convert -size 320x240 xc:lime BMP3:green.bmp
convert -size 320x240 xc:blue BMP3:blue.bmp

# Or make a cyan-magenta gradient image
convert -size 320x240 gradient:cyan-magenta  cyan-magenta-gradient.bmp

示例:

./RGB565 red.bmp | xxd -g2 | more
00000000: 00f8 00f8 00f8 00f8 00f8 00f8 00f8 00f8  ................
00000010: 00f8 00f8 00f8 00f8 00f8 00f8 00f8 00f8  ................

示例:

./RGB565 blue.bmp | xxd -g2 | more
00000000: 1f00 1f00 1f00 1f00 1f00 1f00 1f00 1f00  ................
00000010: 1f00 1f00 1f00 1f00 1f00 1f00 1f00 1f00  ................

关键字: RGB565,rgb565,帧缓冲,帧缓冲,打包,解包,Perl,BMP,PGM,图像,Raspberry Pi,RASPI

答案 1 :(得分:0)

要转换为RGB565,您可以使用ImageMagick:

convert test.png -resize 320x200 -ordered-dither threshold,32,64,32 test2.png

您需要以什么格式输出?

答案 2 :(得分:0)

我假设您只想流出没有任何标题或其他数据的像素数据。

问题的核心已经被描述为here

如果您想自己实施,以下方法可能有所帮助:

打开文件后,你需要通过读取bfOffBits值来跳过BMP标题(参见this BMP format description),最简单的方法可能就是通过读入一个结构来实现它。匹配BMP标题。

(注意:这只能起作用,因为图像的尺寸可以被4整除!查看格式说明以获取更多细节)

然后通过bfOffBits向前搜索并且在文件尚未结束时,使用问题中的方法将三个连续字节(uint8_t)转换为一个16位值(uint16_t)我上面提到过。您需要的基本C文件操作是fopen, fclose, fread, fwrite, fgetc/fgetwc, fputc/fputwcfseek