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

Side by Side Diff: src/codec/SkScaledCodec.cpp

Issue 1365313002: Merge SkCodec with SkScanlineDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 2 months 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
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCodecPriv.h" 8 #include "SkCodecPriv.h"
9 #include "SkScaledCodec.h" 9 #include "SkScaledCodec.h"
10 #include "SkStream.h" 10 #include "SkStream.h"
11 #include "SkWebpCodec.h" 11 #include "SkWebpCodec.h"
12 12
13 13
14 SkCodec* SkScaledCodec::NewFromStream(SkStream* stream) { 14 SkCodec* SkScaledCodec::NewFromStream(SkStream* stream) {
15 bool isWebp = SkWebpCodec::IsWebp(stream); 15 bool isWebp = SkWebpCodec::IsWebp(stream);
16 if (!stream->rewind()) { 16 if (!stream->rewind()) {
17 return nullptr; 17 return nullptr;
18 } 18 }
19 if (isWebp) { 19 if (isWebp) {
20 // Webp codec supports scaling and subsetting natively 20 // Webp codec supports scaling and subsetting natively
21 return SkWebpCodec::NewFromStream(stream); 21 return SkWebpCodec::NewFromStream(stream);
22 } 22 }
23 23
24 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(SkScanlineDecoder::NewFromS tream(stream)); 24 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
25 if (nullptr == scanlineDecoder) { 25 if (nullptr == codec) {
26 return nullptr; 26 return nullptr;
27 } 27 }
28 28
29 // wrap in new SkScaledCodec 29 // wrap in new SkScaledCodec
30 return new SkScaledCodec(scanlineDecoder.detach()); 30 return new SkScaledCodec(codec.detach());
31 } 31 }
32 32
33 SkCodec* SkScaledCodec::NewFromData(SkData* data) { 33 SkCodec* SkScaledCodec::NewFromData(SkData* data) {
34 if (!data) { 34 if (!data) {
35 return nullptr; 35 return nullptr;
36 } 36 }
37 return NewFromStream(new SkMemoryStream(data)); 37 return NewFromStream(new SkMemoryStream(data));
38 } 38 }
39 39
40 SkScaledCodec::SkScaledCodec(SkScanlineDecoder* scanlineDecoder) 40 SkScaledCodec::SkScaledCodec(SkCodec* codec)
41 : INHERITED(scanlineDecoder->getInfo(), nullptr) 41 : INHERITED(codec->getInfo(), nullptr)
42 , fScanlineDecoder(scanlineDecoder) 42 , fCodec(codec)
43 {} 43 {}
44 44
45 SkScaledCodec::~SkScaledCodec() {} 45 SkScaledCodec::~SkScaledCodec() {}
46 46
47 static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& na tiveDims, 47 static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& na tiveDims,
48 const SkISize& scaledCodecDims, float desi redScale) { 48 const SkISize& scaledCodecDims, float desi redScale) {
49 if (nativeDims == scaledCodecDims) { 49 if (nativeDims == scaledCodecDims) {
50 // does not matter which to return if equal. Return here to skip below c alculations 50 // does not matter which to return if equal. Return here to skip below c alculations
51 return nativeDims; 51 return nativeDims;
52 } 52 }
(...skipping 18 matching lines...) Expand all
71 71
72 // return dimensions closest to ideal dimensions. 72 // return dimensions closest to ideal dimensions.
73 // If the differences are equal, return nativeDims, as native scaling is mor e efficient. 73 // If the differences are equal, return nativeDims, as native scaling is mor e efficient.
74 return nativeDiff > scaledCodecDiff ? scaledCodecDims : nativeDims; 74 return nativeDiff > scaledCodecDiff ? scaledCodecDims : nativeDims;
75 } 75 }
76 76
77 /* 77 /*
78 * Return a valid set of output dimensions for this decoder, given an input scal e 78 * Return a valid set of output dimensions for this decoder, given an input scal e
79 */ 79 */
80 SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const { 80 SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const {
81 SkISize nativeDimensions = fScanlineDecoder->getScaledDimensions(desiredScal e); 81 SkISize nativeDimensions = fCodec->getScaledDimensions(desiredScale);
82 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ... 82 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ...
83 SkISize scaledCodecDimensions; 83 SkISize scaledCodecDimensions;
84 if (desiredScale > 0.5f) { 84 if (desiredScale > 0.5f) {
85 // sampleSize = 1 85 // sampleSize = 1
86 scaledCodecDimensions = fScanlineDecoder->getInfo().dimensions(); 86 scaledCodecDimensions = fCodec->getInfo().dimensions();
87 } 87 }
88 // sampleSize determines the step size between samples 88 // sampleSize determines the step size between samples
89 // Ex: sampleSize = 2, sample every second pixel in x and y directions 89 // Ex: sampleSize = 2, sample every second pixel in x and y directions
90 int sampleSize = int ((1.0f / desiredScale) + 0.5f); 90 int sampleSize = int ((1.0f / desiredScale) + 0.5f);
91 91
92 int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize); 92 int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize);
93 int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize ); 93 int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize );
94 94
95 // Return the calculated output dimensions for the given scale 95 // Return the calculated output dimensions for the given scale
96 scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight); 96 scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 178
179 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst, 179 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst,
180 size_t rowBytes, const Options& optio ns, 180 size_t rowBytes, const Options& optio ns,
181 SkPMColor ctable[], int* ctableCount) { 181 SkPMColor ctable[], int* ctableCount) {
182 182
183 if (options.fSubset) { 183 if (options.fSubset) {
184 // Subsets are not supported. 184 // Subsets are not supported.
185 return kUnimplemented; 185 return kUnimplemented;
186 } 186 }
187 187
188 Result result = fScanlineDecoder->start(requestedInfo, &options, ctable, cta bleCount); 188 Result result = fCodec->start(requestedInfo, &options, ctable, ctableCount);
189 if (kSuccess == result) { 189 if (kSuccess == result) {
190 // native decode supported 190 // native decode supported
191 switch (fScanlineDecoder->getScanlineOrder()) { 191 switch (fCodec->getScanlineOrder()) {
192 case SkScanlineDecoder::kTopDown_SkScanlineOrder: 192 case SkCodec::kTopDown_SkScanlineOrder:
193 case SkScanlineDecoder::kBottomUp_SkScanlineOrder: 193 case SkCodec::kBottomUp_SkScanlineOrder:
194 case SkScanlineDecoder::kNone_SkScanlineOrder: 194 case SkCodec::kNone_SkScanlineOrder:
195 return fScanlineDecoder->getScanlines(dst, requestedInfo.height( ), rowBytes); 195 return fCodec->getScanlines(dst, requestedInfo.height(), rowByte s);
196 case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { 196 case SkCodec::kOutOfOrder_SkScanlineOrder: {
197 for (int y = 0; y < requestedInfo.height(); y++) { 197 for (int y = 0; y < requestedInfo.height(); y++) {
198 int dstY = fScanlineDecoder->getY(); 198 int dstY = fCodec->getY();
199 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); 199 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY);
200 result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes) ; 200 result = fCodec->getScanlines(dstPtr, 1, rowBytes);
201 // FIXME (msarett): Make the SkCodec base class take care of filling 201 // FIXME (msarett): Make the SkCodec base class take care of filling
202 // uninitialized pixels so we can return immediately on kInc ompleteInput. 202 // uninitialized pixels so we can return immediately on kInc ompleteInput.
203 if (kSuccess != result && kIncompleteInput != result) { 203 if (kSuccess != result && kIncompleteInput != result) {
204 return result; 204 return result;
205 } 205 }
206 } 206 }
207 return result; 207 return result;
208 } 208 }
209 } 209 }
210 } 210 }
211 211
212 if (kInvalidScale != result) { 212 if (kInvalidScale != result) {
213 // no scaling requested 213 // no scaling requested
214 return result; 214 return result;
215 } 215 }
216 216
217 // scaling requested 217 // scaling requested
218 int sampleX; 218 int sampleX;
219 int sampleY; 219 int sampleY;
220 if (!scaling_supported(requestedInfo, fScanlineDecoder->getInfo(), &sampleX, &sampleY)) { 220 if (!scaling_supported(requestedInfo, fCodec->getInfo(), &sampleX, &sampleY) ) {
221 return kInvalidScale; 221 return kInvalidScale;
222 } 222 }
223 // set first sample pixel in y direction 223 // set first sample pixel in y direction
224 int Y0 = get_start_coord(sampleY); 224 int Y0 = get_start_coord(sampleY);
225 225
226 int dstHeight = requestedInfo.height(); 226 int dstHeight = requestedInfo.height();
227 int srcHeight = fScanlineDecoder->getInfo().height(); 227 int srcHeight = fCodec->getInfo().height();
228 228
229 SkImageInfo info = requestedInfo; 229 SkImageInfo info = requestedInfo;
230 // use original height as scanlineDecoder does not support y sampling native ly 230 // use original height as codec does not support y sampling natively
231 info = info.makeWH(requestedInfo.width(), srcHeight); 231 info = info.makeWH(requestedInfo.width(), srcHeight);
232 232
233 // update scanlineDecoder with new info 233 // update codec with new info
234 result = fScanlineDecoder->start(info, &options, ctable, ctableCount); 234 result = fCodec->start(info, &options, ctable, ctableCount);
235 if (kSuccess != result) { 235 if (kSuccess != result) {
236 return result; 236 return result;
237 } 237 }
238 238
239 switch(fScanlineDecoder->getScanlineOrder()) { 239 switch(fCodec->getScanlineOrder()) {
240 case SkScanlineDecoder::kTopDown_SkScanlineOrder: { 240 case SkCodec::kTopDown_SkScanlineOrder: {
241 result = fScanlineDecoder->skipScanlines(Y0); 241 result = fCodec->skipScanlines(Y0);
242 if (kSuccess != result && kIncompleteInput != result) { 242 if (kSuccess != result && kIncompleteInput != result) {
243 return result; 243 return result;
244 } 244 }
245 for (int y = 0; y < dstHeight; y++) { 245 for (int y = 0; y < dstHeight; y++) {
246 result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); 246 result = fCodec->getScanlines(dst, 1, rowBytes);
247 if (kSuccess != result && kIncompleteInput != result) { 247 if (kSuccess != result && kIncompleteInput != result) {
248 return result; 248 return result;
249 } 249 }
250 if (y < dstHeight - 1) { 250 if (y < dstHeight - 1) {
251 result = fScanlineDecoder->skipScanlines(sampleY - 1); 251 result = fCodec->skipScanlines(sampleY - 1);
252 if (kSuccess != result && kIncompleteInput != result) { 252 if (kSuccess != result && kIncompleteInput != result) {
253 return result; 253 return result;
254 } 254 }
255 } 255 }
256 dst = SkTAddOffset<void>(dst, rowBytes); 256 dst = SkTAddOffset<void>(dst, rowBytes);
257 } 257 }
258 return result; 258 return result;
259 } 259 }
260 case SkScanlineDecoder::kBottomUp_SkScanlineOrder: 260 case SkCodec::kBottomUp_SkScanlineOrder:
261 case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { 261 case SkCodec::kOutOfOrder_SkScanlineOrder: {
262 for (int y = 0; y < srcHeight; y++) { 262 for (int y = 0; y < srcHeight; y++) {
263 int srcY = fScanlineDecoder->getY(); 263 int srcY = fCodec->getY();
264 if (is_coord_necessary(srcY, sampleY, dstHeight)) { 264 if (is_coord_necessary(srcY, sampleY, dstHeight)) {
265 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_co ord(srcY, sampleY)); 265 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_co ord(srcY, sampleY));
266 result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes) ; 266 result = fCodec->getScanlines(dstPtr, 1, rowBytes);
267 if (kSuccess != result && kIncompleteInput != result) { 267 if (kSuccess != result && kIncompleteInput != result) {
268 return result; 268 return result;
269 } 269 }
270 } else { 270 } else {
271 result = fScanlineDecoder->skipScanlines(1); 271 result = fCodec->skipScanlines(1);
272 if (kSuccess != result && kIncompleteInput != result) { 272 if (kSuccess != result && kIncompleteInput != result) {
273 return result; 273 return result;
274 } 274 }
275 } 275 }
276 } 276 }
277 return result; 277 return result;
278 } 278 }
279 case SkScanlineDecoder::kNone_SkScanlineOrder: { 279 case SkCodec::kNone_SkScanlineOrder: {
280 SkAutoMalloc storage(srcHeight * rowBytes); 280 SkAutoMalloc storage(srcHeight * rowBytes);
281 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); 281 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get());
282 result = fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBy tes); 282 result = fCodec->getScanlines(storagePtr, srcHeight, rowBytes);
283 if (kSuccess != result && kIncompleteInput != result) { 283 if (kSuccess != result && kIncompleteInput != result) {
284 return result; 284 return result;
285 } 285 }
286 storagePtr += Y0 * rowBytes; 286 storagePtr += Y0 * rowBytes;
287 for (int y = 0; y < dstHeight; y++) { 287 for (int y = 0; y < dstHeight; y++) {
288 memcpy(dst, storagePtr, rowBytes); 288 memcpy(dst, storagePtr, rowBytes);
289 storagePtr += sampleY * rowBytes; 289 storagePtr += sampleY * rowBytes;
290 dst = SkTAddOffset<void>(dst, rowBytes); 290 dst = SkTAddOffset<void>(dst, rowBytes);
291 } 291 }
292 return result; 292 return result;
293 } 293 }
294 default: 294 default:
295 SkASSERT(false); 295 SkASSERT(false);
296 return kUnimplemented; 296 return kUnimplemented;
297 } 297 }
298 } 298 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698