Chromium Code Reviews| 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 |