bsalomon | f267c1e | 2016-02-01 13:16:14 -0800 | [diff] [blame] | 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; |
reed | e8f3062 | 2016-03-23 18:59:25 -0700 | [diff] [blame] | 41 | auto surface(SkSurface::MakeRasterDirect( |
bsalomon | f267c1e | 2016-02-01 13:16:14 -0800 | [diff] [blame] | 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); |
reed | 374772b | 2016-10-05 17:33:02 -0700 | [diff] [blame] | 48 | paint.setBlendMode(SkBlendMode::kSrc); |
bsalomon | f267c1e | 2016-02-01 13:16:14 -0800 | [diff] [blame] | 49 | int rowStartIdx = 5 * i; |
| 50 | const SkScalar* row = kYUVColorSpaceInvMatrices[colorSpace] + rowStartIdx; |
| 51 | paint.setColorFilter( |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 52 | SkColorMatrixFilterRowMajor255::MakeSingleChannelOutput(row)); |
bsalomon | f267c1e | 2016-02-01 13:16:14 -0800 | [diff] [blame] | 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 | } |