{"id":412001,"date":"2024-06-29T22:17:41","date_gmt":"2024-06-29T22:17:41","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=412001"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T22:17:41","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=412001","title":{"rendered":"<span>Pixel image rotation<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>Brief problem formulation<\/h3>\n<p>The program accepts as input the absolute path to the image in the bmp extension and the path where you save the result of the work. Then, it rotates the image by 90 degrees counterclockwise. Afterwards, the program saves the new image. <\/p>\n<p>The program is executed on C.<\/p>\n<h3>BMP file structure<\/h3>\n<p>BMP-file comprises the heading (it weighs 14 bytes) and the raster array (it weighs 40 bytes). I make the heading by following structure: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/p>\n<p><code>struct __attribute__((packed)) bmp_header {<br \/> \u00a0\u00a0\u00a0 uint16_t bfType;<br \/> \u00a0\u00a0\u00a0 uint32_t bfileSize;<br \/> \u00a0\u00a0\u00a0 uint32_t bfReserved;<br \/> \u00a0\u00a0\u00a0 uint32_t bOffBits;<br \/> \u00a0\u00a0\u00a0 uint32_t biSize;<br \/> \u00a0\u00a0\u00a0 uint32_t biWidth;<br \/> \u00a0\u00a0\u00a0 uint32_t biHeight;<br \/> \u00a0\u00a0\u00a0 uint16_t biPlanes;<br \/> \u00a0\u00a0\u00a0 uint16_t biBitCount;<br \/> \u00a0\u00a0\u00a0 uint32_t biCompression;<br \/> \u00a0\u00a0\u00a0 uint32_t biSizeImage;<br \/> \u00a0\u00a0\u00a0 uint32_t biXPelsPerMeter;<br \/> \u00a0\u00a0\u00a0 uint32_t biYPelsPerMeter;<br \/> \u00a0\u00a0\u00a0 uint32_t biClrUsed;<br \/> \u00a0\u00a0\u00a0 uint32_t biClrImportant;<br \/> };<\/code><\/p>\n<p>BMP-file heading contains the following information: <\/p>\n<ul>\n<li>\n<p><code>bfType<\/code>: 2 bytes, file type;<\/p>\n<\/li>\n<li>\n<p><code>bfSize<\/code>: 4 bytes, file size;<\/p>\n<\/li>\n<li>\n<p><code>bfReserved1<\/code>: 4 bytes, reserved, must be settled to the value of 0;<\/p>\n<\/li>\n<li>\n<p><code>bfOffBits<\/code>: 4 bytes, offset from start to raster data;<\/p>\n<\/li>\n<\/ul>\n<p>Raster information heading (raster information). All in all, there are only 40 bytes of heading of raster image, including the following:<\/p>\n<ul>\n<li>\n<p><code>biSize<\/code>: 4 bytes; the size of the information header, which is 40;<\/p>\n<\/li>\n<li>\n<p><code>biWidth<\/code>: 4 bytes, indicates the image width in pixels;<\/p>\n<\/li>\n<li>\n<p><code>biHeight<\/code>: 4 bytes, indicates the image height in pixels;<\/p>\n<\/li>\n<li>\n<p><code>biPlanes<\/code>: 2 bytes, indicates the number of color planes for the target device, always equal to 1;<\/p>\n<\/li>\n<li>\n<p><code>biBitCount<\/code>: 2 bytes, indicates byte\/pixel quantity and takes the values 1, 2, 4, 8, 16, 24, 32;<\/p>\n<\/li>\n<li>\n<p><code>biCompression<\/code>: 4 bytes, indicates the type of image compression most commonly used 0 (BI_RGB), which means no compression;<\/p>\n<\/li>\n<li>\n<p><code>biSizeImages<\/code>: 4 bytes, indicates the size of the raster data; when using the BI_RGB format, it can be set to 0;<\/p>\n<\/li>\n<li>\n<p><code>biXPelsPerMeter<\/code>: indicates horizontal extension, unit of measurement &#8212; pixel\/meter, signed integer;<\/p>\n<\/li>\n<li>\n<p><code>biClrUsed<\/code>: indicates the number of color indexes in the palette used by the bitmap(raster) image, 0 means to use all;<\/p>\n<\/li>\n<li>\n<p><code>biClrImportant<\/code>: indicates the number of color indexes that have an important effect on the display of the image, and 0 indicates that it is important;<\/p>\n<\/li>\n<\/ul>\n<p>Right after the heading the raster array follows in which pixels are saved consequently and by strokes. Each pixel is set by the following structure of 3 bytes size:<\/p>\n<pre><code class=\"cpp\">struct pixel { uint8_t b; uint8_t g; uint8_t r; };<\/code><\/pre>\n<h3>Padding <\/h3>\n<p>If the width of the image in bytes is a multiple of four, then the lines go one after the other without gaps. If the width is not a multiple of four, then it is padded with garbage bytes to the nearest multiple of four. These bytes are called padding. <\/p>\n<p>Example:<\/p>\n<ol>\n<li>\n<p>Let an image be 10 pixels wide => 10 *3 bytes = 30 bytes, the closest number multiple of four is 32. So, followingly, each new stroke will have an indentation of 32 \u2013 30 = 2 bytes before the next stroke starts. <\/p>\n<\/li>\n<li>\n<p>Let an image be 4 pixels wide => 4 * 3 = 12 bytes. The width is multiple of four, hence, each new stroke comes immediately after the previous without any indentation. <\/p>\n<\/li>\n<\/ol>\n<h3>Image storage<\/h3>\n<p>I split the program into headed files and executed files. Let\u2019s consider the image storage and its useful functions. Let\u2019s write down <strong>image.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_IMAGE_H #define UNTITLED_IMAGE_H  #include &lt;stdint.h> #include &lt;stdio.h>  struct pixel { \u00a0\u00a0\u00a0 uint8_t b; \u00a0\u00a0\u00a0 uint8_t g; \u00a0\u00a0\u00a0 uint8_t r; };  struct image { \u00a0\u00a0\u00a0 uint64_t width; \u00a0\u00a0\u00a0 uint64_t height; \u00a0\u00a0\u00a0 struct pixel *data; };  size_t findIndex(size_t x, size_t y, size_t width); struct image emptyImage(const uint64_t width, const uint64_t height); struct image createImage(const size_t image_width, const size_t image_height, struct pixel* pixels); void imageDestroyer(struct image* image);   #endif \/\/UNTITLED_IMAGE_H<\/code><\/pre>\n<p>Where:<\/p>\n<pre><code class=\"cpp\">struct image { \u00a0\u00a0\u00a0 uint64_t width; \u00a0\u00a0\u00a0 uint64_t height; \u00a0\u00a0\u00a0 struct pixel *data; };<\/code><\/pre>\n<p>Is responsible for storage keeping image\u2019s size and pixels. <\/p>\n<ul>\n<li>\n<p><code>findIndex()<\/code> function allows to find an index in a new already rotated image where the former pixel with initial indices x and y is located. <\/p>\n<\/li>\n<li>\n<p><code>emptyImage()<\/code> function creates an empty image of a certain size.<\/p>\n<\/li>\n<li>\n<p><code>createImage()<\/code> function builds a full image of a certain size. <\/p>\n<\/li>\n<li>\n<p><code>imageDestroyer()<\/code> function frees the memory occupied by the image. <\/p>\n<\/li>\n<\/ul>\n<p>Let\u2019s consider the implementations of all functions in <strong>image.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"image.h\" #include &lt;stdint.h> #include &lt;stdlib.h>  size_t findIndex(const size_t x, const size_t y, const size_t width){ \u00a0\u00a0\u00a0 return y * width + x; }  struct image emptyImage(const uint64_t width, const uint64_t height){ \u00a0\u00a0\u00a0 struct pixel* pixels = malloc(sizeof(struct pixel) * height * width); \u00a0\u00a0\u00a0 return createImage(width, height, pixels); }  struct image createImage(const size_t width, const size_t height, struct pixel* pixels){ \u00a0\u00a0\u00a0 return (struct image) {.data = pixels, .width = width, .height = height}; }  void imageDestroyer(struct image* image){ \u00a0\u00a0\u00a0 free(image->data); }<\/code><\/pre>\n<h3>Opening and closing of images<\/h3>\n<p>This part looks at implemented functions to open an image and record, and after finishing the work, at the function for closing an image. <\/p>\n<p><strong>openFile.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_OPENFILE_H #define UNTITLED_OPENFILE_H  #include &lt;stdbool.h> #include &lt;stdio.h> enum openStatus{ \u00a0\u00a0\u00a0 OPEN_ERROR, \u00a0\u00a0\u00a0 OPEN_OK };  enum openStatus openFile(const char* fileName, FILE** file, const char* type); #endif \/\/UNTITLED_OPENFILE_H<\/code><\/pre>\n<p><strong>openFile.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"openFile.h\"  enum openStatus openFile(const char* fileName, FILE** file, const char* type){ \u00a0\u00a0\u00a0 *file = fopen(fileName, type); \u00a0\u00a0\u00a0 if(*file == NULL){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return OPEN_ERROR; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 return OPEN_OK; }<\/code><\/pre>\n<p><strong>closeFile.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_CLOSEFILE_H #define UNTITLED_CLOSEFILE_H  #include &lt;stdbool.h> #include &lt;stdio.h> enum closeStatus{ \u00a0\u00a0\u00a0 CLOSE_OK, \u00a0\u00a0\u00a0 CLOSE_ERROR };  enum closeStatus closeFile(FILE* file); #endif \/\/UNTITLED_CLOSEFILE_H<\/code><\/pre>\n<p><strong>closeFile.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"closeFile.h\"  enum closeStatus closeFile(FILE* file){ \u00a0\u00a0\u00a0 if(fclose(file) == EOF){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return CLOSE_ERROR; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 return CLOSE_OK; }<\/code><\/pre>\n<h3>Utilities for converting BMP to image and vice versa<\/h3>\n<p>To ease the file transformation, I have decided to create a separate section for necessary functions. <\/p>\n<p><strong>utilsForBmp.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_UTILSFORBMP_H #define UNTITLED_UTILSFORBMP_H  #include \"..\/inputOutput\/fromToBmp.h\" size_t size_of_padding(const size_t width); bool head_read(FILE* file, struct bmp_header* header); size_t size_of_image(const struct image* image); size_t size_of_file(const struct image* image); struct bmp_header create_header(const struct image* image);  #endif \/\/UNTITLED_UTILSFORBMP_H<\/code><\/pre>\n<ul>\n<li>\n<p><code>size_of_padding()<\/code> function decides whether it is necessary to add padding to a file or not. <\/p>\n<\/li>\n<li>\n<p><code>head_read()<\/code> function allows to read only the file\u2019s heading. This is done for splitting the header and the raster array easier.<\/p>\n<\/li>\n<li>\n<p><code>size_of_file()<\/code> function returns the size in bytes that a certain file will occupy (image size + header size).<\/p>\n<\/li>\n<li>\n<p><code>create_header()<\/code> allows to create a header for a particular image for further storage. <\/p>\n<\/li>\n<\/ul>\n<p>All implementations of functions in <strong>utilsForBmp.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"..\/inputOutput\/fromToBmp.h\"  size_t size_of_padding(const size_t width){ \u00a0\u00a0\u00a0 return width % 4; }  bool head_read(FILE* file, struct bmp_header* header){ \u00a0\u00a0\u00a0 return fread(header, sizeof(struct bmp_header), 1, file); }  size_t size_of_image(const struct image* image){ \u00a0\u00a0\u00a0 return (image->width * sizeof(struct pixel) + size_of_padding(image->width)) * image->height; }  size_t size_of_file(const struct image* image){ \u00a0\u00a0\u00a0 return size_of_image(image) + sizeof(struct bmp_header); }  struct bmp_header create_header(const struct image* image){ \u00a0\u00a0\u00a0 return (struct bmp_header){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bfType = 19778, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bfileSize = size_of_file(image), \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bfReserved = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bOffBits = 54, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biSize = 40, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biWidth = image->width, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biHeight = image->height, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biPlanes = 1, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biBitCount = 24, \/\/quantity of bits in bpm file \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biCompression = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biSizeImage = size_of_image(image), \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biXPelsPerMeter = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biYPelsPerMeter = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biClrImportant = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biClrUsed = 0 \u00a0\u00a0\u00a0 }; }<\/code><\/pre>\n<h3>BMP into image and back<\/h3>\n<p>After I have successfully opened the file for reading, I have to read it and transform into an image for an easier work with pixels. I have decided not to split this section into 4 files (as have been done with opening and closing) as I have figured it would complex the reading. <\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_FROMTOBMP_H #define UNTITLED_FROMTOBMP_H  #include \"..\/image\/image.h\" #include &lt;stdbool.h> #include &lt;stdio.h>  struct __attribute__((packed)) bmp_header { \u00a0\u00a0\u00a0 uint16_t bfType; \u00a0\u00a0\u00a0 uint32_t bfileSize; \u00a0\u00a0\u00a0 uint32_t bfReserved; \u00a0\u00a0\u00a0 uint32_t bOffBits; \u00a0\u00a0\u00a0 uint32_t biSize; \u00a0\u00a0\u00a0 uint32_t biWidth; \u00a0\u00a0\u00a0 uint32_t biHeight; \u00a0\u00a0\u00a0 uint16_t biPlanes; \u00a0\u00a0\u00a0 uint16_t biBitCount; \u00a0\u00a0\u00a0 uint32_t biCompression; \u00a0\u00a0\u00a0 uint32_t biSizeImage; \u00a0\u00a0\u00a0 uint32_t biXPelsPerMeter; \u00a0\u00a0\u00a0 uint32_t biYPelsPerMeter; \u00a0\u00a0\u00a0 uint32_t biClrUsed; \u00a0\u00a0\u00a0 uint32_t biClrImportant; };  enum read_status\u00a0 { \u00a0\u00a0\u00a0 READ_OK = 0, \u00a0\u00a0\u00a0 READ_INVALID_SIGNATURE, \u00a0\u00a0\u00a0 READ_INVALID_BITS, \u00a0\u00a0\u00a0 READ_INVALID_HEADER, \u00a0\u00a0\u00a0 READ_INVALID_PADDING };  enum write_status\u00a0 { \u00a0\u00a0\u00a0 WRITE_OK = 0, \u00a0\u00a0\u00a0 WRITE_ERROR, \u00a0\u00a0\u00a0 WRITE_INVALID_BITS, \u00a0\u00a0\u00a0 WRITE_INVALID_SIGNATURE, \u00a0\u00a0\u00a0 WRITE_INVALID_HEADER, \u00a0\u00a0\u00a0 WRITE_INVALID_DATA, \u00a0\u00a0\u00a0 WRITE_INVALID_PADDING };   enum read_status fromBmp(FILE* in, struct image* image); enum write_status toBmp(FILE* out, const struct image* image); #endif \/\/UNTITLED_FROMTOBMP_H<\/code><\/pre>\n<p><code>bmp_header()<\/code> structure returns an empty heading. <\/p>\n<p><code>read_status<\/code> and <code>write_status<\/code> enumerations return the results of <code>fromBmp<\/code> and <code>toBmp<\/code> execution respectively. <\/p>\n<p>Implementation of functions in <strong>fromToBmp.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"fromToBmp.h\" #include \"..\/util\/utilsForBmp.h\"  enum read_status fromBmp(FILE* in, struct image* image){ \u00a0\u00a0\u00a0 struct bmp_header header = {0};  \u00a0\u00a0\u00a0 if(!head_read(in, &amp;header)){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(image); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return READ_INVALID_HEADER; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 if(header.bfType != 19778){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(image); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return READ_INVALID_SIGNATURE; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 *image = emptyImage(header.biWidth, header.biHeight); \u00a0\u00a0\u00a0 const size_t padding = size_of_padding(image->width);  \u00a0\u00a0\u00a0 for(size_t i = 0; i &lt; image->height; i++){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for(size_t j = 0; j &lt; image->width; j++){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(!fread(&amp;(image->data[findIndex(j, i, image->width)]), sizeof(struct pixel), 1, in)){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(image); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return READ_INVALID_BITS; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(padding != 0) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (fseek(in, padding, SEEK_CUR)) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(image); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return READ_INVALID_PADDING; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 return READ_OK; }  enum write_status toBmp(FILE* out, const struct image* image){ \u00a0\u00a0\u00a0 struct bmp_header header = create_header(image);  \u00a0\u00a0\u00a0 if(!fwrite(&amp;header, sizeof(struct bmp_header), 1, out)){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return WRITE_INVALID_HEADER; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 if(fseek(out, header.bOffBits, SEEK_SET)){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return WRITE_INVALID_SIGNATURE; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 const uint8_t paddings[3] = {0}; \u00a0\u00a0\u00a0 const size_t padding = size_of_padding(image->width);  \u00a0\u00a0\u00a0 if(image->data == NULL){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return WRITE_INVALID_DATA; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 for(size_t i = 0; i &lt; image->height; i++){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for(size_t j = 0; j &lt; image->width; j++) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (!fwrite(&amp;image->data[findIndex(j, i, image->width)], sizeof(struct pixel), 1, out)) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return WRITE_INVALID_BITS; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(padding != 0){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(!fwrite(paddings, padding, 1, out)){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return WRITE_INVALID_PADDING; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 return WRITE_OK; }<\/code><\/pre>\n<p>In <code>fromBmp()<\/code>, I, firstly, check whether I can read the file\u2019s heading successfully. Afterwards, I verify whether file\u2019s type (<code>bfType<\/code>) satisfies my case. Then, I create an empty image and get the padding size. After, I start to fill an image, skipping padding if it is present.<\/p>\n<p>In <code>toBmp()<\/code>, I, firstly, try to write down the necessary heading of my image. Next, I get padding size of my image. Then, if our image isn\u2019t empty, I start writing down all data into initial file, remembering to add padding after each new stroke (if needed). <\/p>\n<h3>Image rotation<\/h3>\n<p>This section overviews the image rotation by 90 degrees counterclockwise. <\/p>\n<p><strong>rotate.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_ROTATE_H #define UNTITLED_ROTATE_H #include \"..\/image\/image.h\"  struct image rotate(struct image source);  #endif \/\/UNTITLED_ROTATE_H<\/code><\/pre>\n<p>Implementation is stored in <strong>rotate.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"..\/image\/image.h\" #include &lt;stdlib.h>  struct image rotate(const struct image source){ \u00a0\u00a0\u00a0 if(source.data == NULL){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return emptyImage(source.width, source.height); \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 struct pixel* pixels = malloc(sizeof(struct pixel) * source.width * source.height);  \u00a0\u00a0\u00a0 for(size_t y = 0; y &lt; source.height; y++){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for(size_t x = 0; x &lt; source.width; x++){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pixels[findIndex(source.height - y - 1, x, source.height)] = source.data[findIndex(x, y, source.width)]; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 return createImage(source.height, source.width, pixels); }<\/code><\/pre>\n<p>To begin with, unless the image isn\u2019t full, I return an empty image in which height and width dimensions have been changed. <\/p>\n<p>Next, I allocate the memory necessary to store the pixels. Because the program is generally simple, it just rotates an image by 90 degrees. By this I get two two-dimensional arrays \u2013 one full, another empty. To accomplish the program, I just need to input pixels from a full array into an empty one correctly. Lastly, all work results is returned by createImage(). <\/p>\n<p><strong>Main file:<\/strong><\/p>\n<pre><code class=\"cpp\">#include &lt;stdio.h>  #include \"inputOutput\/fromToBmp.h\" #include \"openClose\/closeFile.h\" #include \"openClose\/openFile.h\" #include \"rotation\/rotate.h\"  int main(int cntArg, char* args[]){ \u00a0\u00a0\u00a0 printf(\"%d\", cntArg);  \u00a0\u00a0\u00a0 if(cntArg != 3){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 perror(\"incorrectly passed arguments\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -1; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 FILE *file; \u00a0\u00a0\u00a0 if (openFile(args[1], &amp;file, \"rb\") != OPEN_OK) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 perror(\"couldn't open the file\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -2; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 struct image img = {0};  \u00a0\u00a0\u00a0 if (fromBmp(file, &amp;img) != READ_OK) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 perror(\"couldn't convert from bmp\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -3; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 struct image res = rotate(img); \u00a0\u00a0\u00a0 FILE *res_file;  \u00a0\u00a0\u00a0 if (openFile(args[2], &amp;res_file, \"wb\") != OPEN_OK) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 perror(\"couldn't open the file\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(&amp;res); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -2; \u00a0\u00a0\u00a0 }  \u00a0\u00a0\u00a0 if (toBmp(res_file, &amp;res) != WRITE_OK) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 perror(\"couldn't convert to bmp\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(&amp;res); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 closeFile(res_file); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -5; \u00a0\u00a0\u00a0 }   \u00a0\u00a0\u00a0 if (closeFile(file) != CLOSE_OK) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 perror(\"couldn't close the file\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(&amp;img); \u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0return -4; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 if (closeFile(res_file) != CLOSE_OK) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 perror(\"couldn't close the file\"); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(&amp;img); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -6; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 imageDestroyer(&amp;img); \u00a0\u00a0\u00a0 imageDestroyer(&amp;res);  \u00a0\u00a0\u00a0 return 0; }<\/code><\/pre>\n<p>Firstly, I check if the number of program arguments is two (the path to the image to be rotated and the path to save the result). Then, I open file and transform it into image. Next, I rotate it, open file for recording, transform image into bmp and save it. Lastly, I free the allocated memory and close all the files. <\/p>\n<p>It could have been done so the ways would be read through the standard entrance, however, you do whatever pleases you.<\/p>\n<p><strong>Example 1: <\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/94e\/1df\/4ef\/94e1df4ef0dc9d075cbc54abe71727a7.jpg\" width=\"1518\" height=\"941\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/94e\/1df\/4ef\/94e1df4ef0dc9d075cbc54abe71727a7.jpg\" data-blurred=\"true\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/5a0\/551\/089\/5a0551089a72cc192074c03fec7643fb.jpg\" width=\"941\" height=\"1518\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5a0\/551\/089\/5a0551089a72cc192074c03fec7643fb.jpg\" data-blurred=\"true\"\/><\/figure>\n<p><strong>Example 2:<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/646\/483\/a60\/646483a609999eee06967f7a8651df87.jpg\" alt=\"\" title=\"\" width=\"941\" height=\"1518\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/646\/483\/a60\/646483a609999eee06967f7a8651df87.jpg\" data-blurred=\"true\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/463\/059\/5bb\/4630595bb51724df6814d967de86a7b7.jpg\" width=\"1518\" height=\"941\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/463\/059\/5bb\/4630595bb51724df6814d967de86a7b7.jpg\" data-blurred=\"true\"\/><\/figure>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/739580\/\"> https:\/\/habr.com\/ru\/articles\/739580\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>Brief problem formulation<\/h3>\n<p>The program accepts as input the absolute path to the image in the bmp extension and the path where you save the result of the work. Then, it rotates the image by 90 degrees counterclockwise. Afterwards, the program saves the new image. <\/p>\n<p>The program is executed on C.<\/p>\n<h3>BMP file structure<\/h3>\n<p>BMP-file comprises the heading (it weighs 14 bytes) and the raster array (it weighs 40 bytes). I make the heading by following structure: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/p>\n<p><code>struct __attribute__((packed)) bmp_header {<br \/> \u00a0\u00a0\u00a0 uint16_t bfType;<br \/> \u00a0\u00a0\u00a0 uint32_t bfileSize;<br \/> \u00a0\u00a0\u00a0 uint32_t bfReserved;<br \/> \u00a0\u00a0\u00a0 uint32_t bOffBits;<br \/> \u00a0\u00a0\u00a0 uint32_t biSize;<br \/> \u00a0\u00a0\u00a0 uint32_t biWidth;<br \/> \u00a0\u00a0\u00a0 uint32_t biHeight;<br \/> \u00a0\u00a0\u00a0 uint16_t biPlanes;<br \/> \u00a0\u00a0\u00a0 uint16_t biBitCount;<br \/> \u00a0\u00a0\u00a0 uint32_t biCompression;<br \/> \u00a0\u00a0\u00a0 uint32_t biSizeImage;<br \/> \u00a0\u00a0\u00a0 uint32_t biXPelsPerMeter;<br \/> \u00a0\u00a0\u00a0 uint32_t biYPelsPerMeter;<br \/> \u00a0\u00a0\u00a0 uint32_t biClrUsed;<br \/> \u00a0\u00a0\u00a0 uint32_t biClrImportant;<br \/> };<\/code><\/p>\n<p>BMP-file heading contains the following information: <\/p>\n<ul>\n<li>\n<p><code>bfType<\/code>: 2 bytes, file type;<\/p>\n<\/li>\n<li>\n<p><code>bfSize<\/code>: 4 bytes, file size;<\/p>\n<\/li>\n<li>\n<p><code>bfReserved1<\/code>: 4 bytes, reserved, must be settled to the value of 0;<\/p>\n<\/li>\n<li>\n<p><code>bfOffBits<\/code>: 4 bytes, offset from start to raster data;<\/p>\n<\/li>\n<\/ul>\n<p>Raster information heading (raster information). All in all, there are only 40 bytes of heading of raster image, including the following:<\/p>\n<ul>\n<li>\n<p><code>biSize<\/code>: 4 bytes; the size of the information header, which is 40;<\/p>\n<\/li>\n<li>\n<p><code>biWidth<\/code>: 4 bytes, indicates the image width in pixels;<\/p>\n<\/li>\n<li>\n<p><code>biHeight<\/code>: 4 bytes, indicates the image height in pixels;<\/p>\n<\/li>\n<li>\n<p><code>biPlanes<\/code>: 2 bytes, indicates the number of color planes for the target device, always equal to 1;<\/p>\n<\/li>\n<li>\n<p><code>biBitCount<\/code>: 2 bytes, indicates byte\/pixel quantity and takes the values 1, 2, 4, 8, 16, 24, 32;<\/p>\n<\/li>\n<li>\n<p><code>biCompression<\/code>: 4 bytes, indicates the type of image compression most commonly used 0 (BI_RGB), which means no compression;<\/p>\n<\/li>\n<li>\n<p><code>biSizeImages<\/code>: 4 bytes, indicates the size of the raster data; when using the BI_RGB format, it can be set to 0;<\/p>\n<\/li>\n<li>\n<p><code>biXPelsPerMeter<\/code>: indicates horizontal extension, unit of measurement &#8212; pixel\/meter, signed integer;<\/p>\n<\/li>\n<li>\n<p><code>biClrUsed<\/code>: indicates the number of color indexes in the palette used by the bitmap(raster) image, 0 means to use all;<\/p>\n<\/li>\n<li>\n<p><code>biClrImportant<\/code>: indicates the number of color indexes that have an important effect on the display of the image, and 0 indicates that it is important;<\/p>\n<\/li>\n<\/ul>\n<p>Right after the heading the raster array follows in which pixels are saved consequently and by strokes. Each pixel is set by the following structure of 3 bytes size:<\/p>\n<pre><code class=\"cpp\">struct pixel { uint8_t b; uint8_t g; uint8_t r; };<\/code><\/pre>\n<h3>Padding <\/h3>\n<p>If the width of the image in bytes is a multiple of four, then the lines go one after the other without gaps. If the width is not a multiple of four, then it is padded with garbage bytes to the nearest multiple of four. These bytes are called padding. <\/p>\n<p>Example:<\/p>\n<ol>\n<li>\n<p>Let an image be 10 pixels wide => 10 *3 bytes = 30 bytes, the closest number multiple of four is 32. So, followingly, each new stroke will have an indentation of 32 \u2013 30 = 2 bytes before the next stroke starts. <\/p>\n<\/li>\n<li>\n<p>Let an image be 4 pixels wide => 4 * 3 = 12 bytes. The width is multiple of four, hence, each new stroke comes immediately after the previous without any indentation. <\/p>\n<\/li>\n<\/ol>\n<h3>Image storage<\/h3>\n<p>I split the program into headed files and executed files. Let\u2019s consider the image storage and its useful functions. Let\u2019s write down <strong>image.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_IMAGE_H #define UNTITLED_IMAGE_H  #include &lt;stdint.h> #include &lt;stdio.h>  struct pixel { \u00a0\u00a0\u00a0 uint8_t b; \u00a0\u00a0\u00a0 uint8_t g; \u00a0\u00a0\u00a0 uint8_t r; };  struct image { \u00a0\u00a0\u00a0 uint64_t width; \u00a0\u00a0\u00a0 uint64_t height; \u00a0\u00a0\u00a0 struct pixel *data; };  size_t findIndex(size_t x, size_t y, size_t width); struct image emptyImage(const uint64_t width, const uint64_t height); struct image createImage(const size_t image_width, const size_t image_height, struct pixel* pixels); void imageDestroyer(struct image* image);   #endif \/\/UNTITLED_IMAGE_H<\/code><\/pre>\n<p>Where:<\/p>\n<pre><code class=\"cpp\">struct image { \u00a0\u00a0\u00a0 uint64_t width; \u00a0\u00a0\u00a0 uint64_t height; \u00a0\u00a0\u00a0 struct pixel *data; };<\/code><\/pre>\n<p>Is responsible for storage keeping image\u2019s size and pixels. <\/p>\n<ul>\n<li>\n<p><code>findIndex()<\/code> function allows to find an index in a new already rotated image where the former pixel with initial indices x and y is located. <\/p>\n<\/li>\n<li>\n<p><code>emptyImage()<\/code> function creates an empty image of a certain size.<\/p>\n<\/li>\n<li>\n<p><code>createImage()<\/code> function builds a full image of a certain size. <\/p>\n<\/li>\n<li>\n<p><code>imageDestroyer()<\/code> function frees the memory occupied by the image. <\/p>\n<\/li>\n<\/ul>\n<p>Let\u2019s consider the implementations of all functions in <strong>image.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"image.h\" #include &lt;stdint.h> #include &lt;stdlib.h>  size_t findIndex(const size_t x, const size_t y, const size_t width){ \u00a0\u00a0\u00a0 return y * width + x; }  struct image emptyImage(const uint64_t width, const uint64_t height){ \u00a0\u00a0\u00a0 struct pixel* pixels = malloc(sizeof(struct pixel) * height * width); \u00a0\u00a0\u00a0 return createImage(width, height, pixels); }  struct image createImage(const size_t width, const size_t height, struct pixel* pixels){ \u00a0\u00a0\u00a0 return (struct image) {.data = pixels, .width = width, .height = height}; }  void imageDestroyer(struct image* image){ \u00a0\u00a0\u00a0 free(image->data); }<\/code><\/pre>\n<h3>Opening and closing of images<\/h3>\n<p>This part looks at implemented functions to open an image and record, and after finishing the work, at the function for closing an image. <\/p>\n<p><strong>openFile.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_OPENFILE_H #define UNTITLED_OPENFILE_H  #include &lt;stdbool.h> #include &lt;stdio.h> enum openStatus{ \u00a0\u00a0\u00a0 OPEN_ERROR, \u00a0\u00a0\u00a0 OPEN_OK };  enum openStatus openFile(const char* fileName, FILE** file, const char* type); #endif \/\/UNTITLED_OPENFILE_H<\/code><\/pre>\n<p><strong>openFile.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"openFile.h\"  enum openStatus openFile(const char* fileName, FILE** file, const char* type){ \u00a0\u00a0\u00a0 *file = fopen(fileName, type); \u00a0\u00a0\u00a0 if(*file == NULL){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return OPEN_ERROR; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 return OPEN_OK; }<\/code><\/pre>\n<p><strong>closeFile.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_CLOSEFILE_H #define UNTITLED_CLOSEFILE_H  #include &lt;stdbool.h> #include &lt;stdio.h> enum closeStatus{ \u00a0\u00a0\u00a0 CLOSE_OK, \u00a0\u00a0\u00a0 CLOSE_ERROR };  enum closeStatus closeFile(FILE* file); #endif \/\/UNTITLED_CLOSEFILE_H<\/code><\/pre>\n<p><strong>closeFile.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"closeFile.h\"  enum closeStatus closeFile(FILE* file){ \u00a0\u00a0\u00a0 if(fclose(file) == EOF){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return CLOSE_ERROR; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 return CLOSE_OK; }<\/code><\/pre>\n<h3>Utilities for converting BMP to image and vice versa<\/h3>\n<p>To ease the file transformation, I have decided to create a separate section for necessary functions. <\/p>\n<p><strong>utilsForBmp.h<\/strong>:<\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_UTILSFORBMP_H #define UNTITLED_UTILSFORBMP_H  #include \"..\/inputOutput\/fromToBmp.h\" size_t size_of_padding(const size_t width); bool head_read(FILE* file, struct bmp_header* header); size_t size_of_image(const struct image* image); size_t size_of_file(const struct image* image); struct bmp_header create_header(const struct image* image);  #endif \/\/UNTITLED_UTILSFORBMP_H<\/code><\/pre>\n<ul>\n<li>\n<p><code>size_of_padding()<\/code> function decides whether it is necessary to add padding to a file or not. <\/p>\n<\/li>\n<li>\n<p><code>head_read()<\/code> function allows to read only the file\u2019s heading. This is done for splitting the header and the raster array easier.<\/p>\n<\/li>\n<li>\n<p><code>size_of_file()<\/code> function returns the size in bytes that a certain file will occupy (image size + header size).<\/p>\n<\/li>\n<li>\n<p><code>create_header()<\/code> allows to create a header for a particular image for further storage. <\/p>\n<\/li>\n<\/ul>\n<p>All implementations of functions in <strong>utilsForBmp.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"..\/inputOutput\/fromToBmp.h\"  size_t size_of_padding(const size_t width){ \u00a0\u00a0\u00a0 return width % 4; }  bool head_read(FILE* file, struct bmp_header* header){ \u00a0\u00a0\u00a0 return fread(header, sizeof(struct bmp_header), 1, file); }  size_t size_of_image(const struct image* image){ \u00a0\u00a0\u00a0 return (image->width * sizeof(struct pixel) + size_of_padding(image->width)) * image->height; }  size_t size_of_file(const struct image* image){ \u00a0\u00a0\u00a0 return size_of_image(image) + sizeof(struct bmp_header); }  struct bmp_header create_header(const struct image* image){ \u00a0\u00a0\u00a0 return (struct bmp_header){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bfType = 19778, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bfileSize = size_of_file(image), \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bfReserved = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .bOffBits = 54, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biSize = 40, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biWidth = image->width, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biHeight = image->height, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biPlanes = 1, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biBitCount = 24, \/\/quantity of bits in bpm file \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biCompression = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biSizeImage = size_of_image(image), \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biXPelsPerMeter = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biYPelsPerMeter = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biClrImportant = 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .biClrUsed = 0 \u00a0\u00a0\u00a0 }; }<\/code><\/pre>\n<h3>BMP into image and back<\/h3>\n<p>After I have successfully opened the file for reading, I have to read it and transform into an image for an easier work with pixels. I have decided not to split this section into 4 files (as have been done with opening and closing) as I have figured it would complex the reading. <\/p>\n<pre><code class=\"cpp\">#ifndef UNTITLED_FROMTOBMP_H #define UNTITLED_FROMTOBMP_H  #include \"..\/image\/image.h\" #include &lt;stdbool.h> #include &lt;stdio.h>  struct __attribute__((packed)) bmp_header { \u00a0\u00a0\u00a0 uint16_t bfType; \u00a0\u00a0\u00a0 uint32_t bfileSize; \u00a0\u00a0\u00a0 uint32_t bfReserved; \u00a0\u00a0\u00a0 uint32_t bOffBits; \u00a0\u00a0\u00a0 uint32_t biSize; \u00a0\u00a0\u00a0 uint32_t biWidth; \u00a0\u00a0\u00a0 uint32_t biHeight; \u00a0\u00a0\u00a0 uint16_t biPlanes; \u00a0\u00a0\u00a0 uint16_t biBitCount; \u00a0\u00a0\u00a0 uint32_t biCompression; \u00a0\u00a0\u00a0 uint32_t biSizeImage; \u00a0\u00a0\u00a0 uint32_t biXPelsPerMeter; \u00a0\u00a0\u00a0 uint32_t biYPelsPerMeter; \u00a0\u00a0\u00a0 uint32_t biClrUsed; \u00a0\u00a0\u00a0 uint32_t biClrImportant; };  enum read_status\u00a0 { \u00a0\u00a0\u00a0 READ_OK = 0, \u00a0\u00a0\u00a0 READ_INVALID_SIGNATURE, \u00a0\u00a0\u00a0 READ_INVALID_BITS, \u00a0\u00a0\u00a0 READ_INVALID_HEADER, \u00a0\u00a0\u00a0 READ_INVALID_PADDING };  enum write_status\u00a0 { \u00a0\u00a0\u00a0 WRITE_OK = 0, \u00a0\u00a0\u00a0 WRITE_ERROR, \u00a0\u00a0\u00a0 WRITE_INVALID_BITS, \u00a0\u00a0\u00a0 WRITE_INVALID_SIGNATURE, \u00a0\u00a0\u00a0 WRITE_INVALID_HEADER, \u00a0\u00a0\u00a0 WRITE_INVALID_DATA, \u00a0\u00a0\u00a0 WRITE_INVALID_PADDING };   enum read_status fromBmp(FILE* in, struct image* image); enum write_status toBmp(FILE* out, const struct image* image); #endif \/\/UNTITLED_FROMTOBMP_H<\/code><\/pre>\n<p><code>bmp_header()<\/code> structure returns an empty heading. <\/p>\n<p><code>read_status<\/code> and <code>write_status<\/code> enumerations return the results of <code>fromBmp<\/code> and <code>toBmp<\/code> execution respectively. <\/p>\n<p>Implementation of functions in <strong>fromToBmp.c<\/strong>:<\/p>\n<pre><code class=\"cpp\">#include \"fromToBmp.h\" #include \"..\/util\/utilsForBmp.h\"  enum read_status fromBmp(FILE* in, struct image* image){ \u00a0\u00a0\u00a0 struct bmp_header header = {0};  \u00a0\u00a0\u00a0 if(!head_read(in, &amp;header)){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 imageDestroyer(image); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return READ_INVALID_HEADER; \u00a0\u00a0\u00a0 } \u00a0\u00a0\u00a0 if(header.bfType != 19778){ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-412001","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/412001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=412001"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/412001\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=412001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=412001"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=412001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}