libPNG& QREnCode将qrcode保存为PNG

时间:2016-07-01 14:13:37

标签: c++ image qr-code libpng

嘿伙计们,我从qrcode数据输出png图像时遇到了麻烦。

此时此刻,我有以下几点:

位图结构:

struct Bitmap {
    std::vector<unsigned char> buf;  // Pixel data if owned by Bitmap
    unsigned char* ptr;  // Pixel data if owned by someone else
    unsigned width, height;
    double ar;  // Aspect ratio
    double timestamp;  // Used for video frames
    pix::Format fmt;
    bool linearPremul;  // Is the data linear RGB and premultiplied (as opposed to sRGB and non-premultiplied)
    bool bottomFirst;  // Upside-down (only used for taking screenshots)
    Bitmap(unsigned char* ptr = NULL): ptr(ptr), width(), height(), ar(), timestamp(), fmt(pix::CHAR_RGBA), linearPremul(), bottomFirst() {}
    void resize(unsigned w, unsigned h) {
        if (!ptr) buf.resize(w * h * 4); else buf.clear();
        width = w;
        height = h;
        ar = double(w) / h;
    }
    void swap(Bitmap& b) {
        if (ptr || b.ptr) throw std::logic_error("Cannot Bitmap::swap foreign pointers.");
        buf.swap(b.buf);
        std::swap(width, b.width);
        std::swap(height, b.height);
        std::swap(ar, b.ar);
        std::swap(timestamp, b.timestamp);
        std::swap(fmt, b.fmt);
    }
    unsigned char const* data() const { return ptr ? ptr : &buf[0]; }
    unsigned char* data() { return ptr ? ptr : &buf[0]; }

    void crop(const unsigned width, const unsigned height, const unsigned x, const unsigned y);
};

然后有一个writePNG函数:

void writePNG(fs::path const& filename, Bitmap const& img, unsigned stride) {
    fs::path name = filename;
    // We use PNG in a non-standard way, with premultiplied alpha, signified by .premul.png extension.
    std::clog << "image/debug: Saving PNG: " + name.string() << std::endl;
    std::vector<png_bytep> rows(img.height);
    // Determine color type and bytes per pixel
    unsigned char bpp;
    int colorType;
    switch (img.fmt) {
        case pix::RGB: bpp = 3; colorType = PNG_COLOR_TYPE_RGB; break;
        case pix::CHAR_RGBA: bpp = 4; colorType = PNG_COLOR_TYPE_RGBA; break;
        default:
            // Byte order would need to be changed for other formats and we don't currently need them...
            throw std::logic_error("Unsupported pixel format in writePNG_internal");
    }
    // Construct row pointers
    bool reverse = img.bottomFirst;
    if (stride == 0) stride = img.width * bpp;
    unsigned pos = reverse ? img.height * stride : -stride;
    for (unsigned y = 0; y < img.height; ++y) {
        pos += (reverse ? -stride : stride);
        rows[y] = (png_bytep)(&img.data()[pos]);
    }
    // Initialize libpng structures
    png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!pngPtr) throw std::runtime_error("png_create_read_struct failed");
    png_infop infoPtr = NULL;
    struct Cleanup {
        png_structpp pngPP;
        png_infopp infoPP;
        Cleanup(png_structp& pngP, png_infop& infoP): pngPP(&pngP), infoPP(&infoP) {}
        ~Cleanup() { png_destroy_write_struct(pngPP, infoPP); }
    } cleanup(pngPtr, infoPtr);
    infoPtr = png_create_info_struct(pngPtr);
    if (!infoPtr) throw std::runtime_error("png_create_info_struct failed");
    png_set_gAMA(pngPtr, infoPtr, img.linearPremul ? 1.0 : 2.2);
    // Write file
    ofstream file(name, std::ios::binary);
    writePNG_internal(pngPtr, infoPtr, file, img.width, img.height, colorType, rows);
}

在我的QRCode代码中,我将一些网址转换为二维码。这个QRCode调用我的writePNG函数但输出一个有点奇怪的图像,当然不是QRCode: strange QRcode

这意味着PNG的标题正确但数据不是..

我正在调用这样的方法:

QRCode::QRCode(const char* data, std::string path): m_qrCode(QRcode_encodeString(data, 4, QR_ECLEVEL_H, QR_MODE_8, 1)), m_path(path) 
{
    //QRCode::WriteBMP(path);

    Bitmap img;
    img.width = 256;
    img.height = 256;
    unsigned stride = (img.width * 3 + 3) & ~3;
    img.buf.resize(stride*img.height);
    img.fmt = pix::RGB;
    img.ptr = m_qrCode->data;

    writePNG(findFile("qrCode.png"), img);
}

我认为我正在使用qrdata做一些奇怪的事情,并且需要重新处理它。

0 个答案:

没有答案