BsBitmapWriter.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. //__________________________ Banshee Project - A modern game development toolkit _________________________________//
  2. //_____________________________________ www.banshee-project.com __________________________________________________//
  3. //________________________ Copyright (c) 2014 Marko Pintera. All rights reserved. ________________________________//
  4. #include "BsBitmapWriter.h"
  5. namespace BansheeEngine
  6. {
  7. #pragma pack(push, 2) // Align to 2byte boundary so we don't get extra 2 bytes for this struct
  8. struct BMP_HEADER
  9. {
  10. UINT16 BM;
  11. UINT32 size_of_file;
  12. UINT32 reserve;
  13. UINT32 offset_of_pixel_data;
  14. UINT32 size_of_header;
  15. UINT32 width;
  16. UINT32 hight;
  17. UINT16 num_of_color_plane;
  18. UINT16 num_of_bit_per_pix;
  19. UINT32 compression;
  20. UINT32 size_of_pix_data;
  21. UINT32 h_resolution;
  22. UINT32 v_resolution;
  23. UINT32 num_of_color_in_palette;
  24. UINT32 important_colors;
  25. };
  26. #pragma pack(pop)
  27. void BitmapWriter::rawPixelsToBMP(const UINT8* input, UINT8* output, UINT32 width, UINT32 height, UINT32 bytesPerPixel)
  28. {
  29. UINT16 bmpBytesPerPixel = 3;
  30. if(bytesPerPixel >= 4)
  31. bmpBytesPerPixel = 4;
  32. UINT32 padding = (width * bmpBytesPerPixel) % 4;
  33. if(padding != 0)
  34. padding = 4 - padding;
  35. UINT32 rowPitch = (width * bmpBytesPerPixel) + padding;
  36. UINT32 dataSize = height * rowPitch;
  37. BMP_HEADER header;
  38. header.BM = 0x4d42;
  39. header.size_of_file = sizeof(header) + dataSize;
  40. header.reserve = 0000;
  41. header.offset_of_pixel_data = 54;
  42. header.size_of_header = 40;
  43. header.width = width;
  44. header.hight = height;
  45. header.num_of_color_plane = 1;
  46. header.num_of_bit_per_pix = bmpBytesPerPixel * 8;
  47. header.compression = 0;
  48. header.size_of_pix_data = dataSize;
  49. header.h_resolution = 2835;
  50. header.v_resolution = 2835;
  51. header.num_of_color_in_palette = 0;
  52. header.important_colors = 0;
  53. // Write header
  54. memcpy(output, &header, sizeof(header));
  55. output += sizeof(header);
  56. // Write bytes
  57. UINT32 widthBytes = width * bytesPerPixel;
  58. // BPP matches so we can just copy directly
  59. if(bmpBytesPerPixel == bytesPerPixel)
  60. {
  61. for(INT32 y = height - 1; y >= 0 ; y--)
  62. {
  63. UINT8* outputPtr = output + y * rowPitch;
  64. memcpy(outputPtr, input, widthBytes);
  65. memset(outputPtr + widthBytes, 0, padding);
  66. input += widthBytes;
  67. }
  68. }
  69. else if(bmpBytesPerPixel < bytesPerPixel) // More bytes in source than supported in BMP, just truncate excess data
  70. {
  71. for(INT32 y = height - 1; y >= 0 ; y--)
  72. {
  73. UINT8* outputPtr = output + y * rowPitch;
  74. for(UINT32 x = 0; x < width; x++)
  75. {
  76. memcpy(outputPtr, input, bmpBytesPerPixel);
  77. outputPtr += bmpBytesPerPixel;
  78. input += bytesPerPixel;
  79. }
  80. memset(outputPtr, 0, padding);
  81. }
  82. }
  83. else // More bytes in BMP than in source (BMP must be 24bit minimum)
  84. {
  85. for(INT32 y = height - 1; y >= 0 ; y--)
  86. {
  87. UINT8* outputPtr = output + y * rowPitch;
  88. for(UINT32 x = 0; x < width; x++)
  89. {
  90. memcpy(outputPtr, input, bytesPerPixel);
  91. // Fill the empty bytes with the last available byte from input
  92. UINT32 remainingBytes = bmpBytesPerPixel - bytesPerPixel;
  93. while(remainingBytes > 0)
  94. {
  95. memcpy(outputPtr + (bmpBytesPerPixel - remainingBytes), input, 1);
  96. remainingBytes--;
  97. }
  98. outputPtr += bmpBytesPerPixel;
  99. input += bytesPerPixel;
  100. }
  101. memset(outputPtr, 0, padding);
  102. }
  103. }
  104. }
  105. UINT32 BitmapWriter::getBMPSize(UINT32 width, UINT32 height, UINT32 bytesPerPixel)
  106. {
  107. UINT16 bmpBytesPerPixel = 3;
  108. if(bytesPerPixel >= 4)
  109. bmpBytesPerPixel = 4;
  110. UINT32 padding = (width * bmpBytesPerPixel) % 4;
  111. if(padding != 0)
  112. padding = 4 - padding;
  113. UINT32 rowPitch = (width * bmpBytesPerPixel) + padding;
  114. UINT32 dataSize = height * rowPitch;
  115. return sizeof(BMP_HEADER) + dataSize;
  116. }
  117. }