Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright 2016 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 "SkRGBAToYUV.h"
      9 #include "SkCanvas.h"
     10 #include "SkColorMatrixFilterRowMajor255.h"
     11 #include "SkImage.h"
     12 #include "SkPaint.h"
     13 #include "SkSurface.h"
     14 
     15 bool SkRGBAToYUV(const SkImage* image, const SkISize sizes[3], void* const planes[3],
     16                  const size_t rowBytes[3], SkYUVColorSpace colorSpace) {
     17     // Matrices that go from RGBA to YUV.
     18     static const SkScalar kYUVColorSpaceInvMatrices[][15] = {
     19         // kJPEG_SkYUVColorSpace
     20         { 0.299001f,  0.586998f,   0.114001f,  0.f, 0.0000821798f * 255.f,
     21          -0.168736f, -0.331263f,   0.499999f,  0.f, 0.499954f * 255.f,
     22           0.499999f, -0.418686f,  -0.0813131f, 0.f, 0.499941f * 255.f},
     23 
     24         // kRec601_SkYUVColorSpace
     25         { 0.256951f,  0.504421f,   0.0977346f, 0.f, 0.0625f * 255.f,
     26          -0.148212f, -0.290954f,   0.439166f,  0.f, 0.5f * 255.f,
     27           0.439166f,  -0.367886f, -0.0712802f, 0.f, 0.5f * 255.f},
     28 
     29         // kRec709_SkYUVColorSpace
     30         { 0.182663f,  0.614473f,  0.061971f,  0.f, 0.0625f * 255.f,
     31          -0.100672f, -0.338658f,  0.43933f,   0.f, 0.5f * 255.f,
     32           0.439142f, -0.39891f,  -0.040231f,  0.f, 0.5f * 255.f},
     33     };
     34     static_assert(kLastEnum_SkYUVColorSpace == 2, "yuv color matrix array problem");
     35     static_assert(kJPEG_SkYUVColorSpace     == 0, "yuv color matrix array problem");
     36     static_assert(kRec601_SkYUVColorSpace   == 1, "yuv color matrix array problem");
     37     static_assert(kRec709_SkYUVColorSpace   == 2, "yuv color matrix array problem");
     38 
     39     for (int i = 0; i < 3; ++i) {
     40         size_t rb = rowBytes[i] ? rowBytes[i] : sizes[i].fWidth;
     41         auto surface(SkSurface::MakeRasterDirect(
     42                 SkImageInfo::MakeA8(sizes[i].fWidth, sizes[i].fHeight), planes[i], rb));
     43         if (!surface) {
     44             return false;
     45         }
     46         SkPaint paint;
     47         paint.setFilterQuality(kLow_SkFilterQuality);
     48         paint.setBlendMode(SkBlendMode::kSrc);
     49         int rowStartIdx = 5 * i;
     50         const SkScalar* row = kYUVColorSpaceInvMatrices[colorSpace] + rowStartIdx;
     51         paint.setColorFilter(
     52                 SkColorMatrixFilterRowMajor255::MakeSingleChannelOutput(row));
     53         surface->getCanvas()->drawImageRect(image, SkIRect::MakeWH(image->width(), image->height()),
     54                                             SkRect::MakeIWH(surface->width(), surface->height()),
     55                                             &paint);
     56     }
     57     return true;
     58 }
     59