BMP format

BMP格式相关介绍
博客提及了BMP格式,BMP格式在信息技术领域常用于图像存储。它可能涉及到字节、颜色等相关内容,与图像的压缩、色彩表示等方面有联系,在Windows系统中也较为常见。
部署运行你感兴趣的模型镜像
 

bmp format

table of contents

introduction
bitmap file format

              general
              bmp contents
field details
             height field
             bits per pixel field
             compression field
             colors field
             important colors field

introduction

this document describes the microsoft windows and ibm os/2 picture bitmap files, called bitmaps or bmp files. most of the descriptions of the bmp file concentrate on the microsoft windows bmp structures like

bmpinfoheader and bmpcoreinfo , but only a few describe the file contents on byte level. this information is therefor only intended to be used in applications where direct reading and writing of a bmp file is required.

bitmap file format

the following chapters contain the detailed information on the contents of the bmp file. first more general information will be given regarding the byte order and file alignment. the second chapter will concentrate on the byte-level contents of a bmp file. the third chapter will elaborate on this chapter and explain some of the concepts - like compression - and/or values in detail.

general

the bmp file has been created by microsoft and ibm and is therefor very strictly bound to the architecture of the main hardware platform that both companies support: the ibm compatible pc. this means that all values stored in the bmp file are in the intel format, sometimes also called the little endian format because of the byte order that an intel processor uses internally to store values.

the bmp files are the way, windows stores bit mapped images. the bmp image data is bit packed but every line must end on a dword boundary - if that

not the case, it must be padded with zeroes. bmp files are stored bottom-up, that means that the first scan line is the bottom line.

the bmp format has four incarnations, two under windows (new and old) and two under os/2, all are described here.

bmp contents

the following table contains a description of the contents of the bmp file. for every field, the file offset, the length and the contents will be given. for a more detailed discussion, see the following chapters.

offset

field

size

contents

0000h

identifier

2 bytes

the characters identifying the bitmap. the following entries are possible:

m- windows 3.1x, 95, nt,

a- os/2 bitmap array

i- os/2 color icon

p- os/2 color pointer

c- os/2 icon

t- os/2 pointer

0002h

file size

1 dword

complete file size in bytes.

0006h

reserved

1 dword

reserved for later use.

000ah

bitmap data offset

1 dword

offset from beginning of file to the beginning of the bitmap data.

000eh

bitmap header size

1 dword

length of the bitmap info header used to describe the bitmap colors, compression,

the following sizes are possible:

28h - windows 3.1x, 95, nt,

0ch - os/2 1.x

f0h - os/2 2.x

0012h

width

1 dword

horizontal width of bitmap in pixels.

0016h

height

1 dword

vertical height of bitmap in pixels.

001ah

planes

1 word

number of planes in this bitmap.

001ch

bits per pixel

1 word

bits per pixel used to store palette entry information. this also identifies in an indirect way the number of possible colors. possible values are:

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

compression specifications. the following values are possible:

0 - none (also identified by bi_rgb)

1 - rle 8-bit / pixel (also identified by bi_rle4)

2 - rle 4-bit / pixel (also identified by bi_rle8)

3 - bitfields (also identified by bi_bitfields)

0022h

bitmap data size

1 dword

size of the bitmap data in bytes. this number must be rounded to the next 4 byte boundary.

0026h

hresolution

1 dword

horizontal resolution expressed in pixel per meter.

002ah

vresolution

1 dword

vertical resolution expressed in pixels per meter.

002eh

colors

1 dword

number of colors used by this bitmap. for a 8-bit / pixel bitmap this will be 100h or 256.

0032h

important colors

1 dword

number of important colors. this number will be equal to the number of colors when every color is important.

0036h

palette

n * 4 byte

the palette specification. for every entry in the palette four bytes are used to describe the rgb values of the color in the following way:

1 byte for blue component

1 byte for green component

1 byte for red component

1 byte filler which is set to 0 (zero)

0436h

bitmap data

x bytes

depending on the compression specifications, this field contains all the bitmap data bytes which represent indices in the color palette.

 

note:

the following sizes were used in the specification above:

size

# bytes

sign

char

1

signed

word

2

unsigned

dword

4

unsigned

field details

some of the fields require some more information. the following chapters will try to provide this information:

height field

the height field identifies the height of the bitmap in pixels. in other words, it describes the number of scan lines of the bitmap. if this field is negative, indicating a top-down dib, the compression field must be either bi_rgb or bi_bitfields. top-down dibs cannot be compressed.

bits per pixel field

the bits per pixel (bbp) field of the bitmap file determines the number of bits that define each pixel and the maximum number of colors in the bitmap.

    • when this field is equal to 1.

    the bitmap is monochrome, and the palette contains two entries. each bit in the bitmap array represents a pixel. if the bit is clear, the pixel is displayed with the color of the first entry in the palette; if the bit is set, the pixel has the color of the second entry in the table.

     

      • when this field is equal to 4.

      the bitmap has a maximum of 16 colors, and the palette contains up to 16 entries. each pixel in the bitmap is represented by a 4-bit index into the palette. for example, if the first byte in the bitmap is 1fh, the byte represents two pixels. the first pixel contains the color in the second palette entry, and the second pixel contains the color in the sixteenth palette entry.

       

        • when this field is equal to 8.

        the bitmap has a maximum of 256 colors, and the palette contains up to 256 entries. in this case, each byte in the array represents a single pixel.

         
          • when this field is equal to 16.

        the bitmap has a maximum of 2^16 colors. if the compression field of the bitmap file is set to bi_rgb, the palette field does not contain any entries. each word in the bitmap array represents a single pixel. the relative intensities of red, green, and blue are represented with 5 bits for each color component. the value for blue is in the least significant 5 bits, followed by 5 bits each for green and red, respectively. the most significant bit is not used.

        if the compression field of the bitmap file is set to bi_bitfields, the palette field contains three dword color masks that specify the red, green, and blue components, respectively, of each pixel. each word in the bitmap array represents a single pixel.

        windows nt specific:

        when the compression field is set to bi_bitfields, bits set in each dword mask must be contiguous and should not overlap the bits of another mask. all the bits in the pixel do not have to be used.

        windows 95 specific:

        when the compression field is set to bi_bitfields, windows 95 supports only the following 16bpp color masks: a 5-5-5 16-bit image, where the blue mask is 0x001f, the green mask is 0x03e0, and the red mask is 0x7c00; and a 5-6-5 16-bit image, where the blue mask is 0x001f, the green mask is 0x07e0, and the red mask is 0xf800.

         
          • when this field is equal to 24.

        the bitmap has a maximum of 2^24 colors, and the palette field does not contain any entries. each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, and red, respectively, for a pixel.

         

          • when this field is equal to 32.

          the bitmap has a maximum of 2^32 colors. if the compression field of the bitmap is set to bi_rgb, the palette field does not contain any entries. each dword in the bitmap array represents the relative intensities of blue, green, and red, respectively, for a pixel. the high byte in each dword is not used.

          if the compression field of the bitmap is set to bi_bitfields, the palette field contains three dword color masks that specify the red, green, and blue components, respectively, of each pixel. each dword in the bitmap array represents a single pixel.

          windows nt specific:

          when the compression field is set to bi_bitfields, bits set in each dword mask must be contiguous and should not overlap the bits of another mask. all the bits in the pixel do not have to be used.

          windows 95 specific:

          when the compression field is set to bi_bitfields, windows 95 supports only the following 32bpp color mask: the blue mask is 0x000000ff, the green mask is 0x0000ff00, and the red mask is 0x00ff0000.

          compression field

          the compression field specifies the way the bitmap data is stored in the file. this information together with the bits per pixel (bpp) field identifies the compression algorithm to follow.

          the following values are possible in this field:

          value

          meaning

          bi_rgb

          an uncompressed format.

          bi_rle4

          an rle format for bitmaps with 4 bits per pixel. the compression format is a two-byte format consisting of a count byte followed by two word-length color indices. for more information, see the following remarks section.

          bi_rle8

          a run-length encoded (rle) format for bitmaps with 8 bits per pixel. the compression format is a two-byte format consisting of a count byte followed by a byte containing a color index. for more information, see the following remarks section.

          bi_bitfields

          specifies that the bitmap is not compressed and that the color table consists of three double word color masks that specify the red, green, and blue components, respectively, of each pixel. this is valid when used with 16- and 32- bits-per-pixel bitmaps.

          when the compression field is bi_rle8, the bitmap is compressed by using a run-length encoding (rle) format for an 8-bit bitmap. this format can be compressed in encoded or absolute modes. both modes can occur anywhere in the same bitmap.

            • encoded mode consists of two bytes:

          the first byte specifies the number of consecutive pixels to be drawn using the color index contained in the second byte. in addition, the first byte of the pair can be set to zero to indicate an escape that denotes an end of line, end of bitmap, or delta. the interpretation of the escape depends on the value of the second byte of the pair, which can be one of the following:

          0

          end of line.

          1

          end of bitmap.

          2

          delta. the two bytes following the escape contain unsigned values indicating the horizontal and vertical offsets of the next pixel from the current position.

            • absolute mode.

            the first byte is zero and the second byte is a value in the range 03h through ffh. the second byte represents the number of bytes that follow, each of which contains the color index of a single pixel. when the second byte is 2 or less, the escape has the same meaning as in encoded mode. in absolute mode, each run must be aligned on a word boundary.

             

             

            the following example shows the hexadecimal values of an 8-bit compressed bitmap.

            03 04 05 06 00 03 45 56 67 00 02 78 00 02 05 01 02 78 00 00 09 1e 00 01

            this bitmap would expand as follows (two-digit values represent a color index for a single pixel):

            04 04 04

            06 06 06 06 06

            45 56 67

            78 78

            move current position 5 right and 1 down

            78 78

            end of line

            1e 1e 1e 1e 1e 1e 1e 1e 1e

            end of rle bitmap

             

            when the compression field is bi_rle4, the bitmap is compressed by using a run-length encoding format for a 4-bit bitmap, which also uses encoded and absolute modes:

              • in encoded mode.

            the first byte of the pair contains the number of pixels to be drawn using the color indices in the second byte. the second byte contains two color indices, one in its high-order four bits and one in its low-order four bits. the first of the pixels is drawn using the color specified by the high-order four bits, the second is drawn using the color in the low-order four bits, the third is drawn using the color in the high-order four bits, and so on, until all the pixels specified by the first byte have been drawn.

              • in absolute mode.

              the first byte is zero, the second byte contains the number of color indices that follow, and subsequent bytes contain color indices in their high- and low-order four bits, one color index for each pixel. in absolute mode, each run must be aligned on a word boundary.

              the end-of-line, end-of-bitmap, and delta escapes described for bi_rle8 also apply to bi_rle4 compression.

               

              the following example shows the hexadecimal values of a 4-bit compressed bitmap.

              03 04 05 06 00 06 45 56 67 00 04 78 00 02 05 01 04 78 00 00 09 1e 00 01

              this bitmap would expand as follows (single-digit values represent a color index for a single pixel):

              0 4 0

              0 6 0 6 0

              4 5 5 6 6 7

              7 8 7 8

              move current position 5 right and 1 down

              7 8 7 8

              end of line

              1 e 1 e 1 e 1 e 1

              end of rle bitmap

              colors field

              the colors field specifies the number of color indices in the color table that are actually used by the bitmap. if this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the bbp field for the compression mode specified by the compression field.

              if the colors field is nonzero and the bbp field less than 16, the colors field specifies the actual number of colors the graphics engine or device driver accesses.

              if the bbp field is 16 or greater, then colors field specifies the size of the color table used to optimize performance of windows color palettes.

              if bbp equals 16 or 32, the optimal color palette starts immediately following the three double word masks.

              if the bitmap is a packed bitmap (a bitmap in which the bitmap array immediately follows the bitmap header and which is referenced by a single pointer), the colors field must be either 0 or the actual size of the color table.

              important colors field

              the important colors field s

              pecifies the number of color indices that are considered important for displaying the bitmap. if this value is zero, all colors are important.

              您可能感兴趣的与本文相关的镜像

              Yolo-v8.3

              Yolo-v8.3

              Yolo

              YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

              #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <linux/input.h> #include <string.h> #include <math.h> #define LCD_WIDTH 800 #define LCD_HEIGHT 480 #define COLOR_RED 0xFF0000 #define COLOR_GREEN 0x00FF00 #define COLOR_BLUE 0x0000FF #define COLOR_YELLOW 0xFFFF00 #define COLOR_MAGENTA 0xFF00FF #define COLOR_CYAN 0x00FFFF #define COLOR_WHITE 0xFFFFFF #define COLOR_BLACK 0x000000 #define COLOR_GRAY 0x808080 #define COLOR_ORANGE 0xFFA500 #define COLOR_LIGHT_GRAY 0xC0C0C0 #define COLOR_DARK_GRAY 0x404040 // BMP文件头结构体(简化版,仅解析24位真彩色BMP) typedef struct { unsigned short bfType; // 文件类型(必须是0x4D42) unsigned int bfSize; // 文件大小 unsigned short bfReserved1; // 保留 unsigned short bfReserved2; // 保留 unsigned int bfOffBits; // 图像数据偏移量 unsigned int biSize; // 信息头大小 int biWidth; // 图像宽度 int biHeight; // 图像高度 unsigned short biPlanes; // 平面数(必须是1) unsigned short biBitCount; // 色深(24位) unsigned int biCompression;// 压缩方式(0=不压缩) unsigned int biSizeImage; // 图像数据大小 int biXPelsPerMeter; // 水平分辨率 int biYPelsPerMeter; // 垂直分辨率 unsigned int biClrUsed; // 使用的颜色数 unsigned int biClrImportant;// 重要颜色数 } BMPHeader; // 全局变量 int colors[] = {COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE}; int current_color_index = 0; int current_brush_size = 2; int *lcd_mem; int lcd_fd; int ts_fd; // 函数声明 void draw_line(int x1, int y1, int x2, int y2, int color, int size); void draw_char_16x16(int x, int y, unsigned char *font, int color); void draw_string_16x16(int x, int y, unsigned char *fonts[], int count, int color); void draw_hints(); void clear_screen(); void draw_circle(int center_x, int center_y, int radius, int color, int fill); void draw_rect(int x1, int y1, int x2, int y2, int color, int fill); // 新增:BMP图片绘制函数 int draw_bmp(int x, int y, const char *bmp_path); // ==================== 16x16点阵字库 ==================== typedef unsigned char uchar; // "颜色切换" uchar font_yan[] = {0x00,0x00,0x7C,0x12,0x11,0x12,0x7C,0x00,0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_se[] = {0x00,0x00,0x3F,0x21,0x21,0x21,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_qie[] = {0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_huan[] = {0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // "笔粗调节" uchar font_bi[] = {0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_cu[] = {0x00,0x00,0x1F,0x11,0x11,0x11,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_tiao[] = {0x00,0x00,0x7C,0x12,0x11,0x12,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_jie[] = {0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // "橡皮擦" uchar font_xiang[] = {0x00,0x00,0x7C,0x0A,0x09,0x0A,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_pi[] = {0x00,0x00,0x3F,0x20,0x20,0x20,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_ca[] = {0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // "一键清除" uchar font_yi[] = {0x00,0x00,0x00,0x7C,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_jian[] = {0x00,0x00,0x38,0x44,0x44,0x10,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_qing[] = {0x00,0x00,0x3C,0x24,0x24,0x24,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar font_chu[] = {0x00,0x00,0x1F,0x01,0x01,0x01,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // ==================== 绘制函数 ==================== // 绘制16x16字符 void draw_char_16x16(int x, int y, uchar *font, int color) { for (int i = 0; i < 16; i++) { for (int j = 0; j < 8; j++) { if (font[i] & (0x80 >> j)) { if (x + j >= 0 && x + j < LCD_WIDTH && y + i >= 0 && y + i < LCD_HEIGHT) { lcd_mem[(y + i) * LCD_WIDTH + (x + j)] = color; } } } for (int j = 0; j < 8; j++) { if (font[i+16] & (0x80 >> j)) { if (x + 8 + j >= 0 && x + 8 + j < LCD_WIDTH && y + i >= 0 && y + i < LCD_HEIGHT) { lcd_mem[(y + i) * LCD_WIDTH + (x + 8 + j)] = color; } } } } } // 绘制16x16字符串 void draw_string_16x16(int x, int y, uchar *fonts[], int count, int color) { for (int i = 0; i < count; i++) { draw_char_16x16(x + i * 16, y, fonts[i], color); } } // 绘制圆形 void draw_circle(int center_x, int center_y, int radius, int color, int fill) { for (int y = -radius; y <= radius; y++) { for (int x = -radius; x <= radius; x++) { if (x*x + y*y <= radius*radius) { int px = center_x + x; int py = center_y + y; if (px >= 0 && px < LCD_WIDTH && py >= 0 && py < LCD_HEIGHT) { if (fill || x*x + y*y >= (radius-1)*(radius-1)) { lcd_mem[py * LCD_WIDTH + px] = color; } } } } } } // 绘制矩形 void draw_rect(int x1, int y1, int x2, int y2, int color, int fill) { if (x1 > x2) { int temp = x1; x1 = x2; x2 = temp; } if (y1 > y2) { int temp = y1; y1 = y2; y2 = temp; } for (int y = y1; y <= y2; y++) { for (int x = x1; x <= x2; x++) { if (x >= 0 && x < LCD_WIDTH && y >= 0 && y < LCD_HEIGHT) { if (fill || x == x1 || x == x2 || y == y1 || y == y2) { lcd_mem[y * LCD_WIDTH + x] = color; } } } } } // 清屏 void clear_screen() { for (int y = 0; y < LCD_HEIGHT; y++) { for (int x = 0; x < LCD_WIDTH; x++) { lcd_mem[y * LCD_WIDTH + x] = COLOR_BLACK; } } } // 绘制BMP图片(仅支持24位真彩色、无压缩BMP) int draw_bmp(int x, int y, const char *bmp_path) { int bmp_fd = open(bmp_path, O_RDONLY); if (bmp_fd < 0) { perror("Open BMP failed"); return -1; } BMPHeader header; // 读取BMP头(注意:BMP是小端存储,x86架构可直接读取) if (read(bmp_fd, &header, sizeof(BMPHeader)) != sizeof(BMPHeader)) { perror("Read BMP header failed"); close(bmp_fd); return -1; } // 校验BMP合法性 if (header.bfType != 0x4D42 || header.biBitCount != 24 || header.biCompression != 0) { fprintf(stderr, "Unsupported BMP format\n"); close(bmp_fd); return -1; } // 计算每行像素的字节数(BMP每行字节数必须是4的倍数) int line_bytes = (header.biWidth * 3 + 3) & ~3; unsigned char *line_buf = malloc(line_bytes); if (!line_buf) { perror("Malloc line buf failed"); close(bmp_fd); return -1; } // 移动文件指针到图像数据起始位置 lseek(bmp_fd, header.bfOffBits, SEEK_SET); // 绘制BMPBMP图像是倒序存储,从下到上绘制) for (int i = 0; i < header.biHeight; i++) { if (read(bmp_fd, line_buf, line_bytes) != line_bytes) { perror("Read BMP data failed"); free(line_buf); close(bmp_fd); return -1; } int draw_y = y + (header.biHeight - 1 - i); // 转换为LCD的Y坐标 if (draw_y < 0 || draw_y >= LCD_HEIGHT) continue; for (int j = 0; j < header.biWidth; j++) { int draw_x = x + j; if (draw_x < 0 || draw_x >= LCD_WIDTH) continue; // BMP是BGR格式,转换为RGB(LCD是RGB格式) unsigned char b = line_buf[j*3]; unsigned char g = line_buf[j*3 + 1]; unsigned char r = line_buf[j*3 + 2]; int color = (r << 16) | (g << 8) | b; lcd_mem[draw_y * LCD_WIDTH + draw_x] = color; } } free(line_buf); close(bmp_fd); return 0; } // 绘制提示区(加载BMP图标) void draw_hints() { // 1. 颜色切换区(0-30行) for (int i = 0; i < 7; i++) { for (int y = 0; y < 30; y++) { for (int x = i * 100; x < (i + 1) * 100; x++) { if (x < LCD_WIDTH) lcd_mem[y * LCD_WIDTH + x] = colors[i]; } } } // 当前颜色指示器 draw_circle(current_color_index * 100 + 50, 15, 8, COLOR_BLACK, 0); // 文字提示:"颜色切换" uchar *str_yanse[] = {&font_yan[0], &font_se[0], &font_qie[0], &font_huan[0]}; draw_string_16x16(720, 5, str_yanse, 4, COLOR_BLACK); draw_string_16x16(718, 7, str_yanse, 4, COLOR_WHITE); // 2. 笔粗调节区(30-60行) for (int y = 30; y < 60; y++) { for (int x = 0; x < LCD_WIDTH; x++) { lcd_mem[y * LCD_WIDTH + x] = COLOR_DARK_GRAY; } } // 画笔图标 draw_rect(20, 35, 40, 50, COLOR_WHITE, 1); draw_rect(45, 35, 65, 50, COLOR_LIGHT_GRAY, 1); draw_line(20, 35, 30, 42, COLOR_BLACK, 1); draw_line(20, 50, 30, 43, COLOR_BLACK, 1); // 画笔预览条 for (int y = 35; y < 55; y++) { for (int x = 80; x < 80 + 20 * current_brush_size; x++) { lcd_mem[y * LCD_WIDTH + x] = COLOR_WHITE; } } // 文字提示:"笔粗调节" uchar *str_bicu[] = {&font_bi[0], &font_cu[0], &font_tiao[0], &font_jie[0]}; draw_string_16x16(150, 35, str_bicu, 4, COLOR_WHITE); // 粗细数字指示 draw_rect(300, 35, 315, 50, COLOR_WHITE, 1); char size_str[2]; sprintf(size_str, "%d", current_brush_size); if (size_str[0] == '1') { draw_rect(304, 38, 306, 47, COLOR_BLACK, 1); } else if (size_str[0] == '2') { draw_rect(302, 38, 308, 41, COLOR_BLACK, 1); draw_rect(308, 41, 308, 44, COLOR_BLACK, 1); draw_rect(302, 44, 308, 47, COLOR_BLACK, 1); draw_rect(302, 47, 302, 50, COLOR_BLACK, 1); draw_rect(302, 50, 308, 50, COLOR_BLACK, 1); } // 3. 橡皮擦区(60-90行,左侧) draw_rect(0, 60, 199, 89, COLOR_WHITE, 0); for (int y = 61; y < 89; y++) { for (int x = 1; x < 199; x++) { lcd_mem[y * LCD_WIDTH + x] = COLOR_BLACK; } } // 加载橡皮BMP图标(替换原手绘图标) draw_bmp(30, 65, "eraser.bmp"); // 文字提示:"橡皮擦" uchar *str_xiangpi[] = {&font_xiang[0], &font_pi[0], &font_ca[0]}; draw_string_16x16(100, 65, str_xiangpi, 3, COLOR_WHITE); // 4. 一键清除区(60-90行,右侧) draw_rect(200, 60, 399, 89, COLOR_BLACK, 0); for (int y = 61; y < 89; y++) { for (int x = 201; x < 399; x++) { lcd_mem[y * LCD_WIDTH + x] = COLOR_WHITE; } } // 加载一键清除BMP图标(替换原手绘图标) draw_bmp(230, 65, "qingchu.bmp"); // 文字提示:"一键清除" uchar *str_qingchu[] = {&font_yi[0], &font_jian[0], &font_qing[0], &font_chu[0]}; draw_string_16x16(300, 65, str_qingchu, 4, COLOR_BLACK); // 5. 分隔线(90行) for (int x = 0; x < LCD_WIDTH; x++) { lcd_mem[90 * LCD_WIDTH + x] = COLOR_GRAY; } } // 流畅画线函数 void draw_line(int x1, int y1, int x2, int y2, int color, int size) { int dx = abs(x2 - x1); int dy = abs(y2 - y1); int sx = (x1 < x2) ? 1 : -1; int sy = (y1 < y2) ? 1 : -1; int err = dx - dy; while (1) { // 圆形画笔 for (int dy_pen = -size; dy_pen <= size; dy_pen++) { for (int dx_pen = -size; dx_pen <= size; dx_pen++) { if (dx_pen*dx_pen + dy_pen*dy_pen <= size*size) { int x = x1 + dx_pen; int y = y1 + dy_pen; if (x >= 0 && x < LCD_WIDTH && y >= 91 && y < LCD_HEIGHT) { lcd_mem[y * LCD_WIDTH + x] = color; } } } } if (x1 == x2 && y1 == y2) break; int e2 = 2 * err; if (e2 > -dy) { err -= dy; x1 += sx; } if (e2 < dx) { err += dx; y1 += sy; } } } // 主函数 int main() { // 打开LCD lcd_fd = open("/dev/fb0", O_RDWR); if (lcd_fd < 0) { perror("Open LCD failed"); return -1; } lcd_mem = (int *)mmap(NULL, LCD_WIDTH*LCD_HEIGHT*4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0); if (lcd_mem == MAP_FAILED) { perror("MMAP LCD failed"); close(lcd_fd); return -1; } // 打开触摸屏 ts_fd = open("/dev/input/event0", O_RDONLY); if (ts_fd < 0) { perror("Open touch failed"); munmap(lcd_mem, LCD_WIDTH*LCD_HEIGHT*4); close(lcd_fd); return -1; } clear_screen(); draw_hints(); struct input_event ev; int prev_x=-1, prev_y=-1, curr_x=-1, curr_y=-1; int is_erasing=0, is_touching=0; while (1) { ssize_t ret = read(ts_fd, &ev, sizeof(ev)); if (ret != sizeof(ev)) { perror("Read touch failed"); continue; } // 更新坐标 if (ev.type == EV_ABS) { if (ev.code == ABS_X) curr_x = ev.value; else if (ev.code == ABS_Y) curr_y = ev.value; } // 触摸按下/抬起 else if (ev.type == EV_KEY && ev.code == BTN_TOUCH) { if (ev.value == 1) { is_touching = 1; // 颜色切换区 if (curr_y < 30) { current_color_index = curr_x / 100; if (current_color_index >=7) current_color_index=6; draw_hints(); } // 笔粗调节区 else if (curr_y < 60) { current_brush_size = (current_brush_size % 5) + 1; draw_hints(); } // 橡皮擦区 else if (curr_y < 90 && curr_x < 200) { is_erasing = 1; // 视觉反馈 draw_rect(0, 60, 199, 89, COLOR_WHITE, 1); draw_bmp(30, 65, "eraser.bmp"); uchar *str_xiangpi[] = {&font_xiang[0], &font_pi[0], &font_ca[0]}; draw_string_16x16(100, 65, str_xiangpi, 3, COLOR_BLACK); usleep(100000); draw_hints(); } // 一键清除区 else if (curr_y < 90 && curr_x >=200 && curr_x <400) { // 视觉反馈 draw_rect(200, 60, 399, 89, COLOR_BLACK, 1); draw_bmp(230, 65, "qingchu.bmp"); uchar *str_qingchu[] = {&font_yi[0], &font_jian[0], &font_qing[0], &font_chu[0]}; draw_string_16x16(300, 65, str_qingchu, 4, COLOR_WHITE); usleep(100000); clear_screen(); draw_hints(); } prev_x = curr_x; prev_y = curr_y; } else { is_touching = 0; is_erasing = 0; prev_x=prev_y=curr_x=curr_y=-1; } } // 绘制 if (is_touching && prev_x!=-1 && prev_y!=-1 && curr_x!=-1 && curr_y!=-1) { if (curr_y >= 91) { int color = is_erasing ? COLOR_BLACK : colors[current_color_index]; draw_line(prev_x, prev_y, curr_x, curr_y, color, current_brush_size); prev_x = curr_x; prev_y = curr_y; } } } // 释放资源 munmap(lcd_mem, LCD_WIDTH*LCD_HEIGHT*4); close(lcd_fd); close(ts_fd); return 0; } 请在对应功能位置给出文本提示,该提示在屏幕上显示
              最新发布
              11-24
              要为C语言编写的LCD触摸屏绘图程序添加对应功能的文本提示并显示在屏幕上,可在原有的绘图功能代码基础上,利用绘图库函数添加文本显示功能。以下结合之前引用中的信息,给出一个示例代码,假设使用的是51单片机和12864显示屏。 ```c // 12864初始化函数 void LCD_Initialization(void) { // 发送初始化指令序列 // 设置显示模式等参数 // 显示初始化提示 // 假设存在一个函数LCD_DisplayText用于显示文本 LCD_DisplayText(0, 0, "Initializing LCD..."); } // 绘制直线函数 void LCD_DrawLine(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2) { // 显示绘制直线提示 LCD_DisplayText(0, 1, "Drawing a line..."); // 计算直线斜率,确定绘制直线算法 // 发送绘图指令 } // 假设的显示文本函数 void LCD_DisplayText(unsigned char x, unsigned char y, char *text) { // 这里需要实现具体的文本显示逻辑,比如根据坐标和字符编码发送指令到LCD // 此函数的具体实现会依赖于LCD的驱动芯片 } ``` 在上述代码中,在`LCD_Initialization`函数里添加了初始化提示,在`LCD_DrawLine`函数里添加了绘制直线的提示。`LCD_DisplayText`函数是一个假设的用于显示文本的函数,实际使用时需要根据具体的LCD驱动芯片来实现该函数。 如果使用Arduino平台和TFT显示屏,结合Adafruit_GFX库,示例代码如下: ```cpp #include <Adafruit_GFX.h> #include <Adafruit_TFTLCD.h> // 定义TFT显示屏引脚 #define TFT_CS 10 #define TFT_DC 9 #define TFT_RST 8 Adafruit_TFTLCD tft(TFT_CS, TFT_DC, TFT_RST); void setup() { // 初始化显示屏 tft.begin(); tft.setRotation(1); // 设置显示方向 // 显示初始化提示 tft.setTextSize(2); tft.setCursor(0, 0); tft.println("Initializing TFT display..."); } void loop() { // 绘制图形示例 tft.setCursor(0, 20); tft.println("Drawing a rectangle..."); tft.fillRect(10, 50, 100, 50, TFT_RED); delay(2000); } ``` 在这个Arduino示例中,在`setup`函数里添加了初始化提示,在`loop`函数里添加了绘制矩形的提示。
              评论 1
              添加红包

              请填写红包祝福语或标题

              红包个数最小为10个

              红包金额最低5元

              当前余额3.43前往充值 >
              需支付:10.00
              成就一亿技术人!
              领取后你会自动成为博主和红包主的粉丝 规则
              hope_wisdom
              发出的红包
              实付
              使用余额支付
              点击重新获取
              扫码支付
              钱包余额 0

              抵扣说明:

              1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
              2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

              余额充值