简单读写.bmp文件C代码

gwo2fgha  于 2023-01-12  发布在  其他
关注(0)|答案(3)|浏览(152)

我尝试做一个简单的读取.bmp文件,然后输出相同的.bmp文件。现在,它只工作,如果宽度和高度是完全相同的。这是一个很好的指标,我的问题是什么,但我似乎不能弄清楚。我正在寻找任何想法或建议,你们都可能有。还有其他问题,但它们看起来并不完全是我所寻找的。然而,当宽度和高度不同时,我的输出与Read/Write SImple BMP Image C++所示的输出类似-基本上是扭曲的、不完整的和重复的,而不是实际的图像。
下面是我在.bmp文件中读取的代码:

bool LoadBmp(const char *filepath)
    {
        FILE *f = fopen(filepath, "rb");
        if (f)
        {
          Bwidth = 0;
          Bheight = 0;
          pixels = NULL;
          unsigned char info[54] = {0};
          fread(info, sizeof(unsigned char), 54, f);
          Bwidth = *(unsigned int *)&info[18];
          Bheight = *(unsigned int *)&info[22];
          unsigned int size = Bwidth * Bheight * 3; // ((((Bwidth * Bheight) + 31) & ~31) / 8) * Bheight;
          pixels = malloc(size);
          fread(pixels, sizeof(unsigned char), size, f);
          fclose(f);
          return true;
       }  
       return false;
   }

请注意,我不确定是像下面这样创建大小(Bwidth * Bheight * 3)还是使用注解掉的内容。还请注意,“Bwidth”和“Bheight”被声明为unsigned int,而“pixels”被定义为unsigned char*。此外,我特意不使用结构体来存储.bmp文件数据。
下面是我用来编写刚才加载的.bmp文件的代码:

static bool WriteBMP(int x, int y, unsigned char *bmp, char * name)
    {
      const unsigned char bmphdr[54] = {66, 77, 255, 255, 255, 255, 0, 0, 0, 0, 54, 4, 0, 0, 40, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, 8, 0, 0, 0, 0, 0, 255, 255, 255, 255, 196, 14, 0, 0, 196, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
      unsigned char hdr[1078];
      int i, j, c, xcorr, diff;
      FILE *f;

      xcorr = (x+3) >> 2 << 2;  // BMPs have to be a multiple of 4 pixels wide.
      diff = xcorr - x;

      for (i = 0; i < 54; i++) hdr[i] = bmphdr[i];
      *((int*)(&hdr[18])) = xcorr;
      *((int*)(&hdr[22])) = y;
      *((int*)(&hdr[34])) = xcorr*y;
      *((int*)(&hdr[2])) = xcorr*y + 1078;
      for (i = 0; i < 256; i++) {
        j = i*4 + 54;
        hdr[j+0] = i;  // blue
        hdr[j+1] = i;  // green
        hdr[j+2] = i;  // red
        hdr[j+3] = 0;  // dummy
      }

      f = fopen(name, "wb");
      if (f) {
          assert(f != NULL);
          c = fwrite(hdr, 1, 1078, f);
          assert(c == 1078);
          if (diff == 0) {
            c = fwrite(bmp, 1, x*y, f);
            assert(c == x*y);
          } else {
            *((int*)(&hdr[0])) = 0;  // need up to three zero bytes
            for (j = 0; j < y; j++) {
              c = fwrite(&bmp[j * x], 1, x, f);
              assert(c == x);
              c = fwrite(hdr, 1, diff, f);
              assert(c == diff);
            }
          }
          fclose(f);
          return true;
      }
      else return false;
    }

提前感谢你的帮助。感谢你抽出时间!

sauutmhj

sauutmhj1#

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include <stdint.h>

 long asciiToBinary(int n);

 long asciiToBinary(int n) {
    int remainder; 
 long binary = 0, i = 1;
   while(n != 0) {
        remainder = n%2;
        n = n/2;
        binary= binary + (remainder*i);
        i = i*10;
                 }
    return binary;
                           }

typedef struct
{ //BITMAPFILEHEADER
  char  bfType[2];
  int   bfSize;
  short bfReserved1;
  short bfReserved2;
  int   bfOffBits;
  //BITMAPINFOHEADER
  int   biSize;
  int   biWidth;
  int   biHeight;
  short biPlanes;
  short biBitCount;
  int   biCompression;
  int   biSizeImage;
  int   biXPelsPerMeter;
  int   biYPelsPerMeter;
  int   biClrUsed;
  int   biClrImportant;
} BITMAPINFOHEADER;

 typedef struct {
   unsigned char blue;
   unsigned char green;
   unsigned char red;
   
} PIXEL;

int imageInfo(BITMAPINFOHEADER *img)
{
  int offset = 0;
  printf("------------------------------------------------------------- BITMAPFILEHEADER\n");
  printf("0x%08X (%08d) bfType           %8c%c (0x%04X)\n", offset, offset, img->bfType[0], img->bfType[1], *(short *)img->bfType);
  offset += sizeof img->bfType;
  printf("0x%08X (%08d) bfSize           %9d (0x%08X)\n",   offset, offset,  img->bfSize, img->bfSize);
  offset += sizeof img->bfSize;
  printf("0x%08X (%08d) bfReserved1      %9hd (0x%04hX)\n", offset, offset,  img->bfReserved1, img->bfReserved1);
  offset += sizeof img->bfReserved1;
  printf("0x%08X (%08d) bfReserved2      %9hd (0x%04hX)\n", offset, offset,  img->bfReserved2, img->bfReserved2);
  offset += sizeof img->bfReserved2;
  printf("0x%08X (%08d) bfOffBits        %9d (0x%08X)\n",   offset, offset,  img->bfOffBits, img->bfOffBits);
  printf("------------------------------------------------------------- BITMAPINFOHEADER\n");
  offset += sizeof img->bfOffBits;
  printf("0x%08X (%08d) biSize           %9d (0x%08X)\n",   offset, offset, img->biSize, img->biSize);
  offset += sizeof img->biSize;
  printf("0x%08X (%08d) biWidth          %9d (0x%08X)\n",   offset, offset, img->biWidth, img->biWidth);
  offset += sizeof img->biWidth;
  printf("0x%08X (%08d) biHeight         %9d (0x%08X)\n",   offset, offset, img->biHeight, img->biHeight);
  offset += sizeof img->biHeight;
  printf("0x%08X (%08d) biPlanes         %9d (0x%04hX)\n",  offset, offset, img->biPlanes, img->biPlanes);
  offset += sizeof img->biPlanes;
  printf("0x%08X (%08d) biBitCount       %9d (0x%04hX)\n",  offset, offset, img->biBitCount, img->biBitCount);
  offset += sizeof img->biBitCount;
  printf("0x%08X (%08d) biCompression    %9d (0x%08X)\n",   offset, offset, img->biCompression, img->biCompression);
  offset += sizeof img->biCompression;
  printf("0x%08X (%08d) biSizeImage      %9d (0x%08X)\n",   offset, offset, img->biSizeImage, img->biSizeImage);
  offset += sizeof img->biSizeImage;
  printf("0x%08X (%08d) biXPelsPerMeter  %9d (0x%08X)\n",   offset, offset, img->biXPelsPerMeter, img->biXPelsPerMeter);
  offset += sizeof img->biXPelsPerMeter;
  printf("0x%08X (%08d) biYPelsPerMeter  %9d (0x%08X)\n",   offset, offset, img->biYPelsPerMeter, img->biYPelsPerMeter);
  offset += sizeof img->biYPelsPerMeter;
  printf("0x%08X (%08d) biClrUsed        %9d (0x%08X)\n",   offset, offset, img->biClrUsed, img->biClrUsed);
  offset += sizeof img->biClrUsed;
  printf("0x%08X (%08d) biClrImportant   %9d (0x%08X)\n",   offset, offset, img->biClrImportant, img->biClrImportant);
  return offset;
}

int main(){
    uint32_t RGB565ColorTable[] = {
        0x7E00000, 0xF8000000, 0x001F0000, 0
    };
  uint16_t myData[64];

    for(int i = 0; i<64; i++)
    {
        myData[i] = 0x241B; //Random Color
    }
    FILE *image;
      const char filename[] = "full.bmp";
  FILE *fichier = fopen(filename, "rb");
  FILE *fptr = fopen("tth.bmp","w+");
    if(!fichier)
    printf ("Erreur a l'ouverture du fichier [%s]\n", filename);
  else
  {
    BITMAPINFOHEADER *img = malloc(sizeof *img);
    char fpath[1000],mydata[100];
    BITMAPINFOHEADER bih;
    int i=0,b[8],g[8],r[8];
    double asciiTobinary;
                      
    image=fopen("full.bmp","rb");
   
    fseek(image,2,SEEK_SET);                                                //reading the height and width
    fread(&bih.biSize,4,1,image);
    printf("\n \n Size of the image=%d\n",bih.biSize);
    fseek(image,18,SEEK_SET);
    fread(&bih.biWidth,4,1,image);
    fseek(image,22,SEEK_SET);
    fread(&bih.biHeight,4,1,image);
    printf("\n \n Width of the image =%d \n Height of the image =%d \n pixel =  b    |    g     |     r \n \n",bih.biWidth,bih.biHeight);

     PIXEL pic[bih.biWidth*bih.biHeight*2],p; 
     
      while(!feof(image)){                                                 //reading the pixels rgb values
      fread(&p.blue,sizeof(p.blue),1,image);                              
      fread(&p.green,sizeof(p.green),1,image);
      fread(&p.red,sizeof(p.red),1,image);
      pic[i]=p;
      printf(" %d=   %u    |     %u    |      %u  ",i+54,pic[i].blue,pic[i].green,pic[i].red);
      i++; }
             
     fclose(image);
if(img)
    {
      int i, tmp, offset;
      printf("\n[%s]\n", filename);
      fread(img, sizeof(BITMAPINFOHEADER), 1, fichier);

      if(img->bfType[0] == 'B' && img->bfType[1] == 'M')
      {
        offset = imageInfo(img);

        if(img->biBitCount == 1)
        {
          printf("---------------------------------------------------------------------- RGBQUAD\n");
          fread(&tmp, sizeof tmp, 1, fichier);
          offset += sizeof img->biClrImportant;
          printf("0x%08X (%08d)                  %9d (0x%08X)\n", offset, offset, tmp, tmp);
          fread(&tmp, sizeof tmp, 1, fichier);
          offset += sizeof tmp;
          printf("0x%08X (%08d)                  %9d (0x%08X)\n", offset, offset, tmp, tmp);

          printf("------------------------------------------------------------------------- BITS\n");
          for(i = 0; i < img->biSizeImage / (int)sizeof tmp; i++)
          {
              char bin[33];
            fread(&tmp, sizeof tmp, 1, fichier);
            offset += sizeof tmp;
            printf("0x%08X (%08d)                   %8d (0x%08X) (%s)\n", offset, offset, tmp, tmp, itoa(tmp, bin, 2));
          }
        }
      }
      free(img);
    }
    fclose(fichier);
  }
     if(fptr == NULL) {
        printf("Error!");
        exit(1);
    }

    fwrite(&filename, sizeof(filename), 1, fptr);
    //fwrite(&myInfoHeader, sizeof(myInfoHeader), 1, fptr);
    fwrite(&RGB565ColorTable, sizeof(RGB565ColorTable), 1, fptr);
    fwrite(&myData, sizeof(myData), 1, fptr);
    fclose(fptr);
     return 0;
}
x9ybnkn6

x9ybnkn62#

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>

 long asciiToBinary(int n);

 long asciiToBinary(int n) {
    int remainder; 
 long binary = 0, i = 1;
   while(n != 0) {
        remainder = n%2;
        n = n/2;
        binary= binary + (remainder*i);
        i = i*10;
                 }
    return binary;
                           }

typedef struct {
   unsigned int width;
   unsigned int height;
   unsigned int size;
} BITMAPINFOHEADER;

 typedef struct {
   unsigned char blue;
   unsigned char green;
   unsigned char red;
   
} PIXEL;

int main(){
    FILE *image;
    FILE *fptr = fopen("tt.bmp","w+");
    long RGB565ColorTable[] = {
        0x7E00000, 0xF8000000, 0x001F0000, 0
    };

    long myData[64];

    for(int i = 0; i<64; i++)
    {
        myData[i] = 0x241B; //Random Color
    }
    char fpath[1000],mydata[100];
    BITMAPINFOHEADER bih;
    int i=0,b[8],g[8],r[8];
    double asciiTobinary;
    //printf("Enter BMP file path");
    //scanf("%s",fpath);
                                
    image=fopen("full.bmp","rb");
    // while(image==NULL){
    //  printf("Error! Enter path again:");
    //     scanf("%s",fpath);
    //                  }

    fseek(image,2,SEEK_SET);                                                //reading the height and width
    fread(&bih.size,4,1,image);
    printf("\n \n Size of the image=%d\n",bih.size);
    fseek(image,18,SEEK_SET);
    fread(&bih.width,4,1,image);
    fseek(image,22,SEEK_SET);
    fread(&bih.height,4,1,image);
    printf("\n \n Width of the image =%d \n Height of the image =%d \n pixel =  b    |    g     |     r \n \n",bih.width,bih.height);

     PIXEL pic[bih.width*bih.height*2],p; 
     
      while(!feof(image)){                                                 //reading the pixels rgb values
      fread(&p.blue,sizeof(p.blue),1,image);                              
      fread(&p.green,sizeof(p.green),1,image);
      fread(&p.red,sizeof(p.red),1,image);
      pic[i]=p;
      printf(" %d=   %u    |     %u    |      %u  ",i+54,pic[i].blue,pic[i].green,pic[i].red);                                                  
      i++;
                       }
            
     fclose(image);
    if(fptr == NULL) {
        printf("Error!");
        exit(1);
    }
    fwrite(&image, sizeof(image), 1, fptr);
    //fwrite(&myInfoHeader, sizeof(myInfoHeader), 1, fptr);
    fwrite(&RGB565ColorTable, sizeof(RGB565ColorTable), 1, fptr);
    fwrite(&myData, sizeof(myData), 1, fptr);
    fclose(fptr);
     return 0;
}
jgwigjjp

jgwigjjp3#

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define MAGIC_VALUE         0x4D42 
#define NUM_PLANE           1
#define COMPRESSION         0
#define NUM_COLORS          0
#define IMPORTANT_COLORS    0
#define BITS_PER_PIXEL      24
#define BITS_PER_BYTE       8
#define BYTES_PER_PIXEL     BITS_PER_PIXEL/BITS_PER_BYTE

#pragma pack(push)  // save the original data alignment
#pragma pack(1)     // Set data alignment to 1 byte boundary

typedef struct BMPHeader_t_ { // Total: 54 bytes
  uint16_t  type;             // Magic identifier: 0x4d42
  uint32_t  size;             // File size in bytes
  uint16_t  reserved1;        // Not used
  uint16_t  reserved2;        // Not used
  uint32_t  offset;           // Offset to image data in bytes from beginning of file (54 bytes)
  uint32_t  dib_header_size;  // DIB Header size in bytes (40 bytes)
  int32_t   width_px;         // Width of the image
  int32_t   height_px;        // Height of image
  uint16_t  num_planes;       // Number of color planes
  uint16_t  bits_per_pixel;   // Bits per pixel
  uint32_t  compression;      // Compression type
  uint32_t  image_size_bytes; // Image size in bytes
  int32_t   x_resolution_ppm; // Pixels per meter
  int32_t   y_resolution_ppm; // Pixels per meter
  uint32_t  num_colors;       // Number of colors  
  uint32_t  important_colors; // Important colors 
} BMPHeader_t;

#pragma pack(pop)  // restore the previous pack setting

typedef struct BMPImage_t_ {
    BMPHeader_t header;
    uint8_t* data; 
} BMPImage_t;

typedef struct RGB_t_ {
    uint8_t r, g, b;
} RGB_t;

const RGB_t BLACK = {0,0,0};
const RGB_t WHITE = {255,255,255};
const RGB_t RED = {255,0,0};
const RGB_t GREEN = {0,255,0};
const RGB_t BLUE = {0,0,255};

static int getPadding(const BMPHeader_t *header) {
    return (4 - (header->width_px * BYTES_PER_PIXEL) % 4) % 4;
}

static int getRowSize(const BMPHeader_t *header) {
  int bytes_per_row_without_padding = header->width_px * BYTES_PER_PIXEL;
  return bytes_per_row_without_padding + getPadding(header);
}

static int getPosition(const BMPHeader_t* header, int x, int y) {
  int j = (header->height_px - y - 1) * getRowSize(header);
  int i = x * BYTES_PER_PIXEL;

  return i + j;
}

int CheckHeader(const BMPHeader_t* header) {
  return header->type == MAGIC_VALUE 
    && header->num_planes == NUM_PLANE
    && header->bits_per_pixel == BITS_PER_PIXEL
    && header->compression == COMPRESSION
    && header->num_colors == NUM_COLORS;
}

BMPImage_t* ReadBMP(const char* filename) {
  BMPImage_t* bmp = malloc(sizeof(BMPImage_t));

  FILE* image = fopen(filename, "rb");
  int ok;
  ok = fread(&bmp->header, 54, 1, image);
  if (ok != 1) {
    printf("Cannot read image header\n");
    exit(-1);
  }

  printf("type=%x\n", bmp->header.type);
  printf("size=%d\n", bmp->header.size);
  printf("reserved1=%d\n", bmp->header.reserved1);
  printf("reserved2=%d\n", bmp->header.reserved2);
  printf("offset=%d\n", bmp->header.offset);
  printf("dib_header_size=%d\n", bmp->header.dib_header_size);
  printf("width_px=%d\n", bmp->header.width_px);
  printf("height_px=%d\n", bmp->header.height_px);
  printf("num_planes=%d\n", bmp->header.num_planes);
  printf("bits_per_pixel=%d\n", bmp->header.bits_per_pixel);
  printf("compression=%d\n", bmp->header.compression);
  printf("image_size_bytes=%d\n", bmp->header.image_size_bytes);
  printf("x_resolution_ppm=%d\n", bmp->header.x_resolution_ppm);
  printf("y_resolution_ppm=%d\n", bmp->header.y_resolution_ppm);
  printf("num_colors=%d\n", bmp->header.num_colors);
  printf("important_colors=%d\n", bmp->header.important_colors);

  if (!CheckHeader(&bmp->header)) {
    printf("Bad image\n");
    exit(-1);
  }

  bmp->data = malloc(bmp->header.image_size_bytes); 
  if (!bmp->data) {
    printf("Cannot allocate %d bytes\n", bmp->header.image_size_bytes);
    exit(-1);
  }
  
  fseek(image, bmp->header.offset, SEEK_SET);
  ok = fread(bmp->data, bmp->header.image_size_bytes, 1, image);
  if (ok != 1) {
    printf("Cannot read image data\n");
    exit(-1);
  }

  fclose(image);

  return bmp;
}
BMPImage_t* CreateBMP(const RGB_t** image);

void SaveBMP(const BMPImage_t* bmp, const char* filename) {
  FILE* fd = fopen(filename, "wb");
  rewind(fd);
  fwrite(&bmp->header, 54, 1, fd);
  fseek(fd, bmp->header.offset, SEEK_SET);
  fwrite(bmp->data, bmp->header.image_size_bytes, 1, fd);
  fclose(fd);
}

void DestroyBMP(BMPImage_t* bmp) {
  if (bmp) {
    if (bmp->data) {
      free(bmp->data);
    }
    free(bmp);
  }
}

RGB_t GetPixel(BMPImage_t* bmp, int x, int y) {
  if (x < 0 || x >= bmp->header.width_px) {
    printf("Error. X should be [%d, %d), but %d\n", 0, bmp->header.width_px, x);
    return BLACK;
  }

  if (y < 0 || y >= bmp->header.height_px) {
    printf("Error. Y should be [%d, %d), but %d\n", 0, bmp->header.height_px, y);
    return BLACK;
  }

  int pos = getPosition(&bmp->header, x, y);
  RGB_t rgb = {
    bmp->data[pos + 2],
    bmp->data[pos + 1],
    bmp->data[pos + 0],
  };
  return rgb;
}

void SetPixel(BMPImage_t* bmp, int x, int y, RGB_t rgb) {
  if (x < 0 || x >= bmp->header.width_px) {
    printf("Error. X should be [%d, %d), but %d\n", 0, bmp->header.width_px, x);
    return;
  }

  if (y < 0 || y >= bmp->header.height_px) {
    printf("Error. Y should be [%d, %d), but %d\n", 0, bmp->header.height_px, y);
    return;
  }

  int pos = getPosition(&bmp->header, x, y);
  bmp->data[pos + 2] = rgb.r;
  bmp->data[pos + 1] = rgb.g;
  bmp->data[pos + 0] = rgb.b;
}

RGB_t** ToImageMatrix(BMPImage_t* bmp) {
  RGB_t** image = calloc(bmp->header.height_px, sizeof(RGB_t*));

  for (int j = 0; j < bmp->header.height_px; j++) {
    image[j] = calloc(bmp->header.width_px, sizeof(RGB_t));
    for (int i = 0; i < bmp->header.width_px; i++) {
      RGB_t pixel = GetPixel(bmp, i, j);
      image[j][i].r = pixel.r;
      image[j][i].g = pixel.g;
      image[j][i].b = pixel.b;
    }
  }

  return image;
} 

int main(void) {
    const char* filename = "image.bmp";

    BMPImage_t* bmp = ReadBMP(filename);

    RGB_t black = {0,0,0};
    for (int i = 0; i < 1280; i++) {
      SetPixel(bmp, i, 10, black);
    }

    SaveBMP(bmp, "pic_out.bmp");
    DestroyBMP(bmp);
    return 0;
}

* The library is based on:
 * - https://engineering.purdue.edu/ece264/17au/hw/HW15
 * - https://en.wikipedia.org/wiki/BMP_file_format
 * - https://codereview.stackexchange.com/questions/196084/read-and-write-bmp-file-in-c

相关问题