1 #ifndef _POINTSTOBITMAP_H
2 #define _POINTSTOBITMAP_H
7 * Map vector of points onto a Bitmap
8 * Because it was easier than working out the OpenGL stuff right now
9 * Points will be mapped according to the bounding rectangle.
10 * Should probably deal with possible aspect ratio difference... or just make sure to always use a square I guess
12 template <class T> void PointsToBitmap(const vector<pair<T, T> > & points, const T & scale = 1, uint8_t r = 0, uint8_t g = 0, uint8_t b = 0, const char * filename = "bezier.bmp", bool overlay = false, uint64_t width = 400, uint64_t height = 400)
15 int ri = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? 0 : 3;
16 int gi = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? 1 : 2;
17 int bi = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? 2 : 1;
18 //int ai = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? 3 : 0; // No alpha in BMP
21 unsigned char * pixels = new unsigned char[width*height*4];
23 // Overlay indicates we should load the bitmap into the pixel buffer first
26 SDL_Surface * bmp = SDL_LoadBMP(filename);
29 overlay = false; // bmp (probably) doesn't exist -> not an error (we hope)
35 for (int i = 0; i < width*height*(bmp->format->BytesPerPixel); ++i)
37 // We're assuming the BMP was stored in the same Byteorder as we will save it
38 pixels[i] = *((unsigned char*)(bmp->pixels)+i);
44 for (int i = 0; i < width*height*4; ++i)
45 pixels[i] = 0xFF; // White pixels
49 typedef long double LD; // The temporary typedef, an underappreciated technique...
51 // Named lambdas... this is getting worrying...
52 auto lessx = [](const pair<T, T> & a, const pair<T, T> & b){return (a.first < b.first);};
53 auto lessy = [](const pair<T, T> & a, const pair<T, T> & b){return (a.second < b.second);};
55 // So I don't have to type as much here
56 pair<T,T> left = *min_element(points.begin(), points.end(), lessx);
57 pair<T,T> right = *max_element(points.begin(), points.end(), lessx);
58 pair<T,T> bottom = *min_element(points.begin(), points.end(), lessy);
59 pair<T,T> top = *max_element(points.begin(), points.end(),lessy);
61 pair<LD,LD> min(left.first, bottom.second);
62 pair<LD,LD> max(right.first, top.second);
64 // Alternately, just do this:
66 pair<LD,LD> min(-scale, -scale);
67 pair<LD,LD> max(scale, scale);
70 // Map each point to a pixel position
71 for (auto i = 0; i < points.size(); ++i)
73 // Do maths with long double; this way any artefacts are more likely due to the creation of the bezier itself than this mapping operation
74 uint64_t x = llround(((LD)(points[i].first) - (LD)(min.first)) * (LD)(width-1)/((LD)max.first - (LD)min.first));
75 uint64_t y = llround(((LD)(points[i].second) - (LD)(min.second)) * (LD)(height-1)/((LD)max.second - (LD)min.second));
76 int index = 4*(y*width + x); // Get index into pixel array
83 // Truly a thing of beauty
84 SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(pixels, width, height, 8*4, width*4,
85 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
86 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
88 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
89 #endif //SDL_BYTEORDER
93 Fatal("SDL_CreateRGBSurfaceFrom(pixels...) failed - %s", SDL_GetError());
94 if (SDL_SaveBMP(surf, filename) != 0)
95 Fatal("SDL_SaveBMP failed - %s", SDL_GetError());
98 SDL_FreeSurface(surf);
102 #endif //_POINTSTOBITMAP_H