|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "nsCRT.h" |
|
6 #include "mozilla/Endian.h" |
|
7 #include "nsBMPEncoder.h" |
|
8 #include "nsPNGEncoder.h" |
|
9 #include "nsICOEncoder.h" |
|
10 #include "prprf.h" |
|
11 #include "nsString.h" |
|
12 #include "nsStreamUtils.h" |
|
13 #include "nsTArray.h" |
|
14 |
|
15 using namespace mozilla; |
|
16 using namespace mozilla::image; |
|
17 |
|
18 NS_IMPL_ISUPPORTS(nsICOEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream) |
|
19 |
|
20 nsICOEncoder::nsICOEncoder() : mImageBufferStart(nullptr), |
|
21 mImageBufferCurr(0), |
|
22 mImageBufferSize(0), |
|
23 mImageBufferReadPoint(0), |
|
24 mFinished(false), |
|
25 mUsePNG(true), |
|
26 mNotifyThreshold(0) |
|
27 { |
|
28 } |
|
29 |
|
30 nsICOEncoder::~nsICOEncoder() |
|
31 { |
|
32 if (mImageBufferStart) { |
|
33 moz_free(mImageBufferStart); |
|
34 mImageBufferStart = nullptr; |
|
35 mImageBufferCurr = nullptr; |
|
36 } |
|
37 } |
|
38 |
|
39 // nsICOEncoder::InitFromData |
|
40 // Two output options are supported: format=<png|bmp>;bpp=<bpp_value> |
|
41 // format specifies whether to use png or bitmap format |
|
42 // bpp specifies the bits per pixel to use where bpp_value can be 24 or 32 |
|
43 NS_IMETHODIMP nsICOEncoder::InitFromData(const uint8_t* aData, |
|
44 uint32_t aLength, |
|
45 uint32_t aWidth, |
|
46 uint32_t aHeight, |
|
47 uint32_t aStride, |
|
48 uint32_t aInputFormat, |
|
49 const nsAString& aOutputOptions) |
|
50 { |
|
51 // validate input format |
|
52 if (aInputFormat != INPUT_FORMAT_RGB && |
|
53 aInputFormat != INPUT_FORMAT_RGBA && |
|
54 aInputFormat != INPUT_FORMAT_HOSTARGB) { |
|
55 return NS_ERROR_INVALID_ARG; |
|
56 } |
|
57 |
|
58 // Stride is the padded width of each row, so it better be longer |
|
59 if ((aInputFormat == INPUT_FORMAT_RGB && |
|
60 aStride < aWidth * 3) || |
|
61 ((aInputFormat == INPUT_FORMAT_RGBA || aInputFormat == INPUT_FORMAT_HOSTARGB) && |
|
62 aStride < aWidth * 4)) { |
|
63 NS_WARNING("Invalid stride for InitFromData"); |
|
64 return NS_ERROR_INVALID_ARG; |
|
65 } |
|
66 |
|
67 nsresult rv; |
|
68 rv = StartImageEncode(aWidth, aHeight, aInputFormat, aOutputOptions); |
|
69 NS_ENSURE_SUCCESS(rv, rv); |
|
70 |
|
71 rv = AddImageFrame(aData, aLength, aWidth, aHeight, aStride, |
|
72 aInputFormat, aOutputOptions); |
|
73 NS_ENSURE_SUCCESS(rv, rv); |
|
74 |
|
75 rv = EndImageEncode(); |
|
76 return rv; |
|
77 } |
|
78 |
|
79 // Returns the number of bytes in the image buffer used |
|
80 // For an ICO file, this is all bytes in the buffer. |
|
81 NS_IMETHODIMP |
|
82 nsICOEncoder::GetImageBufferUsed(uint32_t *aOutputSize) |
|
83 { |
|
84 NS_ENSURE_ARG_POINTER(aOutputSize); |
|
85 *aOutputSize = mImageBufferSize; |
|
86 return NS_OK; |
|
87 } |
|
88 |
|
89 // Returns a pointer to the start of the image buffer |
|
90 NS_IMETHODIMP |
|
91 nsICOEncoder::GetImageBuffer(char **aOutputBuffer) |
|
92 { |
|
93 NS_ENSURE_ARG_POINTER(aOutputBuffer); |
|
94 *aOutputBuffer = reinterpret_cast<char*>(mImageBufferStart); |
|
95 return NS_OK; |
|
96 } |
|
97 |
|
98 NS_IMETHODIMP |
|
99 nsICOEncoder::AddImageFrame(const uint8_t* aData, |
|
100 uint32_t aLength, |
|
101 uint32_t aWidth, |
|
102 uint32_t aHeight, |
|
103 uint32_t aStride, |
|
104 uint32_t aInputFormat, |
|
105 const nsAString& aFrameOptions) |
|
106 { |
|
107 if (mUsePNG) { |
|
108 |
|
109 mContainedEncoder = new nsPNGEncoder(); |
|
110 nsresult rv; |
|
111 nsAutoString noParams; |
|
112 rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight, |
|
113 aStride, aInputFormat, noParams); |
|
114 NS_ENSURE_SUCCESS(rv, rv); |
|
115 |
|
116 uint32_t PNGImageBufferSize; |
|
117 mContainedEncoder->GetImageBufferUsed(&PNGImageBufferSize); |
|
118 mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + |
|
119 PNGImageBufferSize; |
|
120 mImageBufferStart = static_cast<uint8_t*>(moz_malloc(mImageBufferSize)); |
|
121 if (!mImageBufferStart) { |
|
122 return NS_ERROR_OUT_OF_MEMORY; |
|
123 } |
|
124 mImageBufferCurr = mImageBufferStart; |
|
125 mICODirEntry.mBytesInRes = PNGImageBufferSize; |
|
126 |
|
127 EncodeFileHeader(); |
|
128 EncodeInfoHeader(); |
|
129 |
|
130 char *imageBuffer; |
|
131 rv = mContainedEncoder->GetImageBuffer(&imageBuffer); |
|
132 NS_ENSURE_SUCCESS(rv, rv); |
|
133 memcpy(mImageBufferCurr, imageBuffer, PNGImageBufferSize); |
|
134 mImageBufferCurr += PNGImageBufferSize; |
|
135 } else { |
|
136 mContainedEncoder = new nsBMPEncoder(); |
|
137 nsresult rv; |
|
138 |
|
139 nsAutoString params; |
|
140 params.AppendLiteral("bpp="); |
|
141 params.AppendInt(mICODirEntry.mBitCount); |
|
142 |
|
143 rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight, |
|
144 aStride, aInputFormat, params); |
|
145 NS_ENSURE_SUCCESS(rv, rv); |
|
146 |
|
147 uint32_t andMaskSize = ((GetRealWidth() + 31) / 32) * 4 * // row AND mask |
|
148 GetRealHeight(); // num rows |
|
149 |
|
150 uint32_t BMPImageBufferSize; |
|
151 mContainedEncoder->GetImageBufferUsed(&BMPImageBufferSize); |
|
152 mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + |
|
153 BMPImageBufferSize + andMaskSize; |
|
154 mImageBufferStart = static_cast<uint8_t*>(moz_malloc(mImageBufferSize)); |
|
155 if (!mImageBufferStart) { |
|
156 return NS_ERROR_OUT_OF_MEMORY; |
|
157 } |
|
158 mImageBufferCurr = mImageBufferStart; |
|
159 |
|
160 // The icon buffer does not include the BFH at all. |
|
161 mICODirEntry.mBytesInRes = BMPImageBufferSize - BFH_LENGTH + andMaskSize; |
|
162 |
|
163 // Encode the icon headers |
|
164 EncodeFileHeader(); |
|
165 EncodeInfoHeader(); |
|
166 |
|
167 char *imageBuffer; |
|
168 rv = mContainedEncoder->GetImageBuffer(&imageBuffer); |
|
169 NS_ENSURE_SUCCESS(rv, rv); |
|
170 memcpy(mImageBufferCurr, imageBuffer + BFH_LENGTH, |
|
171 BMPImageBufferSize - BFH_LENGTH); |
|
172 // We need to fix the BMP height to be *2 for the AND mask |
|
173 uint32_t fixedHeight = GetRealHeight() * 2; |
|
174 NativeEndian::swapToLittleEndianInPlace(&fixedHeight, 1); |
|
175 // The height is stored at an offset of 8 from the DIB header |
|
176 memcpy(mImageBufferCurr + 8, &fixedHeight, sizeof(fixedHeight)); |
|
177 mImageBufferCurr += BMPImageBufferSize - BFH_LENGTH; |
|
178 |
|
179 // Calculate rowsize in DWORD's |
|
180 uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up |
|
181 int32_t currentLine = GetRealHeight(); |
|
182 |
|
183 // Write out the AND mask |
|
184 while (currentLine > 0) { |
|
185 currentLine--; |
|
186 uint8_t* encoded = mImageBufferCurr + currentLine * rowSize; |
|
187 uint8_t* encodedEnd = encoded + rowSize; |
|
188 while (encoded != encodedEnd) { |
|
189 *encoded = 0; // make everything visible |
|
190 encoded++; |
|
191 } |
|
192 } |
|
193 |
|
194 mImageBufferCurr += andMaskSize; |
|
195 } |
|
196 |
|
197 return NS_OK; |
|
198 } |
|
199 |
|
200 // See ::InitFromData for other info. |
|
201 NS_IMETHODIMP nsICOEncoder::StartImageEncode(uint32_t aWidth, |
|
202 uint32_t aHeight, |
|
203 uint32_t aInputFormat, |
|
204 const nsAString& aOutputOptions) |
|
205 { |
|
206 // can't initialize more than once |
|
207 if (mImageBufferStart || mImageBufferCurr) { |
|
208 return NS_ERROR_ALREADY_INITIALIZED; |
|
209 } |
|
210 |
|
211 // validate input format |
|
212 if (aInputFormat != INPUT_FORMAT_RGB && |
|
213 aInputFormat != INPUT_FORMAT_RGBA && |
|
214 aInputFormat != INPUT_FORMAT_HOSTARGB) { |
|
215 return NS_ERROR_INVALID_ARG; |
|
216 } |
|
217 |
|
218 // Icons are only 1 byte, so make sure our bitmap is in range |
|
219 if (aWidth > 256 || aHeight > 256) { |
|
220 return NS_ERROR_INVALID_ARG; |
|
221 } |
|
222 |
|
223 // parse and check any provided output options |
|
224 uint32_t bpp = 24; |
|
225 bool usePNG = true; |
|
226 nsresult rv = ParseOptions(aOutputOptions, &bpp, &usePNG); |
|
227 NS_ENSURE_SUCCESS(rv, rv); |
|
228 |
|
229 mUsePNG = usePNG; |
|
230 |
|
231 InitFileHeader(); |
|
232 // The width and height are stored as 0 when we have a value of 256 |
|
233 InitInfoHeader(bpp, aWidth == 256 ? 0 : (uint8_t)aWidth, |
|
234 aHeight == 256 ? 0 : (uint8_t)aHeight); |
|
235 |
|
236 return NS_OK; |
|
237 } |
|
238 |
|
239 NS_IMETHODIMP nsICOEncoder::EndImageEncode() |
|
240 { |
|
241 // must be initialized |
|
242 if (!mImageBufferStart || !mImageBufferCurr) { |
|
243 return NS_ERROR_NOT_INITIALIZED; |
|
244 } |
|
245 |
|
246 mFinished = true; |
|
247 NotifyListener(); |
|
248 |
|
249 // if output callback can't get enough memory, it will free our buffer |
|
250 if (!mImageBufferStart || !mImageBufferCurr) { |
|
251 return NS_ERROR_OUT_OF_MEMORY; |
|
252 } |
|
253 |
|
254 return NS_OK; |
|
255 } |
|
256 |
|
257 // Parses the encoder options and sets the bits per pixel to use and PNG or BMP |
|
258 // See InitFromData for a description of the parse options |
|
259 nsresult |
|
260 nsICOEncoder::ParseOptions(const nsAString& aOptions, uint32_t* bpp, |
|
261 bool *usePNG) |
|
262 { |
|
263 // If no parsing options just use the default of 24BPP and PNG yes |
|
264 if (aOptions.Length() == 0) { |
|
265 if (usePNG) { |
|
266 *usePNG = true; |
|
267 } |
|
268 if (bpp) { |
|
269 *bpp = 24; |
|
270 } |
|
271 } |
|
272 |
|
273 // Parse the input string into a set of name/value pairs. |
|
274 // From format: format=<png|bmp>;bpp=<bpp_value> |
|
275 // to format: [0] = format=<png|bmp>, [1] = bpp=<bpp_value> |
|
276 nsTArray<nsCString> nameValuePairs; |
|
277 if (!ParseString(NS_ConvertUTF16toUTF8(aOptions), ';', nameValuePairs)) { |
|
278 return NS_ERROR_INVALID_ARG; |
|
279 } |
|
280 |
|
281 // For each name/value pair in the set |
|
282 for (unsigned i = 0; i < nameValuePairs.Length(); ++i) { |
|
283 |
|
284 // Split the name value pair [0] = name, [1] = value |
|
285 nsTArray<nsCString> nameValuePair; |
|
286 if (!ParseString(nameValuePairs[i], '=', nameValuePair)) { |
|
287 return NS_ERROR_INVALID_ARG; |
|
288 } |
|
289 if (nameValuePair.Length() != 2) { |
|
290 return NS_ERROR_INVALID_ARG; |
|
291 } |
|
292 |
|
293 // Parse the format portion of the string format=<png|bmp>;bpp=<bpp_value> |
|
294 if (nameValuePair[0].Equals("format", nsCaseInsensitiveCStringComparator())) { |
|
295 if (nameValuePair[1].Equals("png", nsCaseInsensitiveCStringComparator())) { |
|
296 *usePNG = true; |
|
297 } |
|
298 else if (nameValuePair[1].Equals("bmp", nsCaseInsensitiveCStringComparator())) { |
|
299 *usePNG = false; |
|
300 } |
|
301 else { |
|
302 return NS_ERROR_INVALID_ARG; |
|
303 } |
|
304 } |
|
305 |
|
306 // Parse the bpp portion of the string format=<png|bmp>;bpp=<bpp_value> |
|
307 if (nameValuePair[0].Equals("bpp", nsCaseInsensitiveCStringComparator())) { |
|
308 if (nameValuePair[1].Equals("24")) { |
|
309 *bpp = 24; |
|
310 } |
|
311 else if (nameValuePair[1].Equals("32")) { |
|
312 *bpp = 32; |
|
313 } |
|
314 else { |
|
315 return NS_ERROR_INVALID_ARG; |
|
316 } |
|
317 } |
|
318 } |
|
319 |
|
320 return NS_OK; |
|
321 } |
|
322 |
|
323 NS_IMETHODIMP nsICOEncoder::Close() |
|
324 { |
|
325 if (mImageBufferStart) { |
|
326 moz_free(mImageBufferStart); |
|
327 mImageBufferStart = nullptr; |
|
328 mImageBufferSize = 0; |
|
329 mImageBufferReadPoint = 0; |
|
330 mImageBufferCurr = nullptr; |
|
331 } |
|
332 |
|
333 return NS_OK; |
|
334 } |
|
335 |
|
336 // Obtains the available bytes to read |
|
337 NS_IMETHODIMP nsICOEncoder::Available(uint64_t *_retval) |
|
338 { |
|
339 if (!mImageBufferStart || !mImageBufferCurr) { |
|
340 return NS_BASE_STREAM_CLOSED; |
|
341 } |
|
342 |
|
343 *_retval = GetCurrentImageBufferOffset() - mImageBufferReadPoint; |
|
344 return NS_OK; |
|
345 } |
|
346 |
|
347 // [noscript] Reads bytes which are available |
|
348 NS_IMETHODIMP nsICOEncoder::Read(char *aBuf, uint32_t aCount, |
|
349 uint32_t *_retval) |
|
350 { |
|
351 return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval); |
|
352 } |
|
353 |
|
354 // [noscript] Reads segments |
|
355 NS_IMETHODIMP nsICOEncoder::ReadSegments(nsWriteSegmentFun aWriter, |
|
356 void *aClosure, uint32_t aCount, |
|
357 uint32_t *_retval) |
|
358 { |
|
359 uint32_t maxCount = GetCurrentImageBufferOffset() - mImageBufferReadPoint; |
|
360 if (maxCount == 0) { |
|
361 *_retval = 0; |
|
362 return mFinished ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK; |
|
363 } |
|
364 |
|
365 if (aCount > maxCount) { |
|
366 aCount = maxCount; |
|
367 } |
|
368 |
|
369 nsresult rv = aWriter(this, aClosure, |
|
370 reinterpret_cast<const char*>(mImageBufferStart + |
|
371 mImageBufferReadPoint), |
|
372 0, aCount, _retval); |
|
373 if (NS_SUCCEEDED(rv)) { |
|
374 NS_ASSERTION(*_retval <= aCount, "bad write count"); |
|
375 mImageBufferReadPoint += *_retval; |
|
376 } |
|
377 // errors returned from the writer end here! |
|
378 return NS_OK; |
|
379 } |
|
380 |
|
381 NS_IMETHODIMP |
|
382 nsICOEncoder::IsNonBlocking(bool *_retval) |
|
383 { |
|
384 *_retval = true; |
|
385 return NS_OK; |
|
386 } |
|
387 |
|
388 NS_IMETHODIMP |
|
389 nsICOEncoder::AsyncWait(nsIInputStreamCallback *aCallback, |
|
390 uint32_t aFlags, |
|
391 uint32_t aRequestedCount, |
|
392 nsIEventTarget *aTarget) |
|
393 { |
|
394 if (aFlags != 0) { |
|
395 return NS_ERROR_NOT_IMPLEMENTED; |
|
396 } |
|
397 |
|
398 if (mCallback || mCallbackTarget) { |
|
399 return NS_ERROR_UNEXPECTED; |
|
400 } |
|
401 |
|
402 mCallbackTarget = aTarget; |
|
403 // 0 means "any number of bytes except 0" |
|
404 mNotifyThreshold = aRequestedCount; |
|
405 if (!aRequestedCount) { |
|
406 mNotifyThreshold = 1024; // We don't want to notify incessantly |
|
407 } |
|
408 |
|
409 // We set the callback absolutely last, because NotifyListener uses it to |
|
410 // determine if someone needs to be notified. If we don't set it last, |
|
411 // NotifyListener might try to fire off a notification to a null target |
|
412 // which will generally cause non-threadsafe objects to be used off the main thread |
|
413 mCallback = aCallback; |
|
414 |
|
415 // What we are being asked for may be present already |
|
416 NotifyListener(); |
|
417 return NS_OK; |
|
418 } |
|
419 |
|
420 NS_IMETHODIMP nsICOEncoder::CloseWithStatus(nsresult aStatus) |
|
421 { |
|
422 return Close(); |
|
423 } |
|
424 |
|
425 void |
|
426 nsICOEncoder::NotifyListener() |
|
427 { |
|
428 if (mCallback && |
|
429 (GetCurrentImageBufferOffset() - mImageBufferReadPoint >= mNotifyThreshold || |
|
430 mFinished)) { |
|
431 nsCOMPtr<nsIInputStreamCallback> callback; |
|
432 if (mCallbackTarget) { |
|
433 callback = NS_NewInputStreamReadyEvent(mCallback, mCallbackTarget); |
|
434 } else { |
|
435 callback = mCallback; |
|
436 } |
|
437 |
|
438 NS_ASSERTION(callback, "Shouldn't fail to make the callback"); |
|
439 // Null the callback first because OnInputStreamReady could reenter |
|
440 // AsyncWait |
|
441 mCallback = nullptr; |
|
442 mCallbackTarget = nullptr; |
|
443 mNotifyThreshold = 0; |
|
444 |
|
445 callback->OnInputStreamReady(this); |
|
446 } |
|
447 } |
|
448 |
|
449 // Initializes the icon file header mICOFileHeader |
|
450 void |
|
451 nsICOEncoder::InitFileHeader() |
|
452 { |
|
453 memset(&mICOFileHeader, 0, sizeof(mICOFileHeader)); |
|
454 mICOFileHeader.mReserved = 0; |
|
455 mICOFileHeader.mType = 1; |
|
456 mICOFileHeader.mCount = 1; |
|
457 } |
|
458 |
|
459 // Initializes the icon directory info header mICODirEntry |
|
460 void |
|
461 nsICOEncoder::InitInfoHeader(uint32_t aBPP, uint8_t aWidth, uint8_t aHeight) |
|
462 { |
|
463 memset(&mICODirEntry, 0, sizeof(mICODirEntry)); |
|
464 mICODirEntry.mBitCount = aBPP; |
|
465 mICODirEntry.mBytesInRes = 0; |
|
466 mICODirEntry.mColorCount = 0; |
|
467 mICODirEntry.mWidth = aWidth; |
|
468 mICODirEntry.mHeight = aHeight; |
|
469 mICODirEntry.mImageOffset = ICONFILEHEADERSIZE + ICODIRENTRYSIZE; |
|
470 mICODirEntry.mPlanes = 1; |
|
471 mICODirEntry.mReserved = 0; |
|
472 } |
|
473 |
|
474 // Encodes the icon file header mICOFileHeader |
|
475 void |
|
476 nsICOEncoder::EncodeFileHeader() |
|
477 { |
|
478 IconFileHeader littleEndianIFH = mICOFileHeader; |
|
479 NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mReserved, 1); |
|
480 NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mType, 1); |
|
481 NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mCount, 1); |
|
482 |
|
483 memcpy(mImageBufferCurr, &littleEndianIFH.mReserved, |
|
484 sizeof(littleEndianIFH.mReserved)); |
|
485 mImageBufferCurr += sizeof(littleEndianIFH.mReserved); |
|
486 memcpy(mImageBufferCurr, &littleEndianIFH.mType, |
|
487 sizeof(littleEndianIFH.mType)); |
|
488 mImageBufferCurr += sizeof(littleEndianIFH.mType); |
|
489 memcpy(mImageBufferCurr, &littleEndianIFH.mCount, |
|
490 sizeof(littleEndianIFH.mCount)); |
|
491 mImageBufferCurr += sizeof(littleEndianIFH.mCount); |
|
492 } |
|
493 |
|
494 // Encodes the icon directory info header mICODirEntry |
|
495 void |
|
496 nsICOEncoder::EncodeInfoHeader() |
|
497 { |
|
498 IconDirEntry littleEndianmIDE = mICODirEntry; |
|
499 |
|
500 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mPlanes, 1); |
|
501 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mBitCount, 1); |
|
502 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mBytesInRes, 1); |
|
503 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mImageOffset, 1); |
|
504 |
|
505 memcpy(mImageBufferCurr, &littleEndianmIDE.mWidth, |
|
506 sizeof(littleEndianmIDE.mWidth)); |
|
507 mImageBufferCurr += sizeof(littleEndianmIDE.mWidth); |
|
508 memcpy(mImageBufferCurr, &littleEndianmIDE.mHeight, |
|
509 sizeof(littleEndianmIDE.mHeight)); |
|
510 mImageBufferCurr += sizeof(littleEndianmIDE.mHeight); |
|
511 memcpy(mImageBufferCurr, &littleEndianmIDE.mColorCount, |
|
512 sizeof(littleEndianmIDE.mColorCount)); |
|
513 mImageBufferCurr += sizeof(littleEndianmIDE.mColorCount); |
|
514 memcpy(mImageBufferCurr, &littleEndianmIDE.mReserved, |
|
515 sizeof(littleEndianmIDE.mReserved)); |
|
516 mImageBufferCurr += sizeof(littleEndianmIDE.mReserved); |
|
517 memcpy(mImageBufferCurr, &littleEndianmIDE.mPlanes, |
|
518 sizeof(littleEndianmIDE.mPlanes)); |
|
519 mImageBufferCurr += sizeof(littleEndianmIDE.mPlanes); |
|
520 memcpy(mImageBufferCurr, &littleEndianmIDE.mBitCount, |
|
521 sizeof(littleEndianmIDE.mBitCount)); |
|
522 mImageBufferCurr += sizeof(littleEndianmIDE.mBitCount); |
|
523 memcpy(mImageBufferCurr, &littleEndianmIDE.mBytesInRes, |
|
524 sizeof(littleEndianmIDE.mBytesInRes)); |
|
525 mImageBufferCurr += sizeof(littleEndianmIDE.mBytesInRes); |
|
526 memcpy(mImageBufferCurr, &littleEndianmIDE.mImageOffset, |
|
527 sizeof(littleEndianmIDE.mImageOffset)); |
|
528 mImageBufferCurr += sizeof(littleEndianmIDE.mImageOffset); |
|
529 } |