如何使用C保存BMP文件?

问题描述 投票:0回答:1

我有一个复制图像和调整亮度的主题。这是我的代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#define xsize 570
#define ysize 456
#define input_filename "robot2.bmp"
#define output_filename "test_image.bmp"

int is_success_open_file(FILE* filename);       // 파일을 성공적으로 열었는지 확인하는 함수
//void is_BMP(BITMAPFILEHEADER hf);               // open한 파일의 형식이 BMP가 맞는지 확인하는 함수
void read_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char InputImg[xsize][ysize]);    // open한 이미지의 픽셀을 읽는 함수
void read_no_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char InputImg[xsize][ysize]);
void copy_image(unsigned char InputImg[xsize][ysize], unsigned char OutputImg[xsize][ysize]);       // read_color_img 함수에서 읽은 픽셀값을 쓰기 전에 저장하는 함수
void write_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char OutputImg[xsize][ysize]);  // copy_image에서 저장한 픽셀을 통해 이미지 파일을 만드는 함수
void write_no_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char OutputImg[xsize][ysize]);
void print_result(BITMAPFILEHEADER hf, BITMAPINFOHEADER hInfo, RGBQUAD hRGB[256]);

int main(void)
{
    // 밑의 값들은 Windows.h 헤더파일에서 값이 정해져있음
    BITMAPFILEHEADER hf;        // "파일정보헤드" 구조체 변수 선언
    BITMAPINFOHEADER hInfo;     // "이미지정보헤드" 구조체 변수 선언
    RGBQUAD hRGB[256];          // 팔레트 정보를 위한 배열 선언

    unsigned char InputImg[xsize][ysize];       // 입력 이미지
    unsigned char OutputImg[xsize][ysize];      // 출력 이미지
    int is_color;

    printf("no color image : 0, color image : 1\n");
    scanf("%d", &is_color);

    if(is_color == 0)
    {
        printf("no color\n");
        read_no_color_img(&hf, &hInfo, hRGB, InputImg);
        print_result(hf, hInfo, hRGB);
        copy_image(InputImg, OutputImg);
        write_no_color_img(&hf, &hInfo, hRGB, OutputImg);
    }

    else
    {
        // 이미지 파일 읽기 (Windows.h 헤더파일의 내장 함수 fread를 통해서)
        read_color_img(&hf, &hInfo, hRGB, InputImg);
        print_result(hf, hInfo, hRGB);
        // 이미지 값들에 +alpha
        // 읽은 이미지 파일의 픽셀들을 복사, OutputImg에 저장
        copy_image(InputImg, OutputImg);
        // 픽셀값이 저장된 OutputImg를 통해서 이미지 저장
        write_color_img(&hf, &hInfo, hRGB, OutputImg);

    }

    return 0;
}

int is_success_open_file(FILE* filename)
{
    if (filename == NULL)
    {
        printf("failed to open file\n\n");
        return 1;

    }
    else
    {
        printf("successed to open file\n\n");
        return 0;
    }
}

void read_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char InputImg[xsize][ysize])
{
    FILE* fp;         // 파일 포인터 선언

    // 이미지 파일 open (파일을 읽거나 쓰기 위한 선행 작업). 아래의 코드로 fp는 다룰 파일을 지칭게 됨. rb의 뜻 : "r" : 읽기, "b" : 이진수로
    fp = fopen(input_filename, "rb");

    // 이미지 파일 열기를 성공적으로 마쳤는지 판단
    if (is_success_open_file(fp) == 1)
    {
        printf("EXIT program");
        exit(1);
    }

    /*
    fread 함수의 첫 번째 인자는 각 구조체의 포인터
    2번째는 byte크기로 각 구조체의 크기를 byte 단위로 반환
    3번째에 있는 숫자는 읽기의 반복 횟수, 4번째는 읽을 파일을 가리킴
    */
    fread(hf, sizeof(BITMAPFILEHEADER), 1, fp);             // hf : BITMAPFILEHEADER 구조체의 포인터
    fread(hInfo, sizeof(BITMAPINFOHEADER), 1, fp);          // hInfo : BITMAPINFOHEADER의 구조체의 포인터
    fread(hRGB, sizeof(RGBQUAD), 256, fp);                  // hRGB : RGBQUA 구조체의 포인터

    // fread(InputImg, xsize * ysize , 1, fp); 왼쪽의 코드를 아래의 코드로 바꾸자, 이미지 파일이 깨지긴 하지만 열리긴 함
    fread(InputImg, xsize * ysize* (hInfo->biBitCount / 8) , 1, fp);                  // InputImg는 main함수에서 선언됐고, 배열명은 포인터기 때문에 InputImg는 포인터
    // 작업을 마쳤으니 close
    fclose(fp);
}




void read_no_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char InputImg[xsize][ysize])
{
    FILE* fp;         // 파일 포인터 선언

    // 이미지 파일 open (파일을 읽거나 쓰기 위한 선행 작업). 아래의 코드로 fp는 다룰 파일을 지칭게 됨. rb의 뜻 : "r" : 읽기, "b" : 이진수로
    fp = fopen(input_filename, "rb");

    // 이미지 파일 열기를 성공적으로 마쳤는지 판단
    if (is_success_open_file(fp) == 1)
    {
        printf("EXIT program");
        exit(1);
    }

    /*
    fread 함수의 첫 번째 인자는 각 구조체의 포인터
    2번째는 byte크기로 각 구조체의 크기를 byte 단위로 반환
    3번째에 있는 숫자는 읽기의 반복 횟수, 4번째는 읽을 파일을 가리킴
    */
    fread(hf, sizeof(BITMAPFILEHEADER), 1, fp);             // hf : BITMAPFILEHEADER 구조체의 포인터
    fread(hInfo, sizeof(BITMAPINFOHEADER), 1, fp);          // hInfo : BITMAPINFOHEADER의 구조체의 포인터
    fread(hRGB, sizeof(RGBQUAD), 256, fp);                  // hRGB : RGBQUA 구조체의 포인터

    // fread(InputImg, xsize * ysize , 1, fp); 왼쪽의 코드를 아래의 코드로 바꾸자, 이미지 파일이 깨지긴 하지만 열리긴 함
    fread(InputImg, xsize * ysize , 1, fp);                  // InputImg는 main함수에서 선언됐고, 배열명은 포인터기 때문에 InputImg는 포인터
    // 작업을 마쳤으니 close
    fclose(fp);
}




void copy_image(unsigned char InputImg[xsize][ysize], unsigned char OutputImg[xsize][ysize])
{
    // 이미지의 픽셀을 2차원으로 분해, OutputImg에 저장
    for (int i = 0; i < xsize; i++)
    {
        for (int j = 0; j < ysize; j++)
        {
            OutputImg[i][j] = InputImg[i][j] ;       // 픽셀 하나당 RGB 값을 가지고 있다.
        }
    }
}

// 함수 : 사용자의 입력값을 RGB 입력값을 받아서 하나의 값으로 반환


void write_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char OutputImg[xsize][ysize])
{
    FILE* fp;           // 파일 포인터 선언
    // 이미지 파일을 저장하기 위해서 다시 open. "w" : 쓰기
    fp = fopen(output_filename, "wb");


    if (is_success_open_file(fp) == 1)
    {
        printf("EXIT program\n");
        exit(1); // 파일 열기 실패 시 프로그램 종료
    }

    // read_color_img에서 설명한 바와 같다. 다만, 3번째 인자는 쓰는 횟수
    fwrite(hf, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(hInfo, sizeof(BITMAPINFOHEADER), 1, fp);
    fwrite(hRGB, sizeof(RGBQUAD), 256, fp);
    fwrite(OutputImg, xsize * ysize*  (hInfo->biBitCount / 8) , 1, fp);


    // 작업을 마쳤으니 close
    fclose(fp);
}

void write_no_color_img(BITMAPFILEHEADER* hf, BITMAPINFOHEADER* hInfo, RGBQUAD hRGB[256], unsigned char OutputImg[xsize][ysize])
{
    FILE* fp;           // 파일 포인터 선언
    // 이미지 파일을 저장하기 위해서 다시 open. "w" : 쓰기
    fp = fopen(output_filename, "wb");


    if (is_success_open_file(fp) == 1)
    {
        printf("EXIT program\n");
        exit(1); // 파일 열기 실패 시 프로그램 종료
    }

    // read_color_img에서 설명한 바와 같다. 다만, 3번째 인자는 쓰는 횟수
    fwrite(hf, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(hInfo, sizeof(BITMAPINFOHEADER), 1, fp);
    fwrite(hRGB, sizeof(RGBQUAD), 256, fp);
    fwrite(OutputImg, xsize * ysize, 1, fp);


    // 작업을 마쳤으니 close
    fclose(fp);    
}


void print_result(BITMAPFILEHEADER hf, BITMAPINFOHEADER hInfo, RGBQUAD hRGB[256])
{
    printf("size of BITMAPINFOHEADER = %d\n", hInfo.biSize);                 // BITMAPINFOHEADER 구조체의 크기
    printf("WIDTH OF IMG = %d\n", hInfo.biWidth);               // 이미지의 가로 크기
    printf("HEIGHT OF IMG = %d\n", hInfo.biHeight);             // 이미지의 세로 크기
    printf("BYTE SIZE OF IMG = %d\n", hf.bfSize);                       // byte 단위로 파일 전체 크기
    printf("IS IMG BMP? = %hx.  if result : 4d42, it means BMP\n", hf.bfType);                      // "파일이 BMP"가 맞는지
    printf("NUMBER OF USED COLORS = %d\n", hInfo.biClrUsed);           // 실제 사용 색상 수
    printf("BIT PER PIXEL = %d\n\n", hInfo.biBitCount);         // 픽셀당 비트 수 (컬러, 흑백 구별)
    
}

robot2 文件是一张黑白照片。然后这段代码可以正常工作并且文件保存得很好。但是robot2文件改为robot(彩色图像),有问题,所以我无法打开保存的文件。

另外,即使文件打开,大部分图片都被剪切或像素扭曲并保存,但我使用了另一个彩色图像,我不小心输入了0(没有彩色图像),文件已保存为彩色。差异仅为每个像素位。

机器人文件的每像素位数是 24,而另一张图像是 32。有什么问题吗?

文件需要妥善保存。我更改了 BMP 文件(两种颜色),但一张图像无法保存得很好,但另一张图像保存得很好。没有彩色图像保存完好,但彩色图像 BMP 文件有问题。

c image pixel rgb bmp
1个回答
0
投票

如果我明白了,那么编写彩色 BMP 是唯一需要克服的障碍。 这不是一个微不足道的任务!这段代码将为您编写一个24位颜色位图,但它确实很麻烦。

通过更多的编辑和添加,它也可以适用于 32 位位图...此处包含的模板适用于 24 位和 32 位之外的其他每像素位 - 特别参见 WriteDIBimageData()。

此代码是可移植的——位图结构当然非常类似于 Windows,但它们包含在此代码中,因此可以将其移植到其他平台。我们永远不想排除我们的“尼克斯朋友”;欢迎大家来参加聚会。

此代码已由我编译并经过我的充分测试;无法保证安全性和有效性。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>


///////////////////////////////////////
#ifndef _WINDEF_
/* typdefs and defines to make this code portable/platform independent.
* The BMP format is somewhat proprietary, so all this stuff is windows.h compatable.*/
#define FAR
#define VOID  void
typedef unsigned char   UCHAR;
typedef unsigned char   BYTE;
typedef signed short    BOOL;
typedef unsigned int    UINT;  //Updated 2023
typedef unsigned short  WORD;
typedef unsigned long   DWORD;
typedef long            LONG;

#define TRUE    1
#define FALSE   0

/* Bitmap Header structures */

/* structures for defining DIBs */
typedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;          /* = sizeof (BITMAPINFOHEADER)  */
        LONG       biWidth;         /* Image wdth */
        LONG       biHeight;        /* Image hgt */
        WORD       biPlanes;        /* Always 1 for our purposes */
        WORD       biBitCount;      /* Image bits per pixel */
        DWORD      biCompression;   /* zero for no compression */
        DWORD      biSizeImage;     /* Ttl image bytes:  WIDTHBYTES((WORD)dwWidth,nBitsPP) * dwHeight */
        LONG       biXPelsPerMeter; /* Always zero for our purposes */
        LONG       biYPelsPerMeter; /* Always zero for our purposes */
        DWORD      biClrUsed;       /* Always zero for our purposes */
        DWORD      biClrImportant;  /* Always zero for our purposes */
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

#pragma pack(push,2)
typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;         /* "BM" */
        DWORD   bfSize;         /* palette size */
        WORD    bfReserved1;    /* Always zero for our purposes */
        WORD    bfReserved2;    /* Always zero for our purposes */
        DWORD   bfOffBits;      /* Offset image data begins: sizeof(BITMAPFILEHEADER) + lpbi->biSize +  PaletteSize*/
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
#pragma pack(pop)

#endif // _WINDEF_
///////////////////////////////////////

typedef struct tagImageInfo
{
    DWORD   ImageW;      //Image X dims
    DWORD   ImageH;      //Image Y dims
    WORD    BitsPP;      //Same as Gplanes OR'd into GifH.Flags
}IMINFO;

typedef struct tagImageObject
{
DWORD           dwSIZE;    //Total number of Bytes used by memory object
UCHAR           *imBuff;   //Actual image bits
IMINFO          image;  //IMAGE data structure
}IMAGEOBJECT,  *pIMAGE;

#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')


#define BITS_TO_BYTES(BITS)  (((BITS)+7)>>3)
#define WIDTHBYTES(w, bitcount) ((((w)*(bitcount)+31)& ~31) >> 3)  

/* Zero for anything higher than 8 bits */
WORD DIBNumColors (void *lpbi){  return 0; }
/* No palette in anything higher than 8 bits */
WORD PaletteSize(void * lpbi){  return  0; /*(DIBNumColors (lpbi) * sizeof (RGBQUAD));*/}

VOID *GetLineMem(pIMAGE pi, DWORD Y)
{
    return &pi->imBuff[Y * WIDTHBYTES(pi->image.ImageW, pi->image.BitsPP)];
}


/*---------------------------------------------------------------------------------
 InitBitmapInfoHeader()

 Purpose:    Generic initialization of a BITMAPINFOHEADER,
             given the Width, Height, and Bits per Pixel for the DIB.
             biCompression is set to "no compression," and all
             other unused fields are 0.

 Parms:  lpBmInfoHdr == pointer to a BITMAPINFOHEADER structure to be filled in.
         dwWidth     == Width of DIB
         dwHeight    == Height of DIB
         nBitsPP        == Bits per Pixel for the DIB.
 *--------------------------------------------------------------------------------*/
void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr, DWORD dwWidth,DWORD dwHeight, int nBitsPP)
{
   memset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
   lpBmInfoHdr->biSize      = sizeof (BITMAPINFOHEADER);
   lpBmInfoHdr->biWidth     = dwWidth;
   lpBmInfoHdr->biHeight    = dwHeight;
   lpBmInfoHdr->biPlanes    = 1;
   lpBmInfoHdr->biBitCount  = nBitsPP;

   if(lpBmInfoHdr->biBitCount != 24 )
   {
       printf("Only 24 bits per pixel supported in this implementation, exiting\n");
       exit(0);
   }
   lpBmInfoHdr->biSizeImage = WIDTHBYTES((WORD)dwWidth,nBitsPP) * dwHeight;
}


/*----------------------------------------------------------------------------
 WriteDIBimageData()
 PURPOSE : Writes data in upside down (BMP style) 'til all the data is written.
 RETURNS : FALSE - If write did not proceed correctly or any issue
           TRUE on success
 *----------------------------------------------------------------------------*/
DWORD  WriteDIBimageData( FILE *hFile, LPBITMAPINFOHEADER  lpbi, pIMAGE pi)
{
DWORD  ImageH = pi->image.ImageH;
DWORD  ImageW = pi->image.ImageW; 
int   outbitspp, bytesw, Y;
BYTE  *psrc = NULL;
BYTE  *write_buff = NULL;
DWORD num_bytes_dest;

    outbitspp = lpbi->biBitCount;
    bytesw = WIDTHBYTES(ImageW,outbitspp);

#if 1
    printf("WriteDIBimageData() details: ------------------\n");
    printf("ImageW = %d \n",ImageW);
    printf("ImageH = %d \n",ImageH);
    printf("OutBitsPP    = %d \n",outbitspp  );
    printf("InBitsPP     = %d \n",pi->image.BitsPP );
    printf("WBytes = %d \n",  bytesw);
#endif

    if(!(write_buff=(UCHAR  *)malloc(bytesw)) )
    {
        printf("Memory error!\n");
        return FALSE;
    }

    num_bytes_dest = BITS_TO_BYTES(outbitspp)*ImageW;
    Y = (int)(ImageH-1L);
    
    do
    {
        memset(write_buff, 0, bytesw);

        if(Y < (int)pi->image.ImageH ) 
        {
            if(!(psrc = (UCHAR  *)GetLineMem(pi, Y)))
            {
                printf("Memory error!\n");
                break;
            }
            switch(outbitspp)
            {
                /*Bit conversions are not supported in this example, but this is where 
                ** the routines would go. From 8 bits input to 32 bits output, or vise versa, etc.. 
                ** ... convert each image row on-the-fly */
                case 1:
                    //PackBits(write_buff,psrc, ImageW);
                case 4:
                    //PackNybbles(write_buff, psrc, ImageW);
                case 8:
                case 16:
                case 32:
                    printf("Bit conversions not supported this example.\n");
                break;

                case 24: /* Just 24 bits in and 24 bits out, this example */
                    /* copy image bits from source to dest */
                    memcpy(write_buff, psrc, bytesw);
                break;

                default:
                    printf("Bit conversions not supported this example.\n");
                    //color_convert_line(psrc,write_buff,GetImBitsPP(pi), outbitspp, GetImPalettePtr(pi),num_bytes_dest);
                break;
            }
        }
        if (fwrite(write_buff, 1, bytesw, hFile) != bytesw)
        {
            printf("Write error!\n");
            free(write_buff);
            return FALSE;
        }
    }while(Y--);

    free(write_buff);
    return TRUE;
}


/*----------------------------------------------------------------------------
 WriteDIB()
 PURPOSE: Write Device-independent bitmap to a BMP file.
 RETURNS: TRUE  - if successful.
          FALSE - otherwise
 *----------------------------------------------------------------------------*/
BOOL WriteDIB(char *pFileName, LPBITMAPINFOHEADER  lpbi, pIMAGE pi)
{
BITMAPFILEHEADER    hdr;
FILE *              hFile;

    hFile = fopen(pFileName, "wb");
    if (!hFile)
        return FALSE;

    /* Fill in the fields of the file header */
    hdr.bfType      = DIB_HEADER_MARKER;  
    hdr.bfSize      = sizeof(BITMAPFILEHEADER) + lpbi->biSize + PaletteSize(lpbi) + lpbi->biSizeImage;
    hdr.bfReserved1 = hdr.bfReserved2 = 0;
    hdr.bfOffBits   = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +   PaletteSize(lpbi);
#if 1
    printf("WriteDIB() details:---------------------------\n");

    printf("sizeof(BITMAPFILEHEADER)  = %d (should be 14)\n", sizeof(BITMAPFILEHEADER) );
    printf("sizeof(BITMAPINFOHEADER)  = %d (should be 40)\n", sizeof(BITMAPINFOHEADER) );
    printf("sizeof(WORD)    = %d  (should be 2)\n", sizeof(WORD) );
    printf("sizeof(DWORD)   = %d  (should be 4)\n", sizeof(DWORD) );
    printf("sizeof(UINT)    = %d  (should be 4)\n", sizeof(UINT) );
    printf("hdr.bfType       = %c%c \n", hdr.bfType&0xFF, (hdr.bfType>>8)&0xFF  );
    printf("hdr.bfSize       = %ld \n",hdr.bfSize      );
    printf("hdr.bfReserved1  = %d \n",hdr.bfReserved1 );
    printf("hdr.bfReserved2  = %d \n",hdr.bfReserved2 );
    printf("hdr.bfOffBits    = %ld \n",hdr.bfOffBits   );

    printf("lpbi->biHeight       = %d \n",lpbi->biHeight);
    printf("lpbi->biWidth        = %ld \n",lpbi->biWidth);
    printf("lpbi->biBitCount     = %d \n",lpbi->biBitCount);
    printf("WIDTHBYTES()         = %d \n",WIDTHBYTES(lpbi->biWidth, lpbi->biBitCount));
    printf("PaletteSize (lpbi)   = %d \n",PaletteSize (lpbi));
    printf("\n");
#endif

    /* Write the file header */
    if (fwrite((void *)&hdr, 1, sizeof(BITMAPFILEHEADER), hFile) != sizeof (BITMAPFILEHEADER))
    {
        printf("Write error!\n");
        fclose (hFile);
        return FALSE;
    }

    /* Write the DIB header  */
    if(fwrite ((void *)lpbi, 1, sizeof (BITMAPINFOHEADER), hFile) != sizeof (BITMAPINFOHEADER))
    {
        printf("Write error!\n");
        fclose (hFile);
        return FALSE;
    }

    /* Write the bits */
    if (!WriteDIBimageData (hFile, lpbi, pi))
    {
        fclose (hFile);
        return FALSE;
    }

    fclose (hFile);
    return TRUE;
}

/*----------------------------------------------------------------------------
  Function:  SaveDIBFile()
   Purpose:  Main entry for the module.  Writes DIB/BMP out in format specified.
   Returns:  FALSE if no file is opened, or an error occurs writing the file.
             TRUE  if successful
 *----------------------------------------------------------------------------*/
BOOL SaveDIBFile( pIMAGE pi, char *szFileName, int desired_bitspp)
{
BITMAPINFOHEADER  bi;
DWORD dwWidth, dwHeight;
    
    if(!pi)
    {
        printf("Memory error! pi is NULL in SaveDIBFile()\n");
        return 0;
    }
    
    if(pi->image.BitsPP > 8 && desired_bitspp < 9)
    {
        /* Image quantization, (ie: from input 24 bits per pixel down to 8bits) would go here */
        printf("Image quantization not suipport this example!\n");
        return FALSE;
    }
    dwWidth  = pi->image.ImageW; 
    dwHeight = pi->image.ImageH; 

    InitBitmapInfoHeader(&bi, dwWidth, dwHeight, desired_bitspp);
    return WriteDIB(szFileName, &bi,pi);
}


#define IMAGE_W 500
#define IMAGE_H 500
#define IMAGE_BITS_PER_PIXEL 24

int main() 
{
IMAGEOBJECT im;
int xxx,yyy, row;
UCHAR *ptrImageData;
int red=0, green=0, blue=0;

    memset(&im, 0, sizeof(im));
    im.dwSIZE = IMAGE_H * WIDTHBYTES(IMAGE_W, IMAGE_BITS_PER_PIXEL);
    im.image.BitsPP =  IMAGE_BITS_PER_PIXEL;
    im.image.ImageW = IMAGE_W;
    im.image.ImageH = IMAGE_H;

    im.imBuff = malloc(im.dwSIZE);
    if(!im.imBuff)
    {
        printf("Couldn't allocate %d bytes memory!\n", im.dwSIZE );
        return 0;
    }
    printf("Successfully allocated %d bytes memory!\n", im.dwSIZE );

    ptrImageData = im.imBuff;
    srand((unsigned)time(NULL));

    /* This logic will create an image of random color horizontal stripes, 
    ** each stripe being row(max) pixels wide. **/
    for(yyy = 0; yyy < IMAGE_H;  yyy+=row)
    {
        /* Just playing with the color channels here; do what you want*/ 
        red+=5;
        green=0;
        blue+=2;
        if(red > 255)
            red = 0;
        if(blue > 255)
            blue = 0;

        for(row = 0; row < 3;  row++)
        {
            for(xxx = 0; xxx < IMAGE_W;  xxx++)
            {
                /*Do each color channel: B then G then R */
                *(ptrImageData++)= blue;  
                *(ptrImageData++)= green;
                *(ptrImageData++)= red;
            }
        }
    }
    if(SaveDIBFile(&im, "myBMP.bmp", 24))
    {
        printf("SaveDIBFile() reports success.\n");
    }
    else
    {
        printf("SaveDIBFile() failed!\n");
    }

    return 0;
}

输出:


    Successfully allocated 750000 bytes memory!
    WriteDIB() details:---------------------------
    sizeof(BITMAPFILEHEADER)  = 14 (should be 14)
    sizeof(BITMAPINFOHEADER)  = 40 (should be 40)
    sizeof(WORD)    = 2  (should be 2)
    sizeof(DWORD)   = 4  (should be 4)
    sizeof(UINT)    = 4  (should be 4)
    hdr.bfType       = BM
    hdr.bfSize       = 750054
    hdr.bfReserved1  = 0
    hdr.bfReserved2  = 0
    hdr.bfOffBits    = 54
    lpbi->biHeight       = 500
    lpbi->biWidth        = 500
    lpbi->biBitCount     = 24
    WIDTHBYTES()         = 1500
    PaletteSize (lpbi)   = 0

    WriteDIBimageData() details: ------------------
    ImageW = 500
    ImageH = 500
    OutBitsPP    = 24
    InBitsPP     = 24
    WBytes = 1500
    SaveDIBFile() reports success.


[![This is the output 500x500 24 bit bitmap:'myBMP.bmp'][1]][1]


  [1]: https://i.stack.imgur.com/5mmbx.png
© www.soinside.com 2019 - 2024. All rights reserved.