美文网首页
1. 解析Bitmap的ARGB,实现图片颜色选择器

1. 解析Bitmap的ARGB,实现图片颜色选择器

作者: 天叔 | 来源:发表于2020-10-22 11:00 被阅读0次
    1. UI界面读取一张图片,鼠标选中一个position,计算出对应图片的像素坐标,传给c++
    2. c++中读取图片地址,解析出*char数组,根据ARGB协议,解析出ARGB的值,传递给UI界面
    3. 在UI界面中解析ARGB值,显示对应的颜色和16进制的字符串表示

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


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

    读取每一个像素值

    像素是以char* 格式存储在内存中,是一个一位数组,bitmap中记录了每一行的长度,即步辐,每个平台都有API可以获取 一个像素对应的bitmap内存位置为:
    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;
        }
        //Process
        int 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<<argb[0]<<argb[1]<<argb[2]<<argb[3];
    
        emit getPixDone(QVariant::fromValue(list));
    }
    

    qml中接收信号,展示结果。注意js中数据的长度有限

            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;
                }
            }
    

    相关文章

      网友评论

          本文标题:1. 解析Bitmap的ARGB,实现图片颜色选择器

          本文链接:https://www.haomeiwen.com/subject/rttdmktx.html