LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/pdf - SkJpegInfo.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 65 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "SkData.h"
       9             : #include "SkJpegInfo.h"
      10             : 
      11             : namespace {
      12             : class JpegSegment {
      13             : public:
      14           0 :     JpegSegment(const SkData* skdata)
      15           0 :         : fData(static_cast<const char*>(skdata->data()))
      16           0 :         , fSize(skdata->size())
      17             :         , fOffset(0)
      18           0 :         , fLength(0) {}
      19           0 :     bool read() {
      20           0 :         if (!this->readBigendianUint16(&fMarker)) {
      21           0 :             return false;
      22             :         }
      23           0 :         if (JpegSegment::StandAloneMarker(fMarker)) {
      24           0 :             fLength = 0;
      25           0 :             fBuffer = nullptr;
      26           0 :             return true;
      27             :         }
      28           0 :         if (!this->readBigendianUint16(&fLength) || fLength < 2) {
      29           0 :             return false;
      30             :         }
      31           0 :         fLength -= 2;  // Length includes itself for some reason.
      32           0 :         if (fOffset + fLength > fSize) {
      33           0 :             return false;  // Segment too long.
      34             :         }
      35           0 :         fBuffer = &fData[fOffset];
      36           0 :         fOffset += fLength;
      37           0 :         return true;
      38             :     }
      39             : 
      40           0 :     bool isSOF() {
      41           0 :         return (fMarker & 0xFFF0) == 0xFFC0 && fMarker != 0xFFC4 &&
      42           0 :                fMarker != 0xFFC8 && fMarker != 0xFFCC;
      43             :     }
      44           0 :     uint16_t marker() { return fMarker; }
      45           0 :     uint16_t length() { return fLength; }
      46           0 :     const char* data() { return fBuffer; }
      47             : 
      48           0 :     static uint16_t GetBigendianUint16(const char* ptr) {
      49             :         // "the most significant byte shall come first"
      50           0 :         return (static_cast<uint8_t>(ptr[0]) << 8) |
      51           0 :             static_cast<uint8_t>(ptr[1]);
      52             :     }
      53             : 
      54             : private:
      55             :     const char* const fData;
      56             :     const size_t fSize;
      57             :     size_t fOffset;
      58             :     const char* fBuffer;
      59             :     uint16_t fMarker;
      60             :     uint16_t fLength;
      61             : 
      62           0 :     bool readBigendianUint16(uint16_t* value) {
      63           0 :         if (fOffset + 2 > fSize) {
      64           0 :             return false;
      65             :         }
      66           0 :         *value = JpegSegment::GetBigendianUint16(&fData[fOffset]);
      67           0 :         fOffset += 2;
      68           0 :         return true;
      69             :     }
      70           0 :     static bool StandAloneMarker(uint16_t marker) {
      71             :         // RST[m] markers or SOI, EOI, TEM
      72           0 :         return (marker & 0xFFF8) == 0xFFD0 || marker == 0xFFD8 ||
      73           0 :                marker == 0xFFD9 || marker == 0xFF01;
      74             :     }
      75             : };
      76             : }  // namespace
      77             : 
      78           0 : bool SkIsJFIF(const SkData* skdata, SkJFIFInfo* info) {
      79             :     static const uint16_t kSOI = 0xFFD8;
      80             :     static const uint16_t kAPP0 = 0xFFE0;
      81           0 :     JpegSegment segment(skdata);
      82           0 :     if (!segment.read() || segment.marker() != kSOI) {
      83           0 :         return false;  // not a JPEG
      84             :     }
      85           0 :     if (!segment.read() || segment.marker() != kAPP0) {
      86           0 :         return false;  // not an APP0 segment
      87             :     }
      88             :     static const char kJfif[] = {'J', 'F', 'I', 'F', '\0'};
      89           0 :     SkASSERT(segment.data());
      90           0 :     if (SkToSizeT(segment.length()) < sizeof(kJfif) ||
      91           0 :         0 != memcmp(segment.data(), kJfif, sizeof(kJfif))) {
      92           0 :         return false;  // Not JFIF JPEG
      93             :     }
      94           0 :     do {
      95           0 :         if (!segment.read()) {
      96           0 :             return false;  // malformed JPEG
      97             :         }
      98           0 :     } while (!segment.isSOF());
      99           0 :     if (segment.length() < 6) {
     100           0 :         return false;  // SOF segment is short
     101             :     }
     102           0 :     if (8 != segment.data()[0]) {
     103           0 :         return false;  // Only support 8-bit precision
     104             :     }
     105           0 :     int numberOfComponents = segment.data()[5];
     106           0 :     if (numberOfComponents != 1 && numberOfComponents != 3) {
     107           0 :         return false;  // Invalid JFIF
     108             :     }
     109           0 :     if (info) {
     110           0 :         info->fSize.set(JpegSegment::GetBigendianUint16(&segment.data()[3]),
     111           0 :                         JpegSegment::GetBigendianUint16(&segment.data()[1]));
     112           0 :         if (numberOfComponents == 3) {
     113           0 :             info->fType = SkJFIFInfo::kYCbCr;
     114             :         } else {
     115           0 :             info->fType = SkJFIFInfo::kGrayscale;
     116             :         }
     117             :     }
     118           0 :     return true;
     119             : }

Generated by: LCOV version 1.13