1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/encoders/ico/nsICOEncoder.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,529 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsCRT.h" 1.9 +#include "mozilla/Endian.h" 1.10 +#include "nsBMPEncoder.h" 1.11 +#include "nsPNGEncoder.h" 1.12 +#include "nsICOEncoder.h" 1.13 +#include "prprf.h" 1.14 +#include "nsString.h" 1.15 +#include "nsStreamUtils.h" 1.16 +#include "nsTArray.h" 1.17 + 1.18 +using namespace mozilla; 1.19 +using namespace mozilla::image; 1.20 + 1.21 +NS_IMPL_ISUPPORTS(nsICOEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream) 1.22 + 1.23 +nsICOEncoder::nsICOEncoder() : mImageBufferStart(nullptr), 1.24 + mImageBufferCurr(0), 1.25 + mImageBufferSize(0), 1.26 + mImageBufferReadPoint(0), 1.27 + mFinished(false), 1.28 + mUsePNG(true), 1.29 + mNotifyThreshold(0) 1.30 +{ 1.31 +} 1.32 + 1.33 +nsICOEncoder::~nsICOEncoder() 1.34 +{ 1.35 + if (mImageBufferStart) { 1.36 + moz_free(mImageBufferStart); 1.37 + mImageBufferStart = nullptr; 1.38 + mImageBufferCurr = nullptr; 1.39 + } 1.40 +} 1.41 + 1.42 +// nsICOEncoder::InitFromData 1.43 +// Two output options are supported: format=<png|bmp>;bpp=<bpp_value> 1.44 +// format specifies whether to use png or bitmap format 1.45 +// bpp specifies the bits per pixel to use where bpp_value can be 24 or 32 1.46 +NS_IMETHODIMP nsICOEncoder::InitFromData(const uint8_t* aData, 1.47 + uint32_t aLength, 1.48 + uint32_t aWidth, 1.49 + uint32_t aHeight, 1.50 + uint32_t aStride, 1.51 + uint32_t aInputFormat, 1.52 + const nsAString& aOutputOptions) 1.53 +{ 1.54 + // validate input format 1.55 + if (aInputFormat != INPUT_FORMAT_RGB && 1.56 + aInputFormat != INPUT_FORMAT_RGBA && 1.57 + aInputFormat != INPUT_FORMAT_HOSTARGB) { 1.58 + return NS_ERROR_INVALID_ARG; 1.59 + } 1.60 + 1.61 + // Stride is the padded width of each row, so it better be longer 1.62 + if ((aInputFormat == INPUT_FORMAT_RGB && 1.63 + aStride < aWidth * 3) || 1.64 + ((aInputFormat == INPUT_FORMAT_RGBA || aInputFormat == INPUT_FORMAT_HOSTARGB) && 1.65 + aStride < aWidth * 4)) { 1.66 + NS_WARNING("Invalid stride for InitFromData"); 1.67 + return NS_ERROR_INVALID_ARG; 1.68 + } 1.69 + 1.70 + nsresult rv; 1.71 + rv = StartImageEncode(aWidth, aHeight, aInputFormat, aOutputOptions); 1.72 + NS_ENSURE_SUCCESS(rv, rv); 1.73 + 1.74 + rv = AddImageFrame(aData, aLength, aWidth, aHeight, aStride, 1.75 + aInputFormat, aOutputOptions); 1.76 + NS_ENSURE_SUCCESS(rv, rv); 1.77 + 1.78 + rv = EndImageEncode(); 1.79 + return rv; 1.80 +} 1.81 + 1.82 +// Returns the number of bytes in the image buffer used 1.83 +// For an ICO file, this is all bytes in the buffer. 1.84 +NS_IMETHODIMP 1.85 +nsICOEncoder::GetImageBufferUsed(uint32_t *aOutputSize) 1.86 +{ 1.87 + NS_ENSURE_ARG_POINTER(aOutputSize); 1.88 + *aOutputSize = mImageBufferSize; 1.89 + return NS_OK; 1.90 +} 1.91 + 1.92 +// Returns a pointer to the start of the image buffer 1.93 +NS_IMETHODIMP 1.94 +nsICOEncoder::GetImageBuffer(char **aOutputBuffer) 1.95 +{ 1.96 + NS_ENSURE_ARG_POINTER(aOutputBuffer); 1.97 + *aOutputBuffer = reinterpret_cast<char*>(mImageBufferStart); 1.98 + return NS_OK; 1.99 +} 1.100 + 1.101 +NS_IMETHODIMP 1.102 +nsICOEncoder::AddImageFrame(const uint8_t* aData, 1.103 + uint32_t aLength, 1.104 + uint32_t aWidth, 1.105 + uint32_t aHeight, 1.106 + uint32_t aStride, 1.107 + uint32_t aInputFormat, 1.108 + const nsAString& aFrameOptions) 1.109 +{ 1.110 + if (mUsePNG) { 1.111 + 1.112 + mContainedEncoder = new nsPNGEncoder(); 1.113 + nsresult rv; 1.114 + nsAutoString noParams; 1.115 + rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight, 1.116 + aStride, aInputFormat, noParams); 1.117 + NS_ENSURE_SUCCESS(rv, rv); 1.118 + 1.119 + uint32_t PNGImageBufferSize; 1.120 + mContainedEncoder->GetImageBufferUsed(&PNGImageBufferSize); 1.121 + mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + 1.122 + PNGImageBufferSize; 1.123 + mImageBufferStart = static_cast<uint8_t*>(moz_malloc(mImageBufferSize)); 1.124 + if (!mImageBufferStart) { 1.125 + return NS_ERROR_OUT_OF_MEMORY; 1.126 + } 1.127 + mImageBufferCurr = mImageBufferStart; 1.128 + mICODirEntry.mBytesInRes = PNGImageBufferSize; 1.129 + 1.130 + EncodeFileHeader(); 1.131 + EncodeInfoHeader(); 1.132 + 1.133 + char *imageBuffer; 1.134 + rv = mContainedEncoder->GetImageBuffer(&imageBuffer); 1.135 + NS_ENSURE_SUCCESS(rv, rv); 1.136 + memcpy(mImageBufferCurr, imageBuffer, PNGImageBufferSize); 1.137 + mImageBufferCurr += PNGImageBufferSize; 1.138 + } else { 1.139 + mContainedEncoder = new nsBMPEncoder(); 1.140 + nsresult rv; 1.141 + 1.142 + nsAutoString params; 1.143 + params.AppendLiteral("bpp="); 1.144 + params.AppendInt(mICODirEntry.mBitCount); 1.145 + 1.146 + rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight, 1.147 + aStride, aInputFormat, params); 1.148 + NS_ENSURE_SUCCESS(rv, rv); 1.149 + 1.150 + uint32_t andMaskSize = ((GetRealWidth() + 31) / 32) * 4 * // row AND mask 1.151 + GetRealHeight(); // num rows 1.152 + 1.153 + uint32_t BMPImageBufferSize; 1.154 + mContainedEncoder->GetImageBufferUsed(&BMPImageBufferSize); 1.155 + mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + 1.156 + BMPImageBufferSize + andMaskSize; 1.157 + mImageBufferStart = static_cast<uint8_t*>(moz_malloc(mImageBufferSize)); 1.158 + if (!mImageBufferStart) { 1.159 + return NS_ERROR_OUT_OF_MEMORY; 1.160 + } 1.161 + mImageBufferCurr = mImageBufferStart; 1.162 + 1.163 + // The icon buffer does not include the BFH at all. 1.164 + mICODirEntry.mBytesInRes = BMPImageBufferSize - BFH_LENGTH + andMaskSize; 1.165 + 1.166 + // Encode the icon headers 1.167 + EncodeFileHeader(); 1.168 + EncodeInfoHeader(); 1.169 + 1.170 + char *imageBuffer; 1.171 + rv = mContainedEncoder->GetImageBuffer(&imageBuffer); 1.172 + NS_ENSURE_SUCCESS(rv, rv); 1.173 + memcpy(mImageBufferCurr, imageBuffer + BFH_LENGTH, 1.174 + BMPImageBufferSize - BFH_LENGTH); 1.175 + // We need to fix the BMP height to be *2 for the AND mask 1.176 + uint32_t fixedHeight = GetRealHeight() * 2; 1.177 + NativeEndian::swapToLittleEndianInPlace(&fixedHeight, 1); 1.178 + // The height is stored at an offset of 8 from the DIB header 1.179 + memcpy(mImageBufferCurr + 8, &fixedHeight, sizeof(fixedHeight)); 1.180 + mImageBufferCurr += BMPImageBufferSize - BFH_LENGTH; 1.181 + 1.182 + // Calculate rowsize in DWORD's 1.183 + uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up 1.184 + int32_t currentLine = GetRealHeight(); 1.185 + 1.186 + // Write out the AND mask 1.187 + while (currentLine > 0) { 1.188 + currentLine--; 1.189 + uint8_t* encoded = mImageBufferCurr + currentLine * rowSize; 1.190 + uint8_t* encodedEnd = encoded + rowSize; 1.191 + while (encoded != encodedEnd) { 1.192 + *encoded = 0; // make everything visible 1.193 + encoded++; 1.194 + } 1.195 + } 1.196 + 1.197 + mImageBufferCurr += andMaskSize; 1.198 + } 1.199 + 1.200 + return NS_OK; 1.201 +} 1.202 + 1.203 +// See ::InitFromData for other info. 1.204 +NS_IMETHODIMP nsICOEncoder::StartImageEncode(uint32_t aWidth, 1.205 + uint32_t aHeight, 1.206 + uint32_t aInputFormat, 1.207 + const nsAString& aOutputOptions) 1.208 +{ 1.209 + // can't initialize more than once 1.210 + if (mImageBufferStart || mImageBufferCurr) { 1.211 + return NS_ERROR_ALREADY_INITIALIZED; 1.212 + } 1.213 + 1.214 + // validate input format 1.215 + if (aInputFormat != INPUT_FORMAT_RGB && 1.216 + aInputFormat != INPUT_FORMAT_RGBA && 1.217 + aInputFormat != INPUT_FORMAT_HOSTARGB) { 1.218 + return NS_ERROR_INVALID_ARG; 1.219 + } 1.220 + 1.221 + // Icons are only 1 byte, so make sure our bitmap is in range 1.222 + if (aWidth > 256 || aHeight > 256) { 1.223 + return NS_ERROR_INVALID_ARG; 1.224 + } 1.225 + 1.226 + // parse and check any provided output options 1.227 + uint32_t bpp = 24; 1.228 + bool usePNG = true; 1.229 + nsresult rv = ParseOptions(aOutputOptions, &bpp, &usePNG); 1.230 + NS_ENSURE_SUCCESS(rv, rv); 1.231 + 1.232 + mUsePNG = usePNG; 1.233 + 1.234 + InitFileHeader(); 1.235 + // The width and height are stored as 0 when we have a value of 256 1.236 + InitInfoHeader(bpp, aWidth == 256 ? 0 : (uint8_t)aWidth, 1.237 + aHeight == 256 ? 0 : (uint8_t)aHeight); 1.238 + 1.239 + return NS_OK; 1.240 +} 1.241 + 1.242 +NS_IMETHODIMP nsICOEncoder::EndImageEncode() 1.243 +{ 1.244 + // must be initialized 1.245 + if (!mImageBufferStart || !mImageBufferCurr) { 1.246 + return NS_ERROR_NOT_INITIALIZED; 1.247 + } 1.248 + 1.249 + mFinished = true; 1.250 + NotifyListener(); 1.251 + 1.252 + // if output callback can't get enough memory, it will free our buffer 1.253 + if (!mImageBufferStart || !mImageBufferCurr) { 1.254 + return NS_ERROR_OUT_OF_MEMORY; 1.255 + } 1.256 + 1.257 + return NS_OK; 1.258 +} 1.259 + 1.260 +// Parses the encoder options and sets the bits per pixel to use and PNG or BMP 1.261 +// See InitFromData for a description of the parse options 1.262 +nsresult 1.263 +nsICOEncoder::ParseOptions(const nsAString& aOptions, uint32_t* bpp, 1.264 + bool *usePNG) 1.265 +{ 1.266 + // If no parsing options just use the default of 24BPP and PNG yes 1.267 + if (aOptions.Length() == 0) { 1.268 + if (usePNG) { 1.269 + *usePNG = true; 1.270 + } 1.271 + if (bpp) { 1.272 + *bpp = 24; 1.273 + } 1.274 + } 1.275 + 1.276 + // Parse the input string into a set of name/value pairs. 1.277 + // From format: format=<png|bmp>;bpp=<bpp_value> 1.278 + // to format: [0] = format=<png|bmp>, [1] = bpp=<bpp_value> 1.279 + nsTArray<nsCString> nameValuePairs; 1.280 + if (!ParseString(NS_ConvertUTF16toUTF8(aOptions), ';', nameValuePairs)) { 1.281 + return NS_ERROR_INVALID_ARG; 1.282 + } 1.283 + 1.284 + // For each name/value pair in the set 1.285 + for (unsigned i = 0; i < nameValuePairs.Length(); ++i) { 1.286 + 1.287 + // Split the name value pair [0] = name, [1] = value 1.288 + nsTArray<nsCString> nameValuePair; 1.289 + if (!ParseString(nameValuePairs[i], '=', nameValuePair)) { 1.290 + return NS_ERROR_INVALID_ARG; 1.291 + } 1.292 + if (nameValuePair.Length() != 2) { 1.293 + return NS_ERROR_INVALID_ARG; 1.294 + } 1.295 + 1.296 + // Parse the format portion of the string format=<png|bmp>;bpp=<bpp_value> 1.297 + if (nameValuePair[0].Equals("format", nsCaseInsensitiveCStringComparator())) { 1.298 + if (nameValuePair[1].Equals("png", nsCaseInsensitiveCStringComparator())) { 1.299 + *usePNG = true; 1.300 + } 1.301 + else if (nameValuePair[1].Equals("bmp", nsCaseInsensitiveCStringComparator())) { 1.302 + *usePNG = false; 1.303 + } 1.304 + else { 1.305 + return NS_ERROR_INVALID_ARG; 1.306 + } 1.307 + } 1.308 + 1.309 + // Parse the bpp portion of the string format=<png|bmp>;bpp=<bpp_value> 1.310 + if (nameValuePair[0].Equals("bpp", nsCaseInsensitiveCStringComparator())) { 1.311 + if (nameValuePair[1].Equals("24")) { 1.312 + *bpp = 24; 1.313 + } 1.314 + else if (nameValuePair[1].Equals("32")) { 1.315 + *bpp = 32; 1.316 + } 1.317 + else { 1.318 + return NS_ERROR_INVALID_ARG; 1.319 + } 1.320 + } 1.321 + } 1.322 + 1.323 + return NS_OK; 1.324 +} 1.325 + 1.326 +NS_IMETHODIMP nsICOEncoder::Close() 1.327 +{ 1.328 + if (mImageBufferStart) { 1.329 + moz_free(mImageBufferStart); 1.330 + mImageBufferStart = nullptr; 1.331 + mImageBufferSize = 0; 1.332 + mImageBufferReadPoint = 0; 1.333 + mImageBufferCurr = nullptr; 1.334 + } 1.335 + 1.336 + return NS_OK; 1.337 +} 1.338 + 1.339 +// Obtains the available bytes to read 1.340 +NS_IMETHODIMP nsICOEncoder::Available(uint64_t *_retval) 1.341 +{ 1.342 + if (!mImageBufferStart || !mImageBufferCurr) { 1.343 + return NS_BASE_STREAM_CLOSED; 1.344 + } 1.345 + 1.346 + *_retval = GetCurrentImageBufferOffset() - mImageBufferReadPoint; 1.347 + return NS_OK; 1.348 +} 1.349 + 1.350 +// [noscript] Reads bytes which are available 1.351 +NS_IMETHODIMP nsICOEncoder::Read(char *aBuf, uint32_t aCount, 1.352 + uint32_t *_retval) 1.353 +{ 1.354 + return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval); 1.355 +} 1.356 + 1.357 +// [noscript] Reads segments 1.358 +NS_IMETHODIMP nsICOEncoder::ReadSegments(nsWriteSegmentFun aWriter, 1.359 + void *aClosure, uint32_t aCount, 1.360 + uint32_t *_retval) 1.361 +{ 1.362 + uint32_t maxCount = GetCurrentImageBufferOffset() - mImageBufferReadPoint; 1.363 + if (maxCount == 0) { 1.364 + *_retval = 0; 1.365 + return mFinished ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK; 1.366 + } 1.367 + 1.368 + if (aCount > maxCount) { 1.369 + aCount = maxCount; 1.370 + } 1.371 + 1.372 + nsresult rv = aWriter(this, aClosure, 1.373 + reinterpret_cast<const char*>(mImageBufferStart + 1.374 + mImageBufferReadPoint), 1.375 + 0, aCount, _retval); 1.376 + if (NS_SUCCEEDED(rv)) { 1.377 + NS_ASSERTION(*_retval <= aCount, "bad write count"); 1.378 + mImageBufferReadPoint += *_retval; 1.379 + } 1.380 + // errors returned from the writer end here! 1.381 + return NS_OK; 1.382 +} 1.383 + 1.384 +NS_IMETHODIMP 1.385 +nsICOEncoder::IsNonBlocking(bool *_retval) 1.386 +{ 1.387 + *_retval = true; 1.388 + return NS_OK; 1.389 +} 1.390 + 1.391 +NS_IMETHODIMP 1.392 +nsICOEncoder::AsyncWait(nsIInputStreamCallback *aCallback, 1.393 + uint32_t aFlags, 1.394 + uint32_t aRequestedCount, 1.395 + nsIEventTarget *aTarget) 1.396 +{ 1.397 + if (aFlags != 0) { 1.398 + return NS_ERROR_NOT_IMPLEMENTED; 1.399 + } 1.400 + 1.401 + if (mCallback || mCallbackTarget) { 1.402 + return NS_ERROR_UNEXPECTED; 1.403 + } 1.404 + 1.405 + mCallbackTarget = aTarget; 1.406 + // 0 means "any number of bytes except 0" 1.407 + mNotifyThreshold = aRequestedCount; 1.408 + if (!aRequestedCount) { 1.409 + mNotifyThreshold = 1024; // We don't want to notify incessantly 1.410 + } 1.411 + 1.412 + // We set the callback absolutely last, because NotifyListener uses it to 1.413 + // determine if someone needs to be notified. If we don't set it last, 1.414 + // NotifyListener might try to fire off a notification to a null target 1.415 + // which will generally cause non-threadsafe objects to be used off the main thread 1.416 + mCallback = aCallback; 1.417 + 1.418 + // What we are being asked for may be present already 1.419 + NotifyListener(); 1.420 + return NS_OK; 1.421 +} 1.422 + 1.423 +NS_IMETHODIMP nsICOEncoder::CloseWithStatus(nsresult aStatus) 1.424 +{ 1.425 + return Close(); 1.426 +} 1.427 + 1.428 +void 1.429 +nsICOEncoder::NotifyListener() 1.430 +{ 1.431 + if (mCallback && 1.432 + (GetCurrentImageBufferOffset() - mImageBufferReadPoint >= mNotifyThreshold || 1.433 + mFinished)) { 1.434 + nsCOMPtr<nsIInputStreamCallback> callback; 1.435 + if (mCallbackTarget) { 1.436 + callback = NS_NewInputStreamReadyEvent(mCallback, mCallbackTarget); 1.437 + } else { 1.438 + callback = mCallback; 1.439 + } 1.440 + 1.441 + NS_ASSERTION(callback, "Shouldn't fail to make the callback"); 1.442 + // Null the callback first because OnInputStreamReady could reenter 1.443 + // AsyncWait 1.444 + mCallback = nullptr; 1.445 + mCallbackTarget = nullptr; 1.446 + mNotifyThreshold = 0; 1.447 + 1.448 + callback->OnInputStreamReady(this); 1.449 + } 1.450 +} 1.451 + 1.452 +// Initializes the icon file header mICOFileHeader 1.453 +void 1.454 +nsICOEncoder::InitFileHeader() 1.455 +{ 1.456 + memset(&mICOFileHeader, 0, sizeof(mICOFileHeader)); 1.457 + mICOFileHeader.mReserved = 0; 1.458 + mICOFileHeader.mType = 1; 1.459 + mICOFileHeader.mCount = 1; 1.460 +} 1.461 + 1.462 +// Initializes the icon directory info header mICODirEntry 1.463 +void 1.464 +nsICOEncoder::InitInfoHeader(uint32_t aBPP, uint8_t aWidth, uint8_t aHeight) 1.465 +{ 1.466 + memset(&mICODirEntry, 0, sizeof(mICODirEntry)); 1.467 + mICODirEntry.mBitCount = aBPP; 1.468 + mICODirEntry.mBytesInRes = 0; 1.469 + mICODirEntry.mColorCount = 0; 1.470 + mICODirEntry.mWidth = aWidth; 1.471 + mICODirEntry.mHeight = aHeight; 1.472 + mICODirEntry.mImageOffset = ICONFILEHEADERSIZE + ICODIRENTRYSIZE; 1.473 + mICODirEntry.mPlanes = 1; 1.474 + mICODirEntry.mReserved = 0; 1.475 +} 1.476 + 1.477 +// Encodes the icon file header mICOFileHeader 1.478 +void 1.479 +nsICOEncoder::EncodeFileHeader() 1.480 +{ 1.481 + IconFileHeader littleEndianIFH = mICOFileHeader; 1.482 + NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mReserved, 1); 1.483 + NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mType, 1); 1.484 + NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mCount, 1); 1.485 + 1.486 + memcpy(mImageBufferCurr, &littleEndianIFH.mReserved, 1.487 + sizeof(littleEndianIFH.mReserved)); 1.488 + mImageBufferCurr += sizeof(littleEndianIFH.mReserved); 1.489 + memcpy(mImageBufferCurr, &littleEndianIFH.mType, 1.490 + sizeof(littleEndianIFH.mType)); 1.491 + mImageBufferCurr += sizeof(littleEndianIFH.mType); 1.492 + memcpy(mImageBufferCurr, &littleEndianIFH.mCount, 1.493 + sizeof(littleEndianIFH.mCount)); 1.494 + mImageBufferCurr += sizeof(littleEndianIFH.mCount); 1.495 +} 1.496 + 1.497 +// Encodes the icon directory info header mICODirEntry 1.498 +void 1.499 +nsICOEncoder::EncodeInfoHeader() 1.500 +{ 1.501 + IconDirEntry littleEndianmIDE = mICODirEntry; 1.502 + 1.503 + NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mPlanes, 1); 1.504 + NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mBitCount, 1); 1.505 + NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mBytesInRes, 1); 1.506 + NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mImageOffset, 1); 1.507 + 1.508 + memcpy(mImageBufferCurr, &littleEndianmIDE.mWidth, 1.509 + sizeof(littleEndianmIDE.mWidth)); 1.510 + mImageBufferCurr += sizeof(littleEndianmIDE.mWidth); 1.511 + memcpy(mImageBufferCurr, &littleEndianmIDE.mHeight, 1.512 + sizeof(littleEndianmIDE.mHeight)); 1.513 + mImageBufferCurr += sizeof(littleEndianmIDE.mHeight); 1.514 + memcpy(mImageBufferCurr, &littleEndianmIDE.mColorCount, 1.515 + sizeof(littleEndianmIDE.mColorCount)); 1.516 + mImageBufferCurr += sizeof(littleEndianmIDE.mColorCount); 1.517 + memcpy(mImageBufferCurr, &littleEndianmIDE.mReserved, 1.518 + sizeof(littleEndianmIDE.mReserved)); 1.519 + mImageBufferCurr += sizeof(littleEndianmIDE.mReserved); 1.520 + memcpy(mImageBufferCurr, &littleEndianmIDE.mPlanes, 1.521 + sizeof(littleEndianmIDE.mPlanes)); 1.522 + mImageBufferCurr += sizeof(littleEndianmIDE.mPlanes); 1.523 + memcpy(mImageBufferCurr, &littleEndianmIDE.mBitCount, 1.524 + sizeof(littleEndianmIDE.mBitCount)); 1.525 + mImageBufferCurr += sizeof(littleEndianmIDE.mBitCount); 1.526 + memcpy(mImageBufferCurr, &littleEndianmIDE.mBytesInRes, 1.527 + sizeof(littleEndianmIDE.mBytesInRes)); 1.528 + mImageBufferCurr += sizeof(littleEndianmIDE.mBytesInRes); 1.529 + memcpy(mImageBufferCurr, &littleEndianmIDE.mImageOffset, 1.530 + sizeof(littleEndianmIDE.mImageOffset)); 1.531 + mImageBufferCurr += sizeof(littleEndianmIDE.mImageOffset); 1.532 +}