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// A container class to hold YUV data and provide various utilities,
18db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra// e.g. to set/get pixel values.
19db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra// Supported formats:
20db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  - YUV420 Planar
21db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  - YUV420 Semi Planar
22db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//
23db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  Currently does not support variable strides.
24db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//
25db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  Implementation: Two simple abstractions are done to simplify access
26db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  to YUV channels for different formats:
27db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  - initializeYUVPointers() sets up pointers (mYdata, mUdata, mVdata) to
28db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  point to the right start locations of the different channel data depending
29db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  on the format.
30db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  - getOffsets() returns the correct offset for the different channels
31db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  depending on the format.
32db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//  Location of any pixel's YUV channels can then be easily computed using these.
33db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra//
34db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
35db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#ifndef YUV_IMAGE_H_
36db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
37db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#define YUV_IMAGE_H_
38db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
39db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#include <stdint.h>
40db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#include <cstring>
41db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
42db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatranamespace android {
43db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
44db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatraclass Rect;
45db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
46db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatraclass YUVImage {
47db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatrapublic:
48db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Supported YUV formats
49db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    enum YUVFormat {
50db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        YUV420Planar,
51db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        YUV420SemiPlanar
52db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    };
53db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
54db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Constructs an image with the given size, format. Also allocates and owns
55db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // the required memory.
56db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height);
57db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
58db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Constructs an image with the given size, format. The memory is provided
59db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // by the caller and we don't own it.
60db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height, uint8_t *buffer);
61db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
62db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Destructor to delete the memory if it owns it.
63db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    ~YUVImage();
64db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
65db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Returns the size of the buffer required to store the YUV data for the given
66db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // format and geometry. Useful when the caller wants to allocate the requisite
67db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // memory.
68db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    static size_t bufferSize(YUVFormat yuvFormat, int32_t width, int32_t height);
69db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
704a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra    int32_t width() const {return mWidth;}
714a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra    int32_t height() const {return mHeight;}
724a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra
734a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra    // Returns true if pixel is the range [0, width-1] x [0, height-1]
744a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra    // and false otherwise.
754a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra    bool validPixel(int32_t x, int32_t y) const;
76db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
77db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Get the pixel YUV value at pixel (x,y).
78db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
794a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra    // Returns true if get was successful and false otherwise.
80db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool getPixelValue(int32_t x, int32_t y,
81db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            uint8_t *yPtr, uint8_t *uPtr, uint8_t *vPtr) const;
82db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
83db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Set the pixel YUV value at pixel (x,y).
84db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
854a6b74563ac0fe752fbdfd15f91772473f8a4711Nipun Kwatra    // Returns true if set was successful and false otherwise.
86db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool setPixelValue(int32_t x, int32_t y,
87db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            uint8_t yValue, uint8_t uValue, uint8_t vValue);
88db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
89db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Uses memcpy to copy an entire row of data
90db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    static void fastCopyRectangle420Planar(
91db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            const Rect& srcRect,
92db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            int32_t destStartX, int32_t destStartY,
93db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            const YUVImage &srcImage, YUVImage &destImage);
94db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
95db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Uses memcpy to copy an entire row of data
96db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    static void fastCopyRectangle420SemiPlanar(
97db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            const Rect& srcRect,
98db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            int32_t destStartX, int32_t destStartY,
99db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            const YUVImage &srcImage, YUVImage &destImage);
100db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
101db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Tries to use memcopy to copy entire rows of data.
102db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Returns false if fast copy is not possible for the passed image formats.
103db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    static bool fastCopyRectangle(
104db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            const Rect& srcRect,
105db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            int32_t destStartX, int32_t destStartY,
106db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra            const YUVImage &srcImage, YUVImage &destImage);
107db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
108db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Convert the given YUV value to RGB.
109db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    void yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,
110db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        uint8_t *r, uint8_t *g, uint8_t *b) const;
111db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
112db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Write the image to a human readable PPM file.
113db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Returns true if write was succesful and false otherwise.
114db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool writeToPPM(const char *filename) const;
115db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
116db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatraprivate:
117db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // YUV Format of the image.
118db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    YUVFormat mYUVFormat;
119db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
120db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    int32_t mWidth;
121db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    int32_t mHeight;
122db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
123db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Pointer to the memory buffer.
124db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    uint8_t *mBuffer;
125db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
126db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Boolean telling whether we own the memory buffer.
127db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool mOwnBuffer;
128db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
129db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Pointer to start of the Y data plane.
130db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    uint8_t *mYdata;
131db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
132db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Pointer to start of the U data plane. Note that in case of interleaved formats like
133db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // YUV420 semiplanar, mUdata points to the start of the U data in the UV plane.
134db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    uint8_t *mUdata;
135db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
136db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Pointer to start of the V data plane. Note that in case of interleaved formats like
137db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // YUV420 semiplanar, mVdata points to the start of the V data in the UV plane.
138db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    uint8_t *mVdata;
139db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
140db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Initialize the pointers mYdata, mUdata, mVdata to point to the right locations for
141db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // the given format and geometry.
142db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Returns true if initialize was succesful and false otherwise.
143db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool initializeYUVPointers();
144db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
145db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // For the given pixel location, this returns the offset of the location of y, u and v
146db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // data from the corresponding base pointers -- mYdata, mUdata, mVdata.
147db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
148db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Returns true if getting offsets was succesful and false otherwise.
149db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool getOffsets(int32_t x, int32_t y,
150db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        int32_t *yOffset, int32_t *uOffset, int32_t *vOffset) const;
151db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
152db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Returns the offset increments incurred in going from one data row to the next data row
153db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // for the YUV channels. Note that this corresponds to data rows and not pixel rows.
154db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // E.g. depending on formats, U/V channels may have only one data row corresponding
155db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // to two pixel rows.
156db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool getOffsetIncrementsPerDataRow(
157db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        int32_t *yDataOffsetIncrement,
158db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        int32_t *uDataOffsetIncrement,
159db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        int32_t *vDataOffsetIncrement) const;
160db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
161db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Given the offset return the address of the corresponding channel's data.
162db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    uint8_t* getYAddress(int32_t offset) const;
163db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    uint8_t* getUAddress(int32_t offset) const;
164db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    uint8_t* getVAddress(int32_t offset) const;
165db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
166db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Given the pixel location, returns the address of the corresponding channel's data.
167db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
168db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    bool getYUVAddresses(int32_t x, int32_t y,
169db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra        uint8_t **yAddr, uint8_t **uAddr, uint8_t **vAddr) const;
170db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
171db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    // Disallow implicit casting and copying.
172db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    YUVImage(const YUVImage &);
173db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra    YUVImage &operator=(const YUVImage &);
174db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra};
175db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
176db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra}  // namespace android
177db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra
178db205a1d75c1e9a7d0dbd8fa011335249ad6f4acNipun Kwatra#endif  // YUV_IMAGE_H_
179