Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef LOAD_BITMAP_123574
- #define LOAD_BITMAP_123574
- struct Bitmap {
- int bpp; //must be 24 or 32
- int height, width;
- unsigned char *buffer;
- inline Bitmap() : buffer(0), bpp(0), width(0), height(0) {}
- inline Bitmap(int _bpp, int _height, int _width) : buffer(0), bpp(_bpp), width(_width), height(_height) {}
- inline void alloc() { buffer = new unsigned char[4 * pixels()]; }
- inline int pixels() const { return height * width; }
- inline int size() const { return pixels() * (bpp/8); }
- };
- void SetBitsPerPixel(Bitmap &bitmap, int dst_bpp);
- Bitmap LoadBMP(const char *name, int dst_bpp = 32);
- void SaveBMP(const Bitmap &bitmap, const char *name, int dst_bpp = 24);
- const Bitmap CreateOnePixelBitmap(double r, double g, double b);
- inline const Bitmap CreateOnePixelBitmap(double l) { return CreateOnePixelBitmap(l, l, l); }
- void CopyBuffer(const Bitmap &bmp, unsigned char *dst);
- void ExtractSubImageFast(const Bitmap &bmp, int r, int c, int h, int w, Bitmap &ret);
- const Bitmap ExtractSubImage(const Bitmap &bmp, int r, int c, int h, int w);
- void InsertSubImage(Bitmap &bmp, int r, int c, const Bitmap &sub);
- const Bitmap Downscale(const Bitmap &src, int dh, int dw);
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <algorithm>
- #include "loadbmp.h"
- typedef unsigned char byte;
- //Scaling picture, working with subpicture
- void CopyBuffer(const Bitmap &bmp, unsigned char *dst) {
- memcpy(dst, bmp.buffer, bmp.size());
- }
- void ExtractSubImageFast(const Bitmap &bmp, int r, int c, int h, int w, Bitmap &ret) {
- if (!ret.buffer) {
- ret = ExtractSubImage(bmp, r, c, h, w);
- return;
- }
- byte *dst = ret.buffer;
- int PLANES = (bmp.bpp>>3);
- for (int i = r; i<r+h; i++) {
- const byte *line = bmp.buffer + (PLANES*bmp.width) * i;
- memcpy(dst, line + PLANES*c, PLANES*w);
- dst += PLANES*w;
- }
- }
- const Bitmap ExtractSubImage(const Bitmap &bmp, int r, int c, int h, int w) {
- assert(bmp.buffer);
- assert(r>=0 && c>=0 && r+h <= bmp.height && c+w <= bmp.width);
- Bitmap ret(bmp.bpp, h, w);
- ret.alloc();
- ExtractSubImageFast(bmp, r, c, h, w, ret);
- return ret;
- }
- void InsertSubImage(Bitmap &bmp, int r, int c, const Bitmap &sub) {
- int h = sub.height;
- int w = sub.width;
- assert(bmp.buffer && sub.buffer);
- assert(r>=0 && c>=0 && r+h <= bmp.height && c+w <= bmp.width);
- const byte *src = sub.buffer;
- int PLANES = bmp.bpp / 8;
- for (int i = r; i<r+h; i++) {
- byte *line = bmp.buffer + (PLANES*bmp.width) * i;
- memcpy(line + PLANES*c, src, PLANES*w);
- src += PLANES*w;
- }
- }
- const Bitmap Downscale(const Bitmap &src, int dh, int dw) {
- assert(src.buffer);
- Bitmap dst(src.bpp, (src.height + dh-1) / dh, (src.width + dw-1) / dw);
- dst.alloc();
- int PLANES = src.bpp / 8;
- for (int i = 0; i<dst.height; i++)
- for (int j = 0; j<dst.width; j++) {
- int sum[4];
- memset(sum, 0, sizeof(sum));
- int cnt = 0;
- for (int u = dh*i; u<std::min(dh*(i+1), src.height); u++)
- for (int v = dw*j; v<std::min(dw*(j+1), src.width); v++) {
- cnt++;
- const byte *pixel = src.buffer + PLANES * (u * src.width + v);
- for (int t = 0; t<PLANES; t++) sum[t] += pixel[t];
- }
- byte *pixel = dst.buffer + PLANES * (i*dst.width + j);
- for (int t = 0; t<PLANES; t++) pixel[t] = byte(double(sum[t])/cnt + 0.5);
- }
- return dst;
- }
- //Managing different BPPs
- void CutAlpha(Bitmap &bmp) {
- int sz = bmp.pixels() * 3;
- byte *src = bmp.buffer;
- byte *dst = new byte[sz];
- for (int i = 0; i<bmp.pixels(); i++) {
- *(dst++) = *(src++);
- *(dst++) = *(src++);
- *(dst++) = *(src++);
- src++;
- }
- dst -= sz;
- memcpy(bmp.buffer, dst, sz);
- delete dst;
- bmp.bpp = 24;
- }
- void AddAlpha(Bitmap &bmp) {
- int sz = bmp.pixels() * 4;
- byte *src = bmp.buffer;
- byte *dst = new byte[sz];
- for (int i = 0; i<bmp.pixels(); i++) {
- *(dst++) = *(src++);
- *(dst++) = *(src++);
- *(dst++) = *(src++);
- *(dst++) = 255;
- }
- dst -= sz;
- memcpy(bmp.buffer, dst, sz);
- delete dst;
- bmp.bpp = 32;
- }
- void SetBitsPerPixel(Bitmap &bitmap, int dst_bpp) {
- assert(dst_bpp == 24 || dst_bpp == 32);
- assert(bitmap.buffer);
- if (dst_bpp == bitmap.bpp) return;
- if (dst_bpp == 32) AddAlpha(bitmap);
- if (dst_bpp == 24) CutAlpha(bitmap);
- }
- const Bitmap CreateOnePixelBitmap(double r, double g, double b) {
- Bitmap bmp(24, 1, 1);
- bmp.alloc();
- bmp.buffer[0] = byte(r*255.0);
- bmp.buffer[1] = byte(g*255.0);
- bmp.buffer[2] = byte(b*255.0);
- return bmp;
- }
- // Loading/Saving .bmp
- #pragma pack(push, 1)
- __declspec(align(1)) struct BMPHeader {
- char id[2];
- unsigned long fileSize;
- unsigned long reserved0;
- unsigned long bitmapDataOffset;
- unsigned long bitmapHeaderSize;
- unsigned long width;
- unsigned long height;
- unsigned short planes;
- unsigned short bitsPerPixel;
- unsigned long compression;
- unsigned long bitmapDataSize;
- unsigned long hRes;
- unsigned long vRes;
- unsigned long colors;
- unsigned long importantColors;
- unsigned char palette[256][4];
- };
- #pragma pack(pop)
- inline bool isPowerOfTwo(int x) {
- return !(x & (x-1));
- }
- inline int stuff4(int x) {
- return (x+3)/4*4 - x;
- }
- int LittleLong(int c) {
- return c;
- }
- short LittleShort(short c) {
- return c;
- }
- Bitmap LoadBMP(const char *name, int dst_bpp) {
- int columns, rows, numPixels;
- byte *pixbuf;
- int row, column;
- byte *buf_p;
- byte *buffer;
- int length;
- BMPHeader bmpHeader;
- byte *bmpRGBA;
- Bitmap ret;
- FILE *bmpfile = fopen(name, "rb");
- assert(bmpfile);
- fseek(bmpfile, 0, SEEK_END);
- length = ftell(bmpfile);
- fseek(bmpfile, 0, SEEK_SET);
- buffer = new byte[length];
- fread(buffer, 1, length, bmpfile);
- fclose(bmpfile);
- buf_p = buffer;
- bmpHeader.id[0] = *buf_p++;
- bmpHeader.id[1] = *buf_p++;
- bmpHeader.fileSize = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.width = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.height = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.planes = LittleShort( * ( short * ) buf_p );
- buf_p += 2;
- bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
- buf_p += 2;
- bmpHeader.compression = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.hRes = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.vRes = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.colors = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- bmpHeader.importantColors = LittleLong( * ( long * ) buf_p );
- buf_p += 4;
- if ( bmpHeader.bitsPerPixel == 8 ) {
- memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
- buf_p += 1024;
- }
- assert( bmpHeader.id[0] == 'B' && bmpHeader.id[1] == 'M' );
- assert( bmpHeader.fileSize == length );
- assert( bmpHeader.compression == 0 );
- assert( bmpHeader.bitsPerPixel >= 8 );
- columns = bmpHeader.width;
- rows = bmpHeader.height;
- bool revrows = false;
- if ( rows < 0 ) {
- rows = -rows;
- revrows = true;
- }
- int rowshlak = stuff4(columns * (bmpHeader.bitsPerPixel / 8));
- numPixels = columns * rows;
- ret.bpp = 32;
- ret.width = columns;
- ret.height = rows;
- bmpRGBA = new byte[ numPixels * 4 ];
- ret.buffer = bmpRGBA;
- for ( row = 0; row < rows; row++ )
- {
- pixbuf = bmpRGBA + (revrows ? rows-1-row : row) * columns*4;
- for ( column = 0; column < columns; column++ )
- {
- unsigned char red, green, blue, alpha;
- int palIndex;
- unsigned short shortPixel;
- switch ( bmpHeader.bitsPerPixel )
- {
- case 8:
- palIndex = *buf_p++;
- *pixbuf++ = bmpHeader.palette[palIndex][2];
- *pixbuf++ = bmpHeader.palette[palIndex][1];
- *pixbuf++ = bmpHeader.palette[palIndex][0];
- *pixbuf++ = 0xff;
- break;
- case 16:
- shortPixel = * ( unsigned short * ) buf_p;
- buf_p += 2;
- *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
- *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
- *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
- *pixbuf++ = 0xff;
- break;
- case 24:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alpha = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alpha;
- break;
- default:
- assert(0);
- break;
- }
- }
- buf_p += rowshlak;
- }
- delete buffer;
- SetBitsPerPixel(ret, dst_bpp);
- return ret;
- }
- void SaveBMP(const Bitmap &bitmap, const char *name, int dst_bpp) {
- assert(dst_bpp == 24 || dst_bpp == 32);
- assert(bitmap.buffer);
- FILE *bmpfile = fopen(name, "wb");
- assert(bmpfile);
- BMPHeader bmpHeader;
- bmpHeader.id[0] = 'B';
- bmpHeader.id[1] = 'M';
- bmpHeader.reserved0 = 0;
- bmpHeader.bitmapHeaderSize = 40;
- bmpHeader.bitmapDataOffset = 14 + bmpHeader.bitmapHeaderSize;
- bmpHeader.width = bitmap.width;
- bmpHeader.height = bitmap.height;
- bmpHeader.planes = 1;
- bmpHeader.bitsPerPixel = dst_bpp;
- bmpHeader.compression = 0;
- bmpHeader.hRes = 0;
- bmpHeader.vRes = 0;
- bmpHeader.colors = 0;
- bmpHeader.importantColors = 0;
- int rows = bmpHeader.height;
- int columns = bmpHeader.width;
- int rowshlak = stuff4(columns * (bmpHeader.bitsPerPixel / 8));
- bmpHeader.bitmapDataSize = rows * (rowshlak + columns*(bmpHeader.bitsPerPixel/8));
- int length = bmpHeader.fileSize = bmpHeader.bitmapDataOffset + bmpHeader.bitmapDataSize;
- byte *buffer = new byte[length];
- byte *buff = buffer;
- memcpy(buff, &bmpHeader, bmpHeader.bitmapDataOffset);
- buff += bmpHeader.bitmapDataOffset;
- byte *bmpData = bitmap.buffer;
- for (int i = 0; i<rows; i++) {
- byte *row = bmpData + i * (bitmap.bpp/8)*columns;
- for (int j = 0; j<columns; j++) {
- byte red, green, blue, alpha;
- red = *(row++);
- green = (bitmap.bpp<24 ? red : *(row++));
- blue = (bitmap.bpp<24 ? red : *(row++));
- alpha = (bitmap.bpp<32 ? 255 : *(row++));
- *(buff++) = blue;
- *(buff++) = green;
- *(buff++) = red;
- if (bmpHeader.bitsPerPixel == 32) *(buff++) = alpha;
- }
- buff += rowshlak;
- }
- fwrite(buffer, 1, length, bmpfile);
- fclose(bmpfile);
- delete buffer;
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement