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 "YUVImage" 19db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 20f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 21db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#include <media/stagefright/YUVImage.h> 22db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#include <ui/Rect.h> 23db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 24db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatranamespace android { 25db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 26db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun KwatraYUVImage::YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height) { 27db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mYUVFormat = yuvFormat; 28db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mWidth = width; 29db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mHeight = height; 30db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 31db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra size_t numberOfBytes = bufferSize(yuvFormat, width, height); 32db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *buffer = new uint8_t[numberOfBytes]; 33db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mBuffer = buffer; 34db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mOwnBuffer = true; 35db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 36db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra initializeYUVPointers(); 37db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 38db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 39db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun KwatraYUVImage::YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height, uint8_t *buffer) { 40db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mYUVFormat = yuvFormat; 41db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mWidth = width; 42db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mHeight = height; 43db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mBuffer = buffer; 44db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mOwnBuffer = false; 45db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 46db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra initializeYUVPointers(); 47db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 48db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 49db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//static 50db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrasize_t YUVImage::bufferSize(YUVFormat yuvFormat, int32_t width, int32_t height) { 51db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t numberOfPixels = width*height; 52db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra size_t numberOfBytes = 0; 53db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (yuvFormat == YUV420Planar || yuvFormat == YUV420SemiPlanar) { 54db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Y takes numberOfPixels bytes and U/V take numberOfPixels/4 bytes each. 55db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra numberOfBytes = (size_t)(numberOfPixels + (numberOfPixels >> 1)); 56db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else { 5729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Format not supported"); 58db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 59db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return numberOfBytes; 60db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 61db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 62db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::initializeYUVPointers() { 63db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t numberOfPixels = mWidth * mHeight; 64db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 65db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (mYUVFormat == YUV420Planar) { 66db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mYdata = (uint8_t *)mBuffer; 67db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mUdata = mYdata + numberOfPixels; 68db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mVdata = mUdata + (numberOfPixels >> 2); 69db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else if (mYUVFormat == YUV420SemiPlanar) { 70db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // U and V channels are interleaved as VUVUVU. 71db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // So V data starts at the end of Y channel and 72db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // U data starts right after V's start. 73db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mYdata = (uint8_t *)mBuffer; 74db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mVdata = mYdata + numberOfPixels; 75db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra mUdata = mVdata + 1; 76db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else { 7729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Format not supported"); 78db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return false; 79db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 80db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 81db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 82db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 83db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun KwatraYUVImage::~YUVImage() { 84db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (mOwnBuffer) delete[] mBuffer; 85db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 86db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 87db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::getOffsets(int32_t x, int32_t y, 88db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t *yOffset, int32_t *uOffset, int32_t *vOffset) const { 89db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *yOffset = y*mWidth + x; 90db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 91db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t uvOffset = (y >> 1) * (mWidth >> 1) + (x >> 1); 92db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (mYUVFormat == YUV420Planar) { 93db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *uOffset = uvOffset; 94db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *vOffset = uvOffset; 95db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else if (mYUVFormat == YUV420SemiPlanar) { 96db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Since U and V channels are interleaved, offsets need 97db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // to be doubled. 98db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *uOffset = 2*uvOffset; 99db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *vOffset = 2*uvOffset; 100db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else { 10129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Format not supported"); 102db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return false; 103db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 104db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 105db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 106db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 107db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 108db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::getOffsetIncrementsPerDataRow( 109db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t *yDataOffsetIncrement, 110db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t *uDataOffsetIncrement, 111db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t *vDataOffsetIncrement) const { 112db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *yDataOffsetIncrement = mWidth; 113db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 114db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t uvDataOffsetIncrement = mWidth >> 1; 115db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 116db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (mYUVFormat == YUV420Planar) { 117db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *uDataOffsetIncrement = uvDataOffsetIncrement; 118db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *vDataOffsetIncrement = uvDataOffsetIncrement; 119db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else if (mYUVFormat == YUV420SemiPlanar) { 120db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Since U and V channels are interleaved, offsets need 121db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // to be doubled. 122db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *uDataOffsetIncrement = 2*uvDataOffsetIncrement; 123db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *vDataOffsetIncrement = 2*uvDataOffsetIncrement; 124db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else { 12529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Format not supported"); 126db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return false; 127db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 128db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 129db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 130db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 131db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 132db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrauint8_t* YUVImage::getYAddress(int32_t offset) const { 133db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return mYdata + offset; 134db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 135db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 136db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrauint8_t* YUVImage::getUAddress(int32_t offset) const { 137db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return mUdata + offset; 138db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 139db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 140db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrauint8_t* YUVImage::getVAddress(int32_t offset) const { 141db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return mVdata + offset; 142db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 143db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 144db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::getYUVAddresses(int32_t x, int32_t y, 145db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t **yAddr, uint8_t **uAddr, uint8_t **vAddr) const { 146db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t yOffset; 147db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t uOffset; 148db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t vOffset; 149db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (!getOffsets(x, y, &yOffset, &uOffset, &vOffset)) return false; 150db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 151db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *yAddr = getYAddress(yOffset); 152db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *uAddr = getUAddress(uOffset); 153db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *vAddr = getVAddress(vOffset); 154db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 155db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 156db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 157db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 1584a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatrabool YUVImage::validPixel(int32_t x, int32_t y) const { 1594a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra return (x >= 0 && x < mWidth && 1604a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra y >= 0 && y < mHeight); 1614a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra} 1624a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra 163db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::getPixelValue(int32_t x, int32_t y, 164db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *yPtr, uint8_t *uPtr, uint8_t *vPtr) const { 1654a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra CHECK(validPixel(x, y)); 1664a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra 167db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *yAddr; 168db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uAddr; 169db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vAddr; 170db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (!getYUVAddresses(x, y, &yAddr, &uAddr, &vAddr)) return false; 171db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 172db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *yPtr = *yAddr; 173db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *uPtr = *uAddr; 174db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *vPtr = *vAddr; 175db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 176db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 177db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 178db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 179db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::setPixelValue(int32_t x, int32_t y, 180db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t yValue, uint8_t uValue, uint8_t vValue) { 1814a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra CHECK(validPixel(x, y)); 1824a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra 183db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *yAddr; 184db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uAddr; 185db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vAddr; 186db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (!getYUVAddresses(x, y, &yAddr, &uAddr, &vAddr)) return false; 187db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 188db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *yAddr = yValue; 189db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *uAddr = uValue; 190db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *vAddr = vValue; 191db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 192db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 193db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 194db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 195db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatravoid YUVImage::fastCopyRectangle420Planar( 196db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra const Rect& srcRect, 197db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t destStartX, int32_t destStartY, 198db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra const YUVImage &srcImage, YUVImage &destImage) { 199db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra CHECK(srcImage.mYUVFormat == YUV420Planar); 200db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra CHECK(destImage.mYUVFormat == YUV420Planar); 201db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 202db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t srcStartX = srcRect.left; 203db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t srcStartY = srcRect.top; 204db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t width = srcRect.width(); 205db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t height = srcRect.height(); 206db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 207db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Get source and destination start addresses 208db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *ySrcAddrBase; 209db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uSrcAddrBase; 210db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vSrcAddrBase; 211db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcImage.getYUVAddresses(srcStartX, srcStartY, 212db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &ySrcAddrBase, &uSrcAddrBase, &vSrcAddrBase); 213db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 214db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *yDestAddrBase; 215db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uDestAddrBase; 216db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vDestAddrBase; 217db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra destImage.getYUVAddresses(destStartX, destStartY, 218db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &yDestAddrBase, &uDestAddrBase, &vDestAddrBase); 219db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 220db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Get source and destination offset increments incurred in going 221db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // from one data row to next. 222db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t ySrcOffsetIncrement; 223db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t uSrcOffsetIncrement; 224db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t vSrcOffsetIncrement; 225db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcImage.getOffsetIncrementsPerDataRow( 226db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &ySrcOffsetIncrement, &uSrcOffsetIncrement, &vSrcOffsetIncrement); 227db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 228db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t yDestOffsetIncrement; 229db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t uDestOffsetIncrement; 230db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t vDestOffsetIncrement; 231db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra destImage.getOffsetIncrementsPerDataRow( 232db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &yDestOffsetIncrement, &uDestOffsetIncrement, &vDestOffsetIncrement); 233db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 234db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Copy Y 235db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra { 236db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra size_t numberOfYBytesPerRow = (size_t) width; 237db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *ySrcAddr = ySrcAddrBase; 238db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *yDestAddr = yDestAddrBase; 239db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra for (int32_t offsetY = 0; offsetY < height; ++offsetY) { 240db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra memcpy(yDestAddr, ySrcAddr, numberOfYBytesPerRow); 241db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 242db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra ySrcAddr += ySrcOffsetIncrement; 243db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra yDestAddr += yDestOffsetIncrement; 244db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 245db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 246db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 247db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Copy U 248db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra { 249db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra size_t numberOfUBytesPerRow = (size_t) (width >> 1); 250db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uSrcAddr = uSrcAddrBase; 251db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uDestAddr = uDestAddrBase; 252db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Every other row has an entry for U/V channel values. Hence only 253db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // go half the height. 254db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra for (int32_t offsetY = 0; offsetY < (height >> 1); ++offsetY) { 255db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra memcpy(uDestAddr, uSrcAddr, numberOfUBytesPerRow); 256db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 257db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uSrcAddr += uSrcOffsetIncrement; 258db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uDestAddr += uDestOffsetIncrement; 259db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 260db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 261db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 262db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Copy V 263db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra { 264db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra size_t numberOfVBytesPerRow = (size_t) (width >> 1); 265db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vSrcAddr = vSrcAddrBase; 266db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vDestAddr = vDestAddrBase; 267db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Every other pixel row has a U/V data row. Hence only go half the height. 268db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra for (int32_t offsetY = 0; offsetY < (height >> 1); ++offsetY) { 269db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra memcpy(vDestAddr, vSrcAddr, numberOfVBytesPerRow); 270db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 271db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra vSrcAddr += vSrcOffsetIncrement; 272db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra vDestAddr += vDestOffsetIncrement; 273db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 274db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 275db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 276db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 277db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatravoid YUVImage::fastCopyRectangle420SemiPlanar( 278db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra const Rect& srcRect, 279db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t destStartX, int32_t destStartY, 280db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra const YUVImage &srcImage, YUVImage &destImage) { 281db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra CHECK(srcImage.mYUVFormat == YUV420SemiPlanar); 282db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra CHECK(destImage.mYUVFormat == YUV420SemiPlanar); 283db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 284db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t srcStartX = srcRect.left; 285db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t srcStartY = srcRect.top; 286db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t width = srcRect.width(); 287db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t height = srcRect.height(); 288db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 289db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Get source and destination start addresses 290db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *ySrcAddrBase; 291db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uSrcAddrBase; 292db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vSrcAddrBase; 293db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcImage.getYUVAddresses(srcStartX, srcStartY, 294db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &ySrcAddrBase, &uSrcAddrBase, &vSrcAddrBase); 295db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 296db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *yDestAddrBase; 297db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *uDestAddrBase; 298db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vDestAddrBase; 299db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra destImage.getYUVAddresses(destStartX, destStartY, 300db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &yDestAddrBase, &uDestAddrBase, &vDestAddrBase); 301db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 302db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Get source and destination offset increments incurred in going 303db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // from one data row to next. 304db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t ySrcOffsetIncrement; 305db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t uSrcOffsetIncrement; 306db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t vSrcOffsetIncrement; 307db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcImage.getOffsetIncrementsPerDataRow( 308db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &ySrcOffsetIncrement, &uSrcOffsetIncrement, &vSrcOffsetIncrement); 309db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 310db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t yDestOffsetIncrement; 311db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t uDestOffsetIncrement; 312db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t vDestOffsetIncrement; 313db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra destImage.getOffsetIncrementsPerDataRow( 314db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra &yDestOffsetIncrement, &uDestOffsetIncrement, &vDestOffsetIncrement); 315db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 316db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Copy Y 317db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra { 318db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra size_t numberOfYBytesPerRow = (size_t) width; 319db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *ySrcAddr = ySrcAddrBase; 320db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *yDestAddr = yDestAddrBase; 321db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra for (int32_t offsetY = 0; offsetY < height; ++offsetY) { 322db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra memcpy(yDestAddr, ySrcAddr, numberOfYBytesPerRow); 323db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 324db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra ySrcAddr = ySrcAddr + ySrcOffsetIncrement; 325db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra yDestAddr = yDestAddr + yDestOffsetIncrement; 326db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 327db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 328db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 329db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Copy UV 330db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra { 331db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // UV are interleaved. So number of UV bytes per row is 2*(width/2). 332db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra size_t numberOfUVBytesPerRow = (size_t) width; 333db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vSrcAddr = vSrcAddrBase; 334db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *vDestAddr = vDestAddrBase; 335db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra // Every other pixel row has a U/V data row. Hence only go half the height. 336db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra for (int32_t offsetY = 0; offsetY < (height >> 1); ++offsetY) { 337db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra memcpy(vDestAddr, vSrcAddr, numberOfUVBytesPerRow); 338db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 339db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra vSrcAddr += vSrcOffsetIncrement; 340db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra vDestAddr += vDestOffsetIncrement; 341db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 342db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 343db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 344db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 345db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra// static 346db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::fastCopyRectangle( 347db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra const Rect& srcRect, 348db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra int32_t destStartX, int32_t destStartY, 349db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra const YUVImage &srcImage, YUVImage &destImage) { 350db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (srcImage.mYUVFormat == destImage.mYUVFormat) { 351db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (srcImage.mYUVFormat == YUV420Planar) { 352db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra fastCopyRectangle420Planar( 353db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcRect, 354db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra destStartX, destStartY, 355db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcImage, destImage); 356db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } else if (srcImage.mYUVFormat == YUV420SemiPlanar) { 357db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra fastCopyRectangle420SemiPlanar( 358db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcRect, 359db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra destStartX, destStartY, 360db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra srcImage, destImage); 361db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 362db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 363db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 364db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return false; 365db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 366db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 367db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrauint8_t clamp(uint8_t v, uint8_t minValue, uint8_t maxValue) { 368db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra CHECK(maxValue >= minValue); 369db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 370db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (v < minValue) return minValue; 371db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra else if (v > maxValue) return maxValue; 372db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra else return v; 373db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 374db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 375db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatravoid YUVImage::yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue, 376db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t *r, uint8_t *g, uint8_t *b) const { 377db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *r = yValue + (1.370705 * (vValue-128)); 378db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *g = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128)); 379db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *b = yValue + (1.732446 * (uValue-128)); 380db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 381db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *r = clamp(*r, 0, 255); 382db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *g = clamp(*g, 0, 255); 383db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra *b = clamp(*b, 0, 255); 384db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 385db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 386db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrabool YUVImage::writeToPPM(const char *filename) const { 387db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra FILE *fp = fopen(filename, "w"); 388db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra if (fp == NULL) { 389db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return false; 390db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 391db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra fprintf(fp, "P3\n"); 392db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra fprintf(fp, "%d %d\n", mWidth, mHeight); 393db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra fprintf(fp, "255\n"); 394db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra for (int32_t y = 0; y < mHeight; ++y) { 395db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra for (int32_t x = 0; x < mWidth; ++x) { 396db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t yValue; 397db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t uValue; 398db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t vValue; 399db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra getPixelValue(x, y, &yValue, &uValue, & vValue); 400db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 401db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t rValue; 402db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t gValue; 403db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra uint8_t bValue; 404db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra yuv2rgb(yValue, uValue, vValue, &rValue, &gValue, &bValue); 405db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 406db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra fprintf(fp, "%d %d %d\n", (int32_t)rValue, (int32_t)gValue, (int32_t)bValue); 407db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 408db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra } 409db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra fclose(fp); 410db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra return true; 411db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} 412db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra 413db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra} // namespace android 414