qt获取某像素点的颜色吗_理解Bitmap的ARGB格式,实现颜色选择器

作者:爱干球的RD

这篇文章通过一个小Demo,手动解析Bitmap每一个像素,分离argb值,来深入理解bitmap内存

用宝贝儿子的靓照做DEMO

qt获取某像素点的颜色吗_理解Bitmap的ARGB格式,实现颜色选择器_第1张图片

一、实现流程

一般图片处理的底层算法都选择C/C++,有良好的跨平台、性能、可移植性

  1. UI界面读取一张图片,鼠标选中一个position,计算出对应图片的像素坐标,传给c++

  2. c++中读取图片地址,解析出*char数组,根据ARGB协议,解析出ARGB的值,回传给UI界面

  3. 在UI界面中解析ARGB值,显示对应的颜色和16进制的字符串表示

二、bitmap 中每个像素的ARGB内存分布

argb格式每一个像素点有四通道,顺序存储

qt获取某像素点的颜色吗_理解Bitmap的ARGB格式,实现颜色选择器_第2张图片

因为大小端的缘故,和我们理解的ARGB的顺序相反,大小端读者有兴趣可以深入了解。
参考:https://zhuanlan.zhihu.com/p/25119530

接下来读取每一个像素值

像素是以char* 格式存储在内存中,是一个一维数组,bitmap中记录了每一行的长度,即步辐。注意步幅 >= 图片的宽度,每一行末尾可能会存储其他图片信息。

每个平台都有API可以获取一个像素对应的坐标(x, y),依次计算bitmap(x,y)处的argb值,注意顺序是反过来的,先算blue通道:

b = y * stride + x * 4 // 计算的是b通道
g = b + 1;
r  =  b + 2;
a = b + 3;

详细代码如下:

int f_getPixel(unsigned char *srcData, int width, int height, int stride, int x, int y, int argb[4]){    x = x < 0 ? 0 : (x > width - 1 ? width - 1 : x);    y = y < 0 ? 0 : (y > height - 1 ? height - 1 : y);int ret = 0;if(srcData == nullptr)    {printf("input image is null!");return -1;    }//Processint pos = x * 4 + y * stride;    argb[0] = srcData[pos + 3];    argb[1] = srcData[pos + 2];    argb[2] = srcData[pos + 1];    argb[3] = srcData[pos + 0];return ret;}

三、实现颜色选择交互

这里基于qml来处理,读者有兴趣迁移到Android/iOS也不复杂

1. 点击鼠标,计算图片的像素坐标,传递给C++。这里简单处理,图片平铺到Image中,如果图片不是平铺,计算稍微麻烦点。

var pox = (mouseX / 640) *imageViewer.sourceSize.width;var poy = (mouseY / 480) * imageViewer.sourceSize.height;console.log("pox = ", pox, "poy = ", poy);processor.getPix(fileDialog.fileUrl, pox, poy);

2.C++中解析Bitmap,注意url是file:///协议,qml中可以识别,C++中不能直接识别,需要处理下;Qt中C++与qml传参有限制,这里需要传递数组,用QVariantList->转成QVariant;最后发送信号

void ImageProcessor::getPix(QString sourceFile, int x, int y){const QUrl url(sourceFile);if (url.isLocalFile()) {        sourceFile = QDir::toNativeSeparators(url.toLocalFile());    }QImage image(sourceFile);if(image.isNull())    {return;    }unsigned char *data = image.bits();int w = image.width();int h = image.height();int stride = image.bytesPerLine();int argb[4];    f_getPixel(data, w, h, stride, x, y, argb);    QVariantList list;list<    emit getPixDone(QVariant::fromValue(list));}

3. qml中接收信号,展示结果

ImageProcessor {function rgba(a,r,g,b){var ret = (r << 16 | g << 8 | b);var strRet =  ("#" + a.toString(16) + ret.toString(16)).toUpperCase();return strRet;      }      id: processor;      onFinished: {          imageViewer.source = "file:///" +newFile;      }      onGetPixDone: {var selectColor = rgba(list[0], list[1],list[2],list[3]);          position.color = selectColor;          positionTex.text = selectColor;      }  }

你可能感兴趣的:(qt获取某像素点的颜色吗)