• 8位灰度图在LCD上显示


    一、概述

    1、灰度

      灰度使用黑色调表示物体,即用黑色为基准色,不同的饱和度的黑色来显示图像。每个灰度对象都具有从 0%(白色)到灰度条100%(黑色)的亮度值。 使用黑白或灰度扫描仪生成的图像通常以灰度显示。

      像素值量化后用一个字节(8 bits)来表示。如把有黑-灰-白连续变化的灰度值量化为256个灰度级,灰度值的范围为0~255,表示亮度从深到浅,对应图像中的颜色为从黑到白。黑白照片包含了黑白之间的所有的灰度色调,每个像素值都是介于黑色和白色之间的256种灰度中的一种。

    2、灰度图

      用灰度表示的图像称作灰度图,灰度图的RGB三通道满足关系式:R=G=B。

    3、灰度图bmp文件格式

                     

    偏移量

    域的名称

    大小

    内容

    图像文件头

    0000h

    标识符(Identifier)

    2 bytes

    两字节的内容用来识别位图的类型:

    BM : Windows 3.1x, 95, NT, 

     

    0002h

    File Size

    1 dword

    用字节表示的整个文件的大小

     

    0006h

    Reserved

    1 dword

    保留,设置为0

     

    000Ah

    Bitmap Data Offset

    1 dword

    从文件开始到位图数据开始之间的数据

    (bitmap data)之间的偏移量

     

    000Eh

    Bitmap Header Size

    1 dword

    位图信息头(Bitmap Info Header)的长度,用来描述

    位图的颜色、压缩方法等。下面的长度表示:

    28h - Windows 3.1x, 95, NT,

    0Ch - OS/2 1.x

    F0h - OS/2 2.x

     

    0012h

    Width

    1 dword

    位图的宽度,以像素为单位

     

    0016h

    Height

    1 dword

    位图的高度,以像素为单位

     

    001Ah

    Planes

    1 word

    位图的位面数


    图像信息头

     

     

    001Ch

    Bits Per Pixel

    1 word

    每个像素的位数

    1 - Monochrome bitmap

    4 - 16 color bitmap

    8 - 256 color bitmap

    16 - 16bit (high color) bitmap

    24 - 24bit (true color) bitmap

    32 - 32bit (true color) bitmap

     

    001Eh

    Compression

    1 dword

    压缩说明:

    0 - none (也使用BI_RGB表示)

    1 - RLE 8-bit / pixel (也使用BI_RLE4表示)

    2 - RLE 4-bit / pixel (也使用BI_RLE8表示)

    3 - Bitfields (也使用BI_BITFIELDS表示)

     

    0022h

    Bitmap Data Size

    1 dword

    用字节数表示的位图数据的大小。该数必须是4的倍数

     

    0026h

    HResolution

    1 dword

    用像素/米表示的水平分辨率

     

    002Ah

    VResolution

    1 dword

    用像素/米表示的垂直分辨率

     

    002Eh

    Colors

    1 dword

    位图使用的颜色数。如8-位/像素表示为100h或者 256.

     

    0032h

    Important Colors

    1 dword

    指定重要的颜色数。当该域的值等于颜色数时,表示所有

    颜色都一样重要

    调色板数据

    0036h

    Palette

    N * 4 byte

    调色板规范。对于调色板中的每个表项,这4个字节用下述

    方法来描述RGB的值:

    • 1字节用于蓝色分量
    • 1字节用于绿色分量
    • 1字节用于红色分量
    • 1字节用于填充符(设置为0)

    图像数据

    0436h

    Bitmap Data

    x bytes

    该域的大小取决于压缩方法,它包含所有的位图数据字节

    ,这些数据实际就是彩色调色板的索引号

     example: gray.bmp

    1)gray.bmp的图片信息

    2)grap.bmp文件的数据

    0000h: 标示符为“BM”

    0002h: 文件大小为0x13036,也就是77878字节

    0006h: 保留

    000Ah:从文件开头到位图数据开始的偏移量为0x436

    000Eh: 位图信息头的长度为0x28

    0012h: 位图的宽度为0x140,也就是宽320个像素

    0016h: 位图的高度为0xF0,也就是高为240个像素

    001Ah: 位图为1帧

    001Ch:像素的位数为8位

    001Eh: 图片无压缩

    0022H: 位图数据的大小为0x12C00,也就是76800个字节

    0026H: 水平分辨率为7200

    002Ah: 垂直分辨率为7200

    002Eh: 位图使用的颜色数--该域并未赋值

    0032h: 重要的颜色数--该域并未赋值

    0036h-0435h: 调色板数据

    0436h: 位图数据区

    3)解读

      位图数据区保存的是图片有效的数据,一个字节的存储单元对应图片的一个像素,一个字节的数值代表了对应像素的灰度值。本例图片是宽320*高240,位图数据区为76800个字节,算上头部的控制块为1078个字节,文件总大小为77878字节。

      在显示的时候,从位图数据区读取数据,获得一个像素的灰度值后,就以灰度值为索引,从调色板区找出灰度值对应的rgb,然后再显示屏上显示出该像素。

    ☆ 注意

      windows规定一个扫描行所占的字节数必须是4的倍数,不足的以0填充。假设一个图片款318个像素,实际上一行占据了320个字节。

    4) bmp文件存储灰度图像的顺序

      bmp文件存储图像的顺序是左下角-->右上角,也就是“从下到上,从左到右”。

      那么在显示bmp图像时也要遵循这样的顺序,即是:由下而上,由左到右。倘若安装"从上到下,从左到右",那么显示的图像实际上是关于Y轴翻转的。

    测试bmp文件:

    WinHex中对应的内容:

    二、8位灰度格式转换到16位565RGB的格式

      灰度图的RGB通道满足:R=G=B,以灰度值替换RGB三个通道就得到RGB格式的数据。考虑到LCD显示器的显示格式是5:6:5(r:g:b),而灰度值是8位灰阶,所以有如下的转换计算公式:

    r = GrayValue/256 * 32 = GrayValue/8 = GrayValue >> 3

    g = GrayValue/256 * 64 = GrayValue/4 = GrayValue >> 2

    b = GrayValue/256 * 32 = GrayValue/8 = GrayValue >> 3

      8位灰度值转换为16位的RGB公式为:

    #define GRAYTORGB16(t) ((t >> 3)|((t & ~3) << 3)|((t & ~7) << 8))

    三、测试程序代码

    /**
      * @brief  显示灰度图 
      * @param  x,y : 显示在LCD上的坐标 
      *         pic_name: 存储在SD卡根目录下的灰度文件名
      * @retval None
      */
    void Lcd_show_bmp(unsigned short int x, unsigned short int y,char *pic_name)
    {
        int i, j;
        int width, height, l_width;    
        BITMAPFILEHEADER bitHead;
        BITMAPINFOHEADER bitInfoHead;
        WORD fileType;
        unsigned int read_num;
    
        f_mount(0, &bmpfs[0]);
        BMP_DEBUG_PRINTF("file mount ok 
    ");    
        bmpres = f_open( &bmpfsrc , (char *)pic_name, FA_OPEN_EXISTING | FA_READ);    
    
        if(bmpres == FR_OK)
        {
            BMP_DEBUG_PRINTF("Open file success
    ");
    
            /* 读取文件头信息  两个字节*/         
            f_read(&bmpfsrc,&fileType,sizeof(WORD),&read_num);     
    
            /* 判断是不是bmp文件 "BM"*/
            if(fileType != 0x4d42)
            {
                BMP_DEBUG_PRINTF("file is not .bmp file!
    ");
                return;
            }
            else
            {
                BMP_DEBUG_PRINTF("Ok this is .bmp file
    ");    
            }        
    
            /* 读取BMP文件头信息*/
            f_read(&bmpfsrc,&bitHead,sizeof(tagBITMAPFILEHEADER),&read_num);        
            showBmpHead(&bitHead);
    
            /* 读取位图信息头信息 */
            f_read(&bmpfsrc,&bitInfoHead,sizeof(BITMAPINFOHEADER),&read_num);        
            showBmpInforHead(&bitInfoHead);
        }    
        else
        {
            BMP_DEBUG_PRINTF("file open fail!
    ");
            return;
        }    
    
        width = bitInfoHead.biWidth;
        height = bitInfoHead.biHeight;
    
        /* 计算位图的实际宽度并确保它为4的倍数    */
        l_width = WIDTHBYTES(width);
        if(l_width > 320)
        {
            BMP_DEBUG_PRINTF("
     SORRY, PIC IS TOO BIG (<=320)
    ");
            return;
        }
        
        /* 设置Lcd Gram 扫描方向为: 右下角-> 左上角 */
        Lcd_GramScan(3);
        
        /* 开一个图片大小的窗口*/
        LCD_OpenWindow(x, y, width, height);
        
        /* 判断是否是8bit灰度图 */
        if(bitInfoHead.biBitCount == 8)
        {
            f_lseek(&bmpfsrc,0x0436);
            
            for(i=0;i< height; i++)
            {      
                /* 读取一行bmp的数据到数组pColorData里面 */
                f_read(&bmpfsrc,pColorData,l_width,&read_num);
    
                for(j=0; j<width; j++)                  //一行有效信息
                {
                    unsigned short d; 
                    d = pColorData[j];
                    LCD_WR_Data(GRAYTORGB16(d));        //写入LCD-GRAM
                } 
            }
        }    
        else 
        {        
            BMP_DEBUG_PRINTF("SORRY, THIS PIC IS NOT A 8BITS GRAY Picture!");
            return ;
        }
        f_close(&bmpfsrc);    
    }
    View Code

     

    参考资料:bmp头文件和8 bit 灰度图的显示

        《STM32库开发实战指南》

  • 相关阅读:
    面向对象设计模式之Facade外观模式(结构型)
    Android 多线程:使用Thread和Handler
    Android源码分析之Handler
    Android View的几个位置坐标关系
    LinearLayout布局问题
    Android app被系统kill的场景
    改变Activity启动时的默认动画
    ViewStub源码分析
    Android measure过程分析
    点击ViewGroup时其子控件也变成pressed状态的原因分析及解决办法
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3862669.html
Copyright © 2020-2023  润新知