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