maint: added make-yum.sh for creating yum repositories under build/
[barry/progweb.git] / src / bmp.cc
blobef564c29bfb1c5d457c9830bb35c8eabb9edbc7b
1 ///
2 /// \file bmp.cc
3 /// BMP conversion routines
4 ///
6 /*
7 Copyright (C) 2009-2011, Net Direct Inc. (http://www.netdirect.ca/)
8 Copyright (C) 2008-2009, Nicolas VIVIEN
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "bmp.h"
24 #include "bmp-internal.h"
25 #include "error.h"
26 #include "endian.h"
27 #include "data.h"
28 #include "m_javaloader.h"
30 namespace Barry {
33 // GetBitmapHeadersSize
35 /// Returns the size of the bitmap headers (both file and info headers).
36 /// You can use this as an offset into the bitmap produced by
37 /// ScreenshotToBitmap to get just the 4-byte RGB data.
38 ///
39 BXEXPORT size_t GetBitmapHeadersSize()
41 return sizeof(bmp_file_header_t) +
42 sizeof(bmp_info_header_t);
46 // GetTotalBitmapSize
48 /// Returns the total number of bytes needed to convert a
49 /// screenshot of the given dimensions into a bitmap,
50 /// using the ScreenshotToBitmap() function.
51 ///
52 BXEXPORT size_t GetTotalBitmapSize(const JLScreenInfo &info)
54 return sizeof(bmp_file_header_t) +
55 sizeof(bmp_info_header_t) +
56 (info.width * info.height * 4); // 4 byte RGB per pixel
61 // ScreenshotToRGB
63 /// Converts screenshot data obtained via JavaLoader::GetScreenshot()
64 /// into uncompressed RGB bitmap format. The results will not have
65 /// a bitmap BMP header. Data will be written to buffer, starting
66 /// at offset. The depth variable can be 24 or 32. If invert is
67 /// true, the result will be inverted, just like a BMP file; otherwise not.
68 ///
69 BXEXPORT void ScreenshotToRGB(const JLScreenInfo &info,
70 const Data &screenshot,
71 Data &buffer,
72 size_t offset,
73 int depth,
74 bool invert)
76 if( depth != 24 && depth != 32 )
77 throw Barry::Error("ScreenshotToRGB: depth must be 24 or 32");
79 size_t width = info.width;
80 size_t height = info.height;
81 size_t bytes_per_pixel = (depth == 24) ? 3 : 4;
82 size_t pixel_count = width * height;
83 size_t total_bitmap_size = pixel_count * bytes_per_pixel;
84 size_t total_buffer_size = total_bitmap_size + offset;
86 // make sure there is enough screeshot pixel data for the
87 // given width and height
88 if( screenshot.GetSize() < (pixel_count * 2) ) // 2 byte screenshot pixel data
89 throw Error("ScreenshotToRGB: Screenshot data size is too small for given width+height");
91 // setup write pointer
92 unsigned char *write = buffer.GetBuffer(total_buffer_size) + offset;
94 // I work with 2 bytes (see the pixel format)
95 const uint16_t *data = (const uint16_t*) screenshot.GetData();
97 // For each pixel... (note BMP format is up and backwards, hence
98 // offset calculation for each pixel in for loop)
99 for( size_t j = 0; j < height; j++ ) {
100 for( size_t i = 0; i < width; i++ ) {
101 // Read one pixel in the picture
102 short value;
103 if( invert )
104 value = data[(pixel_count - 1) - ((width-1 - i) + (width * j))];
105 else
106 value = data[(j * width) + i];
108 // Pixel format used by the handheld is : 16 bits
109 // MSB < .... .... .... .... > LSB
110 // ^^^^^^ : Blue (between 0x00 and 0x1F)
111 // ^^^^^^^ : Green (between 0x00 and 0x3F)
112 // ^^^^^^ : Red (between 0x00 and 0x1F)
114 if( bytes_per_pixel == 4 )
115 write[3] = 0xFF; // alpha
117 write[2] = (((value >> 11) & 0x1F) * 0xFF) / 0x1F; // red
118 write[1] = (((value >> 5) & 0x3F) * 0xFF) / 0x3F; // green
119 write[0] = ((value & 0x1F) * 0xFF) / 0x1F; // blue
121 write += bytes_per_pixel;
125 buffer.ReleaseBuffer(total_buffer_size);
129 // ScreenshotToBitmap
131 /// Converts screenshot data obtained via JavaLoader::GetScreenshot()
132 /// into uncompressed bitmap format, suitable for writing BMP files.
133 /// Arguments info and screenshot come from GetScreenshot() and the
134 /// converted data is stored in bitmap.
137 // This function assumes that the btoh() converter functions match
138 // the needs of the bitmap file format. Namely: little endian.
140 BXEXPORT void ScreenshotToBitmap(const JLScreenInfo &info,
141 const Data &screenshot,
142 Data &bitmap)
144 // Read screen info
145 size_t width = info.width;
146 size_t height = info.height;
147 size_t total_bitmap_size = GetTotalBitmapSize(info);
149 // make sure there is enough screeshot pixel data for the
150 // given width and height
151 if( screenshot.GetSize() < (width * height * 2) ) // 2 byte screenshot pixel data
152 throw Error("Screenshot data size is too small for given width+height");
155 // setup write pointer
156 unsigned char *bitbuf = bitmap.GetBuffer(total_bitmap_size);
157 unsigned char *write = bitbuf;
160 // Build header BMP file
162 bmp_file_header_t *fileheader = (bmp_file_header_t*) write;
163 write += sizeof(bmp_file_header_t);
165 // BMP
166 fileheader->bfType[0] = 'B';
167 fileheader->bfType[1] = 'M';
169 // Size of file
170 fileheader->bfSize = btohl(total_bitmap_size);
172 // Always 0x00
173 fileheader->bfReserved1 = 0;
174 fileheader->bfReserved2 = 0;
176 // Offset to find the data
177 fileheader->bfOffBits = btohl(sizeof(bmp_file_header_t) + sizeof(bmp_info_header_t));
181 // Build info BMP file
183 bmp_info_header_t *infoheader = (bmp_info_header_t*) write;
184 write += sizeof(bmp_info_header_t);
186 // Size of info section
187 infoheader->biSize = btohl(sizeof(bmp_info_header_t));
189 // Width x Height
190 infoheader->biWidth = btohl(width);
191 infoheader->biHeight = btohl(height);
193 // Planes number
194 infoheader->biPlanes = btohs(0x01);
196 // Bit count
197 infoheader->biBitCount = btohs(0x20);
199 // Compression : No
200 infoheader->biCompression = 0;
202 // Size of image
203 infoheader->biSizeImage = btohl(4 * width * height);
205 // Pels Per Meter
206 infoheader->biXPelsPerMeter = 0;
207 infoheader->biYPelsPerMeter = 0;
209 // Color palette used : None
210 infoheader->biClrUsed = 0;
212 // Color palette important : None
213 infoheader->biClrImportant = 0;
215 // Fill in the RGB data
216 ScreenshotToRGB(info, screenshot, bitmap, write - bitbuf, 32, true);
218 bitmap.ReleaseBuffer(total_bitmap_size);
221 } // namespace Barry