You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用stb_image在纯C中写入RGB像素到PNG?代码异常排查

问题:使用stb_image_write生成PNG时出现随机噪点而非预期灰色图像

你的代码核心问题是像素数组的索引计算完全错误,导致读写的内存位置混乱,最终输出噪点。以下是具体问题和修正方案:

错误点分析

  • 输入图像初始化索引错误:image_data[x * y *1]这种写法完全不符合RGB像素数组的存储逻辑,正确的索引应该是(y * 160 + x) * 3 + 通道序号(160是原图像宽度)。x*y的计算会导致大量像素位置重复或越界,大部分内存未被正确初始化,保留随机值。
  • 输出图像填充索引错误:image[(a + add_a) * (b + add_b) * 1]的写法逻辑混乱,输出图像的正确索引应为((b + add_b) * 1280 + (a + add_a)) * 3 + 通道序号(1280是输出图像宽度),否则会错误覆盖像素位置,读取到无效内存数据。
  • zFill函数小问题:strncat(dest, "0", 2)中长度参数应为1,否则可能写入多余字符,不过这不是导致噪点的核心原因。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

void zFill(char * dest, int num, int amount) // fills string with zeros
{
    char str [10];
    sprintf(str, "%d", num);
    int len = 0;
    while (len < amount - strlen(str))
    {
        strncat(dest, "0", 1); // 修正长度参数为1
        len++;
    }
    strncat(dest, str, strlen(str));
}

void save_frame(int frame, uint8_t * data) // Saves image
{
    char file[20];
    sprintf(file, "output/");
    zFill(file, frame, 6);
    strncat(file, ".png", 4); // 修正长度参数为4(".png"是4个字符)
    printf("%s\n", file);
    uint8_t image[1280 * 480 * 3]; // output image is upscaled 8x
    int a = 0, b = 0;
    for (int y = 0; y < 60; y++)
    {
        for (int x = 0; x < 160; x++)
        {
            // 获取原图像当前像素的RGB值
            uint8_t r = data[(y * 160 + x) * 3 + 0];
            uint8_t g = data[(y * 160 + x) * 3 + 1];
            uint8_t b_val = data[(y * 160 + x) * 3 + 2];
            
            // 8倍放大填充对应区域
            for (int add_b = 0; add_b < 8; add_b++)
            {
                for (int add_a = 0; add_a < 8; add_a++)
                {
                    int output_idx = ((b + add_b) * 1280 + (a + add_a)) * 3;
                    image[output_idx + 0] = r;
                    image[output_idx + 1] = g;
                    image[output_idx + 2] = b_val;
                }
            }
            a = a + 8;
        }
        a = 0;
        b = b + 8;
    }
    stbi_write_png(file, 1280, 480, 3, image, 1280 * 3);
}

int main()
{
    uint8_t image_data[160 * 60 * 3];

    for (int y = 0; y < 60; y++)
    {
        for (int x = 0; x < 160; x++)
        {
            int idx = (y * 160 + x) * 3;
            image_data[idx + 0] = 128;
            image_data[idx + 1] = 128;
            image_data[idx + 2] = 128;
        }
    }

    save_frame(1, image_data);

    return 0;
}

关键修正说明

  1. 所有像素数组的索引均改为(行号 * 图像宽度 + 列号) * 通道数 + 通道索引,这是RGB像素数组的标准存储逻辑,确保每个像素的RGB值被正确读写。
  2. 提取原图像像素值时先缓存,避免重复计算索引,提升可读性。
  3. 修正了zFill和strncat的长度参数,避免缓冲区溢出风险。

内容的提问来源于stack exchange,提问作者Jake A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:42:45