如何在 Linux 上用 C++ 读取 JPEG 和 PNG 像素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/694080/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I read JPEG and PNG pixels in C++ on Linux?
提问by Nick Bolton
I'm doing some image processing, and I'd like to individually read each pixel value in a JPEG and PNG images.
我正在做一些图像处理,我想单独读取 JPEG 和 PNG 图像中的每个像素值。
In my deployment scenario, it would be awkward for me to use a 3rd party library (as I have restricted access on the target computer), but I'm assuming that there's no standard C or C++ library for reading JPEG/PNG...
在我的部署场景中,使用 3rd 方库对我来说会很尴尬(因为我在目标计算机上的访问受到限制),但我假设没有用于读取 JPEG/PNG 的标准 C 或 C++ 库......
So, if you know of a way of notusing a library then great, if not then answers are still welcome!
因此,如果您知道一种不使用库的方法,那就太好了,如果不知道,那么仍然欢迎回答!
采纳答案by Nils Pipenbrinck
There is no standard library in the C-standard to read the file-formats.
C 标准中没有标准库来读取文件格式。
However, most programs, especially on the linux platform use the same library to decode the image-formats:
但是,大多数程序,尤其是在 linux 平台上,使用相同的库来解码图像格式:
For jpeg it's libjpeg, for png it's libpng.
对于 jpeg,它是 libjpeg,对于 png,它是 libpng。
The chances that the libs are already installed is veryhigh.
已经安装了库的可能性非常高。
回答by rlbond
For jpeg, there is already a library called libjpeg, and there is libpngfor png. The good news is that they compile right in and so target machines will not need dll files or anything. The bad news is they are in C :(
对于JPEG,已经有一个叫做库的libjpeg,且有libpng的对PNG。好消息是它们可以直接编译,因此目标机器不需要 dll 文件或任何东西。坏消息是它们在 C 中 :(
Also, don't even think of trying to readthe filesyourself. If you want an easy-to-read format, use PPMinstead.
回答by Colin
Unfortunately, jpeg format is compressed, so you would have to decompress it before reading individual pixels. This is a non-trivial task. If you can't use a library, you may want to refer to one to see how it's decompressing the image. There is an open-source library on sourceforge: CImg on sourceforge.
不幸的是,jpeg 格式是压缩的,因此您必须在读取单个像素之前对其进行解压缩。这是一项不平凡的任务。如果您不能使用某个库,您可能需要参考一个库来了解它是如何解压图像的。sourceforge上有一个开源库:sourceforge上的CImg。
回答by Peter Parker
This is a small routine I digged from 10 year old source code (using libjpeg):
这是我从 10 年前的源代码中挖掘的一个小程序(使用 libjpeg):
#include <jpeglib.h>
int loadJpg(const char* Name) {
unsigned char a, r, g, b;
int width, height;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile; /* source file */
JSAMPARRAY pJpegBuffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
if ((infile = fopen(Name, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", Name);
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
(void) jpeg_read_header(&cinfo, TRUE);
(void) jpeg_start_decompress(&cinfo);
width = cinfo.output_width;
height = cinfo.output_height;
unsigned char * pDummy = new unsigned char [width*height*4];
unsigned char * pTest = pDummy;
if (!pDummy) {
printf("NO MEM FOR JPEG CONVERT!\n");
return 0;
}
row_stride = width * cinfo.output_components;
pJpegBuffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
while (cinfo.output_scanline < cinfo.output_height) {
(void) jpeg_read_scanlines(&cinfo, pJpegBuffer, 1);
for (int x = 0; x < width; x++) {
a = 0; // alpha value is not supported on jpg
r = pJpegBuffer[0][cinfo.output_components * x];
if (cinfo.output_components > 2) {
g = pJpegBuffer[0][cinfo.output_components * x + 1];
b = pJpegBuffer[0][cinfo.output_components * x + 2];
} else {
g = r;
b = r;
}
*(pDummy++) = b;
*(pDummy++) = g;
*(pDummy++) = r;
*(pDummy++) = a;
}
}
fclose(infile);
(void) jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
BMap = (int*)pTest;
Height = height;
Width = width;
Depth = 32;
}
回答by Daniel Sloof
回答by RBerteig
Since it could use the exposure, I'll mention one other library to investigate: The IM Toolkit, which is hosted at Sourceforge. It is cross platform, and abstracts the file format completely away from the user, allowing an image to be loaded and processed without worrying about most of the details. It does support both PNG and JPEG out of the box, and can be extended with other import filters if needed.
由于它可以使用曝光,我将提到另一个要调查的库:IM Toolkit,它托管在Sourceforge 上。它是跨平台的,并且将文件格式完全从用户中抽象出来,允许加载和处理图像而无需担心大多数细节。它开箱即用地支持 PNG 和 JPEG,并且可以根据需要使用其他导入过滤器进行扩展。
It comes with a large collection of image processing operators as well...
它还配备了大量的图像处理运算符......
It also has a good quality binding to Lua.
它还具有良好的质量绑定到Lua。
回答by X-Istence
Since the other answers already mention that you will most likely need to use a library, take a look at ImageMagickand see if it is possible to do what you need it to do. It comes with a variety of different ways to interface with the core functionality of ImageMagick, including libraries for almost every single programming language available.
由于其他答案已经提到您很可能需要使用库,请查看ImageMagick并查看是否可以执行您需要执行的操作。它提供了多种不同的方式来与 ImageMagick 的核心功能交互,包括几乎所有可用编程语言的库。
Homepage: ImageMagick
主页:ImageMagick
回答by mloskot
As Nils pointed, there is no such thing as a C or C++ standard library for JPEG compression and image manipulation.
正如 Nils 指出的那样,没有用于 JPEG 压缩和图像处理的 C 或 C++ 标准库。
In case you'd be able to use a third party library, you may want to try GDALwhich supports JPEG, PNG and tens of other formats, compressions and mediums.
如果您能够使用第三方库,您可能想尝试支持 JPEG、PNG 和数十种其他格式、压缩和媒体的GDAL。
Here is simple example that presents how to read pixel data from JPEG file using GDAL C++ API:
下面是一个简单的例子,展示了如何使用 GDAL C++ API 从 JPEG 文件中读取像素数据:
#include <gdal_priv.h>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
int main()
{
GDALAllRegister(); // once per application
// Assume 3-band image with 8-bit per pixel per channel (24-bit depth)
std::string const file("/home/mloskot/test.jpg");
// Open file with image data
GDALDataset* ds = static_cast<GDALDataset*>(GDALOpen(file.c_str(), GA_ReadOnly));
assert(0 != ds);
// Example 1 - Read multiple bands at once, assume 8-bit depth per band
{
int const ncols = ds->GetRasterXSize();
int const nrows = ds->GetRasterYSize();
int const nbands = ds->GetRasterCount();
int const nbpp = GDALGetDataTypeSize(GDT_Byte) / 8;
std::vector<unsigned char> data(ncols * nrows * nbands * nbpp);
CPLErr err = ds->RasterIO(GF_Read, 0, 0, ncols, nrows, &data[0], ncols, nrows, GDT_Byte, nbands, 0, 0, 0, 0);
assert(CE_None == err);
// ... use data
}
// Example 2 - Read first scanline by scanline of 1 band only, assume 8-bit depth per band
{
GDALRasterBand* band1 = ds->GetRasterBand(1);
assert(0 != band1);
int const ncols = band1->GetXSize();
int const nrows = band1->GetYSize();
int const nbpp = GDALGetDataTypeSize(GDT_Byte) / 8;
std::vector<unsigned char> scanline(ncols * nbpp);
for (int i = 0; i < nrows; ++i)
{
CPLErr err = band1->RasterIO(GF_Read, 0, 0, ncols, 1, &scanline[0], ncols, 1, GDT_Byte, 0, 0);
assert(CE_None == err);
// ... use scanline
}
}
return 0;
}
There is more complete GDAL API tutorialavailable.
有更完整的GDAL API 教程可用。