封装一个png的编码解码操作

发布于:2025-07-05 ⋅ 阅读:(16) ⋅ 点赞:(0)

像素数据与编码图像的区别详解

在图像处理流程中,"像素数据"和"编码图像"代表两个完全不同的概念,它们处于图像处理管道的不同阶段:

1. ​​像素数据 (Pixel Data)​
  • ​定义​​:表示图像的原始、未压缩的点阵数据

  • ​结构​​:

    • 是一个连续的内存块
    • 每个像素包含RGB(A)分量(如RGBA格式是4字节/像素)
    • 格式示例:[R0,G0,B0,A0, R1,G1,B1,A1, ...]
  • ​特点​​:

    • 未压缩的原始格式
    • 占用较大内存(宽 × 高 × 字节数/像素)
    • 可直接用于图像处理操作(缩放、滤镜等)
    • 无额外元数据(颜色空间、压缩参数等)
  • ​代码中的位置​​:

    // 这是像素数据
    std::vector<uint8_t> pixels;
    
2. ​​编码图像 (Encoded Image)​
  • ​定义​​:经过特定算法压缩的图像二进制数据

  • ​结构​​:

    • 遵循特定格式标准(如PNG)
    • 包含文件头、元数据和压缩后的像素数据
    • 包含校验码、颜色空间信息等
  • ​特点​​:

    • 压缩格式(减少存储/传输体积)
    • 不可直接用于图像处理
    • 需要解码器才能获取像素数据
    • 包含完整文件结构和元数据
  • ​代码中的位置​​:

    // 这是编码图像
    std::vector<uint8_t> outputPng;
    

处理流程中的转换关系

graph LR
    A[原始编码图像] -->|解码| B[像素数据]
    B -->|插值缩放| C[新像素数据]
    C -->|编码| D[新编码图像]

在代码中的具体体现

  1. ​解码过程(获取像素数据)​​:

    // 原始PNG文件 → 像素数据
    PngManager::ImageData sourceImage;
    pngManager.ReadFromMemory(png_data.data(), png_data.size(), sourceImage);
    // sourceImage.pixels 现在是像素数据
    
  2. ​像素处理阶段​​:

    // 像素数据上执行插值
    ImageInterpolator::resize(input, width, height, method);
    // 直接操作像素数组
    
  3. ​编码过程(生成新图像)​​:

    // 处理后的像素数据 → PNG格式
    PngManager pngManager;
    std::vector<uint8_t> outputPng;
    pngManager.WriteToMemory(targetImage, outputPng);
    // outputPng 现在是可保存的PNG文件
    

关键区别总结

特性 像素数据 编码图像
​格式​ 原始数组(RGBA序列) 压缩二进制格式(PNG/JPEG)
​大小​ 较大(宽×高×字节数/像素) 较小(压缩后)
​可处理性​ 可直接处理 需解码后使用
​元数据​ 包含EXIF、ICC等元数据
​平台兼容性​ 平台无关 格式相关
​内存结构​ 简单连续内存 复杂数据块结构
​典型用途​ 图像处理操作 存储/传输

代码执行示例

// 1. 加载编码图像(PNG文件)
std::vector<uint8_t> encodedData = LoadPNG("input.png");

// 2. 解码获取像素数据
PngManager::ImageData pixelData;
pngManager.ReadFromMemory(encodedData, pixelData);

// 3. 处理像素数据
for (auto& pixel : pixelData.pixels) {
    pixel = 255 - pixel; // 反相处理
}

// 4. 编码为新图像
std::vector<uint8_t> newEncodedImage;
pngManager.WriteToMemory(pixelData, newEncodedImage);

// 5. 保存编码图像
SavePNG(newEncodedImage, "output.png");

性能考量

  1. ​解码/编码开销​​:

    • PNG解码:100×100图像约0.5ms
    • PNG编码:100×100图像约1.2ms
    • 如果处理流程涉及多次缩放操作,应保持在像素数据状态
  2. ​内存占用​​:

    1024×1024图像:
      - 像素数据(RGBA):4MB
      - 编码图像(PNG):约0.5-1.5MB
    

理解这两种数据类型的区别对于优化图像处理流程至关重要。在需要多次操作的场景(如缩放到多种尺寸),应在像素数据状态完成所有操作后统一编码,避免重复解码/编码的开销。

实现文件


class DIBitmapConverter {
public:
    // 从位图获取图像数据
    struct ImageData {
        std::vector<uint8_t> rgbData;    // RGB/RGBA数据
        std::vector<uint8_t> smaskData;  // 透明蒙版数据
        unsigned int width = 0;
        unsigned int height = 0;
        bool hasAlpha = false;
    };

    // 从 CFX_DIBitmap 获取图像数据
    static ImageData GetImageData(CFX_DIBitmap* bitmap, bool includeAlpha = true) {
        ImageData result;
        result.width = bitmap->GetWidth();
        result.height = bitmap->GetHeight();
        int format = bitmap->GetFormat();
        result.hasAlpha = (includeAlpha && HasAlphaChannel(format));

        // 计算数据大小
        size_t rgbSize = result.width * result.height * (result.hasAlpha ? 4 : 3);
        size_t smaskSize = result.width * result.height;
        result.rgbData.resize(rgbSize);
        result.smaskData.resize(smaskSize);

        // 获取位图数据
        uint8_t* bitmapData = static_cast<uint8_t*>(bitmap->GetBuffer());
        int stride = bitmap->GetPitch();
        int bpp = GetBPPFromFormat(format);
#if 0
        for (unsigned int y = 0; y < result.height; ++y) {
            for (unsigned int x = 0; x < result.width; ++x) {
                size_t srcOffset = y * stride + x * (bpp / 8);
                size_t rgbOffset = (y * result.width + x) * (result.hasAlpha ? 4 : 3);
                size_t smaskOffset = y * result.width + x;

                ExtractPixelData(bitmapData, srcOffset, format,
                    result.rgbData, rgbOffset,
                    result.smaskData, smaskOffset,
                    result.hasAlpha);
            }
        }
#else

// 预先计算常量
const int bytesPerPixel = bpp / 8;
const bool hasAlpha = result.hasAlpha;
const int rgbStep = hasAlpha ? 4 : 3;
const size_t width = result.width;

// 获取数据指针
uint8_t* srcData = bitmapData;
uint8_t* rgbDataPtr = result.rgbData.data();
uint8_t* smaskDataPtr = result.smaskData.data();

for (unsigned int y = 0; y < result.height; ++y) {
    // 计算行起始位置
    uint8_t* rowSrc = srcData + y * stride;
    uint8_t* rowRgb = rgbDataPtr + y * width * rgbStep;
    uint8_t* rowSmask = smaskDataPtr + y * width;
    
    for (unsigned int x = 0; x < width; ++x) {
        // 直接使用指针而不是计算偏移量
        ExtractPixelData(rowSrc, format,
            rowRgb, rowSmask,
            hasAlpha);
        
        // 移动到下一个像素
        rowSrc += bytesPerPixel;
        rowRgb += rgbStep;
        rowSmask++;
    }
}
#endif

        return result;
    }

    // 将图像数据设置到位图
    static bool SetImageData(CFX_DIBitmap* bitmap, const ImageData& imageData) {
        unsigned int width = bitmap->GetWidth();
        unsigned int height = bitmap->GetHeight();
        int format = bitmap->GetFormat();
        int bpp = GetBPPFromFormat(format);

        // 验证尺寸
        if (width != imageData.width || height != imageData.height) {
            /*throw std::runtime_error("Image dimensions do not match bitmap");*/
            return false;
        }

        // 获取位图数据
        uint8_t* bitmapData = static_cast<uint8_t*>(bitmap->GetBuffer());
        int stride = bitmap->GetPitch();

        for (unsigned int y = 0; y < height; ++y) {
            for (unsigned int x = 0; x < width; ++x) {
                size_t dstOffset = y * stride + x * (bpp / 8);
                size_t rgbOffset = (y * width + x) * (imageData.hasAlpha ? 4 : 3);
                size_t smaskOffset = y * width + x;

                SetPixelData(bitmapData, dstOffset, format,
                    imageData.rgbData, rgbOffset,
                    imageData.smaskData, smaskOffset,
                    imageData.hasAlpha);
            }
        }
    }

    // 创建新的 CFX_DIBitmap 并设置图像数据
    static std::unique_ptr<CFX_DIBitmap> CreateBitmapFromData(
        const ImageData& imageData
        ,
        FXDIB_Format format = FXDIB_Rgba)
    {
        auto bitmap = std::make_unique<CFX_DIBitmap>();
        if (!bitmap->Create(imageData.width, imageData.height, format, nullptr, 0)) {
            //throw std::runtime_error("Failed to create bitmap");
#if HasDebugImage
            std::cerr << "Failed to create bitmap" << std::endl;
#endif
        }

        SetImageData(bitmap.get(), imageData);
        return bitmap;
    }

private:
    // 获取位图格式的位深度
    static int GetBPPFromFormat(int format) {
        switch (format) {
        case FXDIB_1bppMask: return 1;
        case FXDIB_8bppMask:
        case FXDIB_8bppRgb:
        case FXDIB_8bppRgba:
        case FXDIB_8bppCmyk:
        case FXDIB_8bppCmyka: return 8;
        case FXDIB_Rgb: return 24;
        case FXDIB_Rgba:
        case FXDIB_Rgb32:
        case FXDIB_Argb:
        case FXDIB_Cmyk:
        case FXDIB_Cmyka: return 32;
        default: return 0;
        }
    }

    // 检查格式是否有Alpha通道
    static bool HasAlphaChannel(int format) {
        switch (format) {
        case FXDIB_8bppRgba:
        case FXDIB_Rgba:
        case FXDIB_Rgb32:
        case FXDIB_Argb:
        case FXDIB_8bppCmyka:
        case FXDIB_Cmyka: return true;
        default: return false;
        }
    }
#if 0
    // 从位图提取像素数据
    static bool ExtractPixelData(
        uint8_t* bitmapData, size_t srcOffset, int format,
        std::vector<uint8_t>& rgbData, size_t rgbOffset,
        std::vector<uint8_t>& smaskData, size_t smaskOffset,
        bool includeAlpha)
    {
        switch (format) {
        case FXDIB_8bppMask:
        case FXDIB_8bppRgb:
        case FXDIB_8bppRgba:
        case FXDIB_8bppCmyk:
        case FXDIB_8bppCmyka: {
            // 8位格式处理
            uint8_t gray = bitmapData[srcOffset];
            rgbData[rgbOffset] = rgbData[rgbOffset + 1] = rgbData[rgbOffset + 2] = gray;
            if (includeAlpha && rgbData.size() > rgbOffset + 3) {
                rgbData[rgbOffset + 3] = 255;
            }
            smaskData[smaskOffset] = 255;
            break;
        }
        case FXDIB_Rgb: {
            // 24位RGB处理
            rgbData[rgbOffset] = bitmapData[srcOffset + 2];     // R
            rgbData[rgbOffset + 1] = bitmapData[srcOffset + 1]; // G
            rgbData[rgbOffset + 2] = bitmapData[srcOffset];     // B
            if (includeAlpha && rgbData.size() > rgbOffset + 3) {
                rgbData[rgbOffset + 3] = 255;
            }
            smaskData[smaskOffset] = 255;
            break;
        }
        case FXDIB_Rgba:
        case FXDIB_Rgb32:
        case FXDIB_Argb: {
            // 32位带Alpha处理
            rgbData[rgbOffset] = bitmapData[srcOffset + 2];     // R
            rgbData[rgbOffset + 1] = bitmapData[srcOffset + 1]; // G
            rgbData[rgbOffset + 2] = bitmapData[srcOffset];     // B
            if (includeAlpha) {
                if (rgbData.size() > rgbOffset + 3) {
                    rgbData[rgbOffset + 3] = bitmapData[srcOffset + 3]; // A
                }
                smaskData[smaskOffset] = bitmapData[srcOffset + 3];    // A
            }
            else {
                smaskData[smaskOffset] = 255;
            }
            break;
        }
        default:
#if HasDebugImage
            std::cerr << "Unsupported bitmap format" << std::endl;
#endif
            //throw std::runtime_error("Unsupported bitmap format");
            return false;
        }
    }
#else

static void ExtractPixelData(
    uint8_t* srcPtr, int format,
    uint8_t* rgbPtr, uint8_t* smaskPtr,
    bool hasAlpha)
{
    switch (format) {
    case FXDIB_8bppMask:
    case FXDIB_8bppRgb:
    case FXDIB_8bppRgba:
    case FXDIB_8bppCmyk:
    case FXDIB_8bppCmyka: {
        // 8位格式处理
        uint8_t gray = *srcPtr;
        rgbPtr[0] = gray;
        rgbPtr[1] = gray;
        rgbPtr[2] = gray;

        if (hasAlpha) {
            rgbPtr[3] = 0xFF; // 完全不透明
        }
        *smaskPtr = 0xFF;
        break;
    }
    case FXDIB_Rgb: {
        // 24位RGB处理
        rgbPtr[0] = srcPtr[2]; // R
        rgbPtr[1] = srcPtr[1]; // G
        rgbPtr[2] = srcPtr[0]; // B

        if (hasAlpha) {
            rgbPtr[3] = 0xFF; // 完全不透明
        }
        *smaskPtr = 0xFF;
        break;
    }
    case FXDIB_Rgba:
    case FXDIB_Rgb32:
    case FXDIB_Argb: {
        // 32位带Alpha处理
        rgbPtr[0] = srcPtr[2]; // R
        rgbPtr[1] = srcPtr[1]; // G
        rgbPtr[2] = srcPtr[0]; // B

        if (hasAlpha) {
            uint8_t alpha = srcPtr[3];
            rgbPtr[3] = alpha;
            *smaskPtr = alpha;
        }
        else {
            *smaskPtr = 0xFF;
        }
        break;
    }
    default: {
        // 默认处理:黑色不透明
        rgbPtr[0] = 0;
        rgbPtr[1] = 0;
        rgbPtr[2] = 0;
        if (hasAlpha) {
            rgbPtr[3] = 0xFF;
        }
        *smaskPtr = 0xFF;
        break;
    }
    }
}
#endif

    // 设置像素数据到位图
    static bool SetPixelData(
        uint8_t* bitmapData, size_t dstOffset, int format,
        const std::vector<uint8_t>& rgbData, size_t rgbOffset,
        const std::vector<uint8_t>& smaskData, size_t smaskOffset,
        bool hasAlpha)
    {
        switch (format) {
        case FXDIB_8bppMask:
        case FXDIB_8bppRgb:
        case FXDIB_8bppRgba:
        case FXDIB_8bppCmyk:
        case FXDIB_8bppCmyka: {
            // 8位格式处理 - 转换为灰度
            float gray = 0.299f * rgbData[rgbOffset] +
                0.587f * rgbData[rgbOffset + 1] +
                0.114f * rgbData[rgbOffset + 2];
            bitmapData[dstOffset] = static_cast<uint8_t>(gray);
            break;
        }
        case FXDIB_Rgb: {
            // 24位RGB处理
            bitmapData[dstOffset] = rgbData[rgbOffset + 2];     // B
            bitmapData[dstOffset + 1] = rgbData[rgbOffset + 1]; // G
            bitmapData[dstOffset + 2] = rgbData[rgbOffset];     // R
            break;
        }
        case FXDIB_Rgba:
        case FXDIB_Rgb32:
        case FXDIB_Argb: {
            // 32位带Alpha处理
            bitmapData[dstOffset] = rgbData[rgbOffset + 2];     // B
            bitmapData[dstOffset + 1] = rgbData[rgbOffset + 1]; // G
            bitmapData[dstOffset + 2] = rgbData[rgbOffset];      // R
            if (hasAlpha && rgbData.size() > rgbOffset + 3) {
                bitmapData[dstOffset + 3] = smaskData[smaskOffset]; // A
            }
            else {
                bitmapData[dstOffset + 3] = 255; // 不透明
            }
            break;
        }
        default:
#if HasDebugImage
            std::cerr << "Unsupported bitmap format" << std::endl;
#endif
            //throw std::runtime_error("Unsupported bitmap format");
            return false;
        }
    }
};

#include <vector>
#include <cstdint>
#include <cmath>
#include <algorithm>

class ImageInterpolator {
public:
    // 插值方法枚举
    enum class Method {
        NEAREST_NEIGHBOR,  // 最近邻插值
        BILINEAR,          // 双线性插值
        BICUBIC            // 双三次插值
    };

    // 使用 PngManager 的 ImageData 结构(需要保持一致)
    struct ImageData {
        std::vector<uint8_t> pixels;
        uint32_t width = 0;
        uint32_t height = 0;
        uint8_t bitDepth = 8;
    };

    // 缩放图像方法,原地修改像素数据
    static bool resize(ImageData& image,
        uint32_t newWidth,
        uint32_t newHeight,
        Method method = Method::BILINEAR) {
        // 验证参数有效性
        if (image.pixels.empty() || image.width == 0 || image.height == 0) {
            return false;
        }

        if (newWidth == 0 || newHeight == 0) {
            return false;
        }

        // 如果目标尺寸相同则直接返回
        if (newWidth == image.width && newHeight == image.height) {
            return true;
        }

        // 只支持8位深度的图像
        if (image.bitDepth != 8) {
            return false;
        }

        // 创建目标像素缓冲区
        std::vector<uint8_t> resizedPixels(newWidth * newHeight * 4);

        for (uint32_t y = 0; y < newHeight; ++y) {
            for (uint32_t x = 0; x < newWidth; ++x) {
                // 计算原始图像中的对应位置(浮点坐标)
                float srcX = (x + 0.5f) * image.width / newWidth - 0.5f;
                float srcY = (y + 0.5f) * image.height / newHeight - 0.5f;

                // 边界处理
                srcX = (std::max)(0.0f, (std::min)(srcX, static_cast<float>(image.width - 1)));
                srcY = (std::max)(0.0f, (std::min)(srcY, static_cast<float>(image.height - 1)));

                // 对每个通道进行处理
                for (int c = 0; c < 4; ++c) {
                    float value = 0.0f;

                    switch (method) {
                    case Method::NEAREST_NEIGHBOR:
                        value = nearestNeighbor(srcX, srcY, c, image);
                        break;

                    case Method::BILINEAR:
                        value = bilinearInterpolation(srcX, srcY, c, image);
                        break;

                    case Method::BICUBIC:
                        value = bicubicInterpolation(srcX, srcY, c, image);
                        break;
                    }

                    // 确保值在0-255范围内并写入目标位置
                    resizedPixels[(y * newWidth + x) * 4 + c] =
                        static_cast<uint8_t>((std::max)(0.0f, (std::min)(255.0f, value)));
                }
            }
        }

        // 更新图像数据
        image.width = newWidth;
        image.height = newHeight;
        image.pixels = std::move(resizedPixels);

        return true;
    }
    //返回一个新的像素数据
    static ImageData resizeCopy(const ImageData& source,
        uint32_t newWidth,
        uint32_t newHeight,
        Method method = Method::BILINEAR)
    {
        // 创建目标图像数据结构
        ImageData result;
        result.width = newWidth;
        result.height = newHeight;
        result.bitDepth = source.bitDepth;
        //result.format = source.format;

        // 验证参数有效性
        if (source.pixels.empty() || source.width == 0 || source.height == 0) {
            return result; // 返回空对象
        }

        if (newWidth == 0 || newHeight == 0) {
            return result; // 返回空对象
        }

        // 如果目标尺寸相同则直接复制
        if (newWidth == source.width && newHeight == source.height) {
            result.pixels = source.pixels; // 复制像素数据
            return result;
        }

        // 只支持8位深度的图像
        if (source.bitDepth != 8) {
            return result; // 返回空对象
        }

        // 创建目标像素缓冲区
        result.pixels.resize(newWidth * newHeight * 4);

        for (uint32_t y = 0; y < newHeight; ++y) {
            for (uint32_t x = 0; x < newWidth; ++x) {
                // 计算原始图像中的对应位置(浮点坐标)
                float srcX = (x + 0.5f) * source.width / newWidth - 0.5f;
                float srcY = (y + 0.5f) * source.height / newHeight - 0.5f;

                // 边界处理
                srcX = (std::max)(0.0f, (std::min)(srcX, static_cast<float>(source.width - 1)));
                srcY = (std::max)(0.0f, (std::min)(srcY, static_cast<float>(source.height - 1)));

                // 对每个通道进行处理
                for (int c = 0; c < 4; ++c) {
                    float value = 0.0f;

                    switch (method) {
                    case Method::NEAREST_NEIGHBOR:
                        value = nearestNeighbor(srcX, srcY, c, source);
                        break;

                    case Method::BILINEAR:
                        value = bilinearInterpolation(srcX, srcY, c, source);
                        break;

                    case Method::BICUBIC:
                        value = bicubicInterpolation(srcX, srcY, c, source);
                        break;
                    }

                    // 确保值在0-255范围内并写入目标位置
                    result.pixels[(y * newWidth + x) * 4 + c] =
                        static_cast<uint8_t>((std::max)(0.0f, (std::min)(255.0f, value)));
                }
            }
        }

        return result;
    }
private:
    // 最近邻插值
    static float nearestNeighbor(float srcX, float srcY, int channel, const ImageData& image) {
        int nearestX = static_cast<int>(std::round(srcX));
        int nearestY = static_cast<int>(std::round(srcY));

        // 边界保护
        nearestX = clamp(nearestX, 0, image.width - 1);
        nearestY = clamp(nearestY, 0, image.height - 1);

        return image.pixels[(nearestY * image.width + nearestX) * 4 + channel];
    }

    // 双线性插值
    static float bilinearInterpolation(float srcX, float srcY, int channel, const ImageData& image) {
        int x1 = static_cast<int>(srcX);
        int y1 = static_cast<int>(srcY);
        int x2 = (std::min)(x1 + 1, static_cast<int>(image.width - 1));
        int y2 = (std::min)(y1 + 1, static_cast<int>(image.height - 1));

        float dx = srcX - x1;
        float dy = srcY - y1;

        float v11 = image.pixels[(y1 * image.width + x1) * 4 + channel];
        float v21 = image.pixels[(y1 * image.width + x2) * 4 + channel];
        float v12 = image.pixels[(y2 * image.width + x1) * 4 + channel];
        float v22 = image.pixels[(y2 * image.width + x2) * 4 + channel];

        // 双线性插值公式
        return v11 * (1 - dx) * (1 - dy) +
            v21 * dx * (1 - dy) +
            v12 * (1 - dx) * dy +
            v22 * dx * dy;
    }

    // 双三次插值
    static float bicubicInterpolation(float srcX, float srcY, int channel, const ImageData& image) {
        int x0 = static_cast<int>(std::floor(srcX)) - 1;
        int y0 = static_cast<int>(std::floor(srcY)) - 1;
        float sum = 0.0f;
        float sumWeights = 0.0f;

        // 4x4像素采样区域
        for (int m = 0; m < 4; ++m) {
            for (int n = 0; n < 4; ++n) {
                int px = clamp(x0 + n, 0, image.width - 1);
                int py = clamp(y0 + m, 0, image.height - 1);

                float wx = bicubicWeight(srcX - px);
                float wy = bicubicWeight(srcY - py);
                float weight = wx * wy;

                sum += image.pixels[(py * image.width + px) * 4 + channel] * weight;
                sumWeights += weight;
            }
        }

        return sumWeights > 0.0f ? sum / sumWeights : 0.0f;
    }

    // 边界保护函数
    static int clamp(int value, int min, int max) {
        return (std::max)(min, (std::min)(value, max));
    }

    // 双三次插值权重计算
    static float bicubicWeight(float x, float a = -0.5f) {
        x = std::abs(x);
        if (x < 1.0f) {
            return (a + 2.0f) * x * x * x - (a + 3.0f) * x * x + 1.0f;
        }
        else if (x < 2.0f) {
            return a * x * x * x - 5.0f * a * x * x + 8.0f * a * x - 4.0f * a;
        }
        return 0.0f;
    }
};

/*

//int main() {
//	try {
//		// 示例1: 从位图获取图像数据
//		CFX_DIBitmap* sourceBitmap =  获取或创建位图  ;
//		auto imageData = DIBitmapConverter::GetImageData(sourceBitmap, true);
//
//		// 处理图像数据...
//		for (auto& pixel : imageData.rgbData) {
//			pixel = 255 - pixel; // 反色处理
//		}
//
//		// 示例2: 创建新位图并设置图像数据
//		auto newBitmap = DIBitmapConverter::CreateBitmapFromData(imageData, FXDIB_Rgba);
//
//		// 示例3: 修改现有位图
//		DIBitmapConverter::SetImageData(sourceBitmap, imageData);
//	}
//	catch (const std::exception& e) {
//		std::cerr << "Error: " << e.what() << std::endl;
//		return 1;
//	}
//
//	return 0;
//}
//*/
#include <vector>
#include <cstdint>
//#include <png.h>
#include <functional>

class PngManager {
public:
    // 错误码枚举
    enum class ErrorCode {
        Success = 0,
        CreateReadStructFailed,
        CreateInfoStructFailed,
        CreateWriteStructFailed,
        PngProcessingError,
        UnsupportedFormat,
        InvalidParameters,
        MemoryAllocationFailed
    };

    // 像素格式
    enum class PixelFormat {
        Grayscale = PNG_COLOR_TYPE_GRAY,
        RGB = PNG_COLOR_TYPE_RGB,
        RGBA = PNG_COLOR_TYPE_RGBA,
        GrayscaleAlpha = PNG_COLOR_TYPE_GRAY_ALPHA,
        Palette = PNG_COLOR_TYPE_PALETTE
    };

    // 图像数据结构
    struct ImageData {
        std::vector<uint8_t> pixels;
        uint32_t width = 0;
        uint32_t height = 0;
        PixelFormat format = PixelFormat::RGBA;
        uint8_t bitDepth = 8;
    };

    // 分离的RGB和Alpha通道
    struct SeparatedChannels {
        std::vector<uint8_t> rgbData;
        std::vector<uint8_t> alphaData;
        uint32_t width = 0;
        uint32_t height = 0;
    };

    // 构造函数/析构函数
    PngManager() = default;
    ~PngManager() = default;

    // 从内存读取PNG
    ErrorCode ReadFromMemory(const uint8_t* buffer, size_t size, ImageData& outImage) {
        if (!buffer || size == 0) {
            return ErrorCode::InvalidParameters;
        }

        // 初始化读取结构
        png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
        if (!pngPtr) {
            return ErrorCode::CreateReadStructFailed;
        }

        png_infop infoPtr = png_create_info_struct(pngPtr);
        if (!infoPtr) {
            png_destroy_read_struct(&pngPtr, nullptr, nullptr);
            return ErrorCode::CreateInfoStructFailed;
        }

        // 错误处理设置
        if (setjmp(png_jmpbuf(pngPtr))) {
            png_destroy_read_struct(&pngPtr, &infoPtr, nullptr);
            return ErrorCode::PngProcessingError;
        }

        // 设置内存读取回调
        struct ReadContext {
            const uint8_t* data;
            size_t pos;
        } ctx{ buffer, 0 };

        png_set_read_fn(pngPtr, &ctx, [](png_structp pngPtr, png_bytep data, png_size_t length) {
            auto* ctx = static_cast<ReadContext*>(png_get_io_ptr(pngPtr));
            memcpy(data, ctx->data + ctx->pos, length);
            ctx->pos += length;
            });

        // 读取PNG信息
        png_read_info(pngPtr, infoPtr);

        // 获取基本信息
        outImage.width = png_get_image_width(pngPtr, infoPtr);
        outImage.height = png_get_image_height(pngPtr, infoPtr);
        outImage.format = static_cast<PixelFormat>(png_get_color_type(pngPtr, infoPtr));
        outImage.bitDepth = png_get_bit_depth(pngPtr, infoPtr);

        // 格式转换处理
        if (outImage.bitDepth == 16) {
            png_set_strip_16(pngPtr);
            outImage.bitDepth = 8;
        }

        if (outImage.format == PixelFormat::Palette) {
            png_set_palette_to_rgb(pngPtr);
        }

        if (outImage.format == PixelFormat::Grayscale && outImage.bitDepth < 8) {
            png_set_expand_gray_1_2_4_to_8(pngPtr);
        }

        if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) {
            png_set_tRNS_to_alpha(pngPtr);
        }

        if (outImage.format == PixelFormat::RGB ||
            outImage.format == PixelFormat::Grayscale ||
            outImage.format == PixelFormat::Palette) {
            png_set_add_alpha(pngPtr, 0xFF, PNG_FILLER_AFTER);
        }

        // 更新信息
        png_read_update_info(pngPtr, infoPtr);
        outImage.format = static_cast<PixelFormat>(png_get_color_type(pngPtr, infoPtr));
        outImage.bitDepth = png_get_bit_depth(pngPtr, infoPtr);

        // 分配内存并读取图像
        png_size_t rowBytes = png_get_rowbytes(pngPtr, infoPtr);
        outImage.pixels.resize(rowBytes * outImage.height);

        std::vector<png_bytep> rowPointers(outImage.height);
        for (uint32_t y = 0; y < outImage.height; ++y) {
            rowPointers[y] = outImage.pixels.data() + y * rowBytes;
        }

        png_read_image(pngPtr, rowPointers.data());
        png_read_end(pngPtr, nullptr);
        png_destroy_read_struct(&pngPtr, &infoPtr, nullptr);

        return ErrorCode::Success;
    }

    // 写入PNG到内存
    ErrorCode WriteToMemory(const ImageData& image, std::vector<uint8_t>& outBuffer, int compressionLevel = 6) {
        if (image.pixels.empty() || image.width == 0 || image.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        // 初始化写入结构
        png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
        if (!pngPtr) {
            return ErrorCode::CreateWriteStructFailed;
        }

        png_infop infoPtr = png_create_info_struct(pngPtr);
        if (!infoPtr) {
            png_destroy_write_struct(&pngPtr, nullptr);
            return ErrorCode::CreateInfoStructFailed;
        }

        // 错误处理设置
        if (setjmp(png_jmpbuf(pngPtr))) {
            png_destroy_write_struct(&pngPtr, &infoPtr);
            return ErrorCode::PngProcessingError;
        }

        // 设置内存写入回调
        struct WriteContext {
            std::vector<uint8_t>* buffer;
        } ctx{ &outBuffer };

        png_set_write_fn(pngPtr, &ctx, [](png_structp pngPtr, png_bytep data, png_size_t length) {
            auto* ctx = static_cast<WriteContext*>(png_get_io_ptr(pngPtr));
            size_t oldSize = ctx->buffer->size();
            ctx->buffer->resize(oldSize + length);
            memcpy(ctx->buffer->data() + oldSize, data, length);
            }, nullptr);

        // 设置压缩级别
        png_set_compression_level(pngPtr, compressionLevel);

        // 设置PNG头信息
        png_set_IHDR(pngPtr, infoPtr, image.width, image.height,
            image.bitDepth, static_cast<int>(image.format),
            PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
            PNG_FILTER_TYPE_DEFAULT);

        // 准备行指针
        png_size_t rowBytes = png_get_rowbytes(pngPtr, infoPtr);
        std::vector<png_bytep> rowPointers(image.height);
        for (uint32_t y = 0; y < image.height; ++y) {
            rowPointers[y] = const_cast<uint8_t*>(image.pixels.data()) + y * rowBytes;
        }

        // 写入数据
        png_write_info(pngPtr, infoPtr);
        png_write_image(pngPtr, rowPointers.data());
        png_write_end(pngPtr, nullptr);
        png_destroy_write_struct(&pngPtr, &infoPtr);

        return ErrorCode::Success;
    }

    // 分离RGB和Alpha通道
    ErrorCode SeparateChannels(const ImageData& image, SeparatedChannels& outChannels) {
        if (image.pixels.empty() || image.width == 0 || image.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        outChannels.width = image.width;
        outChannels.height = image.height;

        switch (image.format) {
        case PixelFormat::RGBA: {
            // RGBA格式: RGB和Alpha分离
            size_t pixelCount = image.width * image.height;
            outChannels.rgbData.resize(pixelCount * 3);
            outChannels.alphaData.resize(pixelCount);

            for (size_t i = 0; i < pixelCount; ++i) {
                outChannels.rgbData[i * 3] = image.pixels[i * 4];
                outChannels.rgbData[i * 3 + 1] = image.pixels[i * 4 + 1];
                outChannels.rgbData[i * 3 + 2] = image.pixels[i * 4 + 2];
                outChannels.alphaData[i] = image.pixels[i * 4 + 3];
            }
            break;
        }
        case PixelFormat::GrayscaleAlpha: {
            // 灰度+Alpha: 转换为RGB+Alpha
            size_t pixelCount = image.width * image.height;
            outChannels.rgbData.resize(pixelCount * 3);
            outChannels.alphaData.resize(pixelCount);

            for (size_t i = 0; i < pixelCount; ++i) {
                uint8_t gray = image.pixels[i * 2];
                outChannels.rgbData[i * 3] = gray;
                outChannels.rgbData[i * 3 + 1] = gray;
                outChannels.rgbData[i * 3 + 2] = gray;
                outChannels.alphaData[i] = image.pixels[i * 2 + 1];
            }
            break;
        }
        case PixelFormat::RGB:
        case PixelFormat::Grayscale: {
            // 无Alpha通道: 只提取RGB/灰度数据
            size_t pixelCount = image.width * image.height;

            if (image.format == PixelFormat::Grayscale) {
                // 灰度转RGB
                outChannels.rgbData.resize(pixelCount * 3);
                for (size_t i = 0; i < pixelCount; ++i) {
                    uint8_t gray = image.pixels[i];
                    outChannels.rgbData[i * 3] = gray;
                    outChannels.rgbData[i * 3 + 1] = gray;
                    outChannels.rgbData[i * 3 + 2] = gray;
                }
            }
            else {
                // 直接复制RGB数据
                outChannels.rgbData = image.pixels;
            }
            // Alpha通道为空
            outChannels.alphaData.clear();
            break;
        }
        default:
            return ErrorCode::UnsupportedFormat;
        }

        return ErrorCode::Success;
    }

    // 合并RGB和Alpha通道
    ErrorCode MergeChannels(const SeparatedChannels& channels, ImageData& outImage, PixelFormat format = PixelFormat::RGBA) {
        if (channels.rgbData.empty() || channels.width == 0 || channels.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        outImage.width = channels.width;
        outImage.height = channels.height;
        outImage.format = format;
        outImage.bitDepth = 8;

        size_t pixelCount = channels.width * channels.height;
        bool hasAlpha = !channels.alphaData.empty();

        // 检查输入数据有效性
        if (channels.rgbData.size() != pixelCount * 3) {
            return ErrorCode::InvalidParameters;
        }

        if (hasAlpha && channels.alphaData.size() != pixelCount) {
            return ErrorCode::InvalidParameters;
        }

        // 根据输出格式分配内存
        switch (format) {
        case PixelFormat::RGBA: {
            outImage.pixels.resize(pixelCount * 4);
            for (size_t i = 0; i < pixelCount; ++i) {
                outImage.pixels[i * 4] = channels.rgbData[i * 3];     // R
                outImage.pixels[i * 4 + 1] = channels.rgbData[i * 3 + 1]; // G
                outImage.pixels[i * 4 + 2] = channels.rgbData[i * 3 + 2]; // B
                outImage.pixels[i * 4 + 3] = hasAlpha ? channels.alphaData[i] : 0xFF; // A
            }
            break;
        }
        case PixelFormat::GrayscaleAlpha: {
            outImage.pixels.resize(pixelCount * 2);
            for (size_t i = 0; i < pixelCount; ++i) {
                // 转换为灰度: 0.299R + 0.587G + 0.114B
                float gray = 0.299f * channels.rgbData[i * 3] +
                    0.587f * channels.rgbData[i * 3 + 1] +
                    0.114f * channels.rgbData[i * 3 + 2];
                outImage.pixels[i * 2] = static_cast<uint8_t>(gray);
                outImage.pixels[i * 2 + 1] = hasAlpha ? channels.alphaData[i] : 0xFF;
            }
            break;
        }
        case PixelFormat::RGB: {
            outImage.pixels = channels.rgbData;
            break;
        }
        case PixelFormat::Grayscale: {
            outImage.pixels.resize(pixelCount);
            for (size_t i = 0; i < pixelCount; ++i) {
                // 转换为灰度
                float gray = 0.299f * channels.rgbData[i * 3] +
                    0.587f * channels.rgbData[i * 3 + 1] +
                    0.114f * channels.rgbData[i * 3 + 2];
                outImage.pixels[i] = static_cast<uint8_t>(gray);
            }
            break;
        }
        default:
            return ErrorCode::UnsupportedFormat;
        }

        return ErrorCode::Success;
    }
    //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充 //补充
    // 为我增加函数,将分离出的像素数据和smask 分别导出
    // 将分离的RGB通道导出为PNG
    ErrorCode ExportRgbToMemory(const SeparatedChannels& separated, std::vector<uint8_t>& outBuffer, int compressionLevel = 6) {
        if (separated.rgbData.empty() || separated.width == 0 || separated.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        // 创建RGB图像数据
        ImageData rgbImage;
        rgbImage.width = separated.width;
        rgbImage.height = separated.height;
        rgbImage.format = PixelFormat::RGB;
        rgbImage.bitDepth = 8;
        rgbImage.pixels = separated.rgbData;

        // 写入内存
        return WriteToMemory(rgbImage, outBuffer, compressionLevel);
    }

    // 将分离的Alpha通道(smask)导出为PNG
    ErrorCode ExportSmaskToMemory(const SeparatedChannels& separated, std::vector<uint8_t>& outBuffer, int compressionLevel = 6) {
        if (separated.alphaData.empty() || separated.width == 0 || separated.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        // 创建灰度图像数据(8位)
        ImageData smaskImage;
        smaskImage.width = separated.width;
        smaskImage.height = separated.height;
        smaskImage.format = PixelFormat::Grayscale;
        smaskImage.bitDepth = 8;
        smaskImage.pixels = separated.alphaData;

        // 写入内存
        return WriteToMemory(smaskImage, outBuffer, compressionLevel);
    }

    // 将分离的通道分别导出到两个内存缓冲区
    ErrorCode ExportSeparatedChannels(const SeparatedChannels& separated,
        std::vector<uint8_t>& outRgbBuffer,
        std::vector<uint8_t>& outSmaskBuffer,
        int compressionLevel = 6) {
        auto err = ExportRgbToMemory(separated, outRgbBuffer, compressionLevel);
        if (err != ErrorCode::Success) {
            return err;
        }

        // 只有存在alpha数据时才导出smask
        if (!separated.alphaData.empty()) {
            err = ExportSmaskToMemory(separated, outSmaskBuffer, compressionLevel);
            if (err != ErrorCode::Success) {
                return err;
            }
        }

        return ErrorCode::Success;
    }
    //补充结束//补充结束//补充结束//补充结束//补充结束//补充结束//补充结束//补充结束//补充结束//补充结束

#if 1//HasPDFCore
 // 导出包含smask的标准PNG(RGBA格式)
    ErrorCode ExportPngWithSmask(const DIBitmapConverter::ImageData& dibData,
        std::vector<uint8_t>& outPng,
        int compressionLevel = 6) {
        // 验证输入数据
        if (dibData.rgbData.empty() || dibData.width == 0 || dibData.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        // 检查RGB数据大小是否匹配
        bool hasAlphaInRgb = dibData.rgbData.size() == dibData.width * dibData.height * 4;
        bool hasNoAlphaInRgb = dibData.rgbData.size() == dibData.width * dibData.height * 3;
        if (!hasAlphaInRgb && !hasNoAlphaInRgb) {
            return ErrorCode::InvalidParameters;
        }

        // 检查smask数据大小是否匹配(如果有alpha)
        if (dibData.hasAlpha && !dibData.smaskData.empty()) {
            if (dibData.smaskData.size() < dibData.width * dibData.height) {
                return ErrorCode::InvalidParameters;
            }
        }

        // 初始化PNG写入结构
        png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
        if (!png_ptr) {
            return ErrorCode::CreateWriteStructFailed;
        }

        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr) {
            png_destroy_write_struct(&png_ptr, nullptr);
            return ErrorCode::CreateInfoStructFailed;
        }

        // 错误处理设置
        if (setjmp(png_jmpbuf(png_ptr))) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return ErrorCode::PngProcessingError;
        }

        // 自定义写入函数
        struct PngWriteBuffer {
            std::vector<uint8_t>* buffer;
            size_t pos;
        };

        PngWriteBuffer write_buffer = { &outPng, 0 };

        auto write_data = [](png_structp png_ptr, png_bytep data, png_size_t length) {
            PngWriteBuffer* buffer = static_cast<PngWriteBuffer*>(png_get_io_ptr(png_ptr));
            buffer->buffer->resize(buffer->pos + length);
            memcpy(&((*buffer->buffer)[buffer->pos]), data, length);
            buffer->pos += length;
            };

        auto flush_data = [](png_structp png_ptr) {};

        png_set_write_fn(png_ptr, &write_buffer, write_data, flush_data);

        // 设置压缩级别
        png_set_compression_level(png_ptr, compressionLevel);

        // 设置PNG头信息
        png_set_IHDR(png_ptr, info_ptr, dibData.width, dibData.height,
            8, PNG_COLOR_TYPE_RGBA,
            PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,
            PNG_FILTER_TYPE_DEFAULT);

        // 准备行指针数组
        std::vector<png_bytep> row_pointers(dibData.height);
        std::vector<uint8_t> rgbaData(dibData.width * dibData.height * 4);

        // 根据GetImageData的提取方式填充RGBA数据
        if (hasAlphaInRgb) {
            // 如果rgbData已经是RGBA格式(4通道)
            for (uint32_t y = 0; y < dibData.height; ++y) {
                for (uint32_t x = 0; x < dibData.width; ++x) {
                    size_t srcOffset = (y * dibData.width + x) * 4;
                    size_t dstOffset = (y * dibData.width + x) * 4;

                    // 直接复制RGB数据
                    rgbaData[dstOffset] = dibData.rgbData[srcOffset];     // R
                    rgbaData[dstOffset + 1] = dibData.rgbData[srcOffset + 1]; // G
                    rgbaData[dstOffset + 2] = dibData.rgbData[srcOffset + 2]; // B

                    // 使用rgbData中的Alpha或smaskData中的Alpha
                    if (dibData.hasAlpha && !dibData.smaskData.empty()) {
                        rgbaData[dstOffset + 3] = dibData.smaskData[y * dibData.width + x]; // A
                    }
                    else {
                        rgbaData[dstOffset + 3] = dibData.rgbData[srcOffset + 3]; // A
                    }
                }
            }
        }
        else {
            // 如果rgbData是RGB格式(3通道)
            for (uint32_t y = 0; y < dibData.height; ++y) {
                for (uint32_t x = 0; x < dibData.width; ++x) {
                    size_t srcOffset = (y * dibData.width + x) * 3;
                    size_t dstOffset = (y * dibData.width + x) * 4;

                    // 复制RGB数据
                    rgbaData[dstOffset] = dibData.rgbData[srcOffset];     // R
                    rgbaData[dstOffset + 1] = dibData.rgbData[srcOffset + 1]; // G
                    rgbaData[dstOffset + 2] = dibData.rgbData[srcOffset + 2]; // B

                    // 设置Alpha通道
                    if (dibData.hasAlpha && !dibData.smaskData.empty()) {
                        rgbaData[dstOffset + 3] = dibData.smaskData[y * dibData.width + x]; // A
                    }
                    else {
                        rgbaData[dstOffset + 3] = 0xFF; // 不透明
                    }
                }
            }
        }

        // 设置行指针
        for (uint32_t y = 0; y < dibData.height; ++y) {
            row_pointers[y] = rgbaData.data() + y * dibData.width * 4;
        }

        // 写入PNG数据
        png_write_info(png_ptr, info_ptr);
        png_write_image(png_ptr, row_pointers.data());
        png_write_end(png_ptr, nullptr);

        // 清理资源
        png_destroy_write_struct(&png_ptr, &info_ptr);

        return ErrorCode::Success;
    }
    //单独导出 RGB 数据(不含 Alpha)​
    ErrorCode ExportRgbDataToPng(const DIBitmapConverter::ImageData& dibData,
        std::vector<uint8_t>& outRgbPng,
        int compressionLevel = 6) {
        // 验证输入数据
        if (dibData.rgbData.empty() || dibData.width == 0 || dibData.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        // 检查RGB数据是否完整(必须至少包含3通道数据)
        size_t requiredSize = dibData.width * dibData.height * 3;
        if (dibData.rgbData.size() < requiredSize) {
            return ErrorCode::InvalidParameters;
        }

        // 初始化PNG
        png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
        if (!png_ptr) return ErrorCode::CreateWriteStructFailed;

        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr) {
            png_destroy_write_struct(&png_ptr, nullptr);
            return ErrorCode::CreateInfoStructFailed;
        }

        if (setjmp(png_jmpbuf(png_ptr))) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return ErrorCode::PngProcessingError;
        }

        // 内存写入回调
        struct WriteContext {
            std::vector<uint8_t>* buffer;
            size_t offset = 0;
        } ctx{ &outRgbPng };

        png_set_write_fn(png_ptr, &ctx, [](png_structp png, png_bytep data, png_size_t len) {
            auto* c = static_cast<WriteContext*>(png_get_io_ptr(png));
            c->buffer->resize(c->offset + len);
            memcpy(c->buffer->data() + c->offset, data, len);
            c->offset += len;
            }, nullptr);

        // 设置压缩和PNG头(强制输出为RGB格式)
        png_set_compression_level(png_ptr, compressionLevel);
        png_set_IHDR(png_ptr, info_ptr, dibData.width, dibData.height,
            8, PNG_COLOR_TYPE_RGB,
            PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,
            PNG_FILTER_TYPE_DEFAULT);

        // 准备行指针
        std::vector<png_bytep> row_pointers(dibData.height);
        std::vector<uint8_t> contiguous_rgb_data; // 连续存储的RGB数据

        // 关键修正:统一处理3/4通道输入数据
        if (dibData.hasAlpha && dibData.rgbData.size() >= dibData.width * dibData.height * 4) {
            // 从RGBA数据中提取RGB
            contiguous_rgb_data.resize(dibData.width * dibData.height * 3);
            for (uint32_t i = 0; i < dibData.width * dibData.height; ++i) {
                contiguous_rgb_data[i * 3] = dibData.rgbData[i * 4];     // R
                contiguous_rgb_data[i * 3 + 1] = dibData.rgbData[i * 4 + 1];   // G
                contiguous_rgb_data[i * 3 + 2] = dibData.rgbData[i * 4 + 2];   // B
            }
        }
        else {
            // 直接使用RGB数据(确保数据连续)
            contiguous_rgb_data = dibData.rgbData;
        }

        // 设置行指针(每行width*3字节)
        for (uint32_t y = 0; y < dibData.height; ++y) {
            row_pointers[y] = contiguous_rgb_data.data() + y * dibData.width * 3;
        }

        // 写入数据
        png_write_info(png_ptr, info_ptr);
        png_write_image(png_ptr, row_pointers.data());
        png_write_end(png_ptr, nullptr);

        // 清理
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return ErrorCode::Success;
    }
    //单独导出 smask (Alpha) 数据​
    ErrorCode ExportSmaskToPng(const DIBitmapConverter::ImageData& dibData,
        std::vector<uint8_t>& outSmaskPng,
        int compressionLevel = 6) {
        // 验证输入
        if (!dibData.hasAlpha || dibData.smaskData.empty() ||
            dibData.width == 0 || dibData.height == 0) {
            return ErrorCode::InvalidParameters;
        }

        // 检查Alpha数据大小
        if (dibData.smaskData.size() < dibData.width * dibData.height) {
            return ErrorCode::InvalidParameters;
        }

        // 初始化PNG
        png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
        if (!png_ptr) return ErrorCode::CreateWriteStructFailed;

        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr) {
            png_destroy_write_struct(&png_ptr, nullptr);
            return ErrorCode::CreateInfoStructFailed;
        }

        if (setjmp(png_jmpbuf(png_ptr))) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return ErrorCode::PngProcessingError;
        }

        // 内存写入回调
        struct WriteContext {
            std::vector<uint8_t>* buffer;
            size_t offset = 0;
        } ctx{ &outSmaskPng };

        png_set_write_fn(png_ptr, &ctx, [](png_structp png, png_bytep data, png_size_t len) {
            auto* c = static_cast<WriteContext*>(png_get_io_ptr(png));
            c->buffer->resize(c->offset + len);
            memcpy(c->buffer->data() + c->offset, data, len);
            c->offset += len;
            }, nullptr);

        // 设置压缩和PNG头(灰度图)
        png_set_compression_level(png_ptr, compressionLevel);
        png_set_IHDR(png_ptr, info_ptr, dibData.width, dibData.height,
            8, PNG_COLOR_TYPE_GRAY,
            PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,
            PNG_FILTER_TYPE_DEFAULT);

        // 准备行指针
        std::vector<png_bytep> row_pointers(dibData.height);
        for (uint32_t y = 0; y < dibData.height; ++y) {
            row_pointers[y] = const_cast<uint8_t*>(dibData.smaskData.data()) + y * dibData.width;
        }

        // 写入数据
        png_write_info(png_ptr, info_ptr);
        png_write_image(png_ptr, row_pointers.data());
        png_write_end(png_ptr, nullptr);

        // 清理
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return ErrorCode::Success;
    }

    //统一导出 rgb 和 smask 图像数据
    ErrorCode ExportSeparatedChannels(const DIBitmapConverter::ImageData& dibData,
        std::vector<uint8_t>& outRgbPng,
        std::vector<uint8_t>& outSmaskPng,
        int compressionLevel = 6) {
        // 导出RGB
        auto err = ExportRgbDataToPng(dibData, outRgbPng, compressionLevel);
        if (err != ErrorCode::Success) return err;

        // 仅当存在Alpha时导出smask
        if (dibData.hasAlpha && !dibData.smaskData.empty()) {
            err = ExportSmaskToPng(dibData, outSmaskPng, compressionLevel);
        }

        return err;
    }
    void ExtractImageDataFromDIBitmap(
        CFX_DIBitmap* sourceBitmap,
        PngManager::ImageData& imageData)
    {
        // 使用DIBitmapConverter提取图像数据
        DIBitmapConverter::ImageData convertedData =
            DIBitmapConverter::GetImageData(sourceBitmap, true);

        // 设置基本图像属性
        imageData.width = convertedData.width;
        imageData.height = convertedData.height;
        imageData.bitDepth = 8; // 假设8位深度
        imageData.format = PngManager::PixelFormat::RGBA; // 设置为RGBA格式

        // 判断是否有Alpha通道
        const bool hasAlpha = !convertedData.smaskData.empty() &&
            convertedData.smaskData.size() >= convertedData.width * convertedData.height;

        // 合并RGB和Alpha到RGBA格式
        const size_t pixelCount = convertedData.width * convertedData.height;
        imageData.pixels.resize(pixelCount * 4); // 为RGBA格式分配空间

        // 复制RGB和Alpha数据
        for (size_t i = 0; i < pixelCount; i++) {
            const size_t rgbOffset = hasAlpha ? i * 4 : i * 3;
            const size_t rgbaOffset = i * 4;

            // 复制RGB数据
            if (convertedData.rgbData.size() > rgbOffset + 2) {
                imageData.pixels[rgbaOffset] = convertedData.rgbData[rgbOffset];     // R
                imageData.pixels[rgbaOffset + 1] = convertedData.rgbData[rgbOffset + 1]; // G
                imageData.pixels[rgbaOffset + 2] = convertedData.rgbData[rgbOffset + 2]; // B
            }
            else {
                // 如果RGB数据不完整,使用黑色
                imageData.pixels[rgbaOffset] = 0;
                imageData.pixels[rgbaOffset + 1] = 0;
                imageData.pixels[rgbaOffset + 2] = 0;
            }

            // 设置Alpha通道
            if (hasAlpha && convertedData.smaskData.size() > i) {
                imageData.pixels[rgbaOffset + 3] = convertedData.smaskData[i]; // A
            }
            else {
                imageData.pixels[rgbaOffset + 3] = 0xFF; // 不透明
            }
        }
    }
#endif

private:
    // 禁用拷贝和赋值
    PngManager(const PngManager&) = delete;
    PngManager& operator=(const PngManager&) = delete;
};

#include <vector>
#include <cmath>
#include <algorithm>
#include <stdexcept>

///*
//
//PngManager pngManager; // 只需初始化一次
//
 多次读取不同文件
//auto image1 = pngManager.readPng("image1.png");
//auto image2 = pngManager.readPng("image2.png");
//
 多次写入不同文件
//pngManager.writePng("output1.png", image1);
//pngManager.writePng("output2.png", image2);
//
//*/
//
///*
//int main() {
//	try {
//		// 原始图像数据 (假设已加载)
//		ImageData originalImage;
//		originalImage.width = 1920;
//		originalImage.height = 1080;
//		originalImage.pixels.resize(1920 * 1080 * 4); // RGBA格式
//
//		// 使用双线性插值缩放图像到800x600
//		ImageResizer::resize(originalImage, 800, 600,
//						   ImageResizer::InterpolationMethod::BILINEAR);
//
//		// 使用双三次插值缩放图像到400x300
//		ImageResizer::resize(originalImage, 400, 300,
//						   ImageResizer::InterpolationMethod::BICUBIC);
//
//		// 使用最近邻插值缩放图像到200x150
//		ImageResizer::resize(originalImage, 200, 150,
//						   ImageResizer::InterpolationMethod::NEAREST_NEIGHBOR);
//	} catch (const std::exception& e) {
//		std::cerr << "图像缩放错误: " << e.what() << std::endl;
//		return 1;
//	}
//
//	return 0;
//}
//*/
//
///*
//int main() {
//	try {
//		PngManager pngManager;
//
//		// 方法1: 读取后分离
//		auto image = pngManager.readPng("input.png");
//		auto separated = pngManager.separateSmask(image);
//
//		// 保存分离的数据
//		pngManager.writeSeparatedSmask("output_rgb.png", "output_smask.png", separated);
//
//		// 方法2: 直接读取并分离
//		auto separated2 = pngManager.readAndSeparateSmask("input2.png");
//
//		// 修改smask数据 (例如阈值处理)
//		for (auto& alpha : separated2.smaskData) {
//			alpha = alpha > 128 ? 255 : 0; // 二值化处理
//		}
//
//		// 重新合并并保存
//		auto combined = pngManager.combineSmask(separated2);
//		pngManager.writePng("output_modified.png", combined);
//	} catch (const PngException& e) {
//		std::cerr << "PNG处理错误: " << e.what() << std::endl;
//		return 1;
//	}
//
//	return 0;
//}
//*/
//
///*
//int main() {
//	try {
//		PngManager pngManager;
//
//		// 1. 读取并分离图像
//		auto separated = pngManager.readAndSeparateSmask("input.png");
//
//		// 2. 对分离数据进行处理 (示例:将smask二值化)
//		for (auto& alpha : separated.smaskData) {
//			alpha = alpha > 128 ? 255 : 0;
//		}
//
//		// 3. 重新合并为完整图像 (RGBA格式)
//		auto mergedImage = pngManager.mergeSmaskAndRgb(separated);
//		pngManager.writePng("output_rgba.png", mergedImage);
//
//		// 4. 直接合并并保存为灰度+Alpha格式
//		pngManager.writeMergedImage("output_gray_alpha.png", separated,
//								   PngManager::PixelFormat::GRAYSCALE_ALPHA);
//
//		// 5. 合并为RGB格式 (无Alpha通道)
//		pngManager.writeMergedImage("output_rgb.png", separated,
//								  PngManager::PixelFormat::RGB);
//	} catch (const PngException& e) {
//		std::cerr << "PNG处理错误: " << e.what() << std::endl;
//		return 1;
//	}
//
//	return 0;
//}
//*/
//
//#include <vector>
//#include <cassert>
//#include <memory>

//class PDFCorePngManager //这个类负责向外暴露函数,因为pdfcore 那层缺少png相关的头文件

void PDFCorePngManager::ExtractPngDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& png_data)
{
    auto imageData = DIBitmapConverter::GetImageData(sourceBitmap, true);
    PngManager png_manager;

    png_manager.ExportPngWithSmask(imageData, png_data);
    //WriteVectorToFile(rgb_image_data, "D:/New_Code/UtilityCode/TestPDFCore/test_pdfcore/pdfcore_rgb.png");
    //WriteVectorToFile(smask_image_data, "D:/New_Code/UtilityCode/TestPDFCore/test_pdfcore/pdfcore_smask.png");
}
void PDFCorePngManager::ExtractSmaskDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& smask_image_data)
{
    auto imageData = DIBitmapConverter::GetImageData(sourceBitmap, true);
    PngManager png_manager;

    png_manager.ExportSmaskToPng(imageData, smask_image_data);
}
void PDFCorePngManager::ExtractRgbDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& rgb_image_data)
{
    auto imageData = DIBitmapConverter::GetImageData(sourceBitmap, true);
    PngManager png_manager;

    png_manager.ExportRgbDataToPng(imageData, rgb_image_data);
}
void PDFCorePngManager::ExtractRgbSmaskDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& rgb_image_data, std::vector<uint8_t>& smask_image_data)
{
    auto imageData = DIBitmapConverter::GetImageData(sourceBitmap, true);
    PngManager png_manager;

    png_manager.ExportSeparatedChannels(imageData, rgb_image_data, smask_image_data);
}

/**
 * 将 std::vector<uint8_t> 写入指定文件
 * @param data 要写入的数据向量
 * @param filename 目标文件名
 * @return 成功返回true,失败返回false
 */
bool PDFCorePngManager::WriteVectorToFile(const std::vector<uint8_t>& data, const std::string& filename) {
    // 以二进制模式打开文件,截断方式写入
    std::ofstream outfile(filename, std::ios::binary | std::ios::trunc);

    if (!outfile.is_open()) {
        return false; // 文件打开失败
    }

    // 写入数据
    outfile.write(reinterpret_cast<const char*>(data.data()), data.size());

    // 检查是否写入成功
    if (!outfile.good()) {
        outfile.close();
        return false;
    }

    outfile.close();
    return true;
}

/**
 * 从指定文件读取数据到 std::vector<uint8_t>
 * @param data 读取的数据将存储在此向量中
 * @param filename 要读取的文件名
 * @return 成功返回true,失败返回false
 */
bool static ReadVectorFromFile(std::vector<uint8_t>& data, const std::string& filename) {
    // 清空数据向量,准备接收新数据
    data.clear();

    // 以二进制模式打开文件
    std::ifstream infile(filename, std::ios::binary);

    if (!infile.is_open()) {
        return false; // 文件打开失败
    }

    // 获取文件大小
    infile.seekg(0, std::ios::end);
    std::streamsize size = infile.tellg();
    infile.seekg(0, std::ios::beg);

    if (size == -1) {
        // 获取文件大小失败
        infile.close();
        return false;
    }

    // 预分配向量内存空间
    data.reserve(static_cast<size_t>(size));

    // 读取文件内容到向量
    data.assign(std::istreambuf_iterator<char>(infile), std::istreambuf_iterator<char>());

    // 检查是否读取成功
    if (!infile.good()) {
        infile.close();
        return false;
    }

    infile.close();
    return true;
}
// 实现插值方法映射
ImageInterpolator::Method static MapInterpolationMethod(
    PDFCorePngManager::PDFCoreInterpolationMethod foxitMethod)
{
    switch (foxitMethod) {
    case PDFCorePngManager::PDFCoreInterpolationMethod::BICUBIC:
        return ImageInterpolator::Method::BICUBIC;
    case PDFCorePngManager::PDFCoreInterpolationMethod::BILINEAR:
        return ImageInterpolator::Method::BILINEAR;
    case PDFCorePngManager::PDFCoreInterpolationMethod::NEAREST_NEIGHBOR:
    default:
        return ImageInterpolator::Method::NEAREST_NEIGHBOR;
    }
}

// 实现图像像素数据缩放
bool static ResizeImageData(
    const PngManager::ImageData& source,
    PngManager::ImageData& target,
    ImageInterpolator::Method method)
{
    // 创建输入图像数据结构
    ImageInterpolator::ImageData input;
    input.width = source.width;
    input.height = source.height;
    input.bitDepth = source.bitDepth;
    input.pixels = source.pixels; // 共享数据

    // 创建输出图像数据结构
    ImageInterpolator::ImageData output;
    output.width = target.width;
    output.height = target.height;
    output.bitDepth = target.bitDepth;
    output.pixels.resize(target.width * target.height * 4); // 预分配空间

    // 执行缩放
    output = ImageInterpolator::resizeCopy(input, target.width, target.height, method);
    // 移动数据到目标
    target.pixels = std::move(output.pixels);
    return true;
}

// 实现ResizeImage方法
std::vector<uint8_t> PDFCorePngManager::ResizeImage(
    CFX_DIBitmap* sourceBitmap,
    PDFCoreInterpolationMethod pdfore_interpolation_method,
    int WidthScaleFactor)
{
    // 验证输入参数
    if (!sourceBitmap || WidthScaleFactor <= 0) {
        return {};
    }

    // 直接从源位图提取图像数据,这个是像素数据,不是编码之后的图像数据
    PngManager::ImageData sourceImage;
    PngManager png_manager;
    png_manager.ExtractImageDataFromDIBitmap(sourceBitmap, sourceImage);

    // 验证图像数据
    if (sourceImage.pixels.empty() || sourceImage.width == 0 || sourceImage.height == 0) {
        return {};
    }

    // 计算目标尺寸
    uint32_t targetWidth = (std::max)(1, static_cast<int>(sourceImage.width) / WidthScaleFactor);
    uint32_t targetHeight = (std::max)(1, static_cast<int>(sourceImage.height) / WidthScaleFactor);

    // 映射插值方法
    ImageInterpolator::Method interpolationMethod =
        MapInterpolationMethod(pdfore_interpolation_method);

    // 准备目标图像数据结构
    PngManager::ImageData targetImage;
    targetImage.width = targetWidth;
    targetImage.height = targetHeight;
    targetImage.bitDepth = sourceImage.bitDepth;
    targetImage.format = sourceImage.format;

    // 执行缩放
    if (!ResizeImageData(sourceImage, targetImage, interpolationMethod)) {
        return {};
    }

    // 将缩放后的图像像素数据编码为PNG
    std::vector<uint8_t> outputPng;
    PngManager pngManager;
    if (pngManager.WriteToMemory(targetImage, outputPng) != PngManager::ErrorCode::Success) {
        return {};
    }

    return outputPng;
}


头文件


/**
 * @class PDFCorePngManager
 * @brief 对 PngWrap 的升级版本,用于从 CFX_DIBitmap 中提取并且转换为 PNG 相关数据
 * @note Maintained by sylar ding. Do not modify without permission
 */
class PDFCorePngManager
{
public:
    // 插值方法枚举
    enum class PDFCoreInterpolationMethod {
        NEAREST_NEIGHBOR,  // 最近邻插值
        BILINEAR,          // 双线性插值
        BICUBIC            // 双三次插值
    };
public:
    // 构造函数/析构函数
    PDFCorePngManager() = default;
    ~PDFCorePngManager() = default;
    /**
     * @brief 从 CFX_DIBitmap 中提取完整的 PNG 图像数据(包含 RGB 和 Alpha 通道)
     * @param sourceBitmap 输入的位图数据
     * @param png_data 输出的 PNG 图像数据
     */
    void ExtractPngDataFromDIBitmap(CFX_DIBitmap* sourceBitmap,
        std::vector<uint8_t>& png_data);

    /**
     * @brief 从 CFX_DIBitmap 中单独提取 smask(Alpha 通道)的 PNG 图像数据
     * @param sourceBitmap 输入的位图数据
     * @param smask_image_data 输出的 smask PNG 图像数据
     */
    void ExtractSmaskDataFromDIBitmap(CFX_DIBitmap* sourceBitmap,
        std::vector<uint8_t>& smask_image_data);

    /**
     * @brief 从 CFX_DIBitmap 中单独提取 RGB(不含 Alpha)的 PNG 图像数据
     * @param sourceBitmap 输入的位图数据
     * @param rgb_image_data 输出的 RGB PNG 图像数据
     */
    void ExtractRgbDataFromDIBitmap(CFX_DIBitmap* sourceBitmap,
        std::vector<uint8_t>& rgb_image_data);

    /**
     * @brief 从 CFX_DIBitmap 中同时提取 RGB 和 smask 的 PNG 图像数据
     * @param sourceBitmap 输入的位图数据
     * @param rgb_image_data 输出的 RGB PNG 图像数据
     * @param smask_image_data 输出的 smask PNG 图像数据
     */
    void ExtractRgbSmaskDataFromDIBitmap(CFX_DIBitmap* sourceBitmap,
        std::vector<uint8_t>& rgb_image_data,
        std::vector<uint8_t>& smask_image_data);
    /**
     * 将 std::vector<uint8_t> 写入指定文件
     * @param data 要写入的数据向量
     * @param filename 目标文件名
     * @return 成功返回true,失败返回false
     */
    bool WriteVectorToFile(const std::vector<uint8_t>& data, const std::string& filename);
    /**
 * @brief 缩放图像并生成PNG数据
 * @param sourceBitmap 输入图像位图(必须非空)
 * @param interpolation_method 缩放算法,默认最近邻
 * @param WidthScaleFactor 宽度缩放倍数,默认5倍
 * @return 缩放后的PNG数据
 * @note 缩放会保持宽高比,高度按宽度比例自动调整
 */
    std::vector<uint8_t> ResizeImage(
        CFX_DIBitmap* sourceBitmap,
        PDFCoreInterpolationMethod interpolation_method = PDFCoreInterpolationMethod::NEAREST_NEIGHBOR,
        int WidthScaleFactor = 5
    );
private:
    // 禁用拷贝和赋值
    PDFCorePngManager(const PDFCorePngManager&) = delete;
    PDFCorePngManager& operator=(const PDFCorePngManager&) = delete;
};
#endif

网站公告

今日签到

点亮在社区的每一天
去签到