在C/C++中将图像文件读入数组中

30
如何在C/C++中将灰度JPEG图像文件读入到一个二维数组中?

你们的libjpeg文档(http://www.ijg.org/)或者其他本地API不足吗? - greyfade
3
别忘了为你提出的三个问题选择正确的答案。 - mwcz
看看这个帖子:读写图像文件。还有,看看Stackoverflow上的另一个问题 - Lazer
7个回答

26
如果您决定采用最简化的方法,没有libpng / libjpeg依赖项,我建议使用stb_imagestb_image_write,可以在这里找到。
它就是如此简单,您只需要将头文件stb_image.hstb_image_write.h放在您的文件夹中即可。
以下是您需要阅读图像的代码:
#include <stdint.h>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

int main() {
    int width, height, bpp;

    uint8_t* rgb_image = stbi_load("image.png", &width, &height, &bpp, 3);

    stbi_image_free(rgb_image);

    return 0;
}

这里是编写图像的代码:

#include <stdint.h>

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

#define CHANNEL_NUM 3

int main() {
    int width = 800; 
    int height = 800;

    uint8_t* rgb_image;
    rgb_image = malloc(width*height*CHANNEL_NUM);

    // Write your code to populate rgb_image here

    stbi_write_png("image.png", width, height, CHANNEL_NUM, rgb_image, width*CHANNEL_NUM);

    return 0;
}

您可以不使用标志或依赖项进行编译:

g++ main.cpp

其他轻量级的替代方案包括:


2
我必须在编译时包含math.h库并链接它(https://dev59.com/pmoy5IYBdhLWcg3wQr1i),否则我将在图像库中得到一个未定义的pow引用。 - Ste_95
2
我知道这只是一个例子,但你能解释一下代码中神奇的数字3代表什么吗? - mattshu
2
@mattshu 这是通道数(红、绿、蓝),也许我应该在我的代码中澄清这一点,我会进行编辑。 - Jaime Ivan Cervantes
我如何在没有任何奇怪的库的情况下做类似这样的事情?我不是问题的作者,但我想知道如何仅使用像stdio.h这样的标准库来完成此操作。实际上,如何仅使用stdio.h来完成此操作? - user12211554
机顶盒开发者不太行。 - tripulse
如何将结果存储在一个三维数组中,其中第三个维度是通道? - user3236841

15

2
Boost.GIL不起作用,也没有得到维护。 - Tronic
2
由于C语言是允许的,我认为libjpeg是最轻量级的解决方案。CImg和GIL在语法上肯定更容易——但也需要libjpeg。您可以将CImg对象中的数据轻松地复制到某个STL容器或数组中。 - jiggunjer
1
CImg同样采用LGPL类似的许可证,比libjpeg的BSD类许可证更加严格。 - TypeIA
@Tronic 我看到它仍在维护中 https://github.com/boostorg/gil - phuclv
@Tronic 我看到它仍然在维护 https://github.com/boostorg/gil - undefined

4

请查看英特尔开放CV库...


4

3

Corona 很不错。来自教程:

corona::Image* image = corona::OpenImage("img.jpg", corona::PF_R8G8B8A8);
if (!image) {
  // error!
}

int width  = image->getWidth();
int height = image->getHeight();
void* pixels = image->getPixels();

// we're guaranteed that the first eight bits of every pixel is red,
// the next eight bits is green, and so on...
typedef unsigned char byte;
byte* p = (byte*)pixels;
for (int i = 0; i < width * height; ++i) {
  byte red   = *p++;
  byte green = *p++;
  byte blue  = *p++;
  byte alpha = *p++;
}

像素将是一个一维数组,但您可以轻松地将给定的x和y位置转换为1D数组中的位置。类似于pos =(y * width)+ x


3

试用 CImg 库。可以通过 教程 熟悉该库。获得 CImg 对象后,data() 函数将提供对 2D 像素缓冲区数组的访问。


实际上,它被建模为一个4D像素矩阵,尽管2D灰度图像的深度和颜色维度设置为1。在引擎盖下,它是一个模板类型T的1D数组。 - jiggunjer
我相信CImg需要libjpeg库来加载jpeg。 - Jaime Ivan Cervantes

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接