BMP.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. #pragma pack(push, 1)
  6. struct BitmapFileHeader
  7. {
  8. UShort type;
  9. UInt size, reserved, offBits;
  10. };
  11. struct BitmapInfoHeader
  12. {
  13. UInt size;
  14. Int width, height;
  15. UShort planes, bitCount;
  16. UInt compression, sizeImage;
  17. Int xPelsPerMeter, yPelsPerMeter;
  18. UInt clrUsed, clrImportant;
  19. };
  20. #pragma pack(pop)
  21. /******************************************************************************/
  22. Bool Image::ImportBMPRaw(File &f, Bool ico)
  23. {
  24. BitmapInfoHeader bmih; f>>bmih;
  25. if(Unaligned(bmih.planes)==1)
  26. if(Unaligned(bmih.bitCount)==8 || Unaligned(bmih.bitCount)==24 || Unaligned(bmih.bitCount)==32)
  27. {
  28. if(ico)Unaligned(bmih.height, Unaligned(bmih.height)/2); // ICO files have height 2x bigger
  29. MemtN<Color, 256> palette; if(Unaligned(bmih.bitCount)==8){f.getN(palette.setNum(256).data(), 256); REPA(palette)Swap(palette[i].r, palette[i].b); if(ico)REPAO(palette).a=(i ? 255 : 0);} // load palette, setup alpha for ICO
  30. if(createSoftTry(Unaligned(bmih.width), Unaligned(bmih.height), 1, (Unaligned(bmih.bitCount)==24) ? IMAGE_R8G8B8 : (Unaligned(bmih.bitCount)==32) ? IMAGE_B8G8R8A8 : ico ? IMAGE_B8G8R8A8 : IMAGE_R8G8B8)) // ICO has alpha channel, BMP uses BGRA order
  31. {
  32. Int zeros=Ceil4(pitch())-pitch();
  33. REPD(y, T.h())
  34. {
  35. switch(Unaligned(bmih.bitCount))
  36. {
  37. case 8: FREPD(x, T.w())color(x, y, palette[f.getByte()]); break;
  38. case 24: {Byte *data=T.data() + y*pitch(); f.get(data, T.w()*3); REP(T.w())Swap(data[i*3+0], data[i*3+2]);} break; // FREPD(x, T.w()){Color c; f>>c.b; f>>c.g; f>>c.r; c.a=255; color(x, y, c);}
  39. case 32: {Byte *data=T.data() + y*pitch(); f.get(data, T.w()*4); } break; // FREPD(x, T.w()){Color c; f>>c.b; f>>c.g; f>>c.r; f>>c.a ; color(x, y, c);}
  40. }
  41. f.skip(zeros);
  42. }
  43. if(f.ok())return true;
  44. }
  45. }
  46. del(); return false;
  47. }
  48. Bool Image::ImportBMP(File &f)
  49. {
  50. BitmapFileHeader bmfh; f>>bmfh;
  51. if(Unaligned(bmfh.type)==0x4D42)return ImportBMPRaw(f);
  52. del(); return false;
  53. }
  54. Bool Image::ImportBMP(C Str &name)
  55. {
  56. File f; if(f.readTry(name))return ImportBMP(f);
  57. del(); return false;
  58. }
  59. /******************************************************************************/
  60. static void GetSizeZeros(C Image &image, Byte byte_pp, Int &size, Int &zeros)
  61. {
  62. size=image.w()*byte_pp; zeros=Ceil4(size)-size;
  63. size=(size+zeros)*image.h();
  64. }
  65. Bool Image::ExportBMPRaw(File &f, Byte byte_pp, Bool ico)C // assumes that Image is locked and of accessible data
  66. {
  67. Int size, zeros; GetSizeZeros(T, byte_pp, size, zeros);
  68. Int mask_size; if(ico){mask_size=Ceil4(Ceil8(w())/8)*h(); size+=mask_size;} // include mask
  69. BitmapInfoHeader bmih;
  70. Unaligned(bmih.size , SIZEU(BitmapInfoHeader));
  71. Unaligned(bmih.width , w());
  72. Unaligned(bmih.height , ico ? h()*2 : h()); // ICO files need to have height 2x bigger
  73. _Unaligned(bmih.planes , 1);
  74. _Unaligned(bmih.bitCount , byte_pp*8);
  75. _Unaligned(bmih.compression , 0);
  76. _Unaligned(bmih.sizeImage , size);
  77. Unaligned(bmih.xPelsPerMeter, 0xB12);
  78. Unaligned(bmih.yPelsPerMeter, 0xB12);
  79. _Unaligned(bmih.clrUsed , (byte_pp==1) ? 256 : 0);
  80. _Unaligned(bmih.clrImportant , (byte_pp==1) ? 256 : 0);
  81. f<<bmih;
  82. if(byte_pp==1)FREP(256)f.putUInt(VecB4(i, i, i, 255).u); // palette
  83. REPD(y, T.h())
  84. {
  85. switch(byte_pp)
  86. {
  87. case 1:
  88. {
  89. if(bytePP()==1)f.put(data() + y*pitch(), T.w());else
  90. FREPD(x, T.w())f.putByte(FltToByte(pixelF(x, y)));
  91. }break;
  92. case 3:
  93. {
  94. if(hwType()==IMAGE_B8G8R8)f.put(data()+y*pitch(), T.w()*3);else
  95. FREPD(x, T.w()){Color c=color(x, y); Byte pixel[3]={c.b, c.g, c.r}; f<<pixel;}
  96. }break;
  97. case 4:
  98. {
  99. if(hwType()==IMAGE_B8G8R8A8)f.put(data()+y*pitch(), T.w()*4);else // BMP uses BGRA order
  100. FREPD(x, T.w()){Color c=color(x, y); Swap(c.r, c.b); f<<c;}
  101. }break;
  102. }
  103. f.put(null, zeros);
  104. }
  105. if(ico)f.put(null, mask_size);
  106. return f.ok();
  107. }
  108. Bool Image::ExportBMP(File &f)C
  109. {
  110. Image temp;
  111. C Image *src=this;
  112. IMAGE_TYPE uncompressed_type=src->type(); if(ImageTI[uncompressed_type].compressed)uncompressed_type=IMAGE_B8G8R8A8; // BMP uses BGRA order
  113. if(src->cube ()){ temp.fromCube(*src , uncompressed_type, IMAGE_SOFT ); src=&temp;}
  114. if(src->compressed()){if(src->copyTry ( temp, -1, -1, -1, uncompressed_type, IMAGE_SOFT, 1)) src=&temp;else return false;}
  115. Bool ok=false;
  116. if(src->lockRead())
  117. {
  118. Byte byte_pp=((ImageTI[T.type()].channels==1) ? 1 : ImageTI[T.type()].a ? 4 : 3); // use T.type to have precise information about source type
  119. Int size, zeros; GetSizeZeros(*src, byte_pp, size, zeros);
  120. BitmapFileHeader bmfh;
  121. _Unaligned(bmfh.type , 0x4D42);
  122. _Unaligned(bmfh.size , SIZE(BitmapFileHeader)+SIZE(BitmapInfoHeader)+((byte_pp==1) ? 256*4 : 0)+size);
  123. _Unaligned(bmfh.reserved, 0);
  124. _Unaligned(bmfh.offBits , SIZE(BitmapFileHeader)+SIZE(BitmapInfoHeader)+((byte_pp==1) ? 256*4 : 0));
  125. f<<bmfh;
  126. ok=src->ExportBMPRaw(f, byte_pp);
  127. src->unlock();
  128. }
  129. return ok;
  130. }
  131. Bool Image::ExportBMP(C Str &name)C
  132. {
  133. File f; if(f.writeTry(name)){if(ExportBMP(f) && f.flush())return true; f.del(); FDelFile(name);}
  134. return false;
  135. }
  136. /******************************************************************************/
  137. }
  138. /******************************************************************************/