blob: ea129642db15617ccf4f2a1f23b96c2a2979d9de [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkImageRef.h"
9#include "SkBitmap.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000010#include "SkReadBuffer.h"
11#include "SkWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkImageDecoder.h"
13#include "SkStream.h"
14#include "SkTemplates.h"
15#include "SkThread.h"
16
reed@android.comc6ddc112009-11-10 15:54:55 +000017//#define DUMP_IMAGEREF_LIFECYCLE
18
reed@android.com8a1c16f2008-12-17 15:59:43 +000019///////////////////////////////////////////////////////////////////////////////
20
reed@google.combf790232013-12-13 19:45:58 +000021SkImageRef::SkImageRef(const SkImageInfo& info, SkStreamRewindable* stream,
djsollen@google.com528a5562013-02-01 15:57:13 +000022 int sampleSize, SkBaseMutex* mutex)
reed@google.comd0419b12014-01-06 17:08:27 +000023 : INHERITED(info, mutex), fErrorInDecoding(false)
24{
reed@android.com8a1c16f2008-12-17 15:59:43 +000025 SkASSERT(stream);
reed@android.com1337a7b2009-03-16 13:56:10 +000026 stream->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +000027 fStream = stream;
reed@android.com8a1c16f2008-12-17 15:59:43 +000028 fSampleSize = sampleSize;
reed@android.combb9aea92009-09-24 17:21:05 +000029 fDoDither = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000030 fPrev = fNext = NULL;
reed@android.coma14ea0e2009-03-17 17:59:53 +000031 fFactory = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +000032
33#ifdef DUMP_IMAGEREF_LIFECYCLE
34 SkDebugf("add ImageRef %p [%d] data=%d\n",
reed@google.combf790232013-12-13 19:45:58 +000035 this, this->info().fColorType, (int)stream->getLength());
reed@android.com8a1c16f2008-12-17 15:59:43 +000036#endif
37}
38
39SkImageRef::~SkImageRef() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000040
41#ifdef DUMP_IMAGEREF_LIFECYCLE
42 SkDebugf("delete ImageRef %p [%d] data=%d\n",
reed@google.comd0419b12014-01-06 17:08:27 +000043 this, this->info().fColorType, (int)fStream->getLength());
reed@android.com8a1c16f2008-12-17 15:59:43 +000044#endif
45
reed@android.com1337a7b2009-03-16 13:56:10 +000046 fStream->unref();
reed@google.com82065d62011-02-07 15:30:46 +000047 SkSafeUnref(fFactory);
reed@android.com8a1c16f2008-12-17 15:59:43 +000048}
49
50bool SkImageRef::getInfo(SkBitmap* bitmap) {
djsollen@google.com528a5562013-02-01 15:57:13 +000051 SkAutoMutexAcquire ac(this->mutex());
reed@google.com82065d62011-02-07 15:30:46 +000052
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) {
54 return false;
55 }
reed@google.com82065d62011-02-07 15:30:46 +000056
reed@android.com8a1c16f2008-12-17 15:59:43 +000057 SkASSERT(SkBitmap::kNo_Config != fBitmap.config());
58 if (bitmap) {
59 bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height());
60 }
61 return true;
62}
63
djsollen@google.com57f49692011-02-23 20:46:31 +000064bool SkImageRef::isOpaque(SkBitmap* bitmap) {
65 if (bitmap && bitmap->pixelRef() == this) {
66 bitmap->lockPixels();
reed@google.com383a6972013-10-21 14:00:07 +000067 // what about colortables??????
68 bitmap->setAlphaType(fBitmap.alphaType());
djsollen@google.com57f49692011-02-23 20:46:31 +000069 bitmap->unlockPixels();
70 return true;
71 }
72 return false;
73}
74
reed@android.coma14ea0e2009-03-17 17:59:53 +000075SkImageDecoderFactory* SkImageRef::setDecoderFactory(
76 SkImageDecoderFactory* fact) {
77 SkRefCnt_SafeAssign(fFactory, fact);
78 return fact;
79}
80
reed@android.com8a1c16f2008-12-17 15:59:43 +000081///////////////////////////////////////////////////////////////////////////////
82
scroggo@google.comb5571b32013-09-25 21:34:24 +000083bool SkImageRef::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
reed@android.com8a1c16f2008-12-17 15:59:43 +000084 SkBitmap* bitmap, SkBitmap::Config config,
85 SkImageDecoder::Mode mode) {
86 return codec->decode(stream, bitmap, config, mode);
87}
88
89bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000090
91 if (fErrorInDecoding) {
92 return false;
93 }
reed@google.com82065d62011-02-07 15:30:46 +000094
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 if (NULL != fBitmap.getPixels() ||
96 (SkBitmap::kNo_Config != fBitmap.config() &&
97 SkImageDecoder::kDecodeBounds_Mode == mode)) {
98 return true;
99 }
100
101 SkASSERT(fBitmap.getPixels() == NULL);
102
scroggo@google.com4d213ab2013-08-28 13:08:54 +0000103 if (!fStream->rewind()) {
104 SkDEBUGF(("Failed to rewind SkImageRef stream!"));
105 return false;
106 }
reed@android.coma14ea0e2009-03-17 17:59:53 +0000107
108 SkImageDecoder* codec;
109 if (fFactory) {
110 codec = fFactory->newDecoder(fStream);
111 } else {
112 codec = SkImageDecoder::Factory(fStream);
113 }
114
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115 if (codec) {
116 SkAutoTDelete<SkImageDecoder> ad(codec);
117
118 codec->setSampleSize(fSampleSize);
reed@android.combb9aea92009-09-24 17:21:05 +0000119 codec->setDitherImage(fDoDither);
reed@google.combf790232013-12-13 19:45:58 +0000120 if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121 return true;
122 }
123 }
124
125#ifdef DUMP_IMAGEREF_LIFECYCLE
126 if (NULL == codec) {
127 SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI());
128 } else {
129 SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n",
130 this->getURI(), mode);
131 }
132#endif
133 fErrorInDecoding = true;
134 fBitmap.reset();
135 return false;
136}
137
reed@google.comd0419b12014-01-06 17:08:27 +0000138bool SkImageRef::onNewLockPixels(LockRec* rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 if (NULL == fBitmap.getPixels()) {
140 (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
141 }
142
reed@google.comd0419b12014-01-06 17:08:27 +0000143 if (NULL == fBitmap.getPixels()) {
144 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 }
reed@google.comd0419b12014-01-06 17:08:27 +0000146 rec->fPixels = fBitmap.getPixels();
147 rec->fColorTable = NULL;
148 rec->fRowBytes = fBitmap.rowBytes();
149 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150}
151
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152size_t SkImageRef::ramUsed() const {
153 size_t size = 0;
154
155 if (fBitmap.getPixels()) {
156 size = fBitmap.getSize();
157 if (fBitmap.getColorTable()) {
158 size += fBitmap.getColorTable()->count() * sizeof(SkPMColor);
159 }
160 }
161 return size;
162}
163
164///////////////////////////////////////////////////////////////////////////////
165
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000166SkImageRef::SkImageRef(SkReadBuffer& buffer, SkBaseMutex* mutex)
djsollen@google.com528a5562013-02-01 15:57:13 +0000167 : INHERITED(buffer, mutex), fErrorInDecoding(false) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000168 fSampleSize = buffer.readInt();
reed@android.comc6ddc112009-11-10 15:54:55 +0000169 fDoDither = buffer.readBool();
170
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000171 size_t length = buffer.getArrayCount();
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000172 if (buffer.validateAvailable(length)) {
173 fStream = SkNEW_ARGS(SkMemoryStream, (length));
174 buffer.readByteArray((void*)fStream->getMemoryBase(), length);
175 } else {
176 fStream = NULL;
177 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178
179 fPrev = fNext = NULL;
reed@android.com797d51a2009-03-20 12:08:57 +0000180 fFactory = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181}
182
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000183void SkImageRef::flatten(SkWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 this->INHERITED::flatten(buffer);
185
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000186 buffer.writeInt(fSampleSize);
reed@android.comc6ddc112009-11-10 15:54:55 +0000187 buffer.writeBool(fDoDither);
scroggo@google.com4d213ab2013-08-28 13:08:54 +0000188 // FIXME: Consider moving this logic should go into writeStream itself.
189 // writeStream currently has no other callers, so this may be fine for
190 // now.
191 if (!fStream->rewind()) {
192 SkDEBUGF(("Failed to rewind SkImageRef stream!"));
193 buffer.write32(0);
194 } else {
195 // FIXME: Handle getLength properly here. Perhaps this class should
196 // take an SkStreamAsset.
197 buffer.writeStream(fStream, fStream->getLength());
198 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000199}