Advertisement
STANAANDREY

bmp to black and white

Mar 25th, 2023 (edited)
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.62 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <stdbool.h>
  6. #define errstop(s) fprintf(stderr, s); exit(-1);
  7. #define SUF "_BW"
  8.  
  9. typedef struct {
  10.   char name[2];
  11.   uint32_t size, garbage, imgOffset;
  12. } BMPHeader;
  13.  
  14. typedef struct {
  15.   uint32_t size, width, height;
  16.   uint16_t colorPlanes, bitPerPixel;
  17.   uint32_t compression, imgSize, garbage[4];
  18. } DIBHeader;
  19.  
  20. typedef struct {
  21.   uint8_t red, green, blue;
  22. } Pixel;
  23.  
  24. typedef struct {
  25.   uint32_t height, width;
  26.   Pixel **pixels;
  27. } Image;
  28.  
  29. typedef struct {
  30.   BMPHeader bmpHeader;
  31.   DIBHeader dibHeader;
  32.   Image img;
  33. } BMPFileData;
  34.  
  35. void freeImg(Image *img) {
  36.   for (int i = img->height - 1; i >= 0; i--) {
  37.     free(img->pixels[i]);
  38.   }
  39.   free(img->pixels);
  40. }
  41.  
  42. bool readImgDataInBMP(FILE *file, BMPFileData *bmpFileData) {
  43.   bmpFileData->img = (Image){bmpFileData->dibHeader.height, bmpFileData->dibHeader.width, NULL};
  44.   fseek(file, bmpFileData->bmpHeader.imgOffset, SEEK_SET);
  45.   bmpFileData->img.pixels = (Pixel**)calloc(sizeof(void*), bmpFileData->img.height);
  46.   if (bmpFileData->img.pixels == NULL) {
  47.     perror("");
  48.     fclose(file);
  49.     exit(EXIT_FAILURE);
  50.   }
  51.   uint64_t sz = 0;
  52.   for (int i = bmpFileData->img.height - 1; i >= 0; i--) {
  53.     bmpFileData->img.pixels[i] = (Pixel*)calloc(sizeof(Pixel), bmpFileData->img.width);
  54.     if (bmpFileData->img.pixels[i] == NULL) {
  55.       freeImg(&bmpFileData->img);
  56.       fclose(file);
  57.       perror("");
  58.       exit(EXIT_FAILURE);
  59.     }
  60.     sz += fread(bmpFileData->img.pixels[i], sizeof(Pixel), bmpFileData->img.width, file);
  61.   }//*/
  62.   return sz == 1ULL * bmpFileData->dibHeader.height * bmpFileData->dibHeader.width;
  63. }
  64.  
  65. void pixelToGreyScale(Pixel *pixel) {
  66.   uint8_t mean = (pixel->red + pixel->green + pixel->blue) / 3;
  67.   pixel->red = pixel->green = pixel->blue = mean;
  68. }
  69.  
  70. void imgToGreyScale(Image *img) {
  71.   for (int i = 0; i < img->height; i++) {
  72.     for (int j = 0; j < img->width; j++) {
  73.       pixelToGreyScale(&img->pixels[i][j]);
  74.     }
  75.   }
  76. }
  77.  
  78. void createBWimgBMPFile(BMPFileData bmpFileData, char path[]) {
  79.   FILE *fout = fopen(path, "wb");
  80.   if (fout == NULL) {
  81.     free(path);
  82.     freeImg(&bmpFileData.img);
  83.     perror("");
  84.     exit(EXIT_FAILURE);
  85.   }
  86.  
  87.   imgToGreyScale(&bmpFileData.img);
  88.  
  89.   uint64_t sumw = 0;
  90.   bool ok = true;
  91.   ok &= fwrite(&bmpFileData.bmpHeader.name, sizeof(char), 2, fout) == 2;
  92.   ok &= fwrite(&bmpFileData.bmpHeader.size, sizeof(uint32_t), 3, fout) == 3;
  93.   ok &= fwrite(&bmpFileData.dibHeader, sizeof(DIBHeader), 1, fout) == 1;
  94.  
  95.   for (int i = bmpFileData.img.height - 1; i >= 0; i--) {
  96.     sumw += fwrite(bmpFileData.img.pixels[i], sizeof(Pixel), bmpFileData.img.width, fout);
  97.   }
  98.   ok &= (sumw == 1ULL * bmpFileData.img.height * bmpFileData.img.width);
  99.  
  100.   if (!ok) {
  101.     free(path);
  102.     freeImg(&bmpFileData.img);//*/
  103.     errstop("failed to create file!\n");
  104.   }
  105.  
  106.   if (fclose(fout) == EOF) {
  107.     perror("closing error");
  108.   } else {
  109.     puts("SUCCESS");
  110.   }
  111. }
  112.  
  113. bool readBMPHeader(BMPHeader *bmpHeader, FILE *fin) {
  114.   int sz = 0;
  115.   sz += fread(&bmpHeader->name, sizeof(char), 2, fin);
  116.   sz += fread(&bmpHeader->size, sizeof(uint32_t), 3, fin);
  117.   if (strncmp(bmpHeader->name, "BM", 2) || sz != 5) {
  118.     return false;
  119.   }
  120.   return true;
  121. }
  122.  
  123. bool readDIBHeadder(DIBHeader *dibHeader, FILE *fin) {
  124.   const int WANTED_BPP = 24;
  125.   bool ok = fread(dibHeader, sizeof(*dibHeader), 1, fin) == 1;
  126.   ok &= (dibHeader->colorPlanes);
  127.   ok &= (dibHeader->bitPerPixel == WANTED_BPP);
  128.   return ok;
  129. }
  130.  
  131. bool readBMPFile(BMPFileData *bmpFileData, const char path[]) {
  132.   FILE *fin = fopen(path, "rb");
  133.   if (fin == NULL) {
  134.     perror("");
  135.     exit(EXIT_FAILURE);
  136.   }
  137.   bool successRead = true;
  138.   successRead &= readBMPHeader(&bmpFileData->bmpHeader, fin);
  139.   successRead &= readDIBHeadder(&bmpFileData->dibHeader, fin);
  140.   if (!successRead) {
  141.     fclose(fin);
  142.     return false;
  143.   }
  144.   bool sucReadImg = readImgDataInBMP(fin, bmpFileData);
  145.   fclose(fin);
  146.   return sucReadImg;
  147. }
  148.  
  149. int main(int argc, char *argv[]) {
  150.   if (argc == 1) {
  151.     errstop("specify the file name!\n");
  152.   }
  153.   if (strcmp(strrchr(argv[1], '.'), ".bmp")) {
  154.     errstop("wrong extension!\n");
  155.   }
  156.  
  157.   BMPFileData bmpFileData;
  158.   if (!readBMPFile(&bmpFileData, argv[1])) {
  159.     errstop("corrupted/invalid file!\n");
  160.   }
  161.  
  162.   int len = strlen(argv[1]);
  163.   char *newName = (char*)calloc(sizeof(char), len + strlen(SUF) + 1);
  164.   strcpy(newName, argv[1]);
  165.   newName[strcspn(newName, ".")] = 0;
  166.   strcat(newName, SUF);
  167.   strcat(newName, ".bmp");
  168.   createBWimgBMPFile(bmpFileData, newName);
  169.   freeImg(&bmpFileData.img);
  170.   free(newName);
  171.   return EXIT_SUCCESS;
  172. }
  173.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement