Advertisement
stgatilov

LoadBMP.h+cpp code

Aug 1st, 2015
578
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.28 KB | None | 0 0
  1. #ifndef LOAD_BITMAP_123574
  2. #define LOAD_BITMAP_123574
  3.  
  4. struct Bitmap {
  5.     int bpp;        //must be 24 or 32
  6.     int height, width;
  7.     unsigned char *buffer;
  8.  
  9.     inline Bitmap() : buffer(0), bpp(0), width(0), height(0) {}
  10.     inline Bitmap(int _bpp, int _height, int _width) : buffer(0), bpp(_bpp), width(_width), height(_height) {}
  11.     inline void alloc() { buffer = new unsigned char[4 * pixels()]; }
  12.     inline int pixels() const { return height * width; }
  13.     inline int size() const { return pixels() * (bpp/8); }
  14. };
  15.  
  16. void SetBitsPerPixel(Bitmap &bitmap, int dst_bpp);
  17.  
  18. Bitmap LoadBMP(const char *name, int dst_bpp = 32);
  19. void SaveBMP(const Bitmap &bitmap, const char *name, int dst_bpp = 24);
  20. const Bitmap CreateOnePixelBitmap(double r, double g, double b);
  21. inline const Bitmap CreateOnePixelBitmap(double l) { return CreateOnePixelBitmap(l, l, l); }
  22.  
  23. void CopyBuffer(const Bitmap &bmp, unsigned char *dst);
  24. void ExtractSubImageFast(const Bitmap &bmp, int r, int c, int h, int w, Bitmap &ret);
  25. const Bitmap ExtractSubImage(const Bitmap &bmp, int r, int c, int h, int w);
  26. void InsertSubImage(Bitmap &bmp, int r, int c, const Bitmap &sub);
  27. const Bitmap Downscale(const Bitmap &src, int dh, int dw);
  28.  
  29. #include <stdio.h>
  30. #include <assert.h>
  31. #include <string.h>
  32. #include <algorithm>
  33. #include "loadbmp.h"
  34.  
  35. typedef unsigned char byte;
  36.  
  37. //Scaling picture, working with subpicture
  38.  
  39. void CopyBuffer(const Bitmap &bmp, unsigned char *dst) {
  40.     memcpy(dst, bmp.buffer, bmp.size());
  41. }
  42.  
  43. void ExtractSubImageFast(const Bitmap &bmp, int r, int c, int h, int w, Bitmap &ret) {
  44.     if (!ret.buffer) {
  45.         ret = ExtractSubImage(bmp, r, c, h, w);
  46.         return;
  47.     }
  48.  
  49.     byte *dst = ret.buffer;
  50.     int PLANES = (bmp.bpp>>3);
  51.     for (int i = r; i<r+h; i++) {
  52.         const byte *line = bmp.buffer + (PLANES*bmp.width) * i;
  53.         memcpy(dst, line + PLANES*c, PLANES*w);
  54.         dst += PLANES*w;
  55.     }
  56. }
  57.  
  58. const Bitmap ExtractSubImage(const Bitmap &bmp, int r, int c, int h, int w) {
  59.     assert(bmp.buffer);
  60.     assert(r>=0 && c>=0 && r+h <= bmp.height && c+w <= bmp.width);
  61.     Bitmap ret(bmp.bpp, h, w);
  62.     ret.alloc();
  63.     ExtractSubImageFast(bmp, r, c, h, w, ret);
  64.     return ret;
  65. }
  66.  
  67. void InsertSubImage(Bitmap &bmp, int r, int c, const Bitmap &sub) {
  68.     int h = sub.height;
  69.     int w = sub.width;
  70.     assert(bmp.buffer && sub.buffer);
  71.     assert(r>=0 && c>=0 && r+h <= bmp.height && c+w <= bmp.width);
  72.     const byte *src = sub.buffer;
  73.  
  74.     int PLANES = bmp.bpp / 8;
  75.     for (int i = r; i<r+h; i++) {
  76.         byte *line = bmp.buffer + (PLANES*bmp.width) * i;
  77.         memcpy(line + PLANES*c, src, PLANES*w);
  78.         src += PLANES*w;
  79.     }
  80. }
  81.  
  82. const Bitmap Downscale(const Bitmap &src, int dh, int dw) {
  83.     assert(src.buffer);
  84.     Bitmap dst(src.bpp, (src.height + dh-1) / dh, (src.width + dw-1) / dw);
  85.     dst.alloc();
  86.  
  87.     int PLANES = src.bpp / 8;
  88.     for (int i = 0; i<dst.height; i++)
  89.         for (int j = 0; j<dst.width; j++) {
  90.             int sum[4];
  91.             memset(sum, 0, sizeof(sum));
  92.             int cnt = 0;
  93.             for (int u = dh*i; u<std::min(dh*(i+1), src.height); u++)
  94.                 for (int v = dw*j; v<std::min(dw*(j+1), src.width); v++) {
  95.                     cnt++;
  96.                     const byte *pixel = src.buffer + PLANES * (u * src.width + v);
  97.                     for (int t = 0; t<PLANES; t++) sum[t] += pixel[t];
  98.                 }
  99.             byte *pixel = dst.buffer + PLANES * (i*dst.width + j);
  100.             for (int t = 0; t<PLANES; t++) pixel[t] = byte(double(sum[t])/cnt + 0.5);
  101.         }
  102.     return dst;
  103. }
  104.  
  105. //Managing different BPPs
  106. void CutAlpha(Bitmap &bmp) {
  107.     int sz = bmp.pixels() * 3;
  108.     byte *src = bmp.buffer;
  109.     byte *dst = new byte[sz];
  110.     for (int i = 0; i<bmp.pixels(); i++) {
  111.         *(dst++) = *(src++);
  112.         *(dst++) = *(src++);
  113.         *(dst++) = *(src++);
  114.         src++;
  115.     }
  116.     dst -= sz;
  117.     memcpy(bmp.buffer, dst, sz);
  118.     delete dst;
  119.     bmp.bpp = 24;
  120. }
  121.  
  122. void AddAlpha(Bitmap &bmp) {
  123.     int sz = bmp.pixels() * 4;
  124.     byte *src = bmp.buffer;
  125.     byte *dst = new byte[sz];
  126.     for (int i = 0; i<bmp.pixels(); i++) {
  127.         *(dst++) = *(src++);
  128.         *(dst++) = *(src++);
  129.         *(dst++) = *(src++);
  130.         *(dst++) = 255;
  131.     }
  132.     dst -= sz;
  133.     memcpy(bmp.buffer, dst, sz);
  134.     delete dst;
  135.     bmp.bpp = 32;
  136. }
  137.  
  138. void SetBitsPerPixel(Bitmap &bitmap, int dst_bpp) {
  139.     assert(dst_bpp == 24 || dst_bpp == 32);
  140.     assert(bitmap.buffer);
  141.     if (dst_bpp == bitmap.bpp) return;
  142.     if (dst_bpp == 32) AddAlpha(bitmap);
  143.     if (dst_bpp == 24) CutAlpha(bitmap);
  144. }
  145.  
  146. const Bitmap CreateOnePixelBitmap(double r, double g, double b) {
  147.     Bitmap bmp(24, 1, 1);
  148.     bmp.alloc();
  149.     bmp.buffer[0] = byte(r*255.0);
  150.     bmp.buffer[1] = byte(g*255.0);
  151.     bmp.buffer[2] = byte(b*255.0);
  152.     return bmp;
  153. }
  154.  
  155. //      Loading/Saving .bmp
  156. #pragma pack(push, 1)
  157. __declspec(align(1)) struct BMPHeader {
  158.     char id[2];
  159.     unsigned long fileSize;
  160.     unsigned long reserved0;
  161.     unsigned long bitmapDataOffset;
  162.     unsigned long bitmapHeaderSize;
  163.     unsigned long width;
  164.     unsigned long height;
  165.     unsigned short planes;
  166.     unsigned short bitsPerPixel;
  167.     unsigned long compression;
  168.     unsigned long bitmapDataSize;
  169.     unsigned long hRes;
  170.     unsigned long vRes;
  171.     unsigned long colors;
  172.     unsigned long importantColors;
  173.     unsigned char palette[256][4];
  174. };
  175.  
  176. #pragma pack(pop)
  177. inline bool isPowerOfTwo(int x) {
  178.     return !(x & (x-1));
  179. }
  180. inline int stuff4(int x) {
  181.     return (x+3)/4*4 - x;
  182. }
  183. int LittleLong(int c) {
  184.     return c;
  185. }
  186. short LittleShort(short c) {
  187.     return c;
  188. }
  189.  
  190. Bitmap LoadBMP(const char *name, int dst_bpp) {
  191.     int     columns, rows, numPixels;
  192.     byte    *pixbuf;
  193.     int     row, column;
  194.     byte    *buf_p;
  195.     byte    *buffer;
  196.     int     length;
  197.     BMPHeader bmpHeader;
  198.     byte        *bmpRGBA;
  199.     Bitmap ret;
  200.  
  201.     FILE *bmpfile = fopen(name, "rb");
  202.     assert(bmpfile);
  203.     fseek(bmpfile, 0, SEEK_END);
  204.     length = ftell(bmpfile);
  205.     fseek(bmpfile, 0, SEEK_SET);
  206.     buffer = new byte[length];
  207.     fread(buffer, 1, length, bmpfile);
  208.     fclose(bmpfile);
  209.  
  210.     buf_p = buffer;
  211.  
  212.     bmpHeader.id[0] = *buf_p++;
  213.     bmpHeader.id[1] = *buf_p++;
  214.     bmpHeader.fileSize = LittleLong( * ( long * ) buf_p );
  215.     buf_p += 4;
  216.     bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p );
  217.     buf_p += 4;
  218.     bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p );
  219.     buf_p += 4;
  220.     bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p );
  221.     buf_p += 4;
  222.     bmpHeader.width = LittleLong( * ( long * ) buf_p );
  223.     buf_p += 4;
  224.     bmpHeader.height = LittleLong( * ( long * ) buf_p );
  225.     buf_p += 4;
  226.     bmpHeader.planes = LittleShort( * ( short * ) buf_p );
  227.     buf_p += 2;
  228.     bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
  229.     buf_p += 2;
  230.     bmpHeader.compression = LittleLong( * ( long * ) buf_p );
  231.     buf_p += 4;
  232.     bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p );
  233.     buf_p += 4;
  234.     bmpHeader.hRes = LittleLong( * ( long * ) buf_p );
  235.     buf_p += 4;
  236.     bmpHeader.vRes = LittleLong( * ( long * ) buf_p );
  237.     buf_p += 4;
  238.     bmpHeader.colors = LittleLong( * ( long * ) buf_p );
  239.     buf_p += 4;
  240.     bmpHeader.importantColors = LittleLong( * ( long * ) buf_p );
  241.     buf_p += 4;
  242.  
  243.     if ( bmpHeader.bitsPerPixel == 8 ) {
  244.         memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
  245.         buf_p += 1024;
  246.     }
  247.  
  248.     assert( bmpHeader.id[0] == 'B' && bmpHeader.id[1] == 'M' );
  249.     assert( bmpHeader.fileSize == length );
  250.     assert( bmpHeader.compression == 0 );
  251.     assert( bmpHeader.bitsPerPixel >= 8 );
  252.  
  253.     columns = bmpHeader.width;
  254.     rows = bmpHeader.height;
  255.     bool revrows = false;
  256.     if ( rows < 0 ) {
  257.         rows = -rows;
  258.         revrows = true;
  259.     }
  260.     int rowshlak = stuff4(columns * (bmpHeader.bitsPerPixel / 8));
  261.     numPixels = columns * rows;
  262.  
  263.     ret.bpp = 32;
  264.     ret.width = columns;
  265.     ret.height = rows;
  266.     bmpRGBA = new byte[ numPixels * 4 ];
  267.     ret.buffer =  bmpRGBA;
  268.  
  269.     for ( row = 0; row < rows; row++ )
  270.     {
  271.         pixbuf = bmpRGBA + (revrows ? rows-1-row : row) * columns*4;
  272.  
  273.         for ( column = 0; column < columns; column++ )
  274.         {
  275.             unsigned char red, green, blue, alpha;
  276.             int palIndex;
  277.             unsigned short shortPixel;
  278.  
  279.             switch ( bmpHeader.bitsPerPixel )
  280.             {
  281.             case 8:
  282.                 palIndex = *buf_p++;
  283.                 *pixbuf++ = bmpHeader.palette[palIndex][2];
  284.                 *pixbuf++ = bmpHeader.palette[palIndex][1];
  285.                 *pixbuf++ = bmpHeader.palette[palIndex][0];
  286.                 *pixbuf++ = 0xff;
  287.                 break;
  288.             case 16:
  289.                 shortPixel = * ( unsigned short * ) buf_p;
  290.                 buf_p += 2;
  291.                 *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
  292.                 *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
  293.                 *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
  294.                 *pixbuf++ = 0xff;
  295.                 break;
  296.  
  297.             case 24:
  298.                 blue = *buf_p++;
  299.                 green = *buf_p++;
  300.                 red = *buf_p++;
  301.                 *pixbuf++ = red;
  302.                 *pixbuf++ = green;
  303.                 *pixbuf++ = blue;
  304.                 *pixbuf++ = 255;
  305.                 break;
  306.             case 32:
  307.                 blue = *buf_p++;
  308.                 green = *buf_p++;
  309.                 red = *buf_p++;
  310.                 alpha = *buf_p++;
  311.                 *pixbuf++ = red;
  312.                 *pixbuf++ = green;
  313.                 *pixbuf++ = blue;
  314.                 *pixbuf++ = alpha;
  315.                 break;
  316.             default:
  317.                 assert(0);
  318.                 break;
  319.             }
  320.         }
  321.         buf_p += rowshlak;
  322.     }
  323.     delete buffer;
  324.  
  325.     SetBitsPerPixel(ret, dst_bpp);
  326.     return ret;
  327. }
  328.  
  329. void SaveBMP(const Bitmap &bitmap, const char *name, int dst_bpp) {
  330.     assert(dst_bpp == 24 || dst_bpp == 32);
  331.     assert(bitmap.buffer);
  332.  
  333.     FILE *bmpfile = fopen(name, "wb");
  334.     assert(bmpfile);
  335.  
  336.     BMPHeader bmpHeader;
  337.     bmpHeader.id[0] = 'B';
  338.     bmpHeader.id[1] = 'M';
  339.     bmpHeader.reserved0 = 0;
  340.     bmpHeader.bitmapHeaderSize = 40;
  341.     bmpHeader.bitmapDataOffset = 14 + bmpHeader.bitmapHeaderSize;
  342.     bmpHeader.width = bitmap.width;
  343.     bmpHeader.height = bitmap.height;
  344.     bmpHeader.planes = 1;
  345.     bmpHeader.bitsPerPixel = dst_bpp;
  346.     bmpHeader.compression = 0;
  347.     bmpHeader.hRes = 0;
  348.     bmpHeader.vRes = 0;
  349.     bmpHeader.colors = 0;
  350.     bmpHeader.importantColors = 0;
  351.  
  352.     int rows = bmpHeader.height;
  353.     int columns = bmpHeader.width;
  354.     int rowshlak = stuff4(columns * (bmpHeader.bitsPerPixel / 8));
  355.     bmpHeader.bitmapDataSize = rows * (rowshlak + columns*(bmpHeader.bitsPerPixel/8));
  356.     int length = bmpHeader.fileSize = bmpHeader.bitmapDataOffset + bmpHeader.bitmapDataSize;
  357.  
  358.     byte *buffer = new byte[length];
  359.     byte *buff = buffer;
  360.     memcpy(buff, &bmpHeader, bmpHeader.bitmapDataOffset);
  361.     buff += bmpHeader.bitmapDataOffset;
  362.     byte *bmpData = bitmap.buffer;
  363.     for (int i = 0; i<rows; i++) {
  364.         byte *row = bmpData + i * (bitmap.bpp/8)*columns;
  365.         for (int j = 0; j<columns; j++) {
  366.             byte red, green, blue, alpha;
  367.  
  368.             red = *(row++);
  369.             green = (bitmap.bpp<24 ? red : *(row++));
  370.             blue = (bitmap.bpp<24 ? red : *(row++));
  371.             alpha = (bitmap.bpp<32 ? 255 : *(row++));
  372.  
  373.             *(buff++) = blue;
  374.             *(buff++) = green;
  375.             *(buff++) = red;
  376.             if (bmpHeader.bitsPerPixel == 32) *(buff++) = alpha;
  377.         }
  378.         buff += rowshlak;
  379.     }
  380.  
  381.     fwrite(buffer, 1, length, bmpfile);
  382.     fclose(bmpfile);
  383.     delete buffer;
  384. }
  385.  
  386. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement