1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/multimedia/t_camera_bitmap.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,291 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test/multimedia/t_camera_bitmap.cpp
1.18 +// This is a basic Windows bitmap file writer, that can be used for converting YUV422 data into
1.19 +// RGB format and dumping it to a Windows .bmp file, for manual examination.
1.20 +//
1.21 +//
1.22 +
1.23 +#include <e32test.h>
1.24 +#include <f32file.h>
1.25 +#include "t_camera_bitmap.h"
1.26 +
1.27 +#define CLIP(a) if (a < 0) a = 0; else if (a > 255) a = 255;
1.28 +
1.29 +/**
1.30 +Converts a RGB565 buffer into 24 bit RGB format in a second buffer.
1.31 +@param aDest Pointer to the buffer into which to place the 24 bit RGB data
1.32 +@param aSource Pointer to the buffer containing the RGB565 data to be converted
1.33 +@param aWidth The width of the data in the buffer in pixels
1.34 +@param aHeight The height of the data in the buffer in pixels
1.35 +*/
1.36 +void RBitmap::RGBToRGB(TUint8* aDest, TUint8* aSource, TInt aWidth, TInt aHeight)
1.37 + {
1.38 + TUint16* source = (TUint16*) aSource;
1.39 + TUint16 pixel;
1.40 +
1.41 + for (TInt y = 0; y < aHeight; ++y)
1.42 + {
1.43 + for (TInt x = 0; x < aWidth; ++x)
1.44 + {
1.45 + pixel = *source++;
1.46 + *aDest++ = (TUint8) ((pixel & 0xf800) >> 8);
1.47 + *aDest++ = (TUint8) ((pixel & 0x07e0) >> 3);
1.48 + *aDest++ = (TUint8) ((pixel & 0x001f) << 3);
1.49 + }
1.50 + }
1.51 + }
1.52 +
1.53 +/**
1.54 +Converts a YUV422 buffer into 24 bit RGB format in a second buffer.
1.55 +@param aDest Pointer to the buffer into which to place the 24 bit RGB data
1.56 +@param aSource Pointer to the buffer containing the YUV422 data to be converted
1.57 +@param aWidth The width of the data in the buffer in pixels
1.58 +@param aHeight The height of the data in the buffer in pixels
1.59 +*/
1.60 +void RBitmap::YUVToRGB(TUint8* aDest, TUint8* aSource, TInt aWidth, TInt aHeight)
1.61 + {
1.62 + TInt y, u, v, r, g, b;
1.63 +
1.64 + aDest += ((aWidth * 3) * (aHeight - 1));
1.65 +
1.66 + for (TInt l = 0; l < aHeight; ++l)
1.67 + {
1.68 + for (TInt x = 0; x < (aWidth / 2); ++x)
1.69 + {
1.70 + u = (aSource[0] - 128);
1.71 + v = (aSource[2] - 128);
1.72 + y = (aSource[3] - 16);
1.73 +
1.74 + r = ((298 * y + 409 * u) / 256);
1.75 + g = ((298 * y - 100 * v - 208 * u) / 256);
1.76 + b = ((298 * y + 516 * v) / 256);
1.77 +
1.78 + CLIP(r);
1.79 + CLIP(g);
1.80 + CLIP(b);
1.81 +
1.82 + *aDest++ = (TUint8) r;
1.83 + *aDest++ = (TUint8) g;
1.84 + *aDest++ = (TUint8) b;
1.85 +
1.86 + y = (aSource[1] - 16);
1.87 +
1.88 + r = ((298 * y + 409 * u) / 256);
1.89 + g = ((298 * y - 100 * v - 208 * u) / 256);
1.90 + b = ((298 * y + 516 * v) / 256);
1.91 +
1.92 + CLIP(r);
1.93 + CLIP(g);
1.94 + CLIP(b);
1.95 +
1.96 + *aDest++ = (TUint8) r;
1.97 + *aDest++ = (TUint8) g;
1.98 + *aDest++ = (TUint8) b;
1.99 + aSource += 4;
1.100 + }
1.101 +
1.102 + aDest -= (aWidth * 3 * 2);
1.103 + }
1.104 + }
1.105 +
1.106 +/**
1.107 +Converts a 32 bit long from whatever the host format is into little endian format in a user supplied buffer.
1.108 +@param aBuffer Pointer to the buffer into which to write the value
1.109 +@param aLong The value to be written
1.110 +*/
1.111 +void RBitmap::PutLong(TUint8* aBuffer, TInt aLong)
1.112 + {
1.113 + *aBuffer++ = (TUint8) (aLong & 0xff);
1.114 + *aBuffer++ = (TUint8) ((aLong >> 8) & 0xff);
1.115 + *aBuffer++ = (TUint8) ((aLong >> 16) & 0xff);
1.116 + *aBuffer++ = (TUint8) ((aLong >> 24) & 0xff);
1.117 + }
1.118 +
1.119 +/**
1.120 +Converts a 16 bit short from whatever the host format is into little endian format in a user supplied buffer.
1.121 +@param aBuffer Pointer to the buffer into which to write the value
1.122 +@param aShort The value to be written
1.123 +*/
1.124 +void RBitmap::PutShort(TUint8* aBuffer, TInt16 aShort)
1.125 + {
1.126 + *aBuffer++ = (TUint8) (aShort & 0xff);
1.127 + *aBuffer++ = (TUint8) ((aShort >> 8) & 0xff);
1.128 + }
1.129 +
1.130 +/**
1.131 +Writes a standard Windows .bmp header to a file, including the standard .bmp file header, followed
1.132 +by a V3 DIB header.
1.133 +@param aFile A reference to the file to which to write the header
1.134 +@param aWidth The width of the bitmap in pixels
1.135 +@param aHeight The height of the bitmap in pixels
1.136 +@return KErrNone if write was successful, otherwise one of the other system wide error codes
1.137 +*/
1.138 +TInt RBitmap::WriteHeader(RFile& aFile, TInt aWidth, TInt aHeight)
1.139 + {
1.140 + TBuf8<14> header(14);
1.141 + TUint8* buffer = (TUint8*) header.Ptr();
1.142 +
1.143 + header.Fill(0);
1.144 +
1.145 + header[0] = 'B';
1.146 + header[1] = 'M';
1.147 + PutLong((buffer + 2), (14 + 40 + (aWidth * aHeight * 3)));
1.148 + PutLong((buffer + 10), (14 + 40));
1.149 +
1.150 + TInt r = aFile.Write(header);
1.151 +
1.152 + if (r == KErrNone)
1.153 + {
1.154 + TBuf8<40> bitmapInfoHeader(40);
1.155 + TUint8* buffer = (TUint8*) bitmapInfoHeader.Ptr();
1.156 +
1.157 + bitmapInfoHeader.Fill(0);
1.158 +
1.159 + PutLong(buffer, 40);
1.160 + PutLong((buffer + 4), aWidth);
1.161 + PutLong((buffer + 8), aHeight);
1.162 + PutShort((buffer + 12), 1);
1.163 + PutShort((buffer + 14), 24);
1.164 + PutLong((buffer + 20), (aWidth * aHeight * 3));
1.165 +
1.166 + r = aFile.Write(bitmapInfoHeader);
1.167 + }
1.168 +
1.169 + return r;
1.170 + }
1.171 +
1.172 +/**
1.173 +Converts a YUV422 or RGB565 buffer into 24 bit RGB format and writes it to a file.
1.174 +@param aFile A reference to the file to which to write the data
1.175 +@param aBuffer A pointer to the buffer containing the data to be converted and written
1.176 +@param aPixelFormat UID specifying the format of the source data
1.177 +@param aWidth The width of the data in the buffer in pixels
1.178 +@param aHeight The height of the data in the buffer in pixels
1.179 +@return KErrNone if write was successful, otherwise one of the other system wide error codes
1.180 +*/
1.181 +TInt RBitmap::WriteBitmapData(RFile& aFile, TUint8* aBuffer, SDevCamPixelFormat aPixelFormat, TInt aWidth, TInt aHeight)
1.182 + {
1.183 + TInt length = (aWidth * aHeight * 3);
1.184 + TUint8* rgbBuffer = new TUint8[length];
1.185 +
1.186 + TInt r = KErrNone;
1.187 +
1.188 + if (rgbBuffer)
1.189 + {
1.190 + if (aPixelFormat.iPixelFormat == EUidPixelFormatYUV_422Interleaved)
1.191 + {
1.192 + YUVToRGB(rgbBuffer, aBuffer, aWidth, aHeight);
1.193 + }
1.194 + else if (aPixelFormat.iPixelFormat == EUidPixelFormatRGB_565)
1.195 + {
1.196 + RGBToRGB(rgbBuffer, aBuffer, aWidth, aHeight);
1.197 + }
1.198 + else
1.199 + {
1.200 + r = KErrNotSupported;
1.201 + }
1.202 +
1.203 + if (r == KErrNone)
1.204 + {
1.205 + TPtr8 buffer(rgbBuffer, length, length);
1.206 + r = aFile.Write(buffer);
1.207 + }
1.208 +
1.209 + delete [] rgbBuffer;
1.210 + }
1.211 + else
1.212 + {
1.213 + r = KErrNoMemory;
1.214 + }
1.215 +
1.216 + return r;
1.217 + }
1.218 +
1.219 +/**
1.220 +Converts a YUV422 or RGB565 buffer into 24 bit RGB format and writes it to a Windows .bmp file.
1.221 +@param aFileName A reference to the fully qualified name of the file to write the .bmp file to
1.222 +@param aBuffer A pointer to the buffer containing the data to be converted and written
1.223 +@param aPixelFormat UID specifying the format of the source data
1.224 +@param aWidth The width of the data in the buffer in pixels
1.225 +@param aHeight The height of the data in the buffer in pixels
1.226 +@return KErrNone if write was successful, otherwise one of the other system wide error codes
1.227 +*/
1.228 +TInt RBitmap::WriteBMP(const TDesC& aFileName, TUint8* aBuffer, SDevCamPixelFormat aPixelFormat, TInt aWidth, TInt aHeight)
1.229 + {
1.230 + TInt r;
1.231 + RFile file;
1.232 + RFs fs;
1.233 +
1.234 + if ((r = fs.Connect()) == KErrNone)
1.235 + {
1.236 + if ((r = file.Replace(fs, aFileName, EFileWrite)) == KErrNone)
1.237 + {
1.238 + if ((r = WriteHeader(file, aWidth, aHeight)) == KErrNone)
1.239 + {
1.240 + r = WriteBitmapData(file, aBuffer, aPixelFormat, aWidth, aHeight);
1.241 + }
1.242 +
1.243 + file.Close();
1.244 +
1.245 + // If anything went wrong, delete the file so that we do not leave partial files that
1.246 + // might cause confusion
1.247 + if (r != KErrNone)
1.248 + {
1.249 + fs.Delete(aFileName);
1.250 + }
1.251 + }
1.252 +
1.253 + fs.Close();
1.254 + }
1.255 +
1.256 + return r;
1.257 + }
1.258 +
1.259 +/**
1.260 +Dumps a buffer straight to disk, without any kind of processing.
1.261 +@param aFileName A reference to the fully qualified name of the file to write the file to
1.262 +@param aBuffer A pointer to the buffer containing the data to be converted written
1.263 +@param aSize The size of the buffer to be written, in bytes
1.264 +@return KErrNone if write was successful, otherwise one of the other system wide error codes
1.265 +*/
1.266 +TInt RBitmap::WriteBuffer(const TDesC& aFileName, TUint8* aBuffer, TInt aSize)
1.267 + {
1.268 + TInt r;
1.269 + RFile file;
1.270 + RFs fs;
1.271 +
1.272 + if ((r = fs.Connect()) == KErrNone)
1.273 + {
1.274 + if ((r = file.Replace(fs, aFileName, EFileWrite)) == KErrNone)
1.275 + {
1.276 + TPtrC8 buffer(aBuffer, aSize);
1.277 +
1.278 + r = file.Write(buffer);
1.279 +
1.280 + file.Close();
1.281 +
1.282 + // If anything went wrong, delete the file so that we do not leave partial files that
1.283 + // might cause confusion
1.284 + if (r != KErrNone)
1.285 + {
1.286 + fs.Delete(aFileName);
1.287 + }
1.288 + }
1.289 +
1.290 + fs.Close();
1.291 + }
1.292 +
1.293 + return r;
1.294 + }