环境

  1. jpeg库: jpegsr9a  下载地址:http://www.ijg.org/
  2. 编译环境: vs2015
  3. Opencv 3.4.2

一、RGB数组来自BMP文件,直接输出在文件系统上

1.1 代码

void bmptojpg24(const char *strSourceFileName, constchar *strDestFileName)
{BITMAPFILEHEADER bfh;    // bmp文件头BITMAPINFOHEADER bih;    // bmp头信息RGBQUAD rq[256];         // 调色板int i=0,j=0;int nAdjust;// 用于字节对齐int nAdjust24;// 用于字节对齐BYTE *data=NULL;//new BYTE[bih.biWidth*bih.biHeight];BYTE *pData24= NULL;//newBYTE[bih.biWidth*bih.biHeight];int nComponent= 0;// 打开图像文件FILE *f= fopen(strSourceFileName,"rb");if (f==NULL){printf("Open file error!\n");return;}// 读取文件头fread(&bfh,sizeof(bfh),1,f);// 读取图像信息fread(&bih,sizeof(bih),1,f);// 8位字节对齐nAdjust = bih.biWidth%4;if (nAdjust)nAdjust = 4-nAdjust;// 24位字节对齐nAdjust24 = bih.biWidth*3%4;if (nAdjust24)nAdjust24 = 4-nAdjust24;switch (bih.biBitCount){case 8:if (bfh.bfOffBits-1024<54){fclose(f);return;}data= new BYTE[(bih.biWidth+nAdjust)*bih.biHeight];pData24 = new BYTE[(bih.biWidth*3+nAdjust24)*bih.biHeight];// 定位调色板,并读取调色板fseek(f,bfh.bfOffBits-1024,SEEK_SET);fread(rq,sizeof(RGBQUAD),256,f);// 读取位图fread(data,bih.biWidth*bih.biHeight,1,f);fclose(f);nComponent = 3;for (j=0;j<bih.biHeight;j++) {for (i=0;i<bih.biWidth;i++){pData24[j*(bih.biWidth*3+nAdjust24)+i*3] = rq[data[j*(bih.biWidth+nAdjust)+i]].rgbRed;pData24[j*(bih.biWidth*3+nAdjust24)+i*3+1] = rq[data[j*(bih.biWidth+nAdjust)+i]].rgbGreen;pData24[j*(bih.biWidth*3+nAdjust24)+i*3+2] = rq[data[j*(bih.biWidth+nAdjust)+i]].rgbBlue;}}break;case 24:{data= new BYTE[(bih.biWidth*3+nAdjust24)*bih.biHeight];pData24 = new BYTE[(bih.biWidth*3+nAdjust24)*bih.biHeight];fseek(f,bfh.bfOffBits,SEEK_SET); fread(data,(bih.biWidth*3+nAdjust24)*bih.biHeight,1,f);fclose(f);for (j=0;j<bih.biHeight;j++){for (i = 0;i<bih.biWidth;i++){pData24[j*(bih.biWidth*3+nAdjust24)+i*3]= data[j*(bih.biWidth*3+nAdjust24)+i*3+2];pData24[j*(bih.biWidth*3+nAdjust24)+i*3+1]= data[j*(bih.biWidth*3+nAdjust24)+i*3+1];pData24[j*(bih.biWidth*3+nAdjust24)+i*3+2]= data[j*(bih.biWidth*3+nAdjust24)+i*3];}}nComponent = 3;break;}default:fclose(f);return;}// 以上图像读取完毕cout<<"nAdjust24 = "<<nAdjust24<<endl;if(IsMemory){IMGSTRUCT BMP;BMP.Img= pData24;BMP.height= bih.biHeight;BMP.width= bih.biWidth;BMP.nChannel= nComponent;//cout<<"pData24  is "<<strlen(pData24)<<endl;unsigned char *lpDstBuf = new BYTE[(bih.biWidth*3+nAdjust24)*bih.biHeight];memset(lpDstBuf,0,(bih.biWidth*3+nAdjust24)*bih.biHeight);unsigned long  dwDstBufSize ;int quality= 60;//cout<<"lpDstBuf is"<<strlen(lpDstBuf)<<endl;WriteJPEGtoMemory(&BMP,lpDstBuf,dwDstBufSize,quality);f=fopen(strDestFileName,"wb");if (f==NULL){delete [] data;//delete [] pDataConv;return;}fwrite(lpDstBuf,dwDstBufSize,1,f);fclose(f);delete [] data;delete [] pData24;delete [] lpDstBuf;}else{struct jpeg_compress_structjcs;struct jpeg_error_mgrjem;jcs.err= jpeg_std_error(&jem);jpeg_create_compress(&jcs);f=fopen(strDestFileName,"wb");if (f==NULL){delete [] data;//delete [] pDataConv;return;}jpeg_stdio_dest(&jcs, f);jcs.image_width= bih.biWidth;      // 为图的宽和高,单位为像素jcs.image_height= bih.biHeight;jcs.input_components= nComponent;      // 1,表示灰度图,如果是彩色位图,则为if (nComponent==1)jcs.in_color_space = JCS_GRAYSCALE;//JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像elsejcs.in_color_space = JCS_RGB;jpeg_set_defaults(&jcs);jpeg_set_quality(&jcs, 60, true);jpeg_start_compress(&jcs, TRUE);JSAMPROW row_pointer[1];       // 一行位图int row_stride;                // 每一行的字节数row_stride = jcs.image_width*nComponent;    // 如果不是索引图,此处需要乘以// 对每一行进行压缩while (jcs.next_scanline < jcs.image_height) {row_pointer[0] = & pData24[(jcs.image_height-jcs.next_scanline-1)* (row_stride+nAdjust24)];jpeg_write_scanlines(&jcs, row_pointer,1);}jpeg_finish_compress(&jcs);jpeg_destroy_compress(&jcs);fclose(f);delete [] data;delete [] pData24;}
}

1.2    注意
代码中红色标记的代码:

由于BMP图片格式的原因,读入的RGB颜色顺序是BGR形式的,需要调整为RGB顺序:

pData24[j*(bih.biWidth*3+nAdjust24)+i*3]= data[j*(bih.biWidth*3+nAdjust24)+i*3+2];
pData24[j*(bih.biWidth*3+nAdjust24)+i*3+1]= data[j*(bih.biWidth*3+nAdjust24)+i*3+1];
pData24[j*(bih.biWidth*3+nAdjust24)+i*3+2]= data[j*(bih.biWidth*3+nAdjust24)+i*3];

由于BMP格式中,图片原点是存放在右下角的,所以需要将它颠倒为正序。

row_pointer[0] = & pData24[(jcs.image_height-jcs.next_scanline-1) *(row_stride+nAdjust24)];

二、RGB数组来自opencv,直接输出在内存

2.1 代码

//直接将bayer格式的图片转化为RGB顺序
cvCvtColor(param.img, dst,CV_BayerBG2RGB);
//申请输出空间并且初始化
unsigned char  * out = new unsignedchar[size.width*size.height*3];
memset(out,0,size.width*size.height*3);
//JPEG长度
unsigned long  dwDstBufSize ;
//图像质量
int quality = 95;
// quality = 100,1024*768的RGB图片压缩后是500KB左右
// quality = 95,1024*768的RGB图片压缩后是200KB左右
IMGSTRUCT BMP;
BMP.Img = (unsigned char*)dst->imageData;
BMP.height =size.height;
BMP.width = size.width;
BMP.nChannel = 3;
//out中存放是压缩以后jpeg文件的起始地址,dwDstBufSize是文件的长度
WriteJPEGtoMemory(&BMP,out,dwDstBufSize,quality);// 将pbuf中图像数据JPEG编码到内存中, 与WriteJPEG的主要区别:用jpeg_mem_dest()替换jpeg_stdio_dest()
bool WriteJPEGtoMemory(IMGSTRUCT *pbuf,unsigned char *lpDstBuf, unsignedlong & dwDstBufSize,int quality)
{if (pbuf== NULL) {  // MessageBox(NULL,"WriteJPEGtoMemory() -- 传入的图像结构体指针为NULL!", "错误", MB_ICONHAND);return FALSE;}if (pbuf->height <= 0 || pbuf->width <= 0 || pbuf->Img <= NULL){//MessageBox(NULL, "WriteJPEGtoMemory()-- 图像参数有误!", "错误", MB_ICONHAND);return FALSE;}int nbits;//定义压缩信息struct jpeg_compress_structcinfo;//定义错误信息struct my_error_mgrjerr;//为JPEG文件压缩对象分配内存并对其初始化cinfo.err= jpeg_std_error(&jerr.pub);jerr.pub.error_exit = my_error_exit;if (setjmp(jerr.setjmp_buffer)){jpeg_destroy_compress(&cinfo);return FALSE;}jpeg_create_compress(&cinfo);//确定要用于输出压缩的jpeg的数据空间jpeg_mem_dest(&cinfo, &lpDstBuf,&dwDstBufSize); //设置压缩参数cinfo.image_width  = pbuf->width;cinfo.image_height= pbuf->height;if (pbuf->nChannel == 1) {cinfo.input_components = nbits= 1; cinfo.in_color_space = JCS_GRAYSCALE;}else if(pbuf->nChannel== 3) {cinfo.input_components = nbits= 3;cinfo.in_color_space = JCS_RGB;}else {//MessageBox(NULL,"WriteJPEGFile() -- 传入图像结构体颜色通道不正确!", "错误", MB_ICONHAND);jpeg_destroy_compress(&cinfo);return FALSE;}jpeg_set_defaults(&cinfo);jpeg_set_quality(&cinfo, quality,TRUE );//开始压缩jpeg_start_compress(&cinfo, TRUE);//JSAMPROW outRow[1];BYTE * outRow;int i= 0;//unsigned char *outRow;while (cinfo.next_scanline < cinfo.image_height) {outRow = pbuf->Img +(cinfo.next_scanline * pbuf->width * nbits);(void)jpeg_write_scanlines(&cinfo, &outRow,1);i++;//cout<<"i = "<<i<<endl;}cout<<"Memory~"<<endl;//完成压缩jpeg_finish_compress(&cinfo);//释放压缩对象jpeg_destroy_compress(&cinfo);outRow = NULL;return TRUE;
}

2.2    说明
由于这里是直接调用opencv的函数,将输入的RGB数组顺序调整正确了。所以在压缩的时候,直接使用

outRow = pbuf->Img + (cinfo.next_scanline* pbuf->width * nbits);

不用在调整顺序了。

在内存中取出这张的图片的时候,可以直接保存成文件。代码如下:

f=fopen(strDestFileName,"wb");if (f==NULL){delete [] data;//delete [] pDataConv;return;}fwrite(out,dwDstBufSize,1,f);fclose(f);

OpenCV中将RGB数组在内存中压缩成JPEG文件相关推荐

  1. (二十六)、Java数组在内存中如何存放与分配

    Java中有两种类型的数组: 基本数据类型数组: 对象数组: 当一个对象使用关键字"new"创建时,会在堆上分配内存空间,然后返回对象的引用,这对数组来说是一样的,因为数组也是一个 ...

  2. C++ 数组在内存中的分配

    接前一篇的内容,C++中数组在内存中也有静态分配和动态分配的区别.静态数组建立的方式为:A a[],它在栈上分配空间;动态方式是使用new,malloc在堆上分配. 数组要么在静态存储区被创建(如全局 ...

  3. 初识java中数组、数组在内存中、越界异常、空指针异常

    数组: 当存储多个数据时,此时可能会使用多个变量,这样不断声明变量会很麻烦,而这些变量都有相似的特性,因此我们可以将它们存放到一个容器中,统一处理. 容器:是将多个数据存储到一起,每个数据称为该容器的 ...

  4. Java数组在内存中的分配

    Java数组在内存中的分配 在Java中,数组存储对象的原始值(int,char,...)或引用(也称为指针). 使用"new"创建对象时,会在堆中分配一个内存空间并返回一个引用. ...

  5. c语言二维数组存储坐标,C语言的二维数组在内存中的存放顺序

    C语言的二维数组在内存中的存放顺序 发布时间:2020-06-28 18:23:49 来源:亿速云 阅读:708 作者:Leah 这期内容当中小编将会给大家带来有关C语言的二维数组在内存中的存放顺序, ...

  6. Java 数组在内存中的存储 数组的常见操作

    Java虚拟机的内存划分 为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式. JVM的内存划分: 区域名称 作用 寄存器 给CPU使用,和我们开发无关 ...

  7. Python中利用numpy将数组(矩阵)存成csv文件,将csv文件读取为数组(矩阵)

    Python中利用numpy将数组(矩阵)存成csv文件,将csv文件读取为数组(矩阵) 本博客转载自:https://blog.csdn.net/vernice/article/details/50 ...

  8. 【Java-IO】File、搜索删除剪切、字符集、字符编码、字节流、将内存中的数据写入文件、字符流、缓冲流、Scanner、格式化输出、数据流、对象流、序列化与反序列化、Files工具类

    IO 文章目录 IO 简介 File 分隔符.大小写 常用方法 练习:搜索.删除.剪切 字符集(Character Set) 字符编码(Character Encoding) 字符编码比较 乱码 字节 ...

  9. 将文件夹压缩成zip文件

    一 代码 package ZipFile;import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUt ...

最新文章

  1. IBatis.Net学习笔记四--数据库的缓存模式
  2. Java初学者入门经典:面向对象的思维方法(其实同样非常适合C#的初学者)……非原创,作者忘了,非常抱歉...
  3. Kibana入门安装与介绍
  4. 计算图像的直方图,求峰值点
  5. 数据仓库与数据挖掘(一)
  6. 扩展DOM有什么问题
  7. 【Python】Qt国际化ts文件转excel文件(xml转excel)
  8. 一款超好用的er图制作软件
  9. 微信小程序分享和转发朋友圈功能
  10. 微信小程序转发功能的实现
  11. 物联网-UWB定位技术
  12. python在使用pyinstaller打包文件时提示找不到指定模块
  13. 【论文笔记】Toward A Thousand Lights Decentralized Deep Reinforcement Learning for Large-Scale TSC...
  14. 香港恒生银行App下载
  15. Linux内存管理 —— 为buddy做准备:MMU, TLB, ZONE
  16. Python GDAL矢量转栅格详解
  17. P2254 [NOI2005] 瑰丽华尔兹
  18. 从量变到质变,新华三不求最大但求最强
  19. dede织梦CMS安装页面出现dir的通用安装教程
  20. JSP学习(1)—— 基本语法

热门文章

  1. MySQL查看修改存储引擎总结
  2. 最好的.NET开源免费ZIP库DotNetZip(.NET组件介绍之三)
  3. 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句
  4. 三个关于“契约精神”的故事(转)
  5. ROS Nodelet使用
  6. 另5个你不知道的HTML5接口API
  7. 认识 Express 的 res.send() 和 res.end()
  8. 天津科技大学计算机科学与技术专业怎么样,2021年天津科技大学重点专业排名有哪些,招生优势专业排行榜...
  9. javascript在IE和Firefox中兼容性问题
  10. 全国各地 DNS 服务器 IP 总汇