blob: 0528b144f0bd86b9ef03d81273d4120406f7ab08 [file] [log] [blame]
bsalomonf267c1e2016-02-01 13:16:14 -08001/*
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
15bool 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;
reede8f30622016-03-23 18:59:25 -070041 auto surface(SkSurface::MakeRasterDirect(
bsalomonf267c1e2016-02-01 13:16:14 -080042 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);
reed374772b2016-10-05 17:33:02 -070048 paint.setBlendMode(SkBlendMode::kSrc);
bsalomonf267c1e2016-02-01 13:16:14 -080049 int rowStartIdx = 5 * i;
50 const SkScalar* row = kYUVColorSpaceInvMatrices[colorSpace] + rowStartIdx;
51 paint.setColorFilter(
reedd053ce92016-03-22 10:17:23 -070052 SkColorMatrixFilterRowMajor255::MakeSingleChannelOutput(row));
bsalomonf267c1e2016-02-01 13:16:14 -080053 surface->getCanvas()->drawImageRect(image, SkIRect::MakeWH(image->width(), image->height()),
54 SkRect::MakeIWH(surface->width(), surface->height()),
55 &paint);
56 }
57 return true;
58}