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

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: Skip ICO in SkScaledCodec for now 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
« no previous file with comments | « src/codec/SkJpegCodec.cpp ('k') | src/codec/SkScanlineDecoder.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // FIXME: If no scaling/subsets are requested, we can call fCodec->getPixels .
189 Result result = fCodec->startScanlineDecode(requestedInfo, &options, ctable, ctableCount);
189 if (kSuccess == result) { 190 if (kSuccess == result) {
190 // native decode supported 191 // native decode supported
191 switch (fScanlineDecoder->getScanlineOrder()) { 192 switch (fCodec->getScanlineOrder()) {
192 case SkScanlineDecoder::kTopDown_SkScanlineOrder: 193 case SkCodec::kTopDown_SkScanlineOrder:
193 case SkScanlineDecoder::kBottomUp_SkScanlineOrder: 194 case SkCodec::kBottomUp_SkScanlineOrder:
194 case SkScanlineDecoder::kNone_SkScanlineOrder: 195 case SkCodec::kNone_SkScanlineOrder:
195 return fScanlineDecoder->getScanlines(dst, requestedInfo.height( ), rowBytes); 196 return fCodec->getScanlines(dst, requestedInfo.height(), rowByte s);
196 case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { 197 case SkCodec::kOutOfOrder_SkScanlineOrder: {
197 for (int y = 0; y < requestedInfo.height(); y++) { 198 for (int y = 0; y < requestedInfo.height(); y++) {
198 int dstY = fScanlineDecoder->getY(); 199 int dstY = fCodec->nextScanline();
199 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); 200 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY);
200 result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes) ; 201 result = fCodec->getScanlines(dstPtr, 1, rowBytes);
201 // FIXME (msarett): Make the SkCodec base class take care of filling 202 // FIXME (msarett): Make the SkCodec base class take care of filling
202 // uninitialized pixels so we can return immediately on kInc ompleteInput. 203 // uninitialized pixels so we can return immediately on kInc ompleteInput.
203 if (kSuccess != result && kIncompleteInput != result) { 204 if (kSuccess != result && kIncompleteInput != result) {
204 return result; 205 return result;
205 } 206 }
206 } 207 }
207 return result; 208 return result;
208 } 209 }
209 } 210 }
210 } 211 }
211 212
212 if (kInvalidScale != result) { 213 if (kInvalidScale != result) {
213 // no scaling requested 214 // no scaling requested
214 return result; 215 return result;
215 } 216 }
216 217
217 // scaling requested 218 // scaling requested
218 int sampleX; 219 int sampleX;
219 int sampleY; 220 int sampleY;
220 if (!scaling_supported(requestedInfo, fScanlineDecoder->getInfo(), &sampleX, &sampleY)) { 221 if (!scaling_supported(requestedInfo, fCodec->getInfo(), &sampleX, &sampleY) ) {
221 return kInvalidScale; 222 return kInvalidScale;
222 } 223 }
223 // set first sample pixel in y direction 224 // set first sample pixel in y direction
224 int Y0 = get_start_coord(sampleY); 225 int Y0 = get_start_coord(sampleY);
225 226
226 int dstHeight = requestedInfo.height(); 227 int dstHeight = requestedInfo.height();
227 int srcHeight = fScanlineDecoder->getInfo().height(); 228 int srcHeight = fCodec->getInfo().height();
228 229
229 SkImageInfo info = requestedInfo; 230 SkImageInfo info = requestedInfo;
230 // use original height as scanlineDecoder does not support y sampling native ly 231 // use original height as codec does not support y sampling natively
231 info = info.makeWH(requestedInfo.width(), srcHeight); 232 info = info.makeWH(requestedInfo.width(), srcHeight);
232 233
233 // update scanlineDecoder with new info 234 // update codec with new info
234 result = fScanlineDecoder->start(info, &options, ctable, ctableCount); 235 // FIXME: The previous call to start returned kInvalidScale. This call may
236 // require a rewind. (skbug.com/4284)
237 result = fCodec->startScanlineDecode(info, &options, ctable, ctableCount);
235 if (kSuccess != result) { 238 if (kSuccess != result) {
236 return result; 239 return result;
237 } 240 }
238 241
239 switch(fScanlineDecoder->getScanlineOrder()) { 242 switch(fCodec->getScanlineOrder()) {
240 case SkScanlineDecoder::kTopDown_SkScanlineOrder: { 243 case SkCodec::kTopDown_SkScanlineOrder: {
241 result = fScanlineDecoder->skipScanlines(Y0); 244 result = fCodec->skipScanlines(Y0);
242 if (kSuccess != result && kIncompleteInput != result) { 245 if (kSuccess != result && kIncompleteInput != result) {
243 return result; 246 return result;
244 } 247 }
245 for (int y = 0; y < dstHeight; y++) { 248 for (int y = 0; y < dstHeight; y++) {
246 result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); 249 result = fCodec->getScanlines(dst, 1, rowBytes);
247 if (kSuccess != result && kIncompleteInput != result) { 250 if (kSuccess != result && kIncompleteInput != result) {
248 return result; 251 return result;
249 } 252 }
250 if (y < dstHeight - 1) { 253 if (y < dstHeight - 1) {
251 result = fScanlineDecoder->skipScanlines(sampleY - 1); 254 result = fCodec->skipScanlines(sampleY - 1);
252 if (kSuccess != result && kIncompleteInput != result) { 255 if (kSuccess != result && kIncompleteInput != result) {
253 return result; 256 return result;
254 } 257 }
255 } 258 }
256 dst = SkTAddOffset<void>(dst, rowBytes); 259 dst = SkTAddOffset<void>(dst, rowBytes);
257 } 260 }
258 return result; 261 return result;
259 } 262 }
260 case SkScanlineDecoder::kBottomUp_SkScanlineOrder: 263 case SkCodec::kBottomUp_SkScanlineOrder:
261 case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { 264 case SkCodec::kOutOfOrder_SkScanlineOrder: {
262 for (int y = 0; y < srcHeight; y++) { 265 for (int y = 0; y < srcHeight; y++) {
263 int srcY = fScanlineDecoder->getY(); 266 int srcY = fCodec->nextScanline();
264 if (is_coord_necessary(srcY, sampleY, dstHeight)) { 267 if (is_coord_necessary(srcY, sampleY, dstHeight)) {
265 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_co ord(srcY, sampleY)); 268 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_co ord(srcY, sampleY));
266 result = fScanlineDecoder->getScanlines(dstPtr, 1, rowBytes) ; 269 result = fCodec->getScanlines(dstPtr, 1, rowBytes);
267 if (kSuccess != result && kIncompleteInput != result) { 270 if (kSuccess != result && kIncompleteInput != result) {
268 return result; 271 return result;
269 } 272 }
270 } else { 273 } else {
271 result = fScanlineDecoder->skipScanlines(1); 274 result = fCodec->skipScanlines(1);
272 if (kSuccess != result && kIncompleteInput != result) { 275 if (kSuccess != result && kIncompleteInput != result) {
273 return result; 276 return result;
274 } 277 }
275 } 278 }
276 } 279 }
277 return result; 280 return result;
278 } 281 }
279 case SkScanlineDecoder::kNone_SkScanlineOrder: { 282 case SkCodec::kNone_SkScanlineOrder: {
280 SkAutoMalloc storage(srcHeight * rowBytes); 283 SkAutoMalloc storage(srcHeight * rowBytes);
281 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); 284 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get());
282 result = fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBy tes); 285 result = fCodec->getScanlines(storagePtr, srcHeight, rowBytes);
283 if (kSuccess != result && kIncompleteInput != result) { 286 if (kSuccess != result && kIncompleteInput != result) {
284 return result; 287 return result;
285 } 288 }
286 storagePtr += Y0 * rowBytes; 289 storagePtr += Y0 * rowBytes;
287 for (int y = 0; y < dstHeight; y++) { 290 for (int y = 0; y < dstHeight; y++) {
288 memcpy(dst, storagePtr, rowBytes); 291 memcpy(dst, storagePtr, rowBytes);
289 storagePtr += sampleY * rowBytes; 292 storagePtr += sampleY * rowBytes;
290 dst = SkTAddOffset<void>(dst, rowBytes); 293 dst = SkTAddOffset<void>(dst, rowBytes);
291 } 294 }
292 return result; 295 return result;
293 } 296 }
294 default: 297 default:
295 SkASSERT(false); 298 SkASSERT(false);
296 return kUnimplemented; 299 return kUnimplemented;
297 } 300 }
298 } 301 }
OLDNEW
« no previous file with comments | « src/codec/SkJpegCodec.cpp ('k') | src/codec/SkScanlineDecoder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698