图片压缩处理(二)

读取图片函数

用opencv读取图片返回mat,为避免中文路径的问题,不能直接用imread

用ifstream以二进制打开图片,把文件内容读入到std::vector<uchar> 缓冲区,再用imdecode解码数据为MAT格式返回。

cpp 复制代码
static cv::Mat imread_unicode(const std::wstring& filename) {
        std::ifstream ifs(filename, std::ios::binary);
        std::vector<uchar> buffer((std::istreambuf_iterator<char>(ifs)), {});
        return cv::imdecode(buffer, cv::IMREAD_UNCHANGED);
    }

裁剪图片函数

参数说明:

  • input_path:输入图片路径
  • output_path:输出图片路径
  • x, y:裁剪区域左上角坐标
  • width, height:裁剪区域宽高
  • out_width, out_height:输出图片的宽高(缩放用)
  • max_size:最大允许输出文件大小(未在实现中直接用到)

主要流程:

  1. 用 ifstream 读取 input_path 指定的图片文件内容到内存 buffer。
  2. 用 OpenCV 的 imdecode 解码 buffer 得到 cv::Mat 图像对象。
  3. 检查图像是否加载成功,失败则返回 false。
  4. 校正裁剪区域,确保不会越界。
  5. 用 OpenCV 的 Rect 和 Mat 裁剪出指定区域。
  6. 用 resize 将裁剪后的图片缩放到 out_width × out_height。
  7. 用 imencode 按输出路径的扩展名编码图片到 output_buffer。
  8. 用 ofstream 写入 output_path。
  9. 写入成功返回 true,失败返回 false。
  10. 捕获异常,出错时返回 false 并记录日志。
cpp 复制代码
static bool cropImage(std::string_view input_path, const std::string_view output_path, int x, int y, int width,
                          int height, int out_width, int out_height, int max_size) {
        try {
            std::ifstream ifs(CommonTool::charToWchar(input_path), std::ios::binary);
            std::vector<uchar> buffer((std::istreambuf_iterator<char>(ifs)), {});
            cv::Mat image = cv::imdecode(buffer, cv::IMREAD_UNCHANGED);
            if (image.empty()) {
                spdlog::error("Failed to load image: {}", input_path);
                return false;
            }

            // 确保裁剪区域在图像范围内
            x = std::max(0, x);
            y = std::max(0, y);
            width = std::min(width, image.cols - x);
            height = std::min(height, image.rows - y);

            if (width <= 0 || height <= 0) {
                spdlog::error("Invalid crop dimensions.");
                return false;
            }

            cv::Rect crop_region(x, y, width, height);

            cv::Mat cropped_image = image(crop_region);
            cv::Mat img_fixed;
            resize(cropped_image, img_fixed, {out_width, out_height}, 0, 0, cv::INTER_AREA);

            std::vector<uchar> output_buffer;
            bool success = cv::imencode(CommonTool::getExtension(output_path), img_fixed, output_buffer);

            if (success) {
                std::ofstream ofs(CommonTool::charToWchar(output_path), std::ios::binary);
                if (ofs.is_open()) {
                    ofs.write(reinterpret_cast<const char*>(output_buffer.data()), output_buffer.size());
                    ofs.close();
                } else {
                    spdlog::error("Failed to open file for writing: {}", output_path);
                    return false;
                }
            } else {
                spdlog::error("Failed to encode image");
                return false;
            }

            return true;
        } catch (const cv::Exception& e) {
            spdlog::error("OpenCV error: {}", e.what());
            return false;
        } catch (const std::exception& e) {
            spdlog::error("Standard exception: {}", e.what());
            return false;
        } catch (...) {
            spdlog::error("Unknown error occurred while cropping the image.");
            return false;
        }
    }

获取图像编码器辅助函数

获取编码器数量以及编码器数组大小,遍历数组中的类型,当匹配的时候返回

cpp 复制代码
static int getEncoderClsid(const WCHAR* format, CLSID* pClsid) {
        UINT num = 0;   // 编码器数量
        UINT size = 0;  // 编码器数组大小

        Gdiplus::ImageCodecInfo* codec_info = nullptr;

        Gdiplus::GetImageEncodersSize(&num, &size);
        if (size == 0)
            return -1;  // 失败

        auto buffer = std::make_unique<BYTE[]>(size);
        codec_info = reinterpret_cast<Gdiplus::ImageCodecInfo*>(buffer.get());
        if (!codec_info)
            return -1;  // 失败

        GetImageEncoders(num, size, codec_info);

        for (UINT j = 0; j < num; ++j) {
            if (wcscmp(codec_info[j].MimeType, format) == 0) {
                *pClsid = codec_info[j].Clsid;
                return j;
            }
        }

        return -1;
    }
相关推荐
五岁小孩8 天前
推荐几款免费免登录无损高质量图片压缩工具网站
图片压缩·压缩图片·压缩图片工具
阿幸软件杂货间3 个月前
QuestionPicture:一键批量改图,支持压缩图片
图片压缩
zhz52144 个月前
基于SQLite索引的智能图片压缩存储系统设计与实现
数据库·sqlite·图片压缩·压缩
HUANGKELEN5 个月前
如何高清裁剪证件照尺寸和像素?
图片压缩·证件照裁剪
勇敢牛牛_9 个月前
【Rust基础】使用Rust和WASM开发的图片压缩工具
开发语言·rust·wasm·图片压缩
办公小技巧1 年前
手机图片压缩,推荐五种压缩方式
智能手机·图片压缩
Persus1 年前
通过调整尺寸压缩 PNG 图片并转换为 PDF (Python)
图像处理·python·pdf·图片压缩·png
凄凄迷人1 年前
前端基于Rust实现的Wasm进行图片压缩的技术文档
前端·rust·wasm·图片压缩
hudunkjpdf1 年前
手机照片怎么改大小kb?3个压缩方法分享
经验分享·智能手机·图片压缩·压缩·手机照片