14aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy/*
24aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * Copyright (C) 2010 The Android Open Source Project
34aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *
44aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
54aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * you may not use this file except in compliance with the License.
64aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * You may obtain a copy of the License at
74aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *
84aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
94aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *
104aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * Unless required by applicable law or agreed to in writing, software
114aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
124aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * See the License for the specific language governing permissions and
144aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * limitations under the License.
154aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy */
164aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy
175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#define LOG_NDEBUG 0
185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#define LOG_TAG "YUVCanvas"
194aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy
209fded232a9548a304e0145011df8849fba0dcda7Chris Craik#include <media/stagefright/foundation/ADebug.h>
219fded232a9548a304e0145011df8849fba0dcda7Chris Craik#include <media/stagefright/YUVCanvas.h>
229fded232a9548a304e0145011df8849fba0dcda7Chris Craik#include <media/stagefright/YUVImage.h>
239fded232a9548a304e0145011df8849fba0dcda7Chris Craik#include <ui/Rect.h>
249fded232a9548a304e0145011df8849fba0dcda7Chris Craik
259fded232a9548a304e0145011df8849fba0dcda7Chris Craiknamespace android {
269fded232a9548a304e0145011df8849fba0dcda7Chris Craik
279fded232a9548a304e0145011df8849fba0dcda7Chris CraikYUVCanvas::YUVCanvas(YUVImage &yuvImage)
2809c2d4fe15fbac2faf8a97ba2cc59132ee12222aDerek Sollenberger    : mYUVImage(yuvImage) {
294aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy}
304aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy
314aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain GuyYUVCanvas::~YUVCanvas() {
322dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson}
3309c2d4fe15fbac2faf8a97ba2cc59132ee12222aDerek Sollenberger
347953745dd565167113f8cbfc461bc0521d32d870Romain Guyvoid YUVCanvas::FillYUV(uint8_t yValue, uint8_t uValue, uint8_t vValue) {
357953745dd565167113f8cbfc461bc0521d32d870Romain Guy    for (int32_t y = 0; y < mYUVImage.height(); ++y) {
364aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy        for (int32_t x = 0; x < mYUVImage.width(); ++x) {
374aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy            mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
384aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy        }
394aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy    }
404aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy}
414aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy
424aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guyvoid YUVCanvas::FillYUVRectangle(const Rect& rect,
43ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy        uint8_t yValue, uint8_t uValue, uint8_t vValue) {
44ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy    for (int32_t y = rect.top; y < rect.bottom; ++y) {
455baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        for (int32_t x = rect.left; x < rect.right; ++x) {
46ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy            mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
47ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy        }
48ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy    }
49ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy}
504aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy
51b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guyvoid YUVCanvas::CopyImageRect(
524aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy        const Rect& srcRect,
534aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy        int32_t destStartX, int32_t destStartY,
54c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        const YUVImage &srcImage) {
5512f5e3433226f0a2886a98b0b8da8d5e947c5cdeJohn Reck
562af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik    // Try fast copy first
572af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik    if (YUVImage::fastCopyRectangle(
588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                srcRect,
592dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson                destStartX, destStartY,
602af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik                srcImage, mYUVImage)) {
612af4635e4a9e448a65ff541252f8f94bc6ac48e0Chris Craik        return;
62b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    }
63d6b65f67717025b1162f86f04e2caa5723566cacChris Craik
64b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    int32_t srcStartX = srcRect.left;
65db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik    int32_t srcStartY = srcRect.top;
66b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    for (int32_t offsetY = 0; offsetY < srcRect.height(); ++offsetY) {
67cc882b6518129a11fa007f8c9343e972f03607b4Derek Sollenberger        for (int32_t offsetX = 0; offsetX < srcRect.width(); ++offsetX) {
68db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik            int32_t srcX = srcStartX + offsetX;
69b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy            int32_t srcY = srcStartY + offsetY;
70cc882b6518129a11fa007f8c9343e972f03607b4Derek Sollenberger
719fded232a9548a304e0145011df8849fba0dcda7Chris Craik            int32_t destX = destStartX + offsetX;
725977baa1fa24125c148a72699b53e62abaf08960Chet Haase            int32_t destY = destStartY + offsetY;
7314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
748dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson            uint8_t yValue;
7514e513058ed4168c94e015638d16f5f87fd8063aChris Craik            uint8_t uValue;
76984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            uint8_t vValue;
77cc882b6518129a11fa007f8c9343e972f03607b4Derek Sollenberger
784aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy            srcImage.getPixelValue(srcX, srcY, &yValue, &uValue, &vValue);
7914e513058ed4168c94e015638d16f5f87fd8063aChris Craik            mYUVImage.setPixelValue(destX, destY, yValue, uValue, vValue);
808dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson        }
8114e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
8214e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
8314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
848dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudsonvoid YUVCanvas::downsample(
85072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi        int32_t srcOffsetX, int32_t srcOffsetY,
86072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi        int32_t skipX, int32_t skipY,
87072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi        const YUVImage &srcImage) {
888dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    // TODO: Add a low pass filter for downsampling.
8952244fff29042926e21fa897ef5ab11148e35299John Reck
9014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    // Check that srcImage is big enough to fill mYUVImage.
914aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy    CHECK((srcOffsetX + (mYUVImage.width() - 1) * skipX) < srcImage.width());
9214e513058ed4168c94e015638d16f5f87fd8063aChris Craik    CHECK((srcOffsetY + (mYUVImage.height() - 1) * skipY) < srcImage.height());
938dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson
9414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    uint8_t yValue;
953aadd60521960be063ee06208562ccb63dc414e3Chris Craik    uint8_t uValue;
96956f340aacc7d8fc2d10f776551f13fde2d8d3abChris Craik    uint8_t vValue;
974aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy
9814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    int32_t srcY = srcOffsetY;
99956f340aacc7d8fc2d10f776551f13fde2d8d3abChris Craik    for (int32_t y = 0; y < mYUVImage.height(); ++y) {
1005ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        int32_t srcX = srcOffsetX;
101984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        for (int32_t x = 0; x < mYUVImage.width(); ++x) {
1028dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson            srcImage.getPixelValue(srcX, srcY, &yValue, &uValue, &vValue);
103984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
104e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik
105e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            srcX += skipX;
1066b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik        }
107984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        srcY += skipY;
1088dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson    }
1098dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson}
1108dfaa4904205772cdceee63ef3989bcdedf1a914Tom Hudson
1111db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger}  // namespace android
1121db141f93c4fe79a4669440c3d14f63bc87b2e34Derek Sollenberger