OLD | NEW |
---|---|
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" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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); |
97 | 97 |
98 return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions , | 98 return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions , |
99 scaledCodecDimensions, desiredScale); | 99 scaledCodecDimensions, desiredScale); |
100 } | 100 } |
101 | 101 |
102 // check if scaling to dstInfo size from srcInfo size using sampleSize is possib le | 102 // check if scaling to dstInfo size from srcInfo size using sampleSize is possib le |
103 static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& src Info, | 103 static bool scaling_supported(const SkISize& dstDim, const SkISize& srcDim, |
104 int* sampleX, int* sampleY) { | 104 int* sampleX, int* sampleY) { |
105 SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, sampleX, sampleY); | 105 SkScaledCodec::ComputeSampleSize(dstDim, srcDim, sampleX, sampleY); |
106 const int dstWidth = dstInfo.width(); | 106 const int dstWidth = dstDim.width(); |
107 const int dstHeight = dstInfo.height(); | 107 const int dstHeight = dstDim.height(); |
108 const int srcWidth = srcInfo.width(); | 108 const int srcWidth = srcDim.width(); |
109 const int srcHeight = srcInfo.height(); | 109 const int srcHeight = srcDim.height(); |
110 // only support down sampling, not up sampling | 110 // only support down sampling, not up sampling |
111 if (dstWidth > srcWidth || dstHeight > srcHeight) { | 111 if (dstWidth > srcWidth || dstHeight > srcHeight) { |
112 return false; | 112 return false; |
113 } | 113 } |
114 // check that srcWidth is scaled down by an integer value | 114 // check that srcWidth is scaled down by an integer value |
115 if (get_scaled_dimension(srcWidth, *sampleX) != dstWidth) { | 115 if (get_scaled_dimension(srcWidth, *sampleX) != dstWidth) { |
116 return false; | 116 return false; |
117 } | 117 } |
118 // check that src height is scaled down by an integer value | 118 // check that src height is scaled down by an integer value |
119 if (get_scaled_dimension(srcHeight, *sampleY) != dstHeight) { | 119 if (get_scaled_dimension(srcHeight, *sampleY) != dstHeight) { |
120 return false; | 120 return false; |
121 } | 121 } |
122 // sampleX and sampleY should be equal unless the original sampleSize reques ted was larger | 122 // sampleX and sampleY should be equal unless the original sampleSize reques ted was larger |
123 // than srcWidth or srcHeight. If so, the result of this is dstWidth or dstH eight = 1. | 123 // than srcWidth or srcHeight. If so, the result of this is dstWidth or dstH eight = 1. |
124 // This functionality allows for tall thin images to still be scaled down by scaling factors. | 124 // This functionality allows for tall thin images to still be scaled down by scaling factors. |
125 if (*sampleX != *sampleY){ | 125 if (*sampleX != *sampleY){ |
126 if (1 != dstWidth && 1 != dstHeight) { | 126 if (1 != dstWidth && 1 != dstHeight) { |
127 return false; | 127 return false; |
128 } | 128 } |
129 } | 129 } |
130 return true; | 130 return true; |
131 } | 131 } |
132 | 132 |
133 bool SkScaledCodec::onDimensionsSupported(const SkISize& dim) { | |
134 // Check with fCodec first. No need to call the non-virtual version, which | |
135 // just checks if it matches the original, since a match means this method | |
136 // will not be called. | |
137 if (fCodec->onDimensionsSupported(dim)) { | |
138 return true; | |
139 } | |
140 | |
141 // FIXME: These variables are unused, but are needed by scaling_supported. | |
142 // This class could also cache these values, and avoid calling this in | |
143 // onGetPixels (since getPixels already calls it). | |
144 int sampleX; | |
145 int sampleY; | |
146 return scaling_supported(dim, this->getInfo().dimensions(), &sampleX, &sampl eY); | |
147 } | |
148 | |
133 // calculates sampleSize in x and y direction | 149 // calculates sampleSize in x and y direction |
134 void SkScaledCodec::ComputeSampleSize(const SkImageInfo& dstInfo, const SkImageI nfo& srcInfo, | 150 void SkScaledCodec::ComputeSampleSize(const SkISize& dstDim, const SkISize& srcD im, |
135 int* sampleXPtr, int* sampleYPtr) { | 151 int* sampleXPtr, int* sampleYPtr) { |
136 int srcWidth = srcInfo.width(); | 152 int srcWidth = srcDim.width(); |
137 int dstWidth = dstInfo.width(); | 153 int dstWidth = dstDim.width(); |
138 int srcHeight = srcInfo.height(); | 154 int srcHeight = srcDim.height(); |
139 int dstHeight = dstInfo.height(); | 155 int dstHeight = dstDim.height(); |
140 | 156 |
141 int sampleX = srcWidth / dstWidth; | 157 int sampleX = srcWidth / dstWidth; |
142 int sampleY = srcHeight / dstHeight; | 158 int sampleY = srcHeight / dstHeight; |
143 | 159 |
144 // only support down sampling, not up sampling | 160 // only support down sampling, not up sampling |
145 SkASSERT(dstWidth <= srcWidth); | 161 SkASSERT(dstWidth <= srcWidth); |
146 SkASSERT(dstHeight <= srcHeight); | 162 SkASSERT(dstHeight <= srcHeight); |
147 | 163 |
148 // sampleX and sampleY should be equal unless the original sampleSize reques ted was | 164 // sampleX and sampleY should be equal unless the original sampleSize reques ted was |
149 // larger than srcWidth or srcHeight. | 165 // larger than srcWidth or srcHeight. |
(...skipping 26 matching lines...) Expand all Loading... | |
176 | 192 |
177 // TODO: Implement subsetting in onGetPixels which works when and when not sampl ing | 193 // TODO: Implement subsetting in onGetPixels which works when and when not sampl ing |
178 | 194 |
179 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst, | 195 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst, |
180 size_t rowBytes, const Options& optio ns, | 196 size_t rowBytes, const Options& optio ns, |
181 SkPMColor ctable[], int* ctableCount) { | 197 SkPMColor ctable[], int* ctableCount) { |
182 | 198 |
183 if (options.fSubset) { | 199 if (options.fSubset) { |
184 // Subsets are not supported. | 200 // Subsets are not supported. |
185 return kUnimplemented; | 201 return kUnimplemented; |
186 } | |
187 | |
188 // FIXME: If no scaling/subsets are requested, we can call fCodec->getPixels . | |
189 Result result = fCodec->startScanlineDecode(requestedInfo, &options, ctable, ctableCount); | |
190 if (kSuccess == result) { | |
191 // native decode supported | |
192 switch (fCodec->getScanlineOrder()) { | |
193 case SkCodec::kTopDown_SkScanlineOrder: | |
194 case SkCodec::kBottomUp_SkScanlineOrder: | |
195 case SkCodec::kNone_SkScanlineOrder: | |
196 return fCodec->getScanlines(dst, requestedInfo.height(), rowByte s); | |
197 case SkCodec::kOutOfOrder_SkScanlineOrder: { | |
198 for (int y = 0; y < requestedInfo.height(); y++) { | |
199 int dstY = fCodec->nextScanline(); | |
200 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); | |
201 result = fCodec->getScanlines(dstPtr, 1, rowBytes); | |
202 // FIXME (msarett): Make the SkCodec base class take care of filling | |
203 // uninitialized pixels so we can return immediately on kInc ompleteInput. | |
204 if (kSuccess != result && kIncompleteInput != result) { | |
205 return result; | |
206 } | |
207 } | |
208 return result; | |
209 } | |
210 } | |
211 } | 202 } |
212 | 203 |
213 if (kInvalidScale != result) { | 204 if (fCodec->dimensionsSupported(requestedInfo.dimensions())) { |
214 // no scaling requested | 205 return fCodec->getPixels(requestedInfo, dst, rowBytes, &options, ctable, ctableCount); |
msarett
2015/10/01 19:34:34
Unfortunately, I think I might change this back to
scroggo
2015/10/01 21:16:57
Well, it will have to do scanline decoding if ther
| |
215 return result; | |
216 } | 206 } |
217 | 207 |
218 // scaling requested | 208 // scaling requested |
219 int sampleX; | 209 int sampleX; |
220 int sampleY; | 210 int sampleY; |
221 if (!scaling_supported(requestedInfo, fCodec->getInfo(), &sampleX, &sampleY) ) { | 211 if (!scaling_supported(requestedInfo.dimensions(), fCodec->getInfo().dimensi ons(), |
212 &sampleX, &sampleY)) { | |
222 return kInvalidScale; | 213 return kInvalidScale; |
msarett
2015/10/01 19:34:34
I think we should probably assert false here, sinc
scroggo
2015/10/01 21:16:57
Done.
| |
223 } | 214 } |
215 | |
224 // set first sample pixel in y direction | 216 // set first sample pixel in y direction |
225 int Y0 = get_start_coord(sampleY); | 217 const int Y0 = get_start_coord(sampleY); |
226 | 218 |
227 int dstHeight = requestedInfo.height(); | 219 const int dstHeight = requestedInfo.height(); |
228 int srcHeight = fCodec->getInfo().height(); | 220 const int srcWidth = fCodec->getInfo().width(); |
229 | 221 const int srcHeight = fCodec->getInfo().height(); |
230 SkImageInfo info = requestedInfo; | |
231 // use original height as codec does not support y sampling natively | |
232 info = info.makeWH(requestedInfo.width(), srcHeight); | |
233 | 222 |
234 // update codec with new info | 223 const SkImageInfo info = requestedInfo.makeWH(srcWidth, srcHeight); |
235 // FIXME: The previous call to start returned kInvalidScale. This call may | 224 |
236 // require a rewind. (skbug.com/4284) | 225 Result result = fCodec->startScanlineDecode(info, &options, ctable, ctableCo unt); |
237 result = fCodec->startScanlineDecode(info, &options, ctable, ctableCount); | 226 |
238 if (kSuccess != result) { | 227 if (kSuccess != result) { |
239 return result; | 228 return result; |
240 } | 229 } |
241 | 230 |
231 SkSampler* sampler = fCodec->getSampler(); | |
232 if (!sampler) { | |
233 // Or maybe this should be unimplemented? | |
234 return kInvalidScale; | |
msarett
2015/10/01 19:34:34
I think it should be unimplemented.
scroggo
2015/10/01 21:16:57
Done.
| |
235 } | |
236 | |
237 sampler->setSampleX(sampleX); | |
238 | |
242 switch(fCodec->getScanlineOrder()) { | 239 switch(fCodec->getScanlineOrder()) { |
243 case SkCodec::kTopDown_SkScanlineOrder: { | 240 case SkCodec::kTopDown_SkScanlineOrder: { |
244 result = fCodec->skipScanlines(Y0); | 241 result = fCodec->skipScanlines(Y0); |
245 if (kSuccess != result && kIncompleteInput != result) { | 242 if (kSuccess != result && kIncompleteInput != result) { |
246 return result; | 243 return result; |
247 } | 244 } |
248 for (int y = 0; y < dstHeight; y++) { | 245 for (int y = 0; y < dstHeight; y++) { |
249 result = fCodec->getScanlines(dst, 1, rowBytes); | 246 result = fCodec->getScanlines(dst, 1, rowBytes); |
250 if (kSuccess != result && kIncompleteInput != result) { | 247 if (kSuccess != result && kIncompleteInput != result) { |
251 return result; | 248 return result; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
292 storagePtr += sampleY * rowBytes; | 289 storagePtr += sampleY * rowBytes; |
293 dst = SkTAddOffset<void>(dst, rowBytes); | 290 dst = SkTAddOffset<void>(dst, rowBytes); |
294 } | 291 } |
295 return result; | 292 return result; |
296 } | 293 } |
297 default: | 294 default: |
298 SkASSERT(false); | 295 SkASSERT(false); |
299 return kUnimplemented; | 296 return kUnimplemented; |
300 } | 297 } |
301 } | 298 } |
OLD | NEW |