C.读取BMP图像的像素时出现问题

ujv3wf0j  于 2023-05-22  发布在  其他
关注(0)|答案(1)|浏览(231)

我试图用下面的代码读取BMP图像的像素。首先,我使用函数“readBMPHeader”读取相关的图像数据(宽度,高度和标题)。接下来,我想使用函数“mapBMP”逐行读取文件的像素。然而,我得到的bmp图像“dali”的像素值,你可以在下面找到,是不正确的,我不知道我做错了什么。你能告诉我我的错在哪里吗?

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Macros
#define ALIGNMENT 4
#define HEADER_LOCATION 0x0000
#define DATA_START_LOCATION 0x000A
#define WIDTH_LOCATION 0x0012
#define HEIGHT_LOCATION 0x0016
#define BITS_PER_PIXEL_LOCATION 0x001C

typedef unsigned char byte;


int readBMPHeader(unsigned int* image_header, unsigned int* image_height, unsigned int* image_width,
                  unsigned int* image_start, const char* file_name)
{
  // Here we open the given file for reading in binary mode.
  FILE* image = fopen(file_name, "rb");

  // Here we check whether opening the given file was successful.
  if (image == NULL)
  {
    printf("Invalid File\n");
    return -1;
  }

  // Here we read in the header of the given BM image.
  fseek(image, HEADER_LOCATION, SEEK_SET);
  fread(image_header, 2, 1, image);
  // Here we read in the height of the given BM image.
  fseek(image, HEIGHT_LOCATION, SEEK_SET);
  fread(image_height, 4, 1, image);
  // Here we read in the width of the given BM image.
  fseek(image, WIDTH_LOCATION, SEEK_SET);
  fread(image_width, 4, 1, image);
  fseek(image, DATA_START_LOCATION, SEEK_SET);
  fread(image_start, 4, 1, image);
  fclose(image);

  return 0;

}

void mapBMP(unsigned int height, unsigned int width, char mapped_image[height][width], unsigned int image_start, const char* file_name)
{
  FILE* image = fopen(file_name, "rb");
  // Here we read in the number of bits per pixel in the given BM image.
  unsigned int bits_per_pixel;
  fseek(image, BITS_PER_PIXEL_LOCATION, SEEK_SET);
  fread(&bits_per_pixel, 2, 1, image);
  // Here we compute the number of bytes per pixel in the given BM image.
  unsigned int bytes_per_pixel = ((unsigned int) bits_per_pixel) / 8;
  printf("Bytes per pixel = %u \n", bytes_per_pixel);
  // Here we compute the stride, i.e. the number of bytes in a row (rounded up by alignment)
  unsigned int stride = (width * bytes_per_pixel) + (ALIGNMENT - 1);
  stride /= ALIGNMENT;
  stride *= ALIGNMENT;
  // Here we read in the pixels of the image, the loops have been shortened for testing purposes.
  byte pixel[bytes_per_pixel];
  for (unsigned int i = height - 1; i > height - 2; i = i - 1) // The proper condition is:(unsigned int i = height - 1; i > 0; i = i - 1)
  {
    fseek(image, i * stride, image_start);

    for (unsigned int j = 0; j < 30; j = j + 1) // The proper condition is: (unsigned int j = 0; j < width; j = j + 1)
    {
      fread(pixel, 3, 1, image);
      printf("pixel = %x %x %x\n", pixel[0], pixel[1], pixel[2]);
    }
  }

  fclose(image);
}

int main()
{

  // Here is the BMP Image test.
  unsigned int image_header;
  unsigned int image_width;
  unsigned int image_height;
  unsigned int image_start;
  char* file_name = "dali.bmp";
  int file_opened = readBMPHeader(&image_header, &image_height, &image_width, &image_start, file_name);

  if (file_opened == -1)
    printf("File could not be opened.");
  else
  {
    // Some prints to see the collected data.
    printf("Size of byte in byte = %llu \n", sizeof(byte));
    printf("header (in hex) = %x \n", image_header);
    printf("height (in pixels) = %u \n", image_height);
    printf("width (in pixels) = %u \n", image_width);
    printf("image_start (in bytes) = %u \n", image_start);

    char mapped_image[image_height][image_width];
    mapBMP(image_height, image_width, mapped_image, image_start, file_name);
    //printTable(image_height, image_width, mapped_image);
  }

  return 0;
}

编辑:这里是如何在我的十六进制编辑器文件看起来;我突出显示了图像数据的偏移量。

这里是我的输出,看来我仍然是在头部分的BMP而不是图像开始,我不明白。

这里是如何文件存储在我的文件夹,我不认为它是压缩,因为它有1133 KB的大小。

irlmq6kh

irlmq6kh1#

经审查,张贴的图片是一个.png文件大小与675K字节。
这可能是OP上传图片的伪影。
将使用最近添加的信息审查OP的问题。
至少这些问题:

fseek()使用错误

// fseek(image, i * stride, image_start);
fseek(image, i * stride + image_start, SEEK_SET);

读取宽度不正确

// int readBMPHeader(unsigned int* image_header, ...
// ...
// fread(image_header, 2, 1, image);

int readBMPHeader(uint16_t* image_header, ...
...
fread(image_header, sizeof *image_header, 1, image);

// unsigned int bits_per_pixel;
// ...
// fread(&bits_per_pixel, 2, 1, image);

uint16_t bits_per_pixel;
...
fread(&bits_per_pixel, sizeof bits_per_pixel, 1, image);

提示:避免magic numbers
更好的代码将测试和报告头的所有十六进制数据,以确保预期的编码。
最好使用固定宽度的uint8_t, uint16_t, uint32_t类型而不是char, unsigned来阅读文件。
参考BMP file format

相关问题