企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
**一、交叉编译libjpeg** ~~~ # tar -xzvf libjpeg-turbo-1.2.1.tar.gz  #cd libjpeg-turbo-1.2.1 #mkdir tmp # ./configure --prefix=$PWD/tmp --host=arm-linux #make #make install                /* 会安装在当前目录下面tmp目录里面 */  ~~~ **二、交叉编译jpg2rgb.c** 方法一:编译器后面直接跟上头文件,库文件。路径是我们开始编译出来的路径。 arm-linux-gcc -o jpg2rgb jpg2rgb.c -I /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/include  -L /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/lib  -ljpeg cp jpg2rgb /work/nfs_root/fs_mini_mdev_new cp libjpeg-turbo-1.2.1/tmp/lib/*so* /work/nfs_root/fs_mini_mdev_new/lib/ -d 方法二:把库文件,头文件放在交叉编译里面库文件,头文件的路径下面。 把编译出来的头文件应该放入:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include cd  /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/include cp  *   /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include 把编译出来的库文件应该放入:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib cd  /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/lib cp *so*  -d   /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib  cp *so* /work/nfs_root/      /* 把库文件复制到开发板lib目录下,我们用的是动态库所以需要拷贝 */ arm-linux-gcc -o jpg2rgb jpg2rgb.c -ljpeg      /* 要指定jpeg库,数学库则指定m */  jpg2rgb.c文件如下: ~~~ #include <stdio.h> #include "jpeglib.h" #include <setjmp.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/fb.h> #include <string.h> #include <stdlib.h> #define FB_DEVICE_NAME "/dev/fb0"   /* 指定lcd驱动自动创建的设别节点名 */ #define DBG_PRINTF  printf                /* 方便调试打印 */ static int g_fd; static struct fb_var_screeninfo g_tFBVar;    /* lcd相关的参数,在这篇文章中重点是libjpeg */ static struct fb_fix_screeninfo g_tFBFix; static unsigned char *g_pucFBMem; static unsigned int g_dwScreenSize; static unsigned int g_dwLineWidth; static unsigned int g_dwPixelWidth; static int FBDeviceInit(void) { int ret; g_fd = open(FB_DEVICE_NAME, O_RDWR); if (0 > g_fd) { DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME); } ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar); if (ret < 0) { DBG_PRINTF("can't get fb's var\n"); return -1; } ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix); if (ret < 0) { DBG_PRINTF("can't get fb's fix\n"); return -1; } g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8; g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0); if (0 > g_pucFBMem) { DBG_PRINTF("can't mmap\n"); return -1; } g_dwLineWidth  = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8; g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8; return 0; } static int FBShowPixel(int iX, int iY, unsigned int dwColor) { unsigned char *pucFB; unsigned short *pwFB16bpp; unsigned int *pdwFB32bpp; unsigned short wColor16bpp; /* 565 */ int iRed; int iGreen; int iBlue; if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres)) { DBG_PRINTF("out of region\n"); return -1; } pucFB      = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX; pwFB16bpp  = (unsigned short *)pucFB; pdwFB32bpp = (unsigned int *)pucFB; switch (g_tFBVar.bits_per_pixel) { case 8: { *pucFB = (unsigned char)dwColor; break; } case 16: { iRed   = (dwColor >> (16+3)) & 0x1f; iGreen = (dwColor >> (8+2)) & 0x3f; iBlue  = (dwColor >> 3) & 0x1f; wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue; *pwFB16bpp= wColor16bpp; break; } case 32: { *pdwFB32bpp = dwColor; break; } default : { DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel); return -1; } } return 0; } static int FBCleanScreen(unsigned int dwBackColor) { unsigned char *pucFB; unsigned short *pwFB16bpp; unsigned int *pdwFB32bpp; unsigned short wColor16bpp; /* 565 */ int iRed; int iGreen; int iBlue; int i = 0; pucFB      = g_pucFBMem; pwFB16bpp  = (unsigned short *)pucFB; pdwFB32bpp = (unsigned int *)pucFB; switch (g_tFBVar.bits_per_pixel) { case 8: { memset(g_pucFBMem, dwBackColor, g_dwScreenSize); break; } case 16: { iRed   = (dwBackColor >> (16+3)) & 0x1f; iGreen = (dwBackColor >> (8+2)) & 0x3f; iBlue  = (dwBackColor >> 3) & 0x1f; wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue; while (i < g_dwScreenSize) { *pwFB16bpp= wColor16bpp; pwFB16bpp++; i += 2; } break; } case 32: { while (i < g_dwScreenSize) { *pdwFB32bpp= dwBackColor; pdwFB32bpp++; i += 4; } break; } default : { DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel); return -1; } } return 0; } static int FBShowLine(int iXStart, int iXEnd, int iY, unsigned char *pucRGBArray) { int i = iXStart * 3; int iX; unsigned int dwColor; if (iY >= g_tFBVar.yres) return -1; if (iXStart >= g_tFBVar.xres) return -1; if (iXEnd >= g_tFBVar.xres) { iXEnd = g_tFBVar.xres; } for (iX = iXStart; iX < iXEnd; iX++) { /* 0xRRGGBB */ dwColor = (pucRGBArray[i]<<16) + (pucRGBArray[i+1]<<8) + (pucRGBArray[i+2]<<0); i += 3; FBShowPixel(iX, iY, dwColor); } return 0; } /* 下面才是本文的重点 */ /* Allocate and initialize a JPEG decompression object    // 分配和初始化一个decompression结构体 Specify the source of the compressed data (eg, a file) // 指定源文件 Call jpeg_read_header() to obtain image info  // 用jpeg_read_header获得jpg信息 Set parameters for decompression  // 设置解压参数,比如放大、缩小 jpeg_start_decompress(...);   // 启动解压:jpeg_start_decompress while (scan lines remain to be read) jpeg_read_scanlines(...);  // 循环调用jpeg_read_scanlines jpeg_finish_decompress(...);  // jpeg_finish_decompress Release the JPEG decompression object  // 释放decompression结构体 */ /* Uage: jpg2rgb <jpg_file>  */ int main(int argc, char **argv) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; FILE * infile; int row_stride; unsigned char *buffer; if (argc != 2) { printf("Usage: \n"); printf("%s <jpg_file>\n", argv[0]); return -1; } if (FBDeviceInit())     /* 初始化Lcd */ { return -1; } FBCleanScreen(0);      /* 清屏lcd */ // 分配和初始化一个decompression结构体 cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); // 指定源文件 if ((infile = fopen(argv[1], "rb")) == NULL) { fprintf(stderr, "can't open %s\n", argv[1]); return -1; } jpeg_stdio_src(&cinfo, infile); // 用jpeg_read_header获得jpg信息 jpeg_read_header(&cinfo, TRUE); /* 源信息 */ printf("image_width = %d\n", cinfo.image_width); printf("image_height = %d\n", cinfo.image_height); printf("num_components = %d\n", cinfo.num_components); // 设置解压参数,比如放大、缩小 printf("enter scale M/N:\n"); scanf("%d/%d", &cinfo.scale_num, &cinfo.scale_denom); printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom); // 启动解压:jpeg_start_decompress jpeg_start_decompress(&cinfo); /* 输出的图象的信息 */ printf("output_width = %d\n", cinfo.output_width); printf("output_height = %d\n", cinfo.output_height); printf("output_components = %d\n", cinfo.output_components); // 一行的数据长度 row_stride = cinfo.output_width * cinfo.output_components; buffer = malloc(row_stride); // 循环调用jpeg_read_scanlines来一行一行地获得解压的数据 while (cinfo.output_scanline < cinfo.output_height)  { (void) jpeg_read_scanlines(&cinfo, &buffer, 1); // 写到LCD去 FBShowLine(0, cinfo.output_width, cinfo.output_scanline, buffer); } free(buffer); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return 0; } ~~~ 上文中红色以下的才是本文的重点,lcd驱动才以前驱动部分已经讲得很明白了。