png封装操作,插值算法,压缩算法

发布于:2025-07-24 ⋅ 阅读:(37) ⋅ 点赞:(0)

头文件


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, int compressionLevel = 9);

	/**
	 * @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> ResizePngImage(
		CFX_DIBitmap* sourceBitmap,
		PDFCoreInterpolationMethod interpolation_method = PDFCoreInterpolationMethod::NEAREST_NEIGHBOR,
		int WidthScaleFactor = 5
	);
	/**
 * @brief 使用 libimagequant 压缩 PNG 图像数据(内存到内存)
 *
 * @param input_data  输入参数,包含原始PNG数据的字节向量
 * @param output_data 输出参数,用于接收压缩后的PNG数据
 * @return bool       返回压缩是否成功(true=成功,false=失败)
 *
 * @note 函数特性:
 * 1. 支持 RGBA/RGB 格式的PNG压缩
 * 2. 自动优化调色板(最多256色)
 * 3. 默认启用中等强度的抖动处理
 * 4. 使用 RAII 自动管理资源
 * 5. 异常安全设计
 *
 * @code
 *   std::vector<uint8_t> input, output;
 *   //... 读取PNG到input ...
 *   if(PNGQuantizerCompress(input, output)) {
 *     // 成功写入压缩数据到output
 *   }
 * @endcode
 */
#if !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IPHONE) //排除整个移动端
	bool PNGQuantizerCompress(std::vector<uint8_t>& input_data, std::vector<uint8_t>& output_data);
#endif
	/**
 * @brief 从DIB位图中提取完整的图像像素数据(包含RGBA通道)
 *
 * 该函数通过PngManager从CFX_DIBitmap中提取完整的图像数据,包括:
 * - 宽度、高度、位深度等图像属性
 * - 包含RGBA四通道的完整像素数据
 *
 * @param sourceBitmap 输入参数,源DIB位图对象指针
 * @param image_pixel_data 输出参数,存储提取的像素数据(RGBA格式)
 * @param width 输出参数,返回图像宽度
 * @param height 输出参数,返回图像高度
 * @param bitDepth 输出参数,返回图像位深度(通常为8)
 *
 * @return bool 提取成功返回true(像素数据非空),失败返回false
 *
 * @note 输出的像素数据格式为:
 * - 每个像素占4字节(R,G,B,A)
 * - 数据排列顺序为[R0,G0,B0,A0, R1,G1,B1,A1, ...]
 * - 包含完整的Alpha通道信息
 */
	bool ExtractImageDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& image_pixel_data, uint32_t& width, uint32_t& height,uint8_t& bitDepth);
	/**
 * @brief 从DIB位图中提取RGB图像数据(不含Alpha通道)
 *
 * 该函数通过PngManager从CFX_DIBitmap中提取仅包含RGB通道的图像数据:
 * - 宽度、高度、位深度等图像属性
 * - 仅包含RGB三通道的像素数据
 *
 * @param sourceBitmap 输入参数,源DIB位图对象指针
 * @param image_pixel_data 输出参数,存储提取的像素数据(RGB格式)
 * @param width 输出参数,返回图像宽度
 * @param height 输出参数,返回图像高度
 * @param bitDepth 输出参数,返回图像位深度(通常为8)
 *
 * @return bool 提取成功返回true(像素数据非空),失败返回false
 *
 * @note 输出的像素数据格式为:
 * - 每个像素占3字节(R,G,B)
 * - 数据排列顺序为[R0,G0,B0, R1,G1,B1, ...]
 * - 不包含Alpha通道信息
 * - 相比RGBA版本节省25%内存空间
 */
	bool ExtractRGBDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& image_pixel_data, uint32_t &width, uint32_t &height, uint8_t &bitDepth);

	/**
 * @brief 缩放图像并将结果通过输出参数返回(不进行PNG编码)
 *
 * 该方法从源位图提取图像数据,按指定比例缩放后,通过输出参数返回缩放后的
 * 原始像素数据及图像属性信息,相比ResizeImage()方法避免了对PNG编码的依赖。
 *
 * @param sourceBitmap 输入参数,源图像位图指针
 * @param pdfore_interpolation_method 输入参数,指定的插值方法
 * @param WidthScaleFactor 输入参数,宽度缩放因子(必须>0)
 * @param outWidth 输出参数,缩放后的图像宽度
 * @param outHeight 输出参数,缩放后的图像高度
 * @param outBitDepth 输出参数,缩放后的图像位深度
 * @param outFormat 输出参数,缩放后的像素格式(RGBA/RGB等)
 * @param outPixels 输出参数,存储缩放后的像素数据容器
 *
 * @return bool 缩放成功返回true,失败返回false
 */
	bool ResizeImageToPixel(
		CFX_DIBitmap* sourceBitmap,
		PDFCoreInterpolationMethod pdfore_interpolation_method,
		int WidthScaleFactor,
		uint32_t& outWidth,           // 输出:目标宽度
		uint32_t& outHeight,          // 输出:目标高度
		uint8_t& outBitDepth,         // 输出:位深度
		int& outFormat,               // 输出:像素格式
		std::vector<uint8_t>& outPixels, // 输出:像素数据
		bool isJpegFormat,
		bool use_multithread //是否使用多线程
	);

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

实现文件

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            // 双三次插值
    };

    // 通用图像数据结构,支持PNG(4通道)和JPEG(3通道)
    struct ImageData {
        std::vector<uint8_t> pixels;
        uint32_t width = 0;
        uint32_t height = 0;
        uint8_t bitDepth = 8;
        uint8_t channels = 4; // 默认为4通道(PNG),JPEG为3通道
    };

    // 缩放图像方法,原地修改像素数据
    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;
        }

        // 只支持3或4通道的图像
        if (image.channels != 3 && image.channels != 4) {
            return false;
        }

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

        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 < image.channels; ++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) * image.channels + 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.channels = source.channels;

        // 验证参数有效性
        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; // 返回空对象
        }

        // 只支持3或4通道的图像
        if (source.channels != 3 && source.channels != 4) {
            return result; // 返回空对象
        }

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

        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 < source.channels; ++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) * source.channels + c] =
                        static_cast<uint8_t>((std::max)(0.0f, (std::min)(255.0f, value)));
                }
            }
        }

        return result;
    }
    static bool resizeMulityThread(ImageData& image,
        uint32_t newWidth,
        uint32_t newHeight,
        Method method = Method::BILINEAR,
        unsigned int numThreads = std::thread::hardware_concurrency()) {

        // 参数验证 (与原始代码相同)
        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;
        if (image.bitDepth != 8) return false;
        if (image.channels != 3 && image.channels != 4) return false;

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

        // 限制线程数量以避免过度分割
        numThreads = (std::min)(numThreads, static_cast<unsigned int>(newHeight));
        if (numThreads == 0) numThreads = 1;

        // 线程工作函数
        auto worker = [&](uint32_t startY, uint32_t endY) {
            for (uint32_t y = startY; y < endY; ++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 < image.channels; ++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;
                        }
                        resizedPixels[(y * newWidth + x) * image.channels + c] =
                            static_cast<uint8_t>((std::max)(0.0f, (std::min)(255.0f, value)));
                    }
                }
            }
            };

        // 创建并启动线程
        std::vector<std::thread> threads;
        uint32_t rowsPerThread = newHeight / numThreads;
        uint32_t extraRows = newHeight % numThreads;
        uint32_t startY = 0;

        for (unsigned int i = 0; i < numThreads; ++i) {
            uint32_t endY = startY + rowsPerThread + (i < extraRows ? 1 : 0);
            threads.emplace_back(worker, startY, endY);
            startY = endY;
        }

        // 等待所有线程完成
        for (auto& thread : threads) {
            thread.join();
        }

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

        return true;
    }

    static ImageData resizeCopyMulityThread(const ImageData& source,
        uint32_t newWidth,
        uint32_t newHeight,
        Method method = Method::BILINEAR,
        unsigned int numThreads = std::thread::hardware_concurrency()) {

        ImageData result;
        result.width = newWidth;
        result.height = newHeight;
        result.bitDepth = source.bitDepth;
        result.channels = source.channels;

        // 参数验证 (与原始代码相同)
        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;
        }
        if (source.bitDepth != 8) return result;
        if (source.channels != 3 && source.channels != 4) return result;

        result.pixels.resize(newWidth * newHeight * source.channels);

        // 限制线程数量
        numThreads = (std::min)(numThreads, static_cast<unsigned int>(newHeight));
        if (numThreads == 0) numThreads = 1;

        // 线程工作函数
        auto worker = [&](uint32_t startY, uint32_t endY) {
            for (uint32_t y = startY; y < endY; ++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 < source.channels; ++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;
                        }
                        result.pixels[(y * newWidth + x) * source.channels + c] =
                            static_cast<uint8_t>((std::max)(0.0f, (std::min)(255.0f, value)));
                    }
                }
            }
            };

        // 创建并启动线程
        std::vector<std::thread> threads;
        uint32_t rowsPerThread = newHeight / numThreads;
        uint32_t extraRows = newHeight % numThreads;
        uint32_t startY = 0;

        for (unsigned int i = 0; i < numThreads; ++i) {
            uint32_t endY = startY + rowsPerThread + (i < extraRows ? 1 : 0);
            threads.emplace_back(worker, startY, endY);
            startY = endY;
        }

        // 等待所有线程完成
        for (auto& thread : threads) {
            thread.join();
        }

        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) * image.channels + 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) * image.channels + channel];
        float v21 = image.pixels[(y1 * image.width + x2) * image.channels + channel];
        float v12 = image.pixels[(y2 * image.width + x1) * image.channels + channel];
        float v22 = image.pixels[(y2 * image.width + x2) * image.channels + 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) * image.channels + 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;
    }
};
#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; // 不透明
            }
        }
    }
    // 从DIB位图中提取RGB数据(不含Alpha通道),适合rgb图像
    void ExtractRGBDataFromDIBitmap(
        CFX_DIBitmap* sourceBitmap,      // 输入:源位图对象
        PngManager::ImageData& imageData) // 输出:存储提取的图像数据
    {
        // 使用DIBitmapConverter获取图像数据(第二个参数false表示不处理Alpha通道)
        DIBitmapConverter::ImageData convertedData =
            DIBitmapConverter::GetImageData(sourceBitmap, false);

        // 设置图像基本属性
        imageData.width = convertedData.width;    // 图像宽度
        imageData.height = convertedData.height; // 图像高度
        imageData.bitDepth = 8;                  // 固定8位色深
        imageData.format = PngManager::PixelFormat::RGB; // 设置为RGB格式

        // 计算总像素数并分配RGB数据存储空间(每个像素3字节)
        const size_t pixelCount = convertedData.width * convertedData.height;
        imageData.pixels.resize(pixelCount * 3); // 预分配内存

        // 逐个像素复制RGB数据
        for (size_t i = 0; i < pixelCount; i++) {
            const size_t srcOffset = i * 3;  // 源数据偏移量(每个像素3字节)
            const size_t destOffset = i * 3; // 目标数据偏移量

            // 安全地复制RGB三个分量
            if (convertedData.rgbData.size() > srcOffset + 2) {
                // 正常情况:复制R/G/B三个通道
                imageData.pixels[destOffset] = convertedData.rgbData[srcOffset];     // 红
                imageData.pixels[destOffset + 1] = convertedData.rgbData[srcOffset + 1]; // 绿
                imageData.pixels[destOffset + 2] = convertedData.rgbData[srcOffset + 2]; // 蓝
            }
            else {
                // 异常情况:源数据不足时填充黑色
                imageData.pixels[destOffset] = 0;     // 红=0
                imageData.pixels[destOffset + 1] = 0; // 绿=0
                imageData.pixels[destOffset + 2] = 0; // 蓝=0
            }

            // 注意:此处与原始函数不同,完全不处理Alpha通道数据
        }
    }
#endif

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

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



//todo 扩展PngManager


// 扩展 PngManager 类以支持索引图像
class ExtendedPngManager : public PngManager {
public:
    // 写入索引图像到内存
    PngManager::ErrorCode WriteIndexedToMemory(
        uint32_t width, uint32_t height,
        const std::vector<uint8_t>& indexes,   // 索引数据,大小为 width * height
        const std::vector<png_color>& palette,   // 调色板
        const std::vector<uint8_t>& trans,       // 调色板的透明度(可选)
        std::vector<uint8_t>& outBuffer,
        int compressionLevel = 6)
    {
        if (indexes.size() != width * height) {
            return PngManager::ErrorCode::InvalidParameters;
        }
        if (palette.empty() || palette.size() > 256) {
            return PngManager::ErrorCode::InvalidParameters;
        }

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

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

        // 错误处理设置
        if (setjmp(png_jmpbuf(pngPtr))) {
            png_destroy_write_struct(&pngPtr, &infoPtr);
            return PngManager::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);

        // 设置IHDR:索引模式
        png_set_IHDR(pngPtr, infoPtr, width, height, 8,
            PNG_COLOR_TYPE_PALETTE, // 索引颜色
            PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,
            PNG_FILTER_TYPE_DEFAULT);

        // 设置调色板
        png_color paletteArray[256];
        int paletteSize = static_cast<int>(palette.size());
        if (paletteSize > 256) paletteSize = 256;
        for (int i = 0; i < paletteSize; i++) {
            paletteArray[i] = palette[i];
        }
        png_set_PLTE(pngPtr, infoPtr, paletteArray, paletteSize);

        // 设置透明度(tRNS)块
        if (!trans.empty()) {
            // 如果trans的大小小于调色板大小,则只设置前面的部分
            int transSize = static_cast<int>(trans.size()) < paletteSize ? static_cast<int>(trans.size()) : paletteSize;
            png_byte transArray[256];
            for (int i = 0; i < transSize; i++) {
                transArray[i] = trans[i];
            }
            png_set_tRNS(pngPtr, infoPtr, transArray, transSize, nullptr);
        }

        // 写入信息头
        png_write_info(pngPtr, infoPtr);

        // 准备行指针
        std::vector<png_bytep> rowPointers(height);
        for (uint32_t y = 0; y < height; ++y) {
            // 注意:indexes是一维数组,按行存储
            // 由于indexes是const,但libpng要求非const指针,所以需要const_cast。但注意,libpng不会修改数据。
            rowPointers[y] = const_cast<png_bytep>(&indexes[y * width]);
        }

        // 写入图像数据
        png_write_image(pngPtr, rowPointers.data());
        png_write_end(pngPtr, nullptr);

        // 清理
        png_destroy_write_struct(&pngPtr, &infoPtr);

        return PngManager::ErrorCode::Success;
    }

    // 写入索引图像到文件
    PngManager::ErrorCode WriteIndexedToFile(
        uint32_t width, uint32_t height,
        const std::vector<uint8_t>& indexes,
        const std::vector<png_color>& palette,
        const std::vector<uint8_t>& trans,
        //const std::filesystem::path& path,
        //const fs::path& path,
        std::string path,
        int compressionLevel = 6)
    {
        std::vector<uint8_t> outBuffer;
        ErrorCode err = WriteIndexedToMemory(width, height, indexes, palette, trans, outBuffer, compressionLevel);
        if (err != ErrorCode::Success) {
            return err;
        }

        // 将内存数据写入文件
        std::ofstream file(path, std::ios::binary);
        if (!file) {
            return ErrorCode::PngProcessingError;
        }
        file.write(reinterpret_cast<const char*>(outBuffer.data()), outBuffer.size());
        return ErrorCode::Success;
    }
};

#if defined(_WIN32) || defined(_WIN64)
//PNGQuantizer 需要这些系统库,目前没方法生成vs工程主动包含这些系统库,只能在上层去主动包含
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "userenv.lib")
#pragma comment(lib, "ntdll.lib")
#endif
#if !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IPHONE) //排除整个移动端

// PNG压缩器类
class PNGQuantizer {
public:
    // 压缩参数配置结构体
    /**
 * @brief 完整的压缩参数配置
 *
 * @param max_colors        最大颜色数(值越小压缩越强 ✅)
 *                          (默认256,建议范围16-256)
 *
 * @param dither_level      抖动级别(值越大压缩效果越好但可能有噪点 ✅)
 *                          (0.0=无抖动,1.0=完全抖动,默认1.0)
 *
 * @param speed            处理速度(值越大压缩越快但质量越低 ❌)
 *                         (1=最慢质量最好,10=最快,默认5)
 *
 * @param compression_level PNG压缩级别(值越大压缩越强 ✅)
 *                          (0=不压缩,9=最大压缩,默认9)
 *
 * @param quality_min       最小质量(值越小压缩越强 ✅)
 *                          (0-100,与quality_max配合使用,默认0)
 *
 * @param quality_max       最大质量(值越小压缩越强 ✅)
 *                          (0-100,建议不低于70,默认100)
 *
 * @param posterization     最小色调分级(值越大颜色过渡越生硬 ✅)
 *                          (0=平滑,3=明显色调分离,默认0)
 *
 * @param min_opacity       最小透明度(值越大透明区域越少 ✅)
 *                          (0-255,仅RGBA有效,默认0)
 */
    struct CompressionParams {
        int max_colors = 256;      // ✅ 越小压缩越强
        float dither_level = 1.0f; // ✅ 越大压缩效果越好(但可能有噪点)
        int speed = 5;             // ❌ 越大压缩越快(但质量越低)
        int compression_level = 9; // ✅ 越大压缩越强//这个是libpng的参数
        int quality_min = 0;       // ✅ 越小压缩越强
        int quality_max = 100;     // ✅ 越小压缩越强
        int posterization = 0;     // ✅ 越大颜色过渡越生硬
        int min_opacity = 0;       // ✅ 越大透明区域越少
    };


    // 执行PNG压缩的主方法
    bool compress(const std::vector<uint8_t>& input_png_data,
        std::vector<uint8_t>& output_png_data,
        CompressionParams params) {

        // 创建PNG管理器实例
        ExtendedPngManager pngManager;
        // 存储解码后的图像数据
        PngManager::ImageData imageData;

        // 从内存解码PNG数据
        auto error = pngManager.ReadFromMemory(input_png_data.data(),
            input_png_data.size(),
            imageData);
        // 检查解码是否成功
        if (error != PngManager::ErrorCode::Success) {
            return false;
        }

        // 获取图像基本属性
        const int width = static_cast<int>(imageData.width);  // 图像宽度
        const int height = static_cast<int>(imageData.height); // 图像高度
        // 判断是否包含alpha通道
        const bool has_alpha = (imageData.format == PngManager::PixelFormat::RGBA);

        // 创建并配置量化属性
        UniqueLiqAttr attr(liq_attr_create());
        // 设置最大颜色数
        liq_set_max_colors(attr.get(), params.max_colors);
        // 设置处理速度
        liq_set_speed(attr.get(), params.speed);
        // 如果有alpha通道,设置最小透明度
 
        liq_set_max_colors(attr.get(), params.max_colors);
        liq_set_speed(attr.get(), params.speed);
        liq_set_quality(attr.get(), params.quality_min, params.quality_max);
        liq_set_min_posterization(attr.get(), params.posterization);

        if (has_alpha) {
            liq_set_min_opacity(attr.get(), params.min_opacity);
        }

        // 从原始数据创建量化图像
        UniqueLiqImage image(liq_image_create_rgba(attr.get(),
            imageData.pixels.data(),
            width, height, 0));
        // 执行颜色量化
        UniqueLiqResult result(liq_quantize_image(attr.get(), image.get()));
        // 设置抖动级别
        liq_set_dithering_level(result.get(), params.dither_level);

        // 准备存储索引数据的缓冲区
        std::vector<uint8_t> indexed_data(width * height);
        // 生成调色板索引图像
        liq_write_remapped_image(result.get(),
            image.get(),
            indexed_data.data(),
            indexed_data.size());

        // 获取量化后的调色板
        const liq_palette* palette = liq_get_palette(result.get());
        // 准备PNG调色板数据
        std::vector<png_color> pngPalette;
        // 准备透明度数据(如果有alpha通道)
        std::vector<uint8_t> alpha_channel;

        // 遍历调色板中的所有颜色
        for (int i = 0; i < palette->count; i++) {
            // 添加RGB颜色到调色板
            pngPalette.push_back({
                palette->entries[i].r,  // 红色分量
                palette->entries[i].g,  // 绿色分量
                palette->entries[i].b   // 蓝色分量
                });
            // 如果有alpha通道,添加透明度值
            if (has_alpha) {
                alpha_channel.push_back(palette->entries[i].a);
            }
        }

        // 将索引图像编码为PNG格式
        error = pngManager.WriteIndexedToMemory(
            width, height,            // 图像尺寸
            indexed_data,            // 索引数据
            pngPalette,              // 颜色调色板
            alpha_channel,           // 透明度数据
            output_png_data,         // 输出缓冲区
            params.compression_level // 压缩级别
        );

        // 返回操作是否成功
        return error == PngManager::ErrorCode::Success;
    }
    CompressionParams GetMaxCompressionParams() {
        PNGQuantizer::CompressionParams params;

        // 颜色设置(大幅减少颜色数)
        params.max_colors = 32;          // ✅ 使用32色(最小值建议不低于16)
        params.posterization = 2;        // ✅ 启用明显色调分离

        // 质量与速度设置
        params.quality_min = 0;          // ✅ 不保证最低质量
        params.quality_max = 20;         // ✅ 限制最高质量为50%
        params.speed = 10;               // ❌ 最快速度(牺牲质量)

        // 抖动与透明度设置
        params.dither_level = 0.8f;      // ✅ 适度抖动(平衡文件大小与噪点)
        params.min_opacity = 30;         // ✅ 忽略透明度<30的像素

        // PNG编码设置
        params.compression_level = 9;    // ✅ 最大压缩级别

        return params;
    }
private:
    // liq_attr指针的自定义删除器
    struct LiqAttrDeleter {
        void operator()(liq_attr* attr) const {
            // 安全销毁liq_attr对象
            if (attr) liq_attr_destroy(attr);
        }
    };

    // liq_image指针的自定义删除器
    struct LiqImageDeleter {
        void operator()(liq_image* img) const {
            // 安全销毁liq_image对象
            if (img) liq_image_destroy(img);
        }
    };

    // liq_result指针的自定义删除器
    struct LiqResultDeleter {
        void operator()(liq_result* res) const {
            // 安全销毁liq_result对象
            if (res) liq_result_destroy(res);
        }
    };

    // 使用unique_ptr管理liq_attr生命周期
    using UniqueLiqAttr = std::unique_ptr<liq_attr, LiqAttrDeleter>;
    // 使用unique_ptr管理liq_image生命周期
    using UniqueLiqImage = std::unique_ptr<liq_image, LiqImageDeleter>;
    // 使用unique_ptr管理liq_result生命周期
    using UniqueLiqResult = std::unique_ptr<liq_result, LiqResultDeleter>;
};

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

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

    png_manager.ExportPngWithSmask(imageData, png_data, compressionLevel);
    //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);
}
#if !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IPHONE) //排除整个移动端
bool PDFCorePngManager::PNGQuantizerCompress(std::vector<uint8_t>& input_data, std::vector<uint8_t>& output_data)
{
    PNGQuantizer quantizer;
    // 示例1:普通压缩
    //PNGQuantizer::CompressionParams normal_params;
    //normal_params.max_colors = 128;
    //normal_params.dither_level = 0.8f;
    //quantizer.compress(input_data, output_data, normal_params);

    // 示例2:高质量压缩
   // PNGQuantizer::CompressionParams high_quality_params;
   // high_quality_params.speed = 3;              // 较慢速度
   // high_quality_params.quality_min = 30;       // 最低质量要求
   // high_quality_params.posterization = 1;     // 保留更多色调层次
   //return quantizer.compress(input_data, output_data, high_quality_params);

    //// 示例3:透明图像优化
    //PNGQuantizer::CompressionParams alpha_params;
    //alpha_params.min_opacity = 10;             // 忽略透明度低于10的像素
    //alpha_params.quality_max = 80;            // 平衡质量和大小
    //quantizer.compress(input_data, output_data, alpha_params);
  

    PNGQuantizer::CompressionParams compress_param =  quantizer.GetMaxCompressionParams();
    return quantizer.compress(input_data, output_data, compress_param);
}
#endif
bool PDFCorePngManager::ExtractImageDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& image_pixel_data, uint32_t& width, uint32_t& height, uint8_t& bitDepth)
{
    PngManager png_manager;
    PngManager::ImageData sourceImage;
    png_manager.ExtractImageDataFromDIBitmap(sourceBitmap, sourceImage);
    width = sourceImage.width;
    height = sourceImage.height;
    bitDepth = sourceImage.bitDepth;
    image_pixel_data = std::move(sourceImage.pixels);
    return !image_pixel_data.empty();  // Returns true if there is data
}
bool PDFCorePngManager::ExtractRGBDataFromDIBitmap(CFX_DIBitmap* sourceBitmap, std::vector<uint8_t>& image_pixel_data, uint32_t &width, uint32_t &height, uint8_t &bitDepth)
{
    PngManager png_manager;
    PngManager::ImageData sourceImage;
    png_manager.ExtractRGBDataFromDIBitmap(sourceBitmap, sourceImage);
    width = sourceImage.width;
    height = sourceImage.height;
    bitDepth = sourceImage.bitDepth;
    image_pixel_data = std::move(sourceImage.pixels);
    return !image_pixel_data.empty();  // Returns true if there is 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;
    }
}
// 统一图像缩放函数,支持PNG(4通道)和JPEG(3通道)
bool static ResizeImageData(
    const PngManager::ImageData& source,
    PngManager::ImageData& target,
    ImageInterpolator::Method method,
    bool use_multithread,
    uint8_t channels = 4) // 默认4通道(PNG),JPEG可传3
{
    // 验证源图像有效性
    if (source.pixels.empty() || source.width == 0 || source.height == 0) {
        return false;
    }

    // 验证目标尺寸有效性
    if (target.width == 0 || target.height == 0) {
        return false;
    }

    // 验证通道数有效性
    if (channels != 3 && channels != 4) {
        return false;
    }

    // 验证像素数据大小是否匹配
    if (source.pixels.size() != source.width * source.height * channels) {
        return false;
    }

    // 创建输入图像数据结构
    ImageInterpolator::ImageData input;
    input.width = source.width;
    input.height = source.height;
    input.bitDepth = source.bitDepth;
    input.channels = channels;
    input.pixels = source.pixels; // 复制数据

    // 执行缩放
    ImageInterpolator::ImageData output =
        ImageInterpolator::resizeCopy(input, target.width, target.height, method);

    // 验证输出是否有效
    if (output.pixels.empty() ||
        output.width != target.width ||
        output.height != target.height ||
        output.pixels.size() != target.width * target.height * channels) {
        return false;
    }

    // 更新目标图像数据
    target.width = output.width;
    target.height = output.height;
    target.bitDepth = output.bitDepth;
    target.pixels = std::move(output.pixels);

    return true;
}


// 实现ResizeImage方法
std::vector<uint8_t> PDFCorePngManager::ResizePngImage(
    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, false , 4)) {
        return {};
    }

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

    return outputPng;
}

bool PDFCorePngManager::ResizeImageToPixel(
    CFX_DIBitmap* sourceBitmap,
    PDFCoreInterpolationMethod pdfore_interpolation_method,
    int WidthScaleFactor,
    uint32_t& outWidth,           // 输出:目标宽度
    uint32_t& outHeight,          // 输出:目标高度
    uint8_t& outBitDepth,         // 输出:位深度
    int& outFormat,               // 输出:像素格式
    std::vector<uint8_t>& outPixels, // 输出:像素数据
    bool isJpegFormat,
    bool use_multithread)            // 新增参数:是否为JPEG格式
{
    // 验证输入参数
    if (!sourceBitmap || WidthScaleFactor <= 0) {
        return false;
    }

    PngManager::PixelFormat pix_format;
    PngManager::ImageData sourceImage;
    PngManager png_manager;

    // 根据图像格式提取数据
    if (isJpegFormat) {
        png_manager.ExtractRGBDataFromDIBitmap(sourceBitmap, sourceImage);
    }
    else {
        png_manager.ExtractImageDataFromDIBitmap(sourceBitmap, sourceImage);
    }

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

    // 计算目标尺寸
    outWidth = (std::max)(1, static_cast<int>(sourceImage.width) / WidthScaleFactor);
    outHeight = (std::max)(1, static_cast<int>(sourceImage.height) / WidthScaleFactor);
    outBitDepth = sourceImage.bitDepth;
    pix_format = sourceImage.format;

    // 准备目标图像数据结构
    PngManager::ImageData targetImage;
    targetImage.width = outWidth;
    targetImage.height = outHeight;
    targetImage.bitDepth = outBitDepth;
    targetImage.format = pix_format;

    // 根据格式确定通道数
    int channels = isJpegFormat ? 3 : (pix_format == PngManager::PixelFormat::RGBA ? 4 : 3);
    targetImage.pixels.reserve(outWidth * outHeight * channels);

    // 执行缩放
    if (use_multithread)
    {
        if (!ResizeImageData(sourceImage, targetImage,
            MapInterpolationMethod(pdfore_interpolation_method), true,channels)) {
            return false;
        }
    }
    else {
        if (!ResizeImageData(sourceImage, targetImage,
            MapInterpolationMethod(pdfore_interpolation_method), false,channels)) {
            return false;
        }
    }
   

    // 通过输出参数返回结果
    outPixels = std::move(targetImage.pixels);
    outFormat = static_cast<int>(pix_format);
    return true;
}


//todo 示例用法

/*

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



/*

//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;
//}
//*/
//// 对于JPEG图像(RGB)
//ImageInterpolator::ImageData jpegImage;
//jpegImage.width = 800;
//jpegImage.height = 600;
//jpegImage.channels = 3; // RGB
//jpegImage.pixels.resize(jpegImage.width* jpegImage.height * 3); // 3通道
//
//// 缩放JPEG图像
//ImageInterpolator::resize(jpegImage, 400, 300, ImageInterpolator::Method::BILINEAR);
//
//// 对于PNG图像(RGBA)
//ImageInterpolator::ImageData pngImage;
//pngImage.width = 800;
//pngImage.height = 600;
//pngImage.channels = 4; // RGBA (默认)
//pngImage.pixels.resize(pngImage.width* pngImage.height * 4); // 4通道
//
//// 缩放PNG图像
//ImageInterpolator::resize(pngImage, 400, 300, ImageInterpolator::Method::BICUBIC);
//todo 示例用法


网站公告

今日签到

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