Home | History | Annotate | Download | only in codec
      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 #ifndef SkSwizzler_DEFINED
      9 #define SkSwizzler_DEFINED
     10 
     11 #include "SkCodec.h"
     12 #include "SkColor.h"
     13 #include "SkImageInfo.h"
     14 #include "SkSampler.h"
     15 
     16 class SkSwizzler : public SkSampler {
     17 public:
     18     /**
     19      *  Create a new SkSwizzler.
     20      *  @param encodedInfo Description of the format of the encoded data.
     21      *  @param ctable Unowned pointer to an array of up to 256 colors for an
     22      *                index source.
     23      *  @param dstInfo Describes the destination.
     24      *  @param options Contains partial scanline information and whether the dst is zero-
     25      *                 initialized.
     26      *  @param frame   Is non-NULL if the source pixels are part of an image
     27      *                 frame that is a subset of the full image.
     28      *
     29      *  Note that a deeper discussion of partial scanline subsets and image frame
     30      *  subsets is below.  Currently, we do not support both simultaneously.  If
     31      *  options->fSubset is non-NULL, frame must be NULL.
     32      *
     33      *  @return A new SkSwizzler or nullptr on failure.
     34      */
     35     static std::unique_ptr<SkSwizzler> Make(const SkEncodedInfo& encodedInfo,
     36             const SkPMColor* ctable, const SkImageInfo& dstInfo, const SkCodec::Options&,
     37             const SkIRect* frame = nullptr);
     38 
     39     /**
     40      *  Create a simplified swizzler that does not need to do format conversion. The swizzler
     41      *  only needs to sample and/or subset.
     42      *
     43      *  @param srcBPP Bytes per pixel of the source.
     44      *  @param dstInfo Describes the destination.
     45      *  @param options Contains partial scanline information and whether the dst is zero-
     46      *                 initialized.
     47      *  @return A new SkSwizzler or nullptr on failure.
     48      */
     49     static std::unique_ptr<SkSwizzler> MakeSimple(int srcBPP, const SkImageInfo& dstInfo,
     50                                                   const SkCodec::Options&);
     51 
     52     /**
     53      *  Swizzle a line. Generally this will be called height times, once
     54      *  for each row of source.
     55      *  By allowing the caller to pass in the dst pointer, we give the caller
     56      *  flexibility to use the swizzler even when the encoded data does not
     57      *  store the rows in order.  This also improves usability for scaled and
     58      *  subset decodes.
     59      *  @param dst Where we write the output.
     60      *  @param src The next row of the source data.
     61      */
     62     void swizzle(void* dst, const uint8_t* SK_RESTRICT src);
     63 
     64     int fillWidth() const override {
     65         return fAllocatedWidth;
     66     }
     67 
     68     /**
     69      *  If fSampleX > 1, the swizzler is sampling every fSampleX'th pixel and
     70      *  discarding the rest.
     71      *
     72      *  This getter is currently used by SkBmpStandardCodec for Bmp-in-Ico decodes.
     73      *  Ideally, the subclasses of SkCodec would have no knowledge of sampling, but
     74      *  this allows us to apply a transparency mask to pixels after swizzling.
     75      */
     76     int sampleX() const { return fSampleX; }
     77 
     78     /**
     79      *  Returns the actual number of pixels written to destination memory, taking
     80      *  scaling, subsetting, and partial frames into account.
     81      */
     82     int swizzleWidth() const { return fSwizzleWidth; }
     83 
     84     /**
     85      *  Returns the byte offset at which we write to destination memory, taking
     86      *  scaling, subsetting, and partial frames into account.
     87      */
     88     size_t swizzleOffsetBytes() const { return fDstOffsetBytes; }
     89 
     90 private:
     91 
     92     /**
     93      *  Method for converting raw data to Skia pixels.
     94      *  @param dstRow Row in which to write the resulting pixels.
     95      *  @param src Row of src data, in format specified by SrcConfig
     96      *  @param dstWidth Width in pixels of the destination
     97      *  @param bpp if bitsPerPixel % 8 == 0, deltaSrc is bytesPerPixel
     98      *             else, deltaSrc is bitsPerPixel
     99      *  @param deltaSrc bpp * sampleX
    100      *  @param ctable Colors (used for kIndex source).
    101      *  @param offset The offset before the first pixel to sample.
    102                         Is in bytes or bits based on what deltaSrc is in.
    103      */
    104     typedef void (*RowProc)(void* SK_RESTRICT dstRow,
    105                             const uint8_t* SK_RESTRICT src,
    106                             int dstWidth, int bpp, int deltaSrc, int offset,
    107                             const SkPMColor ctable[]);
    108 
    109     template <RowProc Proc>
    110     static void SkipLeading8888ZerosThen(void* SK_RESTRICT dstRow,
    111                                          const uint8_t* SK_RESTRICT src,
    112                                          int dstWidth, int bpp, int deltaSrc, int offset,
    113                                          const SkPMColor ctable[]);
    114 
    115     template <RowProc Proc>
    116     static void SkipLeadingGrayAlphaZerosThen(void* dst, const uint8_t* src, int width, int bpp,
    117                                               int deltaSrc, int offset, const SkPMColor ctable[]);
    118 
    119     // May be NULL.  We have not implemented optimized functions for all supported transforms.
    120     const RowProc       fFastProc;
    121     // Always non-NULL.  Supports sampling.
    122     const RowProc       fSlowProc;
    123     // The actual RowProc we are using.  This depends on if fFastProc is non-NULL and
    124     // whether or not we are sampling.
    125     RowProc             fActualProc;
    126 
    127     const SkPMColor*    fColorTable;      // Unowned pointer
    128 
    129     // Subset Swizzles
    130     // There are two types of subset swizzles that we support.  We do not
    131     // support both at the same time.
    132     // TODO: If we want to support partial scanlines for gifs (which may
    133     //       use frame subsets), we will need to support both subsetting
    134     //       modes at the same time.
    135     // (1) Partial Scanlines
    136     //         The client only wants to write a subset of the source pixels
    137     //         to the destination.  This subset is specified to CreateSwizzler
    138     //         using options->fSubset.  We will store subset information in
    139     //         the following fields.
    140     //
    141     //         fSrcOffset:      The starting pixel of the source.
    142     //         fSrcOffsetUnits: Derived from fSrcOffset with two key
    143     //                          differences:
    144     //                          (1) This takes the size of source pixels into
    145     //                          account by multiplying by fSrcBPP.  This may
    146     //                          be measured in bits or bytes depending on
    147     //                          which is natural for the SrcConfig.
    148     //                          (2) If we are sampling, this will be larger
    149     //                          than fSrcOffset * fSrcBPP, since sampling
    150     //                          implies that we will skip some pixels.
    151     //         fDstOffset:      Will be zero.  There is no destination offset
    152     //                          for this type of subset.
    153     //         fDstOffsetBytes: Will be zero.
    154     //         fSrcWidth:       The width of the desired subset of source
    155     //                          pixels, before any sampling is performed.
    156     //         fDstWidth:       Will be equal to fSrcWidth, since this is also
    157     //                          calculated before any sampling is performed.
    158     //                          For this type of subset, the destination width
    159     //                          matches the desired subset of the source.
    160     //         fSwizzleWidth:   The actual number of pixels that will be
    161     //                          written by the RowProc.  This is a scaled
    162     //                          version of fSrcWidth/fDstWidth.
    163     //         fAllocatedWidth: Will be equal to fSwizzleWidth.  For this type
    164     //                          of subset, the number of pixels written is the
    165     //                          same as the actual width of the destination.
    166     // (2) Frame Subset
    167     //         The client will decode the entire width of the source into a
    168     //         subset of destination memory.  This subset is specified to
    169     //         CreateSwizzler in the "frame" parameter.  We store subset
    170     //         information in the following fields.
    171     //
    172     //         fSrcOffset:      Will be zero.  The starting pixel of the source.
    173     //         fSrcOffsetUnits: Will only be non-zero if we are sampling,
    174     //                          since sampling implies that we will skip some
    175     //                          pixels.  Note that this is measured in bits
    176     //                          or bytes depending on which is natural for
    177     //                          SrcConfig.
    178     //         fDstOffset:      First pixel to write in destination.
    179     //         fDstOffsetBytes: fDstOffset * fDstBPP.
    180     //         fSrcWidth:       The entire width of the source pixels, before
    181     //                          any sampling is performed.
    182     //         fDstWidth:       The entire width of the destination memory,
    183     //                          before any sampling is performed.
    184     //         fSwizzleWidth:   The actual number of pixels that will be
    185     //                          written by the RowProc.  This is a scaled
    186     //                          version of fSrcWidth.
    187     //         fAllocatedWidth: The actual number of pixels in destination
    188     //                          memory.  This is a scaled version of
    189     //                          fDstWidth.
    190     //
    191     // If we are not subsetting, these fields are more straightforward.
    192     //         fSrcOffset = fDstOffet = fDstOffsetBytes = 0
    193     //         fSrcOffsetUnits may be non-zero (we will skip the first few pixels when sampling)
    194     //         fSrcWidth = fDstWidth = Full original width
    195     //         fSwizzleWidth = fAllcoatedWidth = Scaled width (if we are sampling)
    196     const int           fSrcOffset;
    197     const int           fDstOffset;
    198     int                 fSrcOffsetUnits;
    199     int                 fDstOffsetBytes;
    200     const int           fSrcWidth;
    201     const int           fDstWidth;
    202     int                 fSwizzleWidth;
    203     int                 fAllocatedWidth;
    204 
    205     int                 fSampleX;         // Step between X samples
    206     const int           fSrcBPP;          // Bits/bytes per pixel for the SrcConfig
    207                                           // if bitsPerPixel % 8 == 0
    208                                           //     fBPP is bytesPerPixel
    209                                           // else
    210                                           //     fBPP is bitsPerPixel
    211     const int           fDstBPP;          // Bytes per pixel for the destination color type
    212 
    213     SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
    214             int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP);
    215     static std::unique_ptr<SkSwizzler> Make(const SkImageInfo& dstInfo, RowProc fastProc,
    216             RowProc proc, const SkPMColor* ctable, int srcBPP, int dstBPP,
    217             const SkCodec::Options& options, const SkIRect* frame);
    218 
    219     int onSetSampleX(int) override;
    220 
    221 };
    222 #endif // SkSwizzler_DEFINED
    223