【转】QImage 图像格式小结

图像的数据是以字节为单位保存的,每一行的字节数必须是4的整数倍,不足的补0。

(因为我们使用的是32操作系统,因此数据是按照32位对齐的,所以每行的字节数必须是4的整数倍也就是说每行的数据位必须是32位的整数倍。)这里是按照我的理解的,貌似错了,修正一下,最近在看数据对齐,这段话先忽略了,没有删掉,是因为,想留个足迹,等我找到合适的答案再贴上来。不过,图像的数据确实是按32位对齐的。

如果不是整数倍,则根据公式: W = ( w * bitcount + 31 )/32 * 4;

注:  w是图像的宽度,bitcount是图像的位深,即32、24等, 计算得到的W是程序中图像每行的字节数。

这里讲述QImage的32、24、8位图。

图像格式:QImage::Format_RGB32 ,QImage::Format_RGB888,QImage::Format_Indexed8。

构造图像:

(1)、QImage myImage1 = QImage(filename);  根据文件名打开图像,如果图像本身是32、24位的,程序中图像是32位的,如果图像本身是8位、1位的,程序中对应为8位、1位。

(2)、QImage myImage2 = QImage(width, height, QImage::Format_…); 根据图像宽高来构造一幅图像,程序会自动根据图像格式对齐图像数据。

操作图像:按照(2)的方式构造图像,在Debug下,如果不给图像myImage2初值,图像不是黑的, 但release下,则构造好的图像默认为黑色。

好了,现在我们需要对图像数据操作,32位图像无疑是最简单的,因为它数据是对齐的。用width表示图像宽度,height表示图像高度。

首先熟悉几个函数:

a、uchar* bits();       可以获取图像的首地址

b、int  byteCount();  图像的总字节数

c、int  bytesPerLine(); 图像每行字节数

1、QImage::Format_RGB32,存入格式为B,G,R,A 对应 0,1,2,3

QImage::Format_RGB888,存入格式为R, G, B 对应 0,1,2

QImage::Format_Indexed8,需要设定颜色表,QVector<QRgb>

灰度图像颜色表设定:

QVector<QRgb>  colorTable;

for(int k=0;k<256;++k)
    {

colorTable.push_back( qRgb(k,k,k) );

}

2、QImage  image32 = QImage(width, height, QImage::Format_32);

QImage  image24 = QImage(width, height, QImage::Format_24);

QImage  image8 = QImage(width, height, QImage::Format_8);

image8.setColorTable(colorTable);

3、需要取每个像素处理,采用指针取值,行扫的方式:

int  lineNum_32 = 0;     //行数

int  pixelsub_32 = 0;    //像素下标

uchar*    imagebits_32 = image32.bits();         //获取图像首地址,32位图

uchar*    imagebits24 = image24.bits();

uchar*    imagebits8 = image8.bits();

for(int i=0; i<height; ++i)

{

//按照通常的理解,我们会如下处理,取每行

lineNum_32 = i * width * 4;                  //对于任意图像,这句没有问题

// lineNum_24 = i * width * 3;             //??当width不是4的整数倍时,这句取不到每行开头

// lineNum_8 = i * width;                 //??当width不是4的整数倍时,这句取不到每行开头

for(int j=0; j<width; ++j)

{

int r_32 = imagebits_32[ lineNum_32 + j * 4 + 2];

int g_32 = imagebits_32[ lineNum_32 + j * 4 + 1];

int b_32 = imagebits_32[ lineNum _32 + j * 4];

// int r_24 = imagebits_24[ lineNum_24 + j * 3];        //注意区别32位的图

// int g_24 = imagebits_24[ lineNum_24 + j *3 + 1];

// int b_24 = imagebits_24[ lineNum_24 + j * 3 + 2];

// int gray_8 = imagebits_8[ lineNum_8 + j];

……

//自己的操作

}

}

//??出问题了,因为实际的图像数据并不是以width为真实宽度的,解决,有两种方法:

第一种方法:自己计算实际的宽度

修改为:

// 获取每行的字节数

int  W_32 = ( width * 32 + 31 )/32 * 4;           //注意这里没有四舍五入,所以不要随意换算

int  W_24 = ( width * 24 + 31 )/32 * 4;

int  W_8 = ( width * 8 + 31)/32 * 4;

//也可以使用QT函数来获取,功能和上面一样

{

int  W_32 = image32.bytesPerLine();

int  W_24 = image24.bytesPerLine();

int  W_8 = image8.bytesPerLine();

}

for(int i=0;  i<height;  ++i)

{

//现在可以按照通常的理解,取每行

lineNum_32 = i * W_32;               //注意,这里不再需要乘倍数了(4, 3等)

// lineNum_24 = i * W_24;

// lineNum_8 = i * W_8;

for(int j=0; j<width; ++j)

{

//这里的操作同上面的一样

}

}

第二种方法:采用scanLine(int)来获取每行的首地址,

for(int i=0; i<height; ++i)

{

imagebits_32 = image32.scanLine(i);

imagebits_24 = image24.scanLine(i);

imagebits_8 = image8.scanLine(i);

for(int j=0; j<width; ++j)

{

int r_32 = imagebits_32[ j * 4 + 2];

int g_32 = imagebits_32[ j * 4 + 1];

int b_32 = imagebits_32[ j * 4];

// int r_24 = imagebits_24[ j * 3];

// int g_24 = imagebits_24[ j *3 + 1];

// int b_24 = imagebits_24[ j * 3 + 2];

// int gray_8 = imagebits_8[ j ];

……

//自己的操作

}

}

OK,上述两种方法的索引就不会出现图像数据偏移的问题

4、大家注意到QImage的这个构造函数了吧,QImage::QImage ( uchar * data, int width, int height, Format format )

嗯,这个函数就是从uchar* 的数据来构造图像,一般我们都可能先将图像数据存在uchar*中,

uchar* data32 = new uchar[ width * height * 4];

uchar* data24 = new uchar[ width * height * 3];

uchar* data8 = new uchar[ width * height];

从data32构造图像,不会有任何问题,但是当width不是4的整数倍时,你就不可能从data24和data8构造出自己想要的数据,程序会挂掉的,因为这两个数组的数据量根本不够一幅图(还记得数据补齐不)。

解决办法:

你需要首先计算出,你的图像的真实数据量(字节数),
可以根据QImage.byteCount()函数来获取图像的字节数,当然,你也可以自己计算,计算公式 byteCount = height *
W;   这里的W就是每行的字节数,上面已经讲过了它的计算方法。

然后,你可以由QByteArray来获取转换的指针数据:

如:你的图像数据放在数组  uchar*  srcData;  中

QByteArray imageByteArray = QByteArray( (const char*)srcData,  byteCount );

uchar*  transData = (unsigned char*)imageByteArray.data();

QImage desImage = QImage(transData, width, height, QImage::Format_…);

嗯,经过上述转换后,transData中将是补齐数据的数组,由此构造的图像不会有任何问题。

【转】QImage 图像格式小结

时间: 2024-10-11 10:35:09

【转】QImage 图像格式小结的相关文章

Qt编程之QImage类小结

最近用Qt做图像处理,以下references是需要用到的 references: http://blog.csdn.net/lyc_daniel/article/details/9193881 http://blog.csdn.net/hxingd/article/details/6972417 http://tracey2076.blog.51cto.com/1623739/539690/

QT使用QgraphicView/Qpainter展示RGB/YUV图像

本文记载说明使用Qt做RGB的渲染流程和问题.笔者认为:做媒体渲染这种数据量大而对象少的应用场景,使用Qpainter更佳,在多种RGB的转换中,YUV转RGB565最小而且字节对齐问题不容易发生,故推荐之. 加入与opengl  ddraw sdl 的 对比. RGB->QImage->QPixMap->Scene->GrapView 图像的数据是以字节为单位保存的,每一行的字节数必须是4的整数倍,不足的补0. (因为我们使用的是32操作系统,因此数据是按照32位对齐的,所以每行

arm、linux、qt项目小结

QT资源文件 1.新建文件或工程 -> qt资源2.添加,资源名称(Image),选择路径,完成3,打开Image.qrc, 添加后缀,一般就是 /4.添加文件,添加图片5. 调用 (:/11.png) 转http://blog.sina.com.cn/s/blog_5c70dfc80100r257.html 在Qt中处理图片一般都要用到QImage类,但是QImage的对象不能够直接显示出来,要想能看到图片,初步发现有两种方法. 一.QImage转QPixmap,然后用QLabel::setP

QImage的浅拷贝与深拷贝

 首先简单说说什么是浅拷贝和深拷贝:浅拷贝就比如像引用类型,而深拷贝就比如值类型,即浅拷贝是共用一块内存的,而深拷贝是复制一份内容.   我们再来看看QImage类的几个构造函数: // 浅拷贝 QImage(uchar * data, int width, int height, Format format) // 浅拷贝 QImage(const uchar * data, int width, int height, Format format) // 浅拷贝 QImage(uchar *

QImage

支持的图像格式: BMP ,GIF , JPG , JPEG, PNG, PBM, PGM, PPM, XBM, XPM //使用给定的大小和格式构造图像 QImage(const QSize &size, Format format) //使用给定的大小和格式构造图像 QImage(int width, int height, Format format) //用给定的宽度.高度和格式构造图像,使用一个已有的内存缓冲区.数据.宽度和高度必须指定像素,数据必须是32位对齐,每个扫描线的图像数据中

乱谈常见图像格式

作者:马健邮箱:[email protected]发布:2013.02.15最后更新:2013.02.19 目录一.BMP二.GIF.PNG三.JPEG(JPG)四.JPEG 2000五.TIFF六.DjVu七.PDF八.小结 CEP.CV.UV中都支持多种图像格式,因此经常有人问我相同的问题:不同的图像格式究竟有什么不同?保存图像的时候究竟应该选择哪种图像格式? 本文希望能够对以上问题给出浅显的回答,当然是否已经浅到能让您理解的程度,就要看造化了. 一.BMP BMP是微软提出的一种图像格式,

【转】OpenCV与CxImage转换(IplImage)、IplImage QImage Mat 格式互转

最近由于在项目中用到了Opencv库,但是为了更好的显示图像还是使用了Cximage库,它可以快捷地存取.显示.转换各种图像.Opencv库用于高级图像处理与识别.为了使Cximage图像与Opencv图像交互,写了个Cximage转换到IplImage的类. OpenCV2CXimage.h #pragma once /* * 类说明:OpenCV图像与CXimage图像互转 * 用于OpenCV的图像与CXimage图像格式互转进行封装. OpenCV的图像位数必须是大等于8的整数倍,支持B

QImage和IplImage转换总结

在arm中做图像处理,因为不支持GTK,一般都会用到QT来实现显示功能,所以不可避免的要涉及到QImage和IplImage两种图像格式之间的转换,下面总结一下转换的方法. (下面格式转换的代码都是网友写的,我这里只是归纳修改了一下) IplImage 转换为 QImage 方法1 [plain] view plain copy QImage *IplImageToQImage(const IplImage *img) { QImage *qmg; cvCvtColor(img,img,CV_B

PS与AI快捷键小结

[文档整理系列] PS与AI快捷键小结PS快捷键 填充前景色 alt+del填充背景色 crel+del前景色与背景色互换: x[英文状态] 切换打开的文件:ctrl + tab关闭当前文件: ctrl + w 调整笔头大小 [ ] 调色板: F6 适应屏幕 ctrl+0 快速合并图层: ctrl+E盖印图层: Shift + Option + Command + E 显示/隐藏标尺网格和辅助线:辅助线(Command + ; ),网格(Command + ' ) 字体:加粗 ctrl+shif