How do I read JPEG and PNG pixels in C++ on Linux?

后端 未结 9 2351
北荒
北荒 2020-12-04 18:34

I\'m doing some image processing, and I\'d like to individually read each pixel value in a JPEG and PNG images.

In my deployment scenario, it would be awkward for me

相关标签:
9条回答
  • 2020-12-04 18:54

    As Nils pointed, there is no such thing as a C or C++ standard library for JPEG compression and image manipulation.

    In case you'd be able to use a third party library, you may want to try GDAL which supports JPEG, PNG and tens of other formats, compressions and mediums.

    Here is simple example that presents how to read pixel data from JPEG file using GDAL C++ API:

    #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 tutorial available.

    0 讨论(0)
  • 2020-12-04 18:57

    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.

    0 讨论(0)
  • 2020-12-04 19:05

    If speed is not a problem you can try LodePNG that take a very minimalist approach to PNG loading and saving.

    Or even go with picoPNG from the same author that is a self-contained png loader in a function.

    0 讨论(0)
提交回复
热议问题