当前位置: 首页 > news >正文

QImage高效率像素操作的方法

一 概述  

         在Qt中高效操作QImage像素的关键在于减少函数调用开销、利用直接内存访问和优化数据格式。

二 解决方法

1  选择合适像素格式
    预处理为32位格式(如Format_ARGB32):

QImage image = ...;
image = image.convertToFormat(QImage::Format_ARGB32);
 

2   直接内存访问(避免pixel/setPixel)

int w = image.width();
int h = image.height();
uint32_t *pixels = reinterpret_cast<uint32_t*>(image.bits());
size_t bytesPerLine = image.bytesPerLine(); // 通常为w*4 (32bpp)

for(int y=0; y<h; ++y) {
    uint32_t *line = reinterpret_cast<uint32_t*>(image.scanLine(y));
    for(int x=0; x<w; ++x) {
        // 通过位操作访问颜色分量
        uint8_t a = (line[x] >> 24) & 0xFF;
        uint8_t r = (line[x] >> 16) & 0xFF;
        uint8_t g = (line[x] >> 8) & 0xFF;
        uint8_t b = line[x] & 0xFF;
        
        // 修改后写回
        line[x] = (a << 24) | (r << 16) | (g << 8) | b;
    }
}
 

3  循环优化技巧
   预先计算循环边界,使用指针递增代替二维索引。

uint32_t *p = pixels;
for(int y=0; y<h; ++y) {
    uint32_t *end = p + w;
    while(p < end) {
        // 处理*p
        ++p;
    }
    // 跳过行尾填充字节(如果有)
    p = reinterpret_cast<uint32_t*>(reinterpret_cast<uchar*>(p) + (bytesPerLine - w*4));
}
 

4  并行处理(使用QtConcurrent)

void processStrip(QImage &image, int startY, int endY) {
    for(int y=startY; y<endY; ++y) {
        uint32_t *line = reinterpret_cast<uint32_t*>(image.scanLine(y));
        // ...处理行...
    }
}

// 分割为4个水平条带
int stripHeight = image.height()/4;
QVector<QFuture<void>> futures;
for(int i=0; i<4; ++i) {
    futures.append(QtConcurrent::run([&, i]{
        int start = i*stripHeight;
        int end = (i==3) ? image.height() : (i+1)*stripHeight;
        processStrip(image, start, end);
    }));
}
// 等待所有任务完成
for(auto &f : futures) f.wait();
 

 

三  注意事项
1  修改bits()前需调用bits()触发detach(确保深拷贝)。
2 多线程时确保不同线程处理不同内存区域。
3 使用QImage::Format_ARGB32_Premultiplied可避免重复预乘运算。
4  对8位索引颜色格式需先转换为直接颜色格式。

 

http://www.xdnf.cn/news/467065.html

相关文章:

  • 基于windows环境Oracle主备切换之后OGG同步进程恢复
  • 兰亭妙微B端UI设计:融合多元风格,点亮品牌魅力
  • 嵌软面试每日一阅----通信协议篇(二)之TCP
  • 一招解决Tailwindcss4.x与其他库样式冲突问题
  • 报销单业务笔记
  • 中国近代史2
  • 深度学习框架对比---Pytorch和TensorFlow
  • MySQL 学习(十)执行一条查询语句的内部执行过程、MySQL分层
  • 验证可行分享-Rancher部署文档
  • CSRF攻击 + 观测iframe加载时间利用时间响应差异侧信道攻击 -- reelfreaks DefCamp 2024
  • 第一天的尝试
  • C语言中的指定初始化器
  • java 八股
  • Opencv C++写中文(来自Gemini)
  • uniapp+vite+cli模板引入tailwindcss
  • 智慧鱼塘可视化管理:养殖业数字孪生
  • [IMX] 02.GPIO 寄存器
  • Electron 应用的升级机制详解
  • 文科生如何重新开始学习数学?
  • OGSM 从上到下逐级分解策略:从战略目标到部门计划的标准化落地路径
  • 使用 frp 实现内网穿透:从基础到进阶
  • 司法系统之外的第三方平台未经许可披露企业涉诉信息是否构成侵权
  • 学前数学思维:整体代换
  • 深度解析:如何用DeepSeek等大模型增强MySQL运维效率
  • 访问 Docker 官方镜像源(包括代理)全部被“重置连接”或超时
  • Linux系统中部署java服务(docker)
  • WSF3089 N沟道MOSFET在按摩椅中的应用分析
  • SpringBoot 3.4.5版本导入Lomobok依赖后无法生效的问题
  • 软件设计师考试《综合知识》设计模式之——工厂模式与抽象工厂模式考点分析
  • Windows软件插件-写MP4