OLD | NEW |
---|---|
(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 "SkCodec.h" | |
9 #include "SkRawCodec.h" | |
10 #include "SkCodecPriv.h" | |
11 #include "SkColorPriv.h" | |
12 #include "SkStream.h" | |
13 #include "SkTemplates.h" | |
14 #include "SkTypes.h" | |
15 #include "SkSwizzler.h" | |
16 #include "SkJpegCodec.h" | |
17 | |
18 #include "dng_color_space.h" | |
19 #include "dng_exceptions.h" | |
20 #include "dng_host.h" | |
21 #include "dng_info.h" | |
22 #include "dng_render.h" | |
23 | |
24 #include "src/piex.h" | |
25 | |
26 #include <cstring> | |
27 #include <cmath> | |
28 #include <vector> | |
29 | |
30 namespace { | |
31 | |
32 class SkDngStream : public dng_stream { | |
33 public: | |
34 explicit SkDngStream(SkStream* stream) | |
35 : fData(stream->getMemoryBase()) | |
scroggo
2015/12/18 15:56:26
I brought this up in the other code review (see ht
yujieqin
2016/01/06 18:47:19
Done for the DNG case.
We still plan to do more
| |
36 , fDataSize(stream->getLength()) {} | |
scroggo
2015/12/18 15:56:26
ditto.
yujieqin
2016/01/06 18:47:19
Done.
| |
37 | |
38 ~SkDngStream() override {} | |
39 | |
40 protected: | |
41 uint64 DoGetLength() override { return fDataSize; } | |
42 void DoRead(void* data, uint32 count, uint64 offset) override { | |
43 if (fDataSize < offset + count) { | |
44 ThrowReadFile(); | |
45 } | |
46 std::memcpy(data, | |
scroggo
2015/12/18 15:56:27
Why not just:
memcpy(data, reinterpret_cast<cons
yujieqin
2016/01/06 18:47:19
Done.
| |
47 reinterpret_cast<const uint8*>(fData) + offset, count); | |
48 } | |
49 | |
50 private: | |
51 const void* fData; | |
52 size_t fDataSize; | |
53 }; | |
54 | |
55 class SkPiexStream : public ::piex::StreamInterface { | |
56 public: | |
57 explicit SkPiexStream(SkStream* stream) | |
58 : fData(stream->getMemoryBase()) | |
59 , fDataSize(stream->getLength()) {} | |
60 | |
61 ::piex::Error GetData(const size_t offset, const size_t length, | |
62 uint8* data) override { | |
63 if (offset >= fDataSize || fDataSize - offset < length) { | |
64 return ::piex::Error::kFail; | |
65 } | |
66 std::memcpy(data, | |
67 reinterpret_cast<const uint8*>(fData) + offset, length); | |
68 return ::piex::Error::kOk; | |
69 } | |
70 | |
71 private: | |
72 const void* fData; | |
73 size_t fDataSize; | |
74 }; | |
75 | |
76 bool IsDng(SkStream* data) { | |
77 try { | |
78 SkDngStream stream(data); | |
scroggo
2015/12/18 15:56:27
Please see comments in https://codereview.chromium
yujieqin
2016/01/06 18:47:19
code removed.
| |
79 dng_host host; | |
80 dng_info info; | |
81 info.Parse(host, stream); | |
82 info.PostParse(host); | |
83 const bool ok= info.IsValidDNG(); | |
84 return ok; | |
85 } catch (...) { // Handle all kinds of exceptions as "false". | |
86 return false; | |
87 } | |
88 } | |
89 | |
90 bool IsPiexSupportedRaw(SkStream* data) { | |
91 SkPiexStream stream(data); | |
92 const bool ok = ::piex::IsRaw(&stream); | |
93 return ok; | |
94 } | |
95 | |
96 bool ReadDng(dng_stream* stream, dng_host* host, dng_info* info, | |
97 std::unique_ptr<dng_negative>* negative) { | |
98 const uint32 kPreferredSize = 0; | |
99 const uint32 kMinimumSize = 0; | |
100 const uint32 kMaximumSize = 0; | |
101 try { | |
102 host->SetPreferredSize(kPreferredSize); | |
103 host->SetMinimumSize(kMinimumSize); | |
104 host->SetMaximumSize(kMaximumSize); | |
105 | |
106 host->ValidateSizes(); | |
107 | |
108 // Read stage 1 image into the negative. | |
109 { | |
110 info->Parse(*host, *stream); | |
111 info->PostParse(*host); | |
112 | |
113 if (!info->IsValidDNG()) { | |
114 return false; | |
115 } | |
116 | |
117 negative->reset(host->Make_dng_negative()); | |
118 (*negative)->Parse(*host, *stream, *info); | |
119 (*negative)->PostParse(*host, *stream, *info); | |
120 } | |
121 | |
122 (*negative)->SynchronizeMetadata(); | |
123 } catch (const dng_exception& exception) { | |
124 printf("ReadDng faile with dng_exception\n"); | |
125 return false; | |
126 } catch (...) { | |
127 printf("ReadDng faile with unknown exception\n"); | |
128 return false; | |
129 } | |
130 | |
131 return true; | |
132 } | |
133 | |
134 bool PrepareStage3(dng_stream* stream, dng_host* host, dng_info* info, | |
135 dng_negative* negative) { | |
136 if (negative->Stage3Image() == nullptr) { | |
137 negative->ReadStage1Image(*host, *stream, *info); | |
138 | |
139 if (info->fMaskIndex != -1) { | |
140 negative->ReadTransparencyMask(*host, *stream, *info); | |
141 } | |
142 | |
143 negative->ValidateRawImageDigest(*host); | |
144 if (negative->IsDamaged()) { | |
145 printf("PrepareStage3 Fail: negative->IsDamaged\n"); | |
146 return false; | |
147 } | |
148 | |
149 const int32 kMosaicPlane = -1; | |
150 negative->BuildStage2Image(*host); | |
151 negative->BuildStage3Image(*host, kMosaicPlane); | |
152 } | |
153 | |
154 return true; | |
155 } | |
156 | |
157 } // namespace | |
158 | |
159 bool SkRawCodec::IsRaw(SkStream* stream) { | |
160 const bool ok = IsDng(stream) || IsPiexSupportedRaw(stream); | |
161 return ok; | |
162 } | |
163 | |
164 SkCodec* SkRawCodec::NewFromStream(SkStream* data) { | |
165 if (IsDng(data)) { | |
166 SkDngStream stream(data); | |
167 dng_host host; | |
168 dng_info info; | |
169 std::unique_ptr<dng_negative> negative; | |
170 if (!ReadDng(&stream, &host, &info, &negative) && | |
171 !PrepareStage3(&stream, &host, &info, negative.get())) { | |
172 printf("NewFromStream Dng SDK Failed.\n"); | |
173 return nullptr; | |
174 } | |
175 const SkImageInfo& imageInfo = SkImageInfo::Make( | |
176 negative->DefaultCropSizeH().As_real64(), | |
177 negative->DefaultCropSizeV().As_real64(), kRGBA_8888_SkColorType, | |
178 kOpaque_SkAlphaType); | |
179 return new SkRawCodec(imageInfo, data); | |
180 } else if (IsPiexSupportedRaw(data)) { | |
181 ::piex::PreviewImageData imageData; | |
182 SkPiexStream stream(data); | |
183 ::piex::Error error = ::piex::GetPreviewImageData(&stream, &imageData); | |
184 if (error != ::piex::Error::kOk) { | |
185 printf("NewFromStream Piex Failed.\n"); | |
186 return nullptr; | |
187 } | |
188 | |
189 if (!data->rewind()) { | |
190 printf("Failed to rewind the stream.\n"); | |
191 return nullptr; | |
192 } | |
193 | |
194 data->skip(imageData.jpeg_offset); | |
195 std::vector<unsigned char> | |
196 buffer_jpeg_head(std::min(3u, imageData.jpeg_length)); | |
197 data->read(static_cast<void*>(buffer_jpeg_head.data()), | |
198 buffer_jpeg_head.size()); | |
199 if (!SkJpegCodec::IsJpeg(static_cast<void*>(buffer_jpeg_head.data()), | |
200 buffer_jpeg_head.size())) { | |
201 printf("SkRawCodec Piex -> SkJpegCodec::IsJpeg failed.\n"); | |
202 return nullptr; | |
203 } | |
204 | |
205 if (!data->rewind()) { | |
206 printf("Failed to rewind the stream.\n"); | |
207 return nullptr; | |
208 } | |
209 data->skip(imageData.jpeg_offset); | |
210 SkCodec* newCodec = SkJpegCodec::NewFromStream(data); | |
211 if (newCodec == nullptr) { | |
212 printf("SkRawCodec Piex -> SkJpegCodec is nullptr!\n"); | |
213 } | |
214 return newCodec; | |
215 } | |
216 | |
217 return nullptr; | |
218 } | |
219 | |
220 SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, | |
221 size_t dstRowBytes, const Options& optio ns, | |
222 SkPMColor ctable[], int* ctableCount, | |
223 int* rowsDecoded) { | |
224 const int width = requestedInfo.width(); | |
225 const int height = requestedInfo.height(); | |
226 if (IsDng(this->stream())) { | |
227 std::unique_ptr<dng_image> finalDngImage; | |
228 try { | |
229 SkDngStream stream(this->stream()); | |
230 dng_host host; | |
231 dng_info info; | |
232 std::unique_ptr<dng_negative> negative; | |
233 if (!ReadDng(&stream, &host, &info, &negative) || | |
234 !PrepareStage3(&stream, &host, &info, negative.get())) { | |
235 printf("onGetPixels faile on Prepare\n"); | |
msarett
2015/12/18 16:26:13
nit: Spelling
yujieqin
2016/01/06 18:47:19
code for debugging is removed.
| |
236 return kInvalidInput; | |
237 } | |
238 | |
239 dng_render render(host, *negative); | |
240 render.SetFinalSpace(dng_space_sRGB::Get()); | |
241 render.SetFinalPixelType(ttByte); | |
242 | |
243 finalDngImage.reset(render.Render()); | |
244 } catch (const dng_exception& exception) { | |
245 printf("onGetPixels faile with dng_exception\n"); | |
msarett
2015/12/18 16:26:13
nit: Spelling
yujieqin
2016/01/06 18:47:19
code for debugging is removed.
| |
246 return kInvalidInput; | |
247 } catch (...) { | |
248 printf("onGetPixels faile with unknown exception\n"); | |
msarett
2015/12/18 16:26:12
nit: Spelling
yujieqin
2016/01/06 18:47:19
code for debugging is removed.
| |
249 return kInvalidInput; | |
250 } | |
251 | |
252 void* dstRow = dst; | |
253 uint8 srcRow[width * 3]; | |
254 std::unique_ptr<SkSwizzler> swizzler( | |
255 SkSwizzler::CreateSwizzler(SkSwizzler::kRGB, nullptr, requestedInfo, opt ions)); | |
256 if (!swizzler) { | |
257 printf("onGetPixels swizzler failed\n"); | |
258 return kInvalidInput; | |
259 } | |
260 for (int i = 0; i < height; ++i) { | |
261 dng_pixel_buffer buffer; | |
262 buffer.fData = &srcRow[0]; | |
263 buffer.fArea = dng_rect(i, 0, i + 1, width); | |
264 buffer.fPlane = 0; | |
265 buffer.fPlanes = 3; | |
266 buffer.fColStep = buffer.fPlanes; | |
267 buffer.fPlaneStep = 1; | |
268 buffer.fPixelType = ttByte; | |
269 buffer.fPixelSize = sizeof(uint8); | |
270 buffer.fRowStep = sizeof(srcRow); | |
271 finalDngImage->Get(buffer, dng_image::edge_zero); | |
272 swizzler->swizzle(dstRow, &srcRow[0]); | |
273 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | |
274 } | |
275 return kSuccess; | |
276 } | |
277 | |
278 return kUnimplemented; | |
279 } | |
280 | |
281 SkRawCodec::SkRawCodec(const SkImageInfo& srcInfo, SkStream* stream) | |
282 : INHERITED(srcInfo, stream) {} | |
283 | |
OLD | NEW |