Coverage Report

Created: 2018-09-25 14:53

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