生成隐藏图

什么是隐藏图?请在手机版小红书上打开此链接双指放大图片观看。

本人还写了一个QT程序,可以通过傻瓜式操作生成隐藏图,有兴趣可以自行体验。

主要就是根据透明度展示原理去针对一个通道列方程,然后发现把前景图的色值全部映射到 128 ~ 255 而隐藏图的色值全部映射到 0 ~ 127,方程就刚好是必然有解的,也就是不管任何的前景图色值和隐藏图色值的组合都一定能够找到一对合法的效果图的透明度和色值。

由于每个像素点只有一个透明度但有三个颜色通道,所以彩色图是做不了的。

原理大概就是这样,暂不细讲,后面再填坑,先开源一下代码。

本项目是基于 QT 开发的,构建工具用的 qmake。

首先要在项目的 .pro 文件加下面这句,中文才能正常编码。

QMAKE_CXXFLAGS += /source-charset:utf-8 /execution-charset:utf-8

然后就是 main.cpp 文件了。

#include <QApplication>
#include <QImage>
#include <QFileDialog>
#include <QInputDialog>
#include <iostream>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 使用文件对话框选择图片A
    QString fileA = QFileDialog::getOpenFileName(nullptr, "请选择前景图(白色背景下展示的图片)", "", "Images (*.png *.xpm *.jpg)");
    if (fileA.isEmpty()) {
        std::cerr << "No file selected for Image A." << std::endl;
        return 1;
    }
    QImage imageA(fileA);

    // 使用文件对话框选择图片B
    QString fileB = QFileDialog::getOpenFileName(nullptr, "请选择隐藏图(黑色背景下展示的图片)", "", "Images (*.png *.xpm *.jpg)");
    if (fileB.isEmpty()) {
        std::cerr << "No file selected for Image B." << std::endl;
        return 1;
    }
    QImage imageB(fileB);

    // 使用输入对话框获取最终图片的宽度和高度
    bool ok;
    int width = QInputDialog::getInt(nullptr, "Input Width", "输入效果图宽度(如 500)", 500, 1, 10000, 1, &ok);
    if (!ok) {
        std::cerr << "No width input." << std::endl;
        return 1;
    }
    int height = QInputDialog::getInt(nullptr, "Input Height", "输入效果图高度(如 500)", 500, 1, 10000, 1, &ok);
    if (!ok) {
        std::cerr << "No height input." << std::endl;
        return 1;
    }

    // 转为灰度图
    QImage grayA = imageA.convertToFormat(QImage::Format_Grayscale8);
    QImage grayB = imageB.convertToFormat(QImage::Format_Grayscale8);

    // 都强制修改为用户输入的宽度和高度
    QImage A = grayA.scaled(width, height);
    QImage B = grayB.scaled(width, height);

    QImage image(width, height, QImage::Format_ARGB32);

    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            int a = qGray(A.pixel(i, j));
            int b = qGray(B.pixel(i, j));
            // 把 a(白背景下的)都强制映射到 128~255,b(黑色背景下的)都强制映射到 0~127
            a = a * 0.5 + 128;
            b *= 0.5;
            int x = a - b; // 透明度
            int y = b / (1 - x / 255.0); // 灰度值,这个值就很有趣,会发现 y 范围一定是 0~255 的。
            image.setPixel(i, j, qRgba(y, y, y, 255 - x)); // tmd,原来这个Rgba的“a”是不透明度,值越大就越不透明[捂脸]
        }
    }

    // 使用文件对话框选择保存路径
    QString savePath = QFileDialog::getSaveFileName(nullptr, "保存效果图到", "效果图", "PNG Files (*.png);;All Files (*)");
    if (savePath.isEmpty()) {
        std::cerr << "No file selected for saving the result." << std::endl;
        return 1;
    }

    // 保存图像到文件
    if (!image.save(savePath)) {
        std::cerr << "Failed to save the image." << std::endl;
        return 1;
    }

    return 0;
}

以上就是所有的代码,是不是有种大道至简的感觉呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值