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