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

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

Issue 1260673002: SkScaledCodec class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: use SkWebpCodec native scaling, update comments and spacing Created 5 years, 4 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
(Empty)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkCodecPriv.h"
9 #include "SkScaledCodec.h"
10 #include "SkStream.h"
11 #include "SkWebpCodec.h"
12
13
14 SkCodec* SkScaledCodec::NewFromStream(SkStream* stream) {
15 bool isWebp = SkWebpCodec::IsWebp(stream);
scroggo 2015/07/27 19:29:57 I'd prefer to not include SkWebpCodec here, and re
emmaleer 2015/07/28 14:19:16 Okay, I like that method better too. Just checking
scroggo 2015/07/28 15:58:10 Yeah. For a long time, C++ did not have a standar
emmaleer 2015/07/29 21:55:08 Acknowledged.
16 if (!stream->rewind()) {
17 return NULL;
18 }
19 if (isWebp) {
20 // Webp supports scaling natively
21 return SkWebpCodec::NewFromStream(stream);
22 }
23 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
24 if (NULL == codec) {
25 return NULL;
26 }
27 return SkNEW_ARGS(SkScaledCodec, (codec.detach()));
28 }
29
30 SkCodec* SkScaledCodec::NewFromData(SkData* data) {
31 if (!data) {
32 return NULL;
33 }
34 return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data)));
35 }
36
37 SkScaledCodec::SkScaledCodec(SkCodec* codec)
38 : INHERITED(codec->getInfo(), NULL)
39 , fCodec(codec)
40 {}
41
42 SkScaledCodec::~SkScaledCodec() {}
43
44 /*
45 * Return a valid set of output dimensions for this decoder, given an input scal e
46 */
47 SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const {
48 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ...
49
50 if (desiredScale > 0.5f) {
51 // sampleSize = 1
52 return fCodec->getInfo().dimensions();
53 }
54 // sampleSize determines the step size between samples
55 // Ex: sampleSize = 2, sample every second pixel in x and y directions
56 int sampleSize = 1 / desiredScale;
57
58 // if sampleSize > width or height, will only sample 1 pixel in that directi on
59 int sampleX = SkMin32(sampleSize, this->getInfo().width());
60 int sampleY = SkMin32(sampleSize, this->getInfo().height());
61
62 int scaledWidth = this->getInfo().width() / sampleX;
63 int scaledHeight = this->getInfo().height() / sampleY;
msarett 2015/07/27 20:42:18 You're probably already aware of this, but we need
emmaleer 2015/07/28 14:19:16 This is inconsistent. I think it would be better i
msarett 2015/07/28 20:53:10 AFAICT it's an arbitrary decision.
64
65 // Return the calculated output dimensions for the given scale
66 return SkISize::Make(scaledWidth, scaledHeight);
67 }
68
69 // check if scaling to dstInfo size from srcInfo size is possible
70 static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& sr cInfo){
71 const int dstWidth = dstInfo.width();
72 const int dstHeight = dstInfo.height();
73 const int srcWidth = srcInfo.width();
74 const int srcHeight = srcInfo.height();
75 // only support down sampling, not up sampling
76 if (dstWidth > srcWidth || dstHeight > srcHeight) {
77 return false;
78 }
79 // check that srcWidth is scaled down by an integer value
80 int sampleSizeX = srcWidth / dstWidth;
81 if (srcWidth / sampleSizeX != dstWidth) {
82 return false;
83 }
84 // check that src height is scaled down by an integer value
85 int sampleSizeY = srcHeight / dstHeight;
86 if (srcHeight / sampleSizeY != dstHeight) {
87 return false;
88 }
89 // sampleX and sampleY should be equal unless the original sampleSize reques ted was larger
90 // than srcWidth or srcHeight. If so, the result of this is dstWidth or dstH eight = 1.
91 // This functionality allows for tall thin images to still be scaled down by scaling factors.
92 if (sampleSizeX != sampleSizeY){
93 if (1 != dstWidth && 1 != dstHeight) {
94 return false;
95 }
96 }
97 return true;
98 }
99
100 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst,
101 size_t rowBytes, const Options& optio ns,
102 SkPMColor ctable[], int* ctableCount) {
103
104 Result result = fCodec->getPixels(requestedInfo, dst, rowBytes, &options, ct able, ctableCount);
msarett 2015/07/27 20:42:18 I was going to comment that this seems strange, an
emmaleer 2015/07/28 14:19:16 Yes, this was intended. Okay, I've added a comment
msarett 2015/07/28 20:53:10 Thanks!
105 if (kInvalidScale != result) {
106 // no scaling requested
107 return result;
108 }
109 // scaling requested
110
111 if (!scaling_supported(requestedInfo, fCodec->getInfo())) {
112 return kInvalidScale;
113 }
114
115 bool isInterlaced = fCodec->isInterlaced();
msarett 2015/07/27 20:42:18 For now, isInterlaced() is a decent name for this.
scroggo 2015/07/27 20:47:24 My first thought was the name isSampleable(), but
emmaleer 2015/07/28 14:19:16 What about PostYSample()? Since we have to sample
scroggo 2015/07/28 15:58:10 PostYSample() sounds to me like it actually does s
msarett 2015/07/28 20:53:10 What about isHardToSample()?
emmaleer 2015/07/29 21:55:08 I like isHardToSample, since it's more broad, and
scroggo 2015/07/30 17:53:01 It is broad, but it's not obvious to me what hard
emmaleer 2015/07/30 22:27:55 Should we use requiresPostSampling() ? or what abo
116 Options scaledOptions = options;
117 scaledOptions.fSampled = true;
118
119 int dstHeight = requestedInfo.height();
120 int srcHeight = fCodec->getInfo().height();
121
122 SkImageInfo info = requestedInfo;
123 if (isInterlaced){
124 // must decode entire height for interlaced, then scale after
125 info = info.makeWH(requestedInfo.width(), srcHeight);
126 }
127
128 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(fCodec->getScanlineDecoder( info,
129 &scaledOptions, ctable, cta bleCount));
130 if (NULL == scanlineDecoder) {
131 SkCodecPrintf("failed to create scanline decoder.\n");
132 return kInvalidInput;
133 }
134
135 // set sample values in x and y directions
136 int sampleY = srcHeight / dstHeight;
137 int Y0 = sampleY >> 1;
138 int sampleX = fCodec->getInfo().width() / requestedInfo.width();
139 if (!scanlineDecoder->setSampleX(sampleX)) {
140 return kInvalidScale;
141 }
142
143 if (isInterlaced) {
144 SkAutoMalloc storage(srcHeight * rowBytes);
145 void* storagePtr = storage.get();
146 result = scanlineDecoder->getScanlines(storagePtr, srcHeight, rowBytes);
147
148 storagePtr += Y0 * rowBytes;
149 for (int y = 0; y < dstHeight; y++) {
150 memcpy(dst, storagePtr, rowBytes);
151 storagePtr += sampleY * rowBytes;
152 dst += rowBytes;
153 }
154 } else {
155 // not interlaced
156 scanlineDecoder->skipScanlines(Y0);
157 for (int y = 0; y < dstHeight; y++) {
158 scanlineDecoder->getScanlines(dst, 1, rowBytes);
159 if (y < dstHeight - 1) {
160 scanlineDecoder->skipScanlines(sampleY - 1);
161 }
162 dst += rowBytes;
163 }
164 }
165 return kSuccess;
166 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698