jpg图片解码
来源:互联网 发布:系统检测安全数据 编辑:程序博客网 时间:2024/05/29 21:36
1. bmp 图片格式
bmp :位图像素文件
- 文件头部
/* 位图文件的文件头 */struct BitMapPicHeader{ unsigned short bfType; /* 类型,必须是 0x4d42 */ unsigned long bfSize; /* 该文件的大小 */ unsigned short bfReserved1; /* 保留,不使用 */ unsigned short bfReserved2; unsigned long bfOffBytes; /* 像素数据的偏移地址 */};/* 位图文件的信息头 */struct BitMapPicInfoHeader{ unsigned long biSize; /* 信息头的大小,就是该结构体的大小 */ unsigned long biWidth; /* 图片的宽高 */ unsigned long biHeight; unsigned short biPlanes; /* */ unsigned short biBitCount; /* 像素位宽 */ unsigned long biCompression; unsigned long biSizeImage; /* 像素总大小,也就是图片大小 */ unsigned long biXPelsPerMeter; /* X 分辨率 */ unsigned long biYPelsPerMeter; /* Y 分辨率 */ unsigned long biClrUsed; unsigned long biClrImportant;};
- 剩下的就是像素数据,这些数据是未经过压缩的数据。
- BMP 24位像素的组织方式是 BGR 格式,而不是普通的 RGB
- 它的最后一行像素数据是实际上图片的第一行像素数据,依次往上分别是对应的图片从上到下的像素数据
- 它的像素数据是 4 字节对齐的,也就是一行像素数据如果不够 4 字节的倍数会自动补齐 4 个字节,那几个是空值,我们在读取的时候不需要,这个是跟 windows 系统有关系的
static void ConvertOneLine(int iSrcBpp, int iDesBpp, unsigned char *pucSrcPiexl, unsigned char *pucDesPiexl, int iConvLen){ int iPixelNum = 0; int iRed; int iGreen; int iBlue; unsigned short *pwDes16Bpp = (unsigned short *)pucDesPiexl; unsigned int *pdwDes32Bpp = (unsigned int *)pucDesPiexl; switch(iDesBpp){ case 16: { for(iPixelNum = 0; iPixelNum < iConvLen; iPixelNum ++){ iBlue = pucSrcPiexl[3*iPixelNum]; iGreen = pucSrcPiexl[3*iPixelNum + 1]; iRed = pucSrcPiexl[3*iPixelNum + 2]; iRed = iRed >> 3; iGreen = iGreen >> 2; iBlue = iBlue>> 3; pwDes16Bpp[iPixelNum] = ((iRed << 11) | (iGreen << 5) | (iBlue << 0)); } break; } case 32: { for(iPixelNum = 0; iPixelNum < iConvLen; iPixelNum ++){ iBlue = pucSrcPiexl[3*iPixelNum]; iGreen = pucSrcPiexl[3*iPixelNum + 1]; iRed = pucSrcPiexl[3*iPixelNum + 2]; pdwDes32Bpp[iPixelNum] = (iRed << 16) | (iGreen << 8) | (iBlue << 0); } break; } default : break; }}/* ptPiexlDatasDesc->iBpp = iBpp; * 要从外部输入 */static int BMPGetPiexlDatas(struct FileDesc *ptFileDesc, struct PiexlDatasDesc *ptPiexlDatasDesc){ unsigned char *BMPFileMem; struct BitMapPicHeader *ptBMPHeader; struct BitMapPicInfoHeader *ptBMPInfoHeader; int iWidth; int iHeight; int iBMPLineWidth; int iBpp; int iLineNum = 0; unsigned char *pucPiexlSrc; unsigned char *pucPiexlDes; ptBMPHeader = (struct BitMapPicHeader*)ptFileDesc->pucFileMem; ptBMPInfoHeader = (struct BitMapPicInfoHeader*)(ptFileDesc->pucFileMem + sizeof(struct BitMapPicHeader)); BMPFileMem = ptFileDesc->pucFileMem; iWidth = ptBMPInfoHeader->biWidth; iHeight = ptBMPInfoHeader->biHeight; iBpp = ptBMPInfoHeader->biBitCount; if(iBpp != 24){ DebugPrint(DEBUG_ERR"BMP bpp = %d\n", iBpp); return -1; } ptPiexlDatasDesc->iWidth = iWidth; ptPiexlDatasDesc->iHeight = iHeight; ptPiexlDatasDesc->iLineLength = iWidth * ptPiexlDatasDesc->iBpp / 8; ptPiexlDatasDesc->iTotalLength= iHeight * ptPiexlDatasDesc->iLineLength;// DebugPrint("iLineLength = %d\n", ptPiexlDatasDesc->iLineLength); ptPiexlDatasDesc->pucPiexlDatasMem = malloc(ptPiexlDatasDesc->iTotalLength); if(NULL == ptPiexlDatasDesc->pucPiexlDatasMem){ DebugPrint(DEBUG_ERR"Has no space for PiexlDatasMem\n"); return -1; } /* BMP 位图的像素数据 4 字节对齐,但是 LCD 屏的像素数据不需要对齐 */ iBMPLineWidth = (iWidth * iBpp / 8 + 3) & ~0x03; pucPiexlSrc = (unsigned char *)(BMPFileMem + ptBMPHeader->bfOffBytes); pucPiexlSrc += (iHeight - 1) * iBMPLineWidth; pucPiexlDes = ptPiexlDatasDesc->pucPiexlDatasMem; for(iLineNum = 0; iLineNum < iHeight; iLineNum ++){ ConvertOneLine(iBpp, ptPiexlDatasDesc->iBpp, pucPiexlSrc, pucPiexlDes, iWidth); pucPiexlSrc -= iBMPLineWidth; pucPiexlDes += ptPiexlDatasDesc->iLineLength; } return 0; }
2. jpeg 图片
没有去关注过 jpeg 文件的文件格式,只是用 libjpeg-turbo 进行文件的读取,解压缩
2.1 libjpeg 库的安装
下载
https://sourceforge.net/projects/libjpeg-turbo/安装
mkdir tmpCC= arm-linux-gcc./configure --host=arm-linux --prefix=/work/testfile/digital_prj/libjpeg/libjpeg-turbo-1.5.0/tmpmakemake install
- 拷贝库文件到交叉编译工具链
sudo cp ./lib/*.so* /work/tools/opt/FriendlyARM/toolschain/4.4.3/lib -drfsudo cp ./include/* /work/tools/opt/FriendlyARM/toolschain/4.4.3/include/ -drf
- 拷贝库文件到 arm 开发板上面
cp ../libjpeg-turbo-1.5.0/tmp/lib/*so* /lib/
2.2 libjpeg 的使用
- 解压缩:
- 分配并且初始化一个 JPEG 解压缩结构体对象
- 指定要解压的压缩文件,jpg 格式的
- 调用 jpeg_read_header() 来获得图像信息
- 设置结构体成员
- jpeg_start_decompress(…); 开始解压缩
- while (scan lines remain to be read)
jpeg_read_scanlines(…);
开始不断的扫描读取点数据 - jpeg_finish_decompress(…); 结束解压过程
- 释放 JPEG 解压缩结构体
实例:
#include <stdio.h>#include <stdlib.h>#include <jpeglib.h>#include <setjmp.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <linux/fb.h>#include <unistd.h>#include <sys/mman.h>#include <sys/ioctl.h>static struct fb_var_screeninfo g_tFBVar; static struct fb_fix_screeninfo g_tFBFix;static unsigned int g_dwFBScreenSize = 0;static unsigned char *g_pucFBMem = NULL;static int g_FBfd;static unsigned int g_dwScreenWidth;static unsigned int g_dwScreenHight;static unsigned int g_dwPixelWidth;static int FBDisDeviceInit(void){ int iError; g_FBfd = open("/dev/fb0", O_RDWR); if (g_FBfd < 0){ printf("Can't open /dev/fb0\n"); return -1; } iError = ioctl(g_FBfd, FBIOGET_VSCREENINFO, &g_tFBVar); if (iError){ printf("Can't get the framebuffer screen info\n"); return -1; } iError = ioctl(g_FBfd, FBIOGET_FSCREENINFO, &g_tFBFix); if (iError){ printf("Can't get the fix info\n"); return -1; } g_dwFBScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8; g_pucFBMem = (unsigned char *)mmap(NULL, g_dwFBScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_FBfd, 0); if(g_pucFBMem == (unsigned char *)-1){ printf("mmap g_pucFBMem failed\n"); return -1; } g_dwScreenWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8; g_dwScreenHight = g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8; g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8; return 0;}static int FBShowPiexl(int iPenX, int iPeny, unsigned int dwColor){ int iRed, iGreen, iBlue; unsigned char *pucPen8bpp; unsigned short *pwPen16bpp; unsigned int *pdwPen32bpp; if(iPenX > g_dwScreenWidth || iPeny > g_dwScreenHight){ printf("Out of screen\n"); return -1; } pucPen8bpp = (unsigned char *) g_pucFBMem + (iPeny * g_tFBVar.xres + iPenX) * g_tFBVar.bits_per_pixel / 8; pwPen16bpp = (unsigned short *) g_pucFBMem + (iPeny * g_tFBVar.xres + iPenX) * g_tFBVar.bits_per_pixel / 16; pdwPen32bpp = (unsigned int *) g_pucFBMem + (iPeny * g_tFBVar.xres + iPenX) * g_tFBVar.bits_per_pixel / 32; switch(g_tFBVar.bits_per_pixel){ case 8: { *pucPen8bpp = dwColor; break; } case 16: { iRed = (dwColor >> 16) & 0xff; iGreen = (dwColor >> 8) & 0xff; iBlue = (dwColor >> 0) & 0xff; dwColor = ((iRed >> 3) << 11) | ((iGreen >> 2) << 5) | ((iBlue >> 3)); *pwPen16bpp = dwColor; break; } case 32: { *pdwPen32bpp = dwColor; break; } default:{ printf("Can't support bpp %d\n", g_tFBVar.bits_per_pixel); break; } } return 0;}static int FBCleanScreen(unsigned int dwBackColor){ int iRed, iGreen, iBlue; unsigned char *pucPen8bpp; unsigned short *pwPen16bpp; unsigned int *pdwPen32bpp; unsigned int i = 0; pucPen8bpp = (unsigned char *) g_pucFBMem; pwPen16bpp = (unsigned short *) g_pucFBMem; pdwPen32bpp = (unsigned int *) g_pucFBMem; switch(g_tFBVar.bits_per_pixel){ case 8: { memset(pucPen8bpp, dwBackColor, g_dwFBScreenSize); break; } case 16: { iRed = (dwBackColor >> 16) & 0xff; iGreen = (dwBackColor >> 8) & 0xff; iBlue = (dwBackColor >> 0) & 0xff; dwBackColor = ((iRed >> 3) << 11) | ((iGreen >> 2) << 5) | ((iBlue >> 3)); for(i = 0; i < g_dwFBScreenSize; i += 2){ pwPen16bpp[i/2] = dwBackColor; } break; } case 32: { for(i = 0; i < g_dwFBScreenSize; i += 4){ pdwPen32bpp[i/4] = dwBackColor; } break; } default:{ printf("Can't support bpp %d\n", g_tFBVar.bits_per_pixel); break; } } return 0;}int FbDrawLines(int iXStart, int iXEnd, int iYStart, unsigned char *pucLineBuff, int iPiexlLength){ int iNPiexlNum; unsigned int dwRed; unsigned int dwGreen; unsigned int dwBlue; unsigned int dwColor; if(iYStart >= g_tFBVar.yres){ return -1; } for(iNPiexlNum = iXStart * iPiexlLength; iNPiexlNum < iXEnd * iPiexlLength; iNPiexlNum += iPiexlLength){ if(iNPiexlNum / iPiexlLength >= g_tFBVar.xres){ return -1; } dwRed = pucLineBuff[iNPiexlNum]; dwGreen = pucLineBuff[iNPiexlNum + 1]; dwBlue = pucLineBuff[iNPiexlNum + 2]; dwColor = (dwRed << 16) | (dwGreen << 8) | (dwBlue << 0); FBShowPiexl(iNPiexlNum / iPiexlLength, iYStart, dwColor); } return 0;}static void JPGErrorExit(j_common_ptr ptCInfo){ static char errStr[JMSG_LENGTH_MAX]; struct JPGErrorMgr *ptJPGError; ptJPGError = (struct JPGErrorMgr *)ptCInfo->err; /* 创建信息 */ (*ptCInfo->err->format_message)(ptCInfo, errStr); DebugPrint("%s\n", errStr); longjmp(ptJPGError->setjmp_buffer, 1);}int main(int argc, char *argv[]){ struct jpeg_decompress_struct tJpegInfo; struct jpeg_error_mgr tJpegPub; char cScale[10]; int iSacnlines; unsigned char *pucScanBuffer; int iLineBufferLength; int iError = 0; FILE *ptJpegFile; if(argc != 2){ printf("exe <file.jpg>\n"); return -1; } iError = FBDisDeviceInit(); if(iError){ printf("No such device\n"); return -1; } FBCleanScreen(0); ptJpegFile = fopen(argv[1], "rb"); /* 只读,二进制 */ if(ptJpegFile == NULL){ printf("Open jpeg file failed\n"); return -1; } tJpegInfo.err = jpeg_std_error(&tJpegPub); tJpegPub.error_exit = JPGErrorExit; /* 不使用 libjpeg 库提供的退出函数,那个会导致整个进程直接退出 */ /* 分配一个解压缩结构体 */ jpeg_create_decompress(&tJpegInfo); /* 指定数据文件 */ jpeg_stdio_src(&tJpegInfo, ptJpegFile); printf("Where did this program exit\n"); /* 读取文件头部 */ jpeg_read_header(&tJpegInfo, TRUE); printf("input weight = %d\n", tJpegInfo.image_width); printf("input height = %d\n", tJpegInfo.image_height); printf("input color components = %d\n", tJpegInfo.num_components); scanf("%d/%d", &tJpegInfo.scale_num, &tJpegInfo.scale_denom); printf("scale %d/%d\n", tJpegInfo.scale_num, tJpegInfo.scale_denom); /* 开始解压缩 */ jpeg_start_decompress(&tJpegInfo); printf("out weight = %d\n", tJpegInfo.output_width); printf("out height = %d\n", tJpegInfo.output_height); printf("out color components = %d\n", tJpegInfo.output_components); iLineBufferLength = tJpegInfo.output_width * tJpegInfo.output_components; pucScanBuffer = malloc(iLineBufferLength); if(NULL == pucScanBuffer){ printf("No space for line-buff\n"); goto exit; } /* 不断地逐行读取数据 */ for (iSacnlines = 0; iSacnlines < tJpegInfo.output_height; iSacnlines ++){ /* 每次读取一行的数据 */ jpeg_read_scanlines(&tJpegInfo, &pucScanBuffer, 1); FbDrawLines(0, tJpegInfo.output_width,iSacnlines, pucScanBuffer, tJpegInfo.output_components); } /* 结束解压缩 */ jpeg_finish_decompress(&tJpegInfo); /* 释放结构体 */ jpeg_destroy_decompress(&tJpegInfo); free(pucScanBuffer);exit: /* 关闭文件 */ fclose(ptJpegFile); return 0;}
0 0
- jpg图片解码
- ffmpeg解码JPG和PNG等图片
- ffmpeg解码JPG和PNG等图片
- 使用系统imgdecmp库解码JPG,GIF,PNG,BMP图片
- 使用系统imgdecmp库解码JPG,GIF,PNG,BMP图片
- 关于JPG图片之JPEG编解码过程详解
- JPEG解码,解决JPG图片显示成花屏的问题
- FFmpeg解码视频帧为jpg图片保存到本地
- libjpeg库编码图片为jpg(ffmpeg解码视频存储图片:RGB格式位图压缩为jpg格式图片)
- libjpeg库编码图片为jpg(ffmpeg解码视频存储图片:RGB格式位图压缩为jpg格式图片)
- 实验五-jpg解码
- JPG解码库的应用
- JPG文件编解码详解
- jpg图像的编解码
- Android jpg图像解码崩溃
- java生成jpg图片
- 合并jpg图片
- C# JPG图片压缩
- MySQL快速入门02----数据库操作和表操作
- 结合使用Canvas API与History API——模拟绘图
- MongoDB学习(二) 下载和安装
- PyGobject(一百零八)CSS系列——混合模式
- 第三方支付宝API应用流程
- jpg图片解码
- 状态压缩DP POJ 2411 Mondriaan's Dream
- 操作系统页面置换算法之最优置换(OPT)算法
- 快排,二叉树的逐层遍历(面试常考)
- 添加全局的css样式
- JS中对Cookie的操作详解
- Mac 上升级Ruby
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 9-14
- 杭电1438 钥匙计数一