1db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra/*
2db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * Copyright (C) 2010 The Android Open Source Project
3db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *
4db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * Licensed under the Apache License, Version 2.0 (the "License");
5db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * you may not use this file except in compliance with the License.
6db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * You may obtain a copy of the License at
7db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *
8db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *      http://www.apache.org/licenses/LICENSE-2.0
9db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *
10db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * Unless required by applicable law or agreed to in writing, software
11db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * distributed under the License is distributed on an "AS IS" BASIS,
12db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * See the License for the specific language governing permissions and
14db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra * limitations under the License.
15db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra */
16db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
17db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#define LOG_NDEBUG 0
18db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#define LOG_TAG "YUVCanvas"
19db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
20f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
21db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#include <media/stagefright/YUVCanvas.h>
22db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#include <media/stagefright/YUVImage.h>
23db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#include <ui/Rect.h>
24db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
25db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatranamespace android {
26db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
27db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun KwatraYUVCanvas::YUVCanvas(YUVImage &yuvImage)
28db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    : mYUVImage(yuvImage) {
29db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra}
30db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
31db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun KwatraYUVCanvas::~YUVCanvas() {
32db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra}
33db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
34db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatravoid YUVCanvas::FillYUV(uint8_t yValue, uint8_t uValue, uint8_t vValue) {
35db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    for (int32_t y = 0; y < mYUVImage.height(); ++y) {
36db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        for (int32_t x = 0; x < mYUVImage.width(); ++x) {
37db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
38db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        }
39db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    }
40db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra}
41db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
42db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatravoid YUVCanvas::FillYUVRectangle(const Rect& rect,
43db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        uint8_t yValue, uint8_t uValue, uint8_t vValue) {
44db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    for (int32_t y = rect.top; y < rect.bottom; ++y) {
45db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        for (int32_t x = rect.left; x < rect.right; ++x) {
46db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
47db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        }
48db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    }
49db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra}
50db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
51db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatravoid YUVCanvas::CopyImageRect(
52db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        const Rect& srcRect,
53db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        int32_t destStartX, int32_t destStartY,
54db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        const YUVImage &srcImage) {
55db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
56db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Try fast copy first
57db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    if (YUVImage::fastCopyRectangle(
58db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra                srcRect,
59db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra                destStartX, destStartY,
60db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra                srcImage, mYUVImage)) {
61db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        return;
62db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    }
63db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
64db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    int32_t srcStartX = srcRect.left;
65db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    int32_t srcStartY = srcRect.top;
66db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    for (int32_t offsetY = 0; offsetY < srcRect.height(); ++offsetY) {
67db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        for (int32_t offsetX = 0; offsetX < srcRect.width(); ++offsetX) {
68db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            int32_t srcX = srcStartX + offsetX;
69db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            int32_t srcY = srcStartY + offsetY;
70db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
71db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            int32_t destX = destStartX + offsetX;
72db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            int32_t destY = destStartY + offsetY;
73db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
74db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            uint8_t yValue;
75db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            uint8_t uValue;
76db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            uint8_t vValue;
77db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
78c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra            srcImage.getPixelValue(srcX, srcY, &yValue, &uValue, &vValue);
79db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            mYUVImage.setPixelValue(destX, destY, yValue, uValue, vValue);
80db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        }
81db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    }
82db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra}
83db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
84c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatravoid YUVCanvas::downsample(
85c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra        int32_t srcOffsetX, int32_t srcOffsetY,
86c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra        int32_t skipX, int32_t skipY,
87c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra        const YUVImage &srcImage) {
88c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    // TODO: Add a low pass filter for downsampling.
89c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra
90c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    // Check that srcImage is big enough to fill mYUVImage.
91c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    CHECK((srcOffsetX + (mYUVImage.width() - 1) * skipX) < srcImage.width());
92c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    CHECK((srcOffsetY + (mYUVImage.height() - 1) * skipY) < srcImage.height());
93c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra
94c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    uint8_t yValue;
95c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    uint8_t uValue;
96c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    uint8_t vValue;
97c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra
98c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    int32_t srcY = srcOffsetY;
99c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    for (int32_t y = 0; y < mYUVImage.height(); ++y) {
100c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra        int32_t srcX = srcOffsetX;
101c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra        for (int32_t x = 0; x < mYUVImage.width(); ++x) {
102c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra            srcImage.getPixelValue(srcX, srcY, &yValue, &uValue, &vValue);
103c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra            mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
104c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra
105c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra            srcX += skipX;
106c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra        }
107c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra        srcY += skipY;
108c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra    }
109c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra}
110c0d936ddacc4f7d883f3bd1dd8099586836c820fNipun Kwatra
111db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra}  // namespace android
112