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 "DMSrcSink.h" | 8 #include "DMSrcSink.h" |
9 #include "SamplePipeControllers.h" | 9 #include "SamplePipeControllers.h" |
10 #include "SkCodec.h" | 10 #include "SkCodec.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 // We consider incomplete to be valid, since we should still decode what is | 134 // We consider incomplete to be valid, since we should still decode what is |
135 // available. | 135 // available. |
136 case SkImageGenerator::kIncompleteInput: | 136 case SkImageGenerator::kIncompleteInput: |
137 break; | 137 break; |
138 case SkImageGenerator::kInvalidConversion: | 138 case SkImageGenerator::kInvalidConversion: |
139 return Error::Nonfatal("Incompatible colortype conversion"); | 139 return Error::Nonfatal("Incompatible colortype conversion"); |
140 default: | 140 default: |
141 // Everything else is considered a failure. | 141 // Everything else is considered a failure. |
142 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str( )); | 142 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str( )); |
143 } | 143 } |
144 canvas->drawBitmap(bitmap, 0, 0); | |
144 break; | 145 break; |
145 case kScanline_Mode: { | 146 case kScanline_Mode: { |
146 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecoder(decod eInfo, NULL, | 147 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecoder(decod eInfo, NULL, |
147 colorPtr, colorCountPtr); | 148 colorPtr, colorCountPtr); |
148 if (NULL == scanlineDecoder) { | 149 if (NULL == scanlineDecoder) { |
149 return Error::Nonfatal("Cannot use scanline decoder for all imag es"); | 150 return Error::Nonfatal("Cannot use scanline decoder for all imag es"); |
150 } | 151 } |
151 for (int y = 0; y < decodeInfo.height(); ++y) { | 152 for (int y = 0; y < decodeInfo.height(); ++y) { |
152 const SkImageGenerator::Result result = scanlineDecoder->getScan lines( | 153 const SkImageGenerator::Result result = scanlineDecoder->getScan lines( |
153 bitmap.getAddr(0, y), 1, 0); | 154 bitmap.getAddr(0, y), 1, 0); |
154 switch (result) { | 155 switch (result) { |
155 case SkImageGenerator::kSuccess: | 156 case SkImageGenerator::kSuccess: |
156 case SkImageGenerator::kIncompleteInput: | 157 case SkImageGenerator::kIncompleteInput: |
157 break; | 158 break; |
158 default: | 159 default: |
159 return SkStringPrintf("%s failed after %d scanlines with error message %d", | 160 return SkStringPrintf("%s failed after %d scanlines with error message %d", |
160 fPath.c_str(), y-1, (int) result); | 161 fPath.c_str(), y-1, (int) result); |
161 } | 162 } |
162 } | 163 } |
164 canvas->drawBitmap(bitmap, 0, 0); | |
165 break; | |
166 } | |
167 case kScanline_Subset_Mode: { | |
168 //this mode decodes the image in divisor*divisor subsets, using a sc anline decoder | |
169 const int divisor = 2; | |
170 const int w = decodeInfo.width(); | |
171 const int h = decodeInfo.height(); | |
172 if (divisor > w || divisor > h) { | |
173 return SkStringPrintf("divisor %d is too big for %s with dimensi ons (%d x %d)", | |
174 divisor, fPath.c_str(), w, h); | |
175 } | |
176 const int subsetWidth = w/divisor; | |
177 const int subsetHeight = h/divisor; | |
178 /* | |
179 * if w or h are not evenly divided by divisor need to adjust width a nd height of end | |
180 * subsets to cover entire image. | |
181 * Add w%divisor and h%divisor to largestSubsetBm's width and height to adjust width | |
182 * and height of end subsets. | |
183 * subsetBm is extracted from largestSubsetBm. | |
184 * subsetBm's size is determined based on the current subset and may be larger for end | |
185 * subsets. | |
186 */ | |
187 SkImageInfo largestSubsetDecodeInfo = | |
188 decodeInfo.makeWH(subsetWidth + w%divisor, subsetHeight + h% divisor); | |
189 SkBitmap largestSubsetBm; | |
190 if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, NULL, c olorTable.get())) { | |
191 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPat h.c_str(), | |
192 largestSubsetDecodeInfo.width(), largestSubsetDecodeInfo .height()); | |
193 } | |
194 char* line = SkNEW_ARRAY(char, decodeInfo.minRowBytes()); | |
195 SkAutoTDeleteArray<char> lineDeleter(line); | |
196 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); | |
197 //used if image w and h are not evenly divided by divisor | |
198 int extraX = 0; | |
199 int extraY = 0; | |
200 //currentSubsetWidth may be larger than subsetWidth for end subsets | |
201 int currentSubsetWidth = subsetWidth + extraX; | |
202 int currentSubsetHeight = subsetHeight + extraY; | |
203 for (int x = 0; x < subsetWidth*divisor; x += subsetWidth) { | |
204 //consider extraX for rightmost subset | |
205 if (x + 2*subsetWidth > w) { | |
206 extraX = w - subsetWidth*divisor; | |
scroggo
2015/05/22 14:38:26
Can we remove extraX and extraY entirely? I think
emmaleeroach
2015/05/22 15:58:54
On 2015/05/22 14:38:26, scroggo wrote:
> Can we re
| |
207 currentSubsetWidth = subsetWidth + extraX; | |
208 } | |
209 for (int y = 0; y < subsetHeight*divisor; y += subsetHeight) { | |
210 //consider extraY for bottom subset | |
211 if (y + 2*subsetHeight > h) { | |
212 extraY = h - subsetHeight*divisor; | |
213 currentSubsetHeight = subsetHeight + extraY; | |
214 } | |
215 //create scanline decoder for each subset | |
216 SkScanlineDecoder* subsetScanlineDecoder = codec->getScanlin eDecoder(decodeInfo, | |
217 NULL, colorPtr, colorCountPtr); | |
218 if (NULL == subsetScanlineDecoder) { | |
219 if (x == 0 && y == 0){ | |
220 //first try, image may not be compatible | |
221 return Error::Nonfatal("Cannot use scanline decoder for all images"); | |
222 } else { | |
223 return "Error scanline decoder is NULL"; | |
224 } | |
225 } | |
226 //skip to first line of subset | |
227 const SkImageGenerator::Result skipResult = | |
228 subsetScanlineDecoder->skipScanlines(y); | |
229 switch (skipResult) { | |
230 case SkImageGenerator::kSuccess: | |
231 case SkImageGenerator::kIncompleteInput: | |
232 break; | |
233 default: | |
234 return SkStringPrintf("%s failed after attempting to skip %d scanlines" | |
235 "with error message %d", fPath.c_str(), y, ( int) skipResult); | |
236 } | |
237 //create and set size of subsetBm | |
238 SkBitmap subsetBm; | |
239 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight ); | |
scroggo
2015/05/22 14:38:26
I think you can move the declaration of bounds her
emmaleeroach
2015/05/22 15:58:54
Acknowledged.
| |
240 SkASSERT(largestSubsetBm.extractSubset(&subsetBm, bounds)); | |
scroggo
2015/05/22 14:38:26
This is a little tricky: In Release mode, SkASSERT
emmaleeroach
2015/05/22 15:58:55
Acknowledged.
| |
241 SkAutoLockPixels autlockSubsetBm(subsetBm, true); | |
242 for (int subsetY = 0; subsetY < currentSubsetHeight; ++subse tY) { | |
243 const SkImageGenerator::Result subsetResult = | |
244 subsetScanlineDecoder->getScanlines(line, 1, 0); | |
245 //copy section of line based on x value | |
246 memcpy(subsetBm.getAddr(0, subsetY), | |
247 line + x*largestSubsetDecodeInfo.bytesPerPixel() , | |
scroggo
2015/05/22 14:38:26
nit: since largestSubsetDecodeInfo.bytesPerPixel()
emmaleeroach
2015/05/22 15:58:55
Acknowledged.
| |
248 currentSubsetWidth*largestSubsetDecodeInfo.bytes PerPixel()); | |
249 switch (subsetResult) { | |
250 case SkImageGenerator::kSuccess: | |
251 case SkImageGenerator::kIncompleteInput: | |
252 break; | |
253 default: | |
254 return SkStringPrintf("%s failed after %d scanli nes with error" | |
255 "message %d", fPath.c_str(), y-1, (int) subsetResult); | |
256 } | |
257 } | |
258 canvas->drawBitmap(subsetBm, x, y); | |
259 } | |
260 //reset currentSubsetHeight for each new column | |
261 extraY = 0; | |
262 currentSubsetHeight = subsetHeight + extraY; | |
scroggo
2015/05/22 14:38:26
Alternatively, where you set currentSubsetHeight,
emmaleeroach
2015/05/22 15:58:55
even when that is inside a loop?
scroggo
2015/05/22 18:39:53
I am hesitant to say "always", but I will say that
emmaleer
2015/05/22 21:55:21
On 2015/05/22 18:39:53, scroggo wrote:
> On 2015/0
| |
263 } | |
163 break; | 264 break; |
164 } | 265 } |
165 } | 266 } |
166 canvas->drawBitmap(bitmap, 0, 0); | |
167 return ""; | 267 return ""; |
168 } | 268 } |
169 | 269 |
170 SkISize CodecSrc::size() const { | 270 SkISize CodecSrc::size() const { |
171 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 271 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
172 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); | 272 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); |
173 if (NULL != codec) { | 273 if (NULL != codec) { |
174 return codec->getInfo().dimensions(); | 274 return codec->getInfo().dimensions(); |
175 } else { | 275 } else { |
176 return SkISize::Make(0, 0); | 276 return SkISize::Make(0, 0); |
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
780 skr.visit<void>(i, drawsAsSingletonPictures); | 880 skr.visit<void>(i, drawsAsSingletonPictures); |
781 } | 881 } |
782 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 882 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
783 | 883 |
784 canvas->drawPicture(macroPic); | 884 canvas->drawPicture(macroPic); |
785 return ""; | 885 return ""; |
786 }); | 886 }); |
787 } | 887 } |
788 | 888 |
789 } // namespace DM | 889 } // namespace DM |
OLD | NEW |