| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright 2016 Google Inc. | 2  * Copyright 2016 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 "SkCodec.h" | 8 #include "SkCodec.h" | 
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" | 
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" | 
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 150         // To avoid arbitary allocation requests which might lead to out-of-memo
     ry, limit the | 150         // To avoid arbitary allocation requests which might lead to out-of-memo
     ry, limit the | 
| 151         // amount of memory that can be allocated at once. The memory limit is b
     ased on experiments | 151         // amount of memory that can be allocated at once. The memory limit is b
     ased on experiments | 
| 152         // and supposed to be sufficient for all valid DNG images. | 152         // and supposed to be sufficient for all valid DNG images. | 
| 153         if (size > 300 * 1024 * 1024) {  // 300 MB | 153         if (size > 300 * 1024 * 1024) {  // 300 MB | 
| 154             ThrowMemoryFull(); | 154             ThrowMemoryFull(); | 
| 155         } | 155         } | 
| 156         return dng_memory_allocator::Allocate(size); | 156         return dng_memory_allocator::Allocate(size); | 
| 157     } | 157     } | 
| 158 }; | 158 }; | 
| 159 | 159 | 
|  | 160 bool is_asset_stream(const SkStream& stream) { | 
|  | 161     return stream.hasLength() && stream.hasPosition(); | 
|  | 162 } | 
|  | 163 | 
| 160 }  // namespace | 164 }  // namespace | 
| 161 | 165 | 
| 162 // Note: this class could throw exception if it is used as dng_stream. | 166 class SkRawStream { | 
| 163 class SkRawStream : public ::piex::StreamInterface { |  | 
| 164 public: | 167 public: | 
| 165     // Note that this call will take the ownership of stream. | 168     virtual ~SkRawStream() {} | 
| 166     explicit SkRawStream(SkStream* stream) |  | 
| 167         : fStream(stream), fWholeStreamRead(false) {} |  | 
| 168 | 169 | 
| 169     ~SkRawStream() override {} | 170    /* | 
|  | 171     * Gets the length of the stream. Depending on the type of stream, this may r
     equire reading to | 
|  | 172     * the end of the stream. | 
|  | 173     */ | 
|  | 174    virtual uint64 getLength() = 0; | 
|  | 175 | 
|  | 176    virtual bool read(void* data, size_t offset, size_t length) = 0; | 
| 170 | 177 | 
| 171     /* | 178     /* | 
| 172      * Creates an SkMemoryStream from the offset with size. | 179      * Creates an SkMemoryStream from the offset with size. | 
| 173      * Note: for performance reason, this function is destructive to the SkRawSt
     ream. One should | 180      * Note: for performance reason, this function is destructive to the SkRawSt
     ream. One should | 
| 174      *       abandon current object after the function call. | 181      *       abandon current object after the function call. | 
| 175      */ | 182      */ | 
| 176     SkMemoryStream* transferBuffer(size_t offset, size_t size) { | 183    virtual SkMemoryStream* transferBuffer(size_t offset, size_t size) = 0; | 
|  | 184 }; | 
|  | 185 | 
|  | 186 class SkRawBufferedStream : public SkRawStream { | 
|  | 187 public: | 
|  | 188     // Will take the ownership of the stream. | 
|  | 189     explicit SkRawBufferedStream(SkStream* stream) | 
|  | 190         : fStream(stream) | 
|  | 191         , fWholeStreamRead(false) | 
|  | 192     { | 
|  | 193         // Only use SkRawBufferedStream when the stream is not an asset stream. | 
|  | 194         SkASSERT(!is_asset_stream(*stream)); | 
|  | 195     } | 
|  | 196 | 
|  | 197     ~SkRawBufferedStream() override {} | 
|  | 198 | 
|  | 199     uint64 getLength() override { | 
|  | 200         if (!this->bufferMoreData(kReadToEnd)) {  // read whole stream | 
|  | 201             ThrowReadFile(); | 
|  | 202         } | 
|  | 203         return fStreamBuffer.bytesWritten(); | 
|  | 204     } | 
|  | 205 | 
|  | 206     bool read(void* data, size_t offset, size_t length) override { | 
|  | 207         if (length == 0) { | 
|  | 208             return true; | 
|  | 209         } | 
|  | 210 | 
|  | 211         size_t sum; | 
|  | 212         if (!safe_add_to_size_t(offset, length, &sum)) { | 
|  | 213             return false; | 
|  | 214         } | 
|  | 215 | 
|  | 216         return this->bufferMoreData(sum) && fStreamBuffer.read(data, offset, len
     gth); | 
|  | 217     } | 
|  | 218 | 
|  | 219     SkMemoryStream* transferBuffer(size_t offset, size_t size) override { | 
| 177         SkAutoTUnref<SkData> data(SkData::NewUninitialized(size)); | 220         SkAutoTUnref<SkData> data(SkData::NewUninitialized(size)); | 
| 178         if (offset > fStreamBuffer.bytesWritten()) { | 221         if (offset > fStreamBuffer.bytesWritten()) { | 
| 179             // If the offset is not buffered, read from fStream directly and ski
     p the buffering. | 222             // If the offset is not buffered, read from fStream directly and ski
     p the buffering. | 
| 180             const size_t skipLength = offset - fStreamBuffer.bytesWritten(); | 223             const size_t skipLength = offset - fStreamBuffer.bytesWritten(); | 
| 181             if (fStream->skip(skipLength) != skipLength) { | 224             if (fStream->skip(skipLength) != skipLength) { | 
| 182                 return nullptr; | 225                 return nullptr; | 
| 183             } | 226             } | 
| 184             const size_t bytesRead = fStream->read(data->writable_data(), size); | 227             const size_t bytesRead = fStream->read(data->writable_data(), size); | 
| 185             if (bytesRead < size) { | 228             if (bytesRead < size) { | 
| 186                 data.reset(SkData::NewSubset(data.get(), 0, bytesRead)); | 229                 data.reset(SkData::NewSubset(data.get(), 0, bytesRead)); | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 201                     if (!safe_add_to_size_t(alreadyBuffered, bytesRead, &newSize
     )) { | 244                     if (!safe_add_to_size_t(alreadyBuffered, bytesRead, &newSize
     )) { | 
| 202                         return nullptr; | 245                         return nullptr; | 
| 203                     } | 246                     } | 
| 204                     data.reset(SkData::NewSubset(data.get(), 0, newSize)); | 247                     data.reset(SkData::NewSubset(data.get(), 0, newSize)); | 
| 205                 } | 248                 } | 
| 206             } | 249             } | 
| 207         } | 250         } | 
| 208         return new SkMemoryStream(data); | 251         return new SkMemoryStream(data); | 
| 209     } | 252     } | 
| 210 | 253 | 
| 211     // For PIEX |  | 
| 212     ::piex::Error GetData(const size_t offset, const size_t length, |  | 
| 213                           uint8* data) override { |  | 
| 214         if (offset == 0 && length == 0) { |  | 
| 215             return ::piex::Error::kOk; |  | 
| 216         } |  | 
| 217         size_t sum; |  | 
| 218         if (!safe_add_to_size_t(offset, length, &sum) || !this->bufferMoreData(s
     um)) { |  | 
| 219             return ::piex::Error::kFail; |  | 
| 220         } |  | 
| 221         if (!fStreamBuffer.read(data, offset, length)) { |  | 
| 222             return ::piex::Error::kFail; |  | 
| 223         } |  | 
| 224         return ::piex::Error::kOk; |  | 
| 225     } |  | 
| 226 |  | 
| 227     // For dng_stream |  | 
| 228     uint64 getLength() { |  | 
| 229         if (!this->bufferMoreData(kReadToEnd)) {  // read whole stream |  | 
| 230             ThrowReadFile(); |  | 
| 231         } |  | 
| 232         return fStreamBuffer.bytesWritten(); |  | 
| 233     } |  | 
| 234 |  | 
| 235     // For dng_stream |  | 
| 236     void read(void* data, uint32 count, uint64 offset) { |  | 
| 237         if (count == 0 && offset == 0) { |  | 
| 238             return; |  | 
| 239         } |  | 
| 240         size_t sum; |  | 
| 241         if (!safe_add_to_size_t(static_cast<uint64>(count), offset, &sum) || |  | 
| 242             !this->bufferMoreData(sum)) { |  | 
| 243             ThrowReadFile(); |  | 
| 244         } |  | 
| 245 |  | 
| 246         if (!fStreamBuffer.read(data, static_cast<size_t>(offset), count)) { |  | 
| 247             ThrowReadFile(); |  | 
| 248         } |  | 
| 249     } |  | 
| 250 |  | 
| 251 private: | 254 private: | 
| 252     // Note: if the newSize == kReadToEnd (0), this function will read to the en
     d of stream. | 255     // Note: if the newSize == kReadToEnd (0), this function will read to the en
     d of stream. | 
| 253     bool bufferMoreData(size_t newSize) { | 256     bool bufferMoreData(size_t newSize) { | 
| 254         if (newSize == kReadToEnd) { | 257         if (newSize == kReadToEnd) { | 
| 255             if (fWholeStreamRead) {  // already read-to-end. | 258             if (fWholeStreamRead) {  // already read-to-end. | 
| 256                 return true; | 259                 return true; | 
| 257             } | 260             } | 
| 258 | 261 | 
| 259             // TODO: optimize for the special case when the input is SkMemoryStr
     eam. | 262             // TODO: optimize for the special case when the input is SkMemoryStr
     eam. | 
| 260             return SkStreamCopy(&fStreamBuffer, fStream.get()); | 263             return SkStreamCopy(&fStreamBuffer, fStream.get()); | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 280     } | 283     } | 
| 281 | 284 | 
| 282     SkAutoTDelete<SkStream> fStream; | 285     SkAutoTDelete<SkStream> fStream; | 
| 283     bool fWholeStreamRead; | 286     bool fWholeStreamRead; | 
| 284 | 287 | 
| 285     SkDynamicMemoryWStream fStreamBuffer; | 288     SkDynamicMemoryWStream fStreamBuffer; | 
| 286 | 289 | 
| 287     const size_t kReadToEnd = 0; | 290     const size_t kReadToEnd = 0; | 
| 288 }; | 291 }; | 
| 289 | 292 | 
|  | 293 class SkRawAssetStream : public SkRawStream { | 
|  | 294 public: | 
|  | 295     // Will take the ownership of the stream. | 
|  | 296     explicit SkRawAssetStream(SkStream* stream) | 
|  | 297         : fStream(stream) | 
|  | 298     { | 
|  | 299         // Only use SkRawAssetStream when the stream is an asset stream. | 
|  | 300         SkASSERT(is_asset_stream(*stream)); | 
|  | 301     } | 
|  | 302 | 
|  | 303     ~SkRawAssetStream() override {} | 
|  | 304 | 
|  | 305     uint64 getLength() override { | 
|  | 306         return fStream->getLength(); | 
|  | 307     } | 
|  | 308 | 
|  | 309 | 
|  | 310     bool read(void* data, size_t offset, size_t length) override { | 
|  | 311         if (length == 0) { | 
|  | 312             return true; | 
|  | 313         } | 
|  | 314 | 
|  | 315         size_t sum; | 
|  | 316         if (!safe_add_to_size_t(offset, length, &sum)) { | 
|  | 317             return false; | 
|  | 318         } | 
|  | 319 | 
|  | 320         return fStream->seek(offset) && (fStream->read(data, length) == length); | 
|  | 321     } | 
|  | 322 | 
|  | 323     SkMemoryStream* transferBuffer(size_t offset, size_t size) override { | 
|  | 324         if (fStream->getLength() < offset) { | 
|  | 325             return nullptr; | 
|  | 326         } | 
|  | 327 | 
|  | 328         size_t sum; | 
|  | 329         if (!safe_add_to_size_t(offset, size, &sum)) { | 
|  | 330             return nullptr; | 
|  | 331         } | 
|  | 332 | 
|  | 333         // This will allow read less than the requested "size", because the JPEG
      codec wants to | 
|  | 334         // handle also a partial JPEG file. | 
|  | 335         const size_t bytesToRead = SkTMin(sum, fStream->getLength()) - offset; | 
|  | 336         if (bytesToRead == 0) { | 
|  | 337             return nullptr; | 
|  | 338         } | 
|  | 339 | 
|  | 340         if (fStream->getMemoryBase()) {  // directly copy if getMemoryBase() is 
     available. | 
|  | 341             SkAutoTUnref<SkData> data(SkData::NewWithCopy( | 
|  | 342                 static_cast<const uint8_t*>(fStream->getMemoryBase()) + offset, 
     bytesToRead)); | 
|  | 343             fStream.free(); | 
|  | 344             return new SkMemoryStream(data); | 
|  | 345         } else { | 
|  | 346             SkAutoTUnref<SkData> data(SkData::NewUninitialized(bytesToRead)); | 
|  | 347             if (!fStream->seek(offset)) { | 
|  | 348                 return nullptr; | 
|  | 349             } | 
|  | 350             const size_t bytesRead = fStream->read(data->writable_data(), bytesT
     oRead); | 
|  | 351             if (bytesRead < bytesToRead) { | 
|  | 352                 data.reset(SkData::NewSubset(data.get(), 0, bytesRead)); | 
|  | 353             } | 
|  | 354             return new SkMemoryStream(data); | 
|  | 355         } | 
|  | 356     } | 
|  | 357 private: | 
|  | 358     SkAutoTDelete<SkStream> fStream; | 
|  | 359 }; | 
|  | 360 | 
|  | 361 class SkPiexStream : public ::piex::StreamInterface { | 
|  | 362 public: | 
|  | 363     // Will NOT take the ownership of the stream. | 
|  | 364     explicit SkPiexStream(SkRawStream* stream) : fStream(stream) {} | 
|  | 365 | 
|  | 366     ~SkPiexStream() override {} | 
|  | 367 | 
|  | 368     ::piex::Error GetData(const size_t offset, const size_t length, | 
|  | 369                           uint8* data) override { | 
|  | 370         return fStream->read(static_cast<void*>(data), offset, length) ? | 
|  | 371             ::piex::Error::kOk : ::piex::Error::kFail; | 
|  | 372     } | 
|  | 373 | 
|  | 374 private: | 
|  | 375     SkRawStream* fStream; | 
|  | 376 }; | 
|  | 377 | 
| 290 class SkDngStream : public dng_stream { | 378 class SkDngStream : public dng_stream { | 
| 291 public: | 379 public: | 
| 292     SkDngStream(SkRawStream* rawStream) : fRawStream(rawStream) {} | 380     // Will NOT take the ownership of the stream. | 
|  | 381     SkDngStream(SkRawStream* stream) : fStream(stream) {} | 
| 293 | 382 | 
| 294     uint64 DoGetLength() override { return fRawStream->getLength(); } | 383     ~SkDngStream() override {} | 
|  | 384 | 
|  | 385     uint64 DoGetLength() override { return fStream->getLength(); } | 
| 295 | 386 | 
| 296     void DoRead(void* data, uint32 count, uint64 offset) override { | 387     void DoRead(void* data, uint32 count, uint64 offset) override { | 
| 297         fRawStream->read(data, count, offset); | 388         size_t sum; | 
|  | 389         if (!safe_add_to_size_t(static_cast<uint64>(count), offset, &sum) || | 
|  | 390             !fStream->read(data, static_cast<size_t>(offset), static_cast<size_t
     >(count))) { | 
|  | 391             ThrowReadFile(); | 
|  | 392         } | 
| 298     } | 393     } | 
| 299 | 394 | 
| 300 private: | 395 private: | 
| 301     SkRawStream* fRawStream; | 396     SkRawStream* fStream; | 
| 302 }; | 397 }; | 
| 303 | 398 | 
| 304 class SkDngImage { | 399 class SkDngImage { | 
| 305 public: | 400 public: | 
|  | 401     // Will take the ownership of the stream. | 
| 306     static SkDngImage* NewFromStream(SkRawStream* stream) { | 402     static SkDngImage* NewFromStream(SkRawStream* stream) { | 
| 307         SkAutoTDelete<SkDngImage> dngImage(new SkDngImage(stream)); | 403         SkAutoTDelete<SkDngImage> dngImage(new SkDngImage(stream)); | 
| 308         if (!dngImage->readDng()) { | 404         if (!dngImage->readDng()) { | 
| 309             return nullptr; | 405             return nullptr; | 
| 310         } | 406         } | 
| 311 | 407 | 
| 312         SkASSERT(dngImage->fNegative); | 408         SkASSERT(dngImage->fNegative); | 
| 313         return dngImage.release(); | 409         return dngImage.release(); | 
| 314     } | 410     } | 
| 315 | 411 | 
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 432     bool fIsScalable; | 528     bool fIsScalable; | 
| 433     bool fIsXtransImage; | 529     bool fIsXtransImage; | 
| 434 }; | 530 }; | 
| 435 | 531 | 
| 436 /* | 532 /* | 
| 437  * Tries to handle the image with PIEX. If PIEX returns kOk and finds the previe
     w image, create a | 533  * Tries to handle the image with PIEX. If PIEX returns kOk and finds the previe
     w image, create a | 
| 438  * SkJpegCodec. If PIEX returns kFail, then the file is invalid, return nullptr.
      In other cases, | 534  * SkJpegCodec. If PIEX returns kFail, then the file is invalid, return nullptr.
      In other cases, | 
| 439  * fallback to create SkRawCodec for DNG images. | 535  * fallback to create SkRawCodec for DNG images. | 
| 440  */ | 536  */ | 
| 441 SkCodec* SkRawCodec::NewFromStream(SkStream* stream) { | 537 SkCodec* SkRawCodec::NewFromStream(SkStream* stream) { | 
| 442     SkAutoTDelete<SkRawStream> rawStream(new SkRawStream(stream)); | 538     SkAutoTDelete<SkRawStream> rawStream; | 
|  | 539     if (is_asset_stream(*stream)) { | 
|  | 540         rawStream.reset(new SkRawAssetStream(stream)); | 
|  | 541     } else { | 
|  | 542         rawStream.reset(new SkRawBufferedStream(stream)); | 
|  | 543     } | 
|  | 544 | 
|  | 545     // Does not take the ownership of rawStream. | 
|  | 546     SkPiexStream piexStream(rawStream.get()); | 
| 443     ::piex::PreviewImageData imageData; | 547     ::piex::PreviewImageData imageData; | 
| 444     if (::piex::IsRaw(rawStream.get())) { | 548     if (::piex::IsRaw(&piexStream)) { | 
| 445         ::piex::Error error = ::piex::GetPreviewImageData(rawStream.get(), &imag
     eData); | 549         ::piex::Error error = ::piex::GetPreviewImageData(&piexStream, &imageDat
     a); | 
| 446 | 550 | 
| 447         if (error == ::piex::Error::kOk && imageData.preview_length > 0) { | 551         if (error == ::piex::Error::kOk && imageData.preview_length > 0) { | 
| 448 #if !defined(GOOGLE3) | 552 #if !defined(GOOGLE3) | 
| 449             // transferBuffer() is destructive to the rawStream. Abandon the raw
     Stream after this | 553             // transferBuffer() is destructive to the rawStream. Abandon the raw
     Stream after this | 
| 450             // function call. | 554             // function call. | 
| 451             // FIXME: one may avoid the copy of memoryStream and use the buffere
     d rawStream. | 555             // FIXME: one may avoid the copy of memoryStream and use the buffere
     d rawStream. | 
| 452             SkMemoryStream* memoryStream = | 556             SkMemoryStream* memoryStream = | 
| 453                     rawStream->transferBuffer(imageData.preview_offset, imageDat
     a.preview_length); | 557                 rawStream->transferBuffer(imageData.preview_offset, imageData.pr
     eview_length); | 
| 454             return memoryStream ? SkJpegCodec::NewFromStream(memoryStream) : nul
     lptr; | 558             return memoryStream ? SkJpegCodec::NewFromStream(memoryStream) : nul
     lptr; | 
| 455 #else | 559 #else | 
| 456             return nullptr; | 560             return nullptr; | 
| 457 #endif | 561 #endif | 
| 458         } else if (error == ::piex::Error::kFail) { | 562         } else if (error == ::piex::Error::kFail) { | 
| 459             return nullptr; | 563             return nullptr; | 
| 460         } | 564         } | 
| 461     } | 565     } | 
| 462 | 566 | 
|  | 567     // Takes the ownership of the rawStream. | 
| 463     SkAutoTDelete<SkDngImage> dngImage(SkDngImage::NewFromStream(rawStream.relea
     se())); | 568     SkAutoTDelete<SkDngImage> dngImage(SkDngImage::NewFromStream(rawStream.relea
     se())); | 
| 464     if (!dngImage) { | 569     if (!dngImage) { | 
| 465         return nullptr; | 570         return nullptr; | 
| 466     } | 571     } | 
| 467 | 572 | 
| 468     return new SkRawCodec(dngImage.release()); | 573     return new SkRawCodec(dngImage.release()); | 
| 469 } | 574 } | 
| 470 | 575 | 
| 471 SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& requestedInfo, void* 
     dst, | 576 SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& requestedInfo, void* 
     dst, | 
| 472                                         size_t dstRowBytes, const Options& optio
     ns, | 577                                         size_t dstRowBytes, const Options& optio
     ns, | 
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 559     SkISize sizeFloor = this->onGetScaledDimensions(1.f / std::floor(fullShortEd
     ge / shortEdge)); | 664     SkISize sizeFloor = this->onGetScaledDimensions(1.f / std::floor(fullShortEd
     ge / shortEdge)); | 
| 560     SkISize sizeCeil = this->onGetScaledDimensions(1.f / std::ceil(fullShortEdge
      / shortEdge)); | 665     SkISize sizeCeil = this->onGetScaledDimensions(1.f / std::ceil(fullShortEdge
      / shortEdge)); | 
| 561     return sizeFloor == dim || sizeCeil == dim; | 666     return sizeFloor == dim || sizeCeil == dim; | 
| 562 } | 667 } | 
| 563 | 668 | 
| 564 SkRawCodec::~SkRawCodec() {} | 669 SkRawCodec::~SkRawCodec() {} | 
| 565 | 670 | 
| 566 SkRawCodec::SkRawCodec(SkDngImage* dngImage) | 671 SkRawCodec::SkRawCodec(SkDngImage* dngImage) | 
| 567     : INHERITED(dngImage->getImageInfo(), nullptr) | 672     : INHERITED(dngImage->getImageInfo(), nullptr) | 
| 568     , fDngImage(dngImage) {} | 673     , fDngImage(dngImage) {} | 
| OLD | NEW | 
|---|