Advertisement
Guest User

Untitled

a guest
Feb 8th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.81 KB | None | 0 0
  1. #ifndef BMPWRITER_
  2. #define BMPWRITER_
  3.  
  4. #include <stdint.h>
  5.  
  6. int write24BitBMP(const char *outputFileName, uint32_t width, uint32_t height, uint8_t *rgbData);
  7.  
  8. #endif /* ifndef BMPWRITER_ */
  9.  
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12.  
  13. #include "bmpWriter.h"
  14.  
  15. typedef struct {
  16. uint16_t bfType; // Header field used to identify the BMP. Must be set to 'B','M' (0x42 0x4d).
  17. uint32_t bfSize; // Size of the complete file (Header + InfoHeader + PixelData) in bytes.
  18. uint32_t bfReserved; // Reserved. Must be set to zero.
  19. uint32_t bfOffBits; // Number of bytes until the pixel data starts (counted from the file-start). Always 54?
  20. } BMPHEADER;
  21.  
  22. typedef struct {
  23. uint32_t biSize; // The size of the info header in bytes (40).
  24. uint32_t biWidth; // The Bitmap width in pixels.
  25. uint32_t biHeight; // The Bitmap height in pixels.
  26. uint16_t biPlanes; // The number of color planes. Must be set to one.
  27. uint16_t biBitCount; // The number of bits per pixel (color depth).
  28. uint32_t biCompression; // The compression method being used (zero equals no compression).
  29. uint32_t biSizeImage; // The size of the raw bitmap data. Zero is fine.
  30. uint32_t biXPelsPerMeter; // Horizontal resolution of the image. Zero is fine.
  31. uint32_t biYPelsPerMeter; // Vertical resolution of the image. Zero is fine.
  32. uint32_t biClrUsed; // Number of colors in the color paletter. Zero is fine.
  33. uint32_t biClrImportant; // Number of important colors used. Zero equals every color is important.
  34. } BMPINFOHEADER;
  35.  
  36. // BMP RELATED
  37. static void writeBMPHeader(FILE *outputFile, BMPHEADER *bmph);
  38. static void writeBMPInfoHeader(FILE *outoutFile, BMPINFOHEADER *bmpih);
  39.  
  40. // HANDLE ENDIANESS
  41. static void reverseBytes(void *data, uint8_t width);
  42. static void reverseBMPHeader(BMPHEADER *bmph);
  43. static void reverseBMPInfoHeader(BMPINFOHEADER *bmpih);
  44. static int isLittleEndian(void);
  45.  
  46. int write24BitBMP(const char *outputFileName, uint32_t width, uint32_t height, uint8_t *rgbData) {
  47. FILE *outputFile = fopen(outputFileName, "wb");
  48.  
  49. if (!outputFile)
  50. return -1;
  51.  
  52. // One data row needs to consist of a multiple of four bytes. This is the needed overhead.
  53. uint8_t overhead = 3*width % 4 ? 4 - 3*width % 4 : 0;
  54.  
  55. // BMPHEADER
  56. BMPHEADER bmph;
  57. bmph.bfType = 0x4d42; // 'MB' as HEX, little endian will store this as 'BM'.
  58. bmph.bfSize = (54 + (3*width+overhead)*height);
  59. bmph.bfReserved = 0;
  60. bmph.bfOffBits = 54;
  61.  
  62. // BMPINFOHEADER
  63. BMPINFOHEADER bmpih;
  64. bmpih.biSize = 40;
  65. bmpih.biWidth = width;
  66. bmpih.biHeight = height;
  67. bmpih.biPlanes = 1;
  68. bmpih.biBitCount = 24;
  69. bmpih.biCompression = 0;
  70. bmpih.biSizeImage = (3*width+overhead) * height;
  71. bmpih.biXPelsPerMeter = 0;
  72. bmpih.biYPelsPerMeter = 0;
  73. bmpih.biClrUsed = 0;
  74. bmpih.biClrImportant = 0;
  75.  
  76. if (!isLittleEndian()) {
  77. reverseBMPHeader(&bmph);
  78. reverseBMPInfoHeader(&bmpih);
  79. }
  80.  
  81. // OR WRITE AS A WHOLE, BUT WHAT HAPPENS TO PADDING?
  82. writeBMPHeader(outputFile, &bmph);
  83. writeBMPInfoHeader(outputFile, &bmpih);
  84.  
  85. // DOES THIS WORK WITH BIG ENDIAN AS WELL?
  86. uint8_t *rawData = malloc((3*width+overhead)*height);
  87. uint32_t i, currRow, currColumn, oi;
  88.  
  89. if (rawData == NULL)
  90. return -1;
  91.  
  92. for (currRow = height, i = 0; currRow > 0; currRow--) {
  93. for (currColumn = 0; currColumn < width; currColumn++) {
  94. rawData[i++] = rgbData[3*width*(currRow-1) + 3*currColumn + 2];
  95. rawData[i++] = rgbData[3*width*(currRow-1) + 3*currColumn + 1];
  96. rawData[i++] = rgbData[3*width*(currRow-1) + 3*currColumn];
  97. }
  98. for (oi = 0; oi < overhead; oi++) {
  99. rawData[i++] = 0;
  100. }
  101. }
  102.  
  103. fwrite(rawData, (3*width+overhead)*height, 1, outputFile);
  104.  
  105. // ->
  106. // RGB1 RGB2
  107. // RGB3 RGB4
  108. //
  109. // ->
  110. // RGB3 RGB4 OVERHEAD[2]
  111. // RGB1 RGB2 OVERHEAD[2]
  112.  
  113. free(rawData);
  114. fclose(outputFile);
  115. return 0;
  116. }
  117.  
  118. void writeBMPHeader(FILE *outputFile, BMPHEADER *bmph) {
  119. fwrite(&bmph->bfType , sizeof(bmph->bfType) , 1, outputFile);
  120. fwrite(&bmph->bfSize , sizeof(bmph->bfSize) , 1, outputFile);
  121. fwrite(&bmph->bfReserved, sizeof(bmph->bfReserved), 1, outputFile);
  122. fwrite(&bmph->bfOffBits , sizeof(bmph->bfOffBits) , 1, outputFile);
  123. }
  124.  
  125. void writeBMPInfoHeader(FILE *outputFile, BMPINFOHEADER *bmpih) {
  126. fwrite(&bmpih->biSize , sizeof(bmpih->biSize) , 1, outputFile);
  127. fwrite(&bmpih->biWidth , sizeof(bmpih->biWidth) , 1, outputFile);
  128. fwrite(&bmpih->biHeight , sizeof(bmpih->biHeight) , 1, outputFile);
  129. fwrite(&bmpih->biPlanes , sizeof(bmpih->biPlanes) , 1, outputFile);
  130. fwrite(&bmpih->biBitCount , sizeof(bmpih->biBitCount) , 1, outputFile);
  131. fwrite(&bmpih->biCompression , sizeof(bmpih->biCompression) , 1, outputFile);
  132. fwrite(&bmpih->biSizeImage , sizeof(bmpih->biSizeImage) , 1, outputFile);
  133. fwrite(&bmpih->biXPelsPerMeter , sizeof(bmpih->biXPelsPerMeter), 1, outputFile);
  134. fwrite(&bmpih->biYPelsPerMeter , sizeof(bmpih->biYPelsPerMeter), 1, outputFile);
  135. fwrite(&bmpih->biClrUsed , sizeof(bmpih->biClrUsed) , 1, outputFile);
  136. fwrite(&bmpih->biClrImportant , sizeof(bmpih->biClrImportant) , 1, outputFile);
  137. }
  138.  
  139. int isLittleEndian() {
  140. int tmp = 1;
  141. return *(char*)&tmp ? 1 : 0;
  142. }
  143.  
  144. void reverseBytes(void *data, uint8_t width) {
  145. uint8_t i, tmp;
  146.  
  147. for (i =0; i < width/2; i++) {
  148. tmp = ((uint8_t *)data)[i];
  149. ((uint8_t *)data)[i] = ((uint8_t *)data)[width-i-1];
  150. ((uint8_t *)data)[width-i-1] = tmp;
  151. }
  152. }
  153.  
  154. void reverseBMPHeader(BMPHEADER *bmph) {
  155. reverseBytes(&bmph->bfType, sizeof(bmph->bfType));
  156. reverseBytes(&bmph->bfSize, sizeof(bmph->bfSize));
  157. /* reverseBytes(&bmph->bfReserved, sizeof(bmph->bfReserved)); */
  158. reverseBytes(&bmph->bfOffBits, sizeof(bmph->bfOffBits));
  159. }
  160.  
  161. void reverseBMPInfoHeader(BMPINFOHEADER *bmpih) {
  162. reverseBytes(&bmpih->biSize , sizeof(bmpih->biSize));
  163. reverseBytes(&bmpih->biWidth , sizeof(bmpih->biWidth));
  164. reverseBytes(&bmpih->biHeight , sizeof(bmpih->biHeight));
  165. reverseBytes(&bmpih->biPlanes , sizeof(bmpih->biPlanes));
  166. reverseBytes(&bmpih->biBitCount , sizeof(bmpih->biBitCount));
  167. /* reverseBytes(&bmpih->biCompression , sizeof(bmpih->biCompression)); */
  168. reverseBytes(&bmpih->biSizeImage , sizeof(bmpih->biSizeImage));
  169. /* reverseBytes(&bmpih->biXPelsPerMeter , sizeof(bmpih->biXPelsPerMeter)); */
  170. /* reverseBytes(&bmpih->biYPelsPerMeter , sizeof(bmpih->biYPelsPerMeter)); */
  171. /* reverseBytes(&bmpih->biClrUsed , sizeof(bmpih->biClrUsed)); */
  172. /* reverseBytes(&bmpih->biClrImportant , sizeof(bmpih->biClrImportant)); */
  173. }
  174.  
  175. #include <stdio.h>
  176. #include "bmpWriter.h"
  177.  
  178. int main() {
  179. char *outputFileName = "output.bmp";
  180.  
  181. uint8_t rgbData[] = {
  182. 230, 200, 200, 150, 180, 150, 100, 100, 130,
  183. 255, 120, 80, 120, 255, 120, 80, 120, 255,
  184. 130, 100, 100, 150, 180, 150, 200, 200, 230
  185. };
  186.  
  187. write24BitBMP(outputFileName, 3, 3, rgbData);
  188. return 0;
  189. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement