Qt细节记录
QImage
图像行宽4字节对齐
背景
从文件中读取图片数据,赋值给QImage进行显示:
QImage(&pData8[0], width, height, QImage::Format_Indexed8);
当数据长度不是4的倍数时,QImage将会奔溃,程序将会未知原因奔溃。
原因
bitmap文件存储时,在raw data数据部分,要求每一行对齐到4字节。假设保存像素数据的数据类型是2字节的,如果宽 * 2不是4的倍数,比如原本我们期待宽为5,则5*2=10不是4的倍数,则实际系统会把本应放在第二行的前两个字节放在第一行的最后进行补充。导致错乱,最终野指针非法访问内存。
解决方法
- 计算出一行实际的lineWidth = (width * bitCounts + 31) / 32 * 4,其中bitCounts 是我们保存数据的类型所占字节数。显示图像时,数据只能使用一个字节的数据类型进行保存,因此bitCounts = 8;
- 对pData8赋值时,赋值完width个数据,则下一行从linewidth*rows开始赋值,即跳过末尾补充的几个字节
pData8.resize(lineWidth * height);
for(int i = 0 ; i < m_nHeight ; i++)
{
for(int j = 0 ; j < m_nWidth ; j++)
{
pData8[i * m_linewidth + j] = pixValue;
}
}
QImage(&pData8[0], width, height, QImage::Format_Indexed8);
缩放失真
背景
需求高效的缩放且在放大的情况下可以看到每个像素块,缩放无失真。如果使用默认的缩放–”快速缩放(FastTransformation)”,将会在缩小时出现纹理失真,细节消失的问题
原因
”快速缩放(FastTransformation)”模式在缩放时的算法不是将图像像矢量一样进行缩放,缩小时图片质量不佳
解决方法
- 放大时使用快速缩放(FastTransformation)
- 缩小时使用平滑缩放(SmoothTransformation)
小知识
QImage提供了缩放图片的函数 scaled, 并且可以用参数指定”快速缩放(FastTransformation)”还是”平滑缩放(SmoothTransformation)”, 使用还是很方便的。但是如果你用缩放函数去做大图片的缩略图可能会发现”快速缩放”得到的图片质量不佳, 而”平滑缩放”质量很好但速度欠佳, 特别是原图非常大的时候smoothscale简直就是个噩梦阿。 这里就可以使用被称为“Cheat Scaling”的缩小图片的技巧了, 那就是先使用”快速缩放”得到一个中等大小的图片以获得较快的缩放速度, 再使用”平滑缩放”缩小至需要的大小以获得较好的图片质量。
QPainter
绘制长宽小于1px的图形
背景
QPainter绘制图形的那些api传入的长宽参数必须大于1,否则将不显示或仅为一条线
原因
…
解决方法
- 放大长宽的值:width * 100.0 ,height * 100.0
- 设置缩放比:painter->scale(1 / 100.0, 1 / 100.0);
- 绘制图形