将2d数组写入文件图像的最快方法?

时间:2014-01-25 13:27:59

标签: c image

我有一个简单的2d数组,如下所示:

unsigned char myArray[100][100];

我不需要任何高级图像处理,我只需要在文件中写入此图像(灰度级)(它可以是任何图像格式)。

我想我可以使用图像格式:.ppm(http://rosettacode.org/wiki/Bitmap/Write_a_PPM_file#C),如下所示:

 (void) fprintf(fp, "P6\n%d %d\n255\n", dimx, dimy);
  for (j = 0; j < dimy; ++j)
  {
    for (i = 0; i < dimx; ++i)
    {
      static unsigned char color[3];
      color[0] = i % 256;  /* red */
      color[1] = j % 256;  /* green */
      color[2] = (i * j) % 256;  /* blue */
      (void) fwrite(color, 1, 3, fp);
    }
  }

我可以为RGB编写相同的值来模拟灰度图像,但是有更好的选择吗?

2 个答案:

答案 0 :(得分:1)

您可以使用比PPM更常见的TGA格式,并允许使用真正的灰度图像。保存它们非常容易。准备一个包含9个元素的数组:

uint16 header[9]

写入:0,3,0,0,0,0,宽度,高度,8

fwrite那18个字节,然后一次性你的100x100阵列。就是这样。

答案 1 :(得分:0)

问题是:如果您使用灰度,则只需要1个通道,因此每个通道只有8位就足够了。写一个BMP文件。 BMP格式随处可见,标题很容易自己编写。不是每个人都打开PPM或PGM。

提示:下载010 Editor(十六进制编辑器,获得试用版)并在其上加载位图。您可以浏览位图的标题。它将加快关于标题的学习。所以你可以自己写...当然,每像素1个字节。

在我的示例中,我使用了C ++ ...但是如果你愿意,可以很容易地转换为C.

#include <iostream>
#include <fstream>

#pragma pack( push, 2 ) // avoid structure padding... I am using Win32 here

struct BITMAPFILEHEADER
{
    unsigned short  bfType;
    unsigned int    bfSize;
    unsigned short  bfReserved1;
    unsigned short  bfReserved2;
    unsigned int    bfOffBits;
};

struct BITMAPINFOHEADER
{
    unsigned int    biSize;
    int             biWidth;
    int             biHeight;
    unsigned short  biPlanes;
    unsigned short  biBitCount;
    unsigned int    biCompression;
    unsigned int    biSizeImage;
    int             biXPelsPerMeter;
    int             biYPelsPerMeter;
    unsigned int    biClrUsed;
    unsigned int    biClrImportant;
};

#pragma pack() // avoid structure padding... I am using Win32 here

using namespace std;

void saveBitmap( const string & p_output, int p_width, int p_height )
{
    BITMAPFILEHEADER bitmapFileHeader;
    memset( &bitmapFileHeader, 0xff, sizeof( BITMAPFILEHEADER ) );
    bitmapFileHeader.bfType = ( 'B' | 'M' << 8 );
    bitmapFileHeader.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER );
    bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + ( p_width + ( p_width % 4 ? ( 4 - p_width % 4 ) : 0 ) ) * p_height; // multiply by 3 if you wanna switch to RGB

    BITMAPINFOHEADER bitmapInfoHeader;
    memset( &bitmapInfoHeader, 0, sizeof( BITMAPINFOHEADER ) );
    bitmapInfoHeader.biSize = sizeof( BITMAPINFOHEADER );
    bitmapInfoHeader.biWidth = p_width;
    bitmapInfoHeader.biHeight = p_height;
    bitmapInfoHeader.biPlanes = 1;
    bitmapInfoHeader.biBitCount = 8; // this means grayscale, change to 24 if you wanna switch to RGB

    ofstream file( p_output, ios::binary );

    file.write( reinterpret_cast< char * >( &bitmapFileHeader ), sizeof( bitmapFileHeader ) );
    file.write( reinterpret_cast< char * >( &bitmapInfoHeader ), sizeof( bitmapInfoHeader ) );

    // bitmaps grayscale must have a table of colors... don't write this table if you want RGB
    unsigned char grayscale[ 4 ];

    for ( int i( 0 ); i < 256; ++i )
    {
        memset( grayscale, i, sizeof( grayscale ) );
        file.write( reinterpret_cast< char * >( grayscale ), sizeof( grayscale ) );
    }

    // here we record the pixels... I created a gradient...
    // remember that the pixels ordem is from left to right, "bottom to top"...
    unsigned char pixel[ 1 ]; // do pixel[ 3 ] if you want RGB

    for ( int y( 0 ); y < p_height; ++y )
    {
        for ( int x( 0 ); x < p_width + ( p_width % 4 ? ( 4 - p_width % 4 ) : 0 ); ++x ) // + ( p_width % 4 ? ( 4 - p_width % 4 ) : 0 ) because BMP has a padding of 4 bytes per line
        {
            if ( x > p_width )
            {
                pixel[ 0 ] = 0; // this is just padding
                file.write( reinterpret_cast< char * >( pixel ), sizeof( pixel ) );
            }
            else
            {
                pixel[ 0 ] = 255 * ( x * y ) / ( p_width * p_height );
                file.write( reinterpret_cast< char * >( pixel ), sizeof( pixel ) );
            }
        }
    }

    file.close( );
}

int main( int argc, char * argv[] )
{
    saveBitmap( "test.bmp", 1000, 1000 );
    return 0;
}
相关问题