Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: Source/core/platform/image-decoders/ImageDecoder.h

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #ifndef ImageDecoder_h
28 #define ImageDecoder_h
29
30 #include "SkColorPriv.h"
31 #include "core/platform/graphics/ImageSource.h"
32 #include "core/platform/graphics/skia/NativeImageSkia.h"
33 #include "platform/PlatformScreen.h"
34 #include "platform/SharedBuffer.h"
35 #include "platform/geometry/IntRect.h"
36 #include "public/platform/Platform.h"
37 #include "wtf/Assertions.h"
38 #include "wtf/RefPtr.h"
39 #include "wtf/text/WTFString.h"
40 #include "wtf/Vector.h"
41
42 #if USE(QCMSLIB)
43 #include "qcms.h"
44 #if OS(MACOSX)
45 #include <ApplicationServices/ApplicationServices.h>
46 #include "core/platform/graphics/cg/GraphicsContextCG.h"
47 #include "wtf/RetainPtr.h"
48 #endif
49 #endif
50
51 namespace WebCore {
52
53 // ImageFrame represents the decoded image data. This buffer is what all
54 // decoders write a single frame into.
55 class ImageFrame {
56 public:
57 enum Status { FrameEmpty, FramePartial, FrameComplete };
58 enum DisposalMethod {
59 // If you change the numeric values of these, make sure you audit
60 // all users, as some users may cast raw values to/from these
61 // constants.
62 DisposeNotSpecified, // Leave frame in framebuffer
63 DisposeKeep, // Leave frame in framebuffer
64 DisposeOverwriteBgcolor, // Clear frame to fully transparent
65 DisposeOverwritePrevious // Clear frame to previous framebuffer cont ents
66 };
67 // Indicates how non-opaque pixels in the current frame rectangle
68 // are blended with those in the previous frame.
69 // Notes:
70 // * GIF always uses 'BlendAtopPreviousFrame'.
71 // * WebP also uses the 'BlendAtopBgcolor' option. This is useful for
72 // cases where one wants to transform a few opaque pixels of the
73 // previous frame into non-opaque pixels in the current frame.
74 enum AlphaBlendSource {
75 // Blend non-opaque pixels atop the corresponding pixels in the
76 // initial buffer state (i.e. any previous frame buffer after having
77 // been properly disposed).
78 BlendAtopPreviousFrame,
79
80 // Blend non-opaque pixels against fully transparent (i.e. simply
81 // overwrite the corresponding pixels).
82 BlendAtopBgcolor,
83 };
84 typedef uint32_t PixelData;
85
86 ImageFrame();
87
88 ImageFrame(const ImageFrame& other) { operator=(other); }
89
90 // For backends which refcount their data, this operator doesn't need to
91 // create a new copy of the image data, only increase the ref count.
92 ImageFrame& operator=(const ImageFrame& other);
93
94 // These do not touch other metadata, only the raw pixel data.
95 void clearPixelData();
96 void zeroFillPixelData();
97 void zeroFillFrameRect(const IntRect&);
98
99 // Makes this frame have an independent copy of the provided image's
100 // pixel data, so that modifications in one frame are not reflected in
101 // the other. Returns whether the copy succeeded.
102 bool copyBitmapData(const ImageFrame&);
103
104 // Copies the pixel data at [(startX, startY), (endX, startY)) to the
105 // same X-coordinates on each subsequent row up to but not including
106 // endY.
107 void copyRowNTimes(int startX, int endX, int startY, int endY)
108 {
109 ASSERT(startX < width());
110 ASSERT(endX <= width());
111 ASSERT(startY < height());
112 ASSERT(endY <= height());
113 const int rowBytes = (endX - startX) * sizeof(PixelData);
114 const PixelData* const startAddr = getAddr(startX, startY);
115 for (int destY = startY + 1; destY < endY; ++destY)
116 memcpy(getAddr(startX, destY), startAddr, rowBytes);
117 }
118
119 // Allocates space for the pixel data. Must be called before any pixels
120 // are written. Must only be called once. Returns whether allocation
121 // succeeded.
122 bool setSize(int newWidth, int newHeight);
123
124 // Returns a caller-owned pointer to the underlying native image data.
125 // (Actual use: This pointer will be owned by BitmapImage and freed in
126 // FrameData::clear()).
127 PassRefPtr<NativeImageSkia> asNewNativeImage() const;
128
129 bool hasAlpha() const;
130 const IntRect& originalFrameRect() const { return m_originalFrameRect; }
131 Status status() const { return m_status; }
132 unsigned duration() const { return m_duration; }
133 DisposalMethod disposalMethod() const { return m_disposalMethod; }
134 AlphaBlendSource alphaBlendSource() const { return m_alphaBlendSource; }
135 bool premultiplyAlpha() const { return m_premultiplyAlpha; }
136 SkBitmap::Allocator* allocator() const { return m_allocator; }
137 const SkBitmap& getSkBitmap() const { return m_bitmap->bitmap(); }
138 // Returns true if the pixels changed, but the bitmap has not yet been n otified.
139 bool pixelsChanged() const { return m_pixelsChanged; }
140
141 size_t requiredPreviousFrameIndex() const
142 {
143 ASSERT(m_requiredPreviousFrameIndexValid);
144 return m_requiredPreviousFrameIndex;
145 }
146 #if !ASSERT_DISABLED
147 bool requiredPreviousFrameIndexValid() const { return m_requiredPrevious FrameIndexValid; }
148 #endif
149 void setHasAlpha(bool alpha);
150 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
151 void setStatus(Status);
152 void setDuration(unsigned duration) { m_duration = duration; }
153 void setDisposalMethod(DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; }
154 void setAlphaBlendSource(AlphaBlendSource alphaBlendSource) { m_alphaBle ndSource = alphaBlendSource; }
155 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = p remultiplyAlpha; }
156 void setMemoryAllocator(SkBitmap::Allocator* allocator) { m_allocator = allocator; }
157 void setSkBitmap(const SkBitmap& bitmap) { m_bitmap = NativeImageSkia::c reate(bitmap); }
158 // The pixelsChanged flag needs to be set when the raw pixel data was di rectly modified
159 // (e.g. through a pointer or setRGBA). The flag is usually set after a batch of changes was made.
160 void setPixelsChanged(bool pixelsChanged) { m_pixelsChanged = pixelsChan ged; }
161
162 void setRequiredPreviousFrameIndex(size_t previousFrameIndex)
163 {
164 m_requiredPreviousFrameIndex = previousFrameIndex;
165 #if !ASSERT_DISABLED
166 m_requiredPreviousFrameIndexValid = true;
167 #endif
168 }
169
170 inline PixelData* getAddr(int x, int y)
171 {
172 return m_bitmap->bitmap().getAddr32(x, y);
173 }
174
175 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, un signed a)
176 {
177 setRGBA(getAddr(x, y), r, g, b, a);
178 }
179
180 static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 2 4)) + 1;
181
182 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
183 {
184 if (m_premultiplyAlpha && a < 255) {
185 if (!a) {
186 *dest = 0;
187 return;
188 }
189
190 unsigned alpha = a * div255;
191 r = (r * alpha) >> 24;
192 g = (g * alpha) >> 24;
193 b = (b * alpha) >> 24;
194 }
195
196 // Call the "NoCheck" version since we may deliberately pass non-pre multiplied
197 // values, and we don't want an assert.
198 *dest = SkPackARGB32NoCheck(a, r, g, b);
199 }
200
201 inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
202 {
203 *dest = SkPackARGB32NoCheck(a, r, g, b);
204 }
205
206 // Notifies the SkBitmap if any pixels changed and resets the flag.
207 inline void notifyBitmapIfPixelsChanged()
208 {
209 if (m_pixelsChanged)
210 m_bitmap->bitmap().notifyPixelsChanged();
211 m_pixelsChanged = false;
212 }
213
214 private:
215 int width() const
216 {
217 return m_bitmap->bitmap().width();
218 }
219
220 int height() const
221 {
222 return m_bitmap->bitmap().height();
223 }
224
225 RefPtr<NativeImageSkia> m_bitmap;
226 SkBitmap::Allocator* m_allocator;
227 bool m_hasAlpha;
228 // This will always just be the entire buffer except for GIF or WebP
229 // frames whose original rect was smaller than the overall image size.
230 IntRect m_originalFrameRect;
231 Status m_status;
232 unsigned m_duration;
233 DisposalMethod m_disposalMethod;
234 AlphaBlendSource m_alphaBlendSource;
235 bool m_premultiplyAlpha;
236 // True if the pixels changed, but the bitmap has not yet been notified.
237 bool m_pixelsChanged;
238
239 // The frame that must be decoded before this frame can be decoded.
240 // WTF::kNotFound if this frame doesn't require any previous frame.
241 // This is used by ImageDecoder::clearCacheExceptFrame(), and will never
242 // be read for image formats that do not have multiple frames.
243 size_t m_requiredPreviousFrameIndex;
244 #if !ASSERT_DISABLED
245 bool m_requiredPreviousFrameIndexValid;
246 #endif
247 };
248
249 // ImageDecoder is a base for all format-specific decoders
250 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache.
251 //
252 class ImageDecoder {
253 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
254 public:
255 static const size_t noDecodedImageByteLimit = blink::Platform::noDecoded ImageByteLimit;
256
257 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAnd ColorProfileOption gammaAndColorProfileOption, size_t maxDecodedBytes)
258 : m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
259 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSo urce::GammaAndColorProfileIgnored)
260 , m_maxDecodedBytes(maxDecodedBytes)
261 , m_sizeAvailable(false)
262 , m_isAllDataReceived(false)
263 , m_failed(false) { }
264
265 virtual ~ImageDecoder() { }
266
267 // Returns a caller-owned decoder of the appropriate type. Returns 0 if
268 // we can't sniff a supported type from the provided data (possibly
269 // because there isn't enough data yet).
270 // Sets m_maxDecodedBytes to Platform::maxImageDecodedBytes().
271 static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSo urce::AlphaOption, ImageSource::GammaAndColorProfileOption);
272
273 // Returns a decoder with custom maxDecodedSize.
274 static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSo urce::AlphaOption, ImageSource::GammaAndColorProfileOption, size_t maxDecodedSiz e);
275
276 virtual String filenameExtension() const = 0;
277
278 bool isAllDataReceived() const { return m_isAllDataReceived; }
279
280 virtual void setData(SharedBuffer* data, bool allDataReceived)
281 {
282 if (m_failed)
283 return;
284 m_data = data;
285 m_isAllDataReceived = allDataReceived;
286 }
287
288 // Lazily-decodes enough of the image to get the size (if possible).
289 // FIXME: Right now that has to be done by each subclass; factor the
290 // decode call out and use it here.
291 virtual bool isSizeAvailable()
292 {
293 return !m_failed && m_sizeAvailable;
294 }
295
296 virtual IntSize size() const { return m_size; }
297
298 // Decoders which downsample images should override this method to
299 // return the actual decoded size.
300 virtual IntSize decodedSize() const { return size(); }
301
302 // This will only differ from size() for ICO (where each frame is a
303 // different icon) or other formats where different frames are different
304 // sizes. This does NOT differ from size() for GIF or WebP, since
305 // decoding GIF or WebP composites any smaller frames against previous
306 // frames to create full-size frames.
307 virtual IntSize frameSizeAtIndex(size_t) const
308 {
309 return size();
310 }
311
312 // Returns whether the size is legal (i.e. not going to result in
313 // overflow elsewhere). If not, marks decoding as failed.
314 virtual bool setSize(unsigned width, unsigned height)
315 {
316 if (sizeCalculationMayOverflow(width, height))
317 return setFailed();
318 m_size = IntSize(width, height);
319 m_sizeAvailable = true;
320 return true;
321 }
322
323 // Lazily-decodes enough of the image to get the frame count (if
324 // possible), without decoding the individual frames.
325 // FIXME: Right now that has to be done by each subclass; factor the
326 // decode call out and use it here.
327 virtual size_t frameCount() { return 1; }
328
329 virtual int repetitionCount() const { return cAnimationNone; }
330
331 // Decodes as much of the requested frame as possible, and returns an
332 // ImageDecoder-owned pointer.
333 virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
334
335 // Make the best effort guess to check if the requested frame has alpha channel.
336 virtual bool frameHasAlphaAtIndex(size_t) const;
337
338 // Whether or not the frame is fully received.
339 virtual bool frameIsCompleteAtIndex(size_t) const;
340
341 // Duration for displaying a frame in seconds. This method is used by an imated images only.
342 virtual float frameDurationAtIndex(size_t) const { return 0; }
343
344 // Number of bytes in the decoded frame requested. Return 0 if not yet d ecoded.
345 virtual unsigned frameBytesAtIndex(size_t) const;
346
347 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorPro file = flag; }
348 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorP rofile; }
349
350 ImageOrientation orientation() const { return m_orientation; }
351
352 enum { iccColorProfileHeaderLength = 128 };
353
354 static bool rgbColorProfile(const char* profileData, unsigned profileLen gth)
355 {
356 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderL ength);
357
358 return !memcmp(&profileData[16], "RGB ", 4);
359 }
360
361 static bool inputDeviceColorProfile(const char* profileData, unsigned pr ofileLength)
362 {
363 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderL ength);
364
365 return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[ 12], "scnr", 4);
366 }
367
368 #if USE(QCMSLIB)
369 static qcms_profile* qcmsOutputDeviceProfile()
370 {
371 static qcms_profile* outputDeviceProfile = 0;
372
373 static bool qcmsInitialized = false;
374 if (!qcmsInitialized) {
375 qcmsInitialized = true;
376 // FIXME: Add optional ICCv4 support.
377 #if OS(MACOSX)
378 RetainPtr<CGColorSpaceRef> monitorColorSpace(AdoptCF, CGDisplayC opyColorSpace(CGMainDisplayID()));
379 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpac e.get()));
380 if (iccProfile) {
381 size_t length = CFDataGetLength(iccProfile);
382 const unsigned char* systemProfile = CFDataGetBytePtr(iccPro file);
383 outputDeviceProfile = qcms_profile_from_memory(systemProfile , length);
384 }
385 #else
386 // FIXME: add support for multiple monitors.
387 ColorProfile profile;
388 screenColorProfile(profile);
389 if (!profile.isEmpty())
390 outputDeviceProfile = qcms_profile_from_memory(profile.data( ), profile.size());
391 #endif
392 if (outputDeviceProfile && qcms_profile_is_bogus(outputDevicePro file)) {
393 qcms_profile_release(outputDeviceProfile);
394 outputDeviceProfile = 0;
395 }
396 if (!outputDeviceProfile)
397 outputDeviceProfile = qcms_profile_sRGB();
398 if (outputDeviceProfile)
399 qcms_profile_precache_output_transform(outputDeviceProfile);
400 }
401 return outputDeviceProfile;
402 }
403 #endif
404
405 // Sets the "decode failure" flag. For caller convenience (since so
406 // many callers want to return false after calling this), returns false
407 // to enable easy tailcalling. Subclasses may override this to also
408 // clean up any local data.
409 virtual bool setFailed()
410 {
411 m_failed = true;
412 return false;
413 }
414
415 bool failed() const { return m_failed; }
416
417 // Clears decoded pixel data from all frames except the provided frame.
418 // Callers may pass WTF::kNotFound to clear all frames.
419 // Note: If |m_frameBufferCache| contains only one frame, it won't be cl eared.
420 // Returns the number of bytes of frame data actually cleared.
421 virtual size_t clearCacheExceptFrame(size_t);
422
423 // If the image has a cursor hot-spot, stores it in the argument
424 // and returns true. Otherwise returns false.
425 virtual bool hotSpot(IntPoint&) const { return false; }
426
427 virtual void setMemoryAllocator(SkBitmap::Allocator* allocator)
428 {
429 // FIXME: this doesn't work for images with multiple frames.
430 if (m_frameBufferCache.isEmpty()) {
431 m_frameBufferCache.resize(1);
432 m_frameBufferCache[0].setRequiredPreviousFrameIndex(
433 findRequiredPreviousFrame(0, false));
434 }
435 m_frameBufferCache[0].setMemoryAllocator(allocator);
436 }
437
438 protected:
439 // Calculates the most recent frame whose image data may be needed in
440 // order to decode frame |frameIndex|, based on frame disposal methods
441 // and |frameRectIsOpaque|, where |frameRectIsOpaque| signifies whether
442 // the rectangle of frame at |frameIndex| is known to be opaque.
443 // If no previous frame's data is required, returns WTF::kNotFound.
444 //
445 // This function requires that the previous frame's
446 // |m_requiredPreviousFrameIndex| member has been set correctly. The
447 // easiest way to ensure this is for subclasses to call this method and
448 // store the result on the frame via setRequiredPreviousFrameIndex()
449 // as soon as the frame has been created and parsed sufficiently to
450 // determine the disposal method; assuming this happens for all frames
451 // in order, the required invariant will hold.
452 //
453 // Image formats which do not use more than one frame do not need to
454 // worry about this; see comments on
455 // ImageFrame::m_requiredPreviousFrameIndex.
456 size_t findRequiredPreviousFrame(size_t frameIndex, bool frameRectIsOpaq ue);
457
458 virtual void clearFrameBuffer(size_t frameIndex);
459
460 RefPtr<SharedBuffer> m_data; // The encoded data.
461 Vector<ImageFrame, 1> m_frameBufferCache;
462 bool m_premultiplyAlpha;
463 bool m_ignoreGammaAndColorProfile;
464 ImageOrientation m_orientation;
465
466 // The maximum amount of memory a decoded image should require. Ideally,
467 // image decoders should downsample large images to fit under this limit
468 // (and then return the downsampled size from decodedSize()). Ignoring
469 // this limit can cause excessive memory use or even crashes on low-
470 // memory devices.
471 size_t m_maxDecodedBytes;
472
473 private:
474 // Some code paths compute the size of the image as "width * height * 4"
475 // and return it as a (signed) int. Avoid overflow.
476 static bool sizeCalculationMayOverflow(unsigned width, unsigned height)
477 {
478 unsigned long long total_size = static_cast<unsigned long long>(widt h)
479 * static_cast<unsigned long long>(heig ht);
480 return total_size > ((1 << 29) - 1);
481 }
482
483 IntSize m_size;
484 bool m_sizeAvailable;
485 bool m_isAllDataReceived;
486 bool m_failed;
487 };
488
489 } // namespace WebCore
490
491 #endif
OLDNEW
« no previous file with comments | « Source/core/platform/graphics/win/UniscribeHelperTextRun.cpp ('k') | Source/core/platform/image-decoders/ImageDecoder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698