菜单

如何对图片进行非等比缩放

下载

1. 使用stb_image库,将stb_image.h和stb_image_write.h放到项目的代码目录下。

下载[stb_image.zip]

2. 写缩放函数resize_image,有特殊要求可直接问AI生成函数

#include <iostream>
#include <cmath>

#define STB_IMAGE_IMPLEMENTATION
#include "../stb_image.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "../stb_image_write.h"

// 修复后的双线性插值函数:增加 channel 参数,指定当前计算的通道
unsigned char bilinear_interpolate(
    const unsigned char* src_data,
    int src_w, int src_h,
    float x, float y,
    int channels,
    int channel  // 新增:当前要计算的通道(0=R,1=G,2=B,3=A)
) {
    int x0 = static_cast<int>(floor(x));
    int x1 = std::min(x0 + 1, src_w - 1);
    int y0 = static_cast<int>(floor(y));
    int y1 = std::min(y0 + 1, src_h - 1);

    float tx = x - x0;
    float ty = y - y0;

    // 关键修复:每个通道单独计算索引(+ channel)
    int idx00 = (y0 * src_w + x0) * channels + channel;
    int idx01 = (y1 * src_w + x0) * channels + channel;
    int idx10 = (y0 * src_w + x1) * channels + channel;
    int idx11 = (y1 * src_w + x1) * channels + channel;

    float val = (1 - tx) * (1 - ty) * src_data[idx00] +
                tx * (1 - ty) * src_data[idx10] +
                (1 - tx) * ty * src_data[idx01] +
                tx * ty * src_data[idx11];

    return static_cast<unsigned char>(std::round(val));
}

bool resize_image(const char* input_path, const char* output_path, int target_w, int target_h) {
    int src_w, src_h, channels;
    unsigned char* src_data = stbi_load(input_path, &src_w, &src_h, &channels, 0);
    if (!src_data) {
        std::cerr << "加载图片失败:" << stbi_failure_reason() << std::endl;
        return false;
    }

    int dst_size = target_w * target_h * channels;
    unsigned char* dst_data = new unsigned char[dst_size]();

    float scale_x = static_cast<float>(src_w) / target_w;
    float scale_y = static_cast<float>(src_h) / target_h;

    for (int y = 0; y < target_h; ++y) {
        for (int x = 0; x < target_w; ++x) {
            float src_x = x * scale_x;
            float src_y = y * scale_y;

            for (int c = 0; c < channels; ++c) {
                int dst_idx = (y * target_w + x) * channels + c;
                // 关键修复:传入当前通道 c
                dst_data[dst_idx] = bilinear_interpolate(src_data, src_w, src_h, src_x, src_y, channels, c);
            }
        }
    }

    bool success = stbi_write_png(output_path, target_w, target_h, channels, dst_data, target_w * channels);

    stbi_image_free(src_data);
    delete[] dst_data;

    if (success) {
        std::cout << "图片缩放完成(彩色),保存至:" << output_path << std::endl;
    } else {
        std::cerr << "保存图片失败!" << std::endl;
    }

    return success;
}

3. 调用缩放后,并为图片控件指定文件

void Frm02::wMButton1_clk_cb(uint16_t code, LvEvent e) {
    /*wMButton1(功能键)的点击事件*/
    resize_image("./res/pic/add.png", "./res/pic/add_resized1.png", 300, 200);
    wMImage1->setSrc("./res/pic/add_resized1.png");
}

上一个
从服务器下载下来的图片不能显示
下一个
2.3.9 列表框
最近修改: 2026-03-23Powered by