# bmp.cc

Go to the documentation of this file.

    00001 ///
    00002 /// \file       bmp.cc
    00003 ///             BMP conversion routines
    00004 ///
    00005
    00006 /*
    00007     Copyright (C) 2009-2011, Net Direct Inc. (http://www.netdirect.ca/)
    00008     Copyright (C) 2008-2009, Nicolas VIVIEN
    00009
    00010     This program is free software; you can redistribute it and/or modify
    00011     it under the terms of the GNU General Public License as published by
    00012     the Free Software Foundation; either version 2 of the License, or
    00013     (at your option) any later version.
    00014
    00015     This program is distributed in the hope that it will be useful,
    00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00018
    00019     See the GNU General Public License in the COPYING file at the
    00020     root directory of this project for more details.
    00021 */
    00022
    00023 #include "bmp.h"
    00024 #include "bmp-internal.h"
    00025 #include "error.h"
    00026 #include "endian.h"
    00027
    00028 namespace Barry {
    00029
    00030 //
    00031 // GetTotalBitmapSize
    00032 //
    00033 /// Returns the total number of bytes needed to convert a
    00034 /// screenshot of the given dimensions into a bitmap,
    00035 /// using the ScreenshotToBitmap() function.
    00036 ///
    00037 BXEXPORT size_t GetTotalBitmapSize(const JLScreenInfo &info)
    00038 {
    00039         return sizeof(bmp_file_header_t) +
    00040                 sizeof(bmp_info_header_t) +
    00041                 (info.width * info.height * 4); // 4 byte RGB per pixel
    00042
    00043 }
    00044
    00045 //
    00046 // ScreenshotToBitmap
    00047 //
    00048 /// Converts screenshot data obtained via JavaLoader::GetScreenshot()
    00049 /// into uncompressed bitmap format, suitable for writing BMP files.
    00050 /// Arguments info and screenshot come from GetScreenshot() and the
    00051 /// converted data is stored in bitmap.
    00052 ///
    00053 //
    00054 // This function assumes that the btoh() converter functions match
    00055 // the needs of the bitmap file format.  Namely: little endian.
    00056 //
    00057 BXEXPORT void ScreenshotToBitmap(const JLScreenInfo &info,
    00058                                  const Data &screenshot,
    00059                                  Data &bitmap)
    00060 {
    00061         // Read screen info
    00062         size_t width = info.width;
    00063         size_t height = info.height;
    00064         size_t total_bitmap_size = GetTotalBitmapSize(info);
    00065
    00066         // make sure there is enough screeshot pixel data for the
    00067         // given width and height
    00068         if( screenshot.GetSize() < (width * height * 2) ) // 2 byte screenshot pixel data
    00069                 throw Error("Screenshot data size is too small for given width+height");
    00070
    00071
    00072         // setup write pointer
    00073         unsigned char *write = bitmap.GetBuffer(total_bitmap_size);
    00074
    00075         //
    00076         // Build header BMP file
    00077         //
    00078         bmp_file_header_t *fileheader = (bmp_file_header_t*) write;
    00079         write += sizeof(bmp_file_header_t);
    00080
    00081         // BMP
    00082         fileheader->bfType[0] = 'B';
    00083         fileheader->bfType[1] = 'M';
    00084
    00085         // Size of file
    00086         fileheader->bfSize = btohl(total_bitmap_size);
    00087
    00088         // Always 0x00
    00089         fileheader->bfReserved1 = 0;
    00090         fileheader->bfReserved2 = 0;
    00091
    00092         // Offset to find the data
    00093         fileheader->bfOffBits = btohl(sizeof(bmp_file_header_t) + sizeof(bmp_info_header_t));
    00094
    00095
    00096         //
    00097         // Build info BMP file
    00098         //
    00099         bmp_info_header_t *infoheader = (bmp_info_header_t*) write;
    00100         write += sizeof(bmp_info_header_t);
    00101
    00102         // Size of info section
    00103         infoheader->biSize = btohl(sizeof(bmp_info_header_t));
    00104
    00105         // Width x Height
    00106         infoheader->biWidth = btohl(width);
    00107         infoheader->biHeight = btohl(height);
    00108
    00109         // Planes number
    00110         infoheader->biPlanes = btohs(0x01);
    00111
    00112         // Bit count
    00113         infoheader->biBitCount = btohs(0x20);
    00114
    00115         // Compression : No
    00116         infoheader->biCompression = 0;
    00117
    00118         // Size of image
    00119         infoheader->biSizeImage = btohl(4 * width * height);
    00120
    00121         // Pels Per Meter
    00122         infoheader->biXPelsPerMeter = 0;
    00123         infoheader->biYPelsPerMeter = 0;
    00124
    00125         // Color palette used : None
    00126         infoheader->biClrUsed = 0;
    00127
    00128         // Color palette important : None
    00129         infoheader->biClrImportant = 0;
    00130
    00131
    00132         // I work with 2 bytes (see the pixel format)
    00133         const uint16_t *data = (const uint16_t*) screenshot.GetData();
    00134         size_t pixel_count = width * height;
    00135
    00136         // For each pixel... (note BMP format is up and backwards, hence
    00137         // offset calculation for each pixel in for loop)
    00138         for (size_t j=0; j<height; j++) {
    00139                 for (size_t i=0; i<width; i++) {
    00140                         // Read one pixel in the picture
    00141                         short value = data[(pixel_count - 1) - ((width-1 - i) + (width * j))];
    00142
    00143                         // Pixel format used by the handheld is : 16 bits
    00144                         // MSB < .... .... .... .... > LSB
    00145                         //                    ^^^^^^ : Blue (between 0x00 and 0x1F)
    00146                         //             ^^^^^^^ : Green (between 0x00 and 0x3F)
    00147                         //       ^^^^^^ : Red (between 0x00 and 0x1F)
    00148
    00149                         write[3] = 0x00;                                        // alpha
    00150                         write[2] = (((value >> 11) & 0x1F) * 0xFF) / 0x1F;      // red
    00151                         write[1] = (((value >> 5) & 0x3F) * 0xFF) / 0x3F;       // green
    00152                         write[0] = ((value & 0x1F) * 0xFF) / 0x1F;              // blue
    00153
    00154                         write += 4;
    00155                 }
    00156         }
    00157
    00158         bitmap.ReleaseBuffer(total_bitmap_size);
    00159 }
    00160
    00161 } // namespace Barry
    00162