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