1e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*
2e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Copyright (C) 2011 The Android Open Source Project
3e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
4e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License");
5e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * you may not use this file except in compliance with the License.
6e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * You may obtain a copy of the License at
7e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
8e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *      http://www.apache.org/licenses/LICENSE-2.0
9e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
10e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Unless required by applicable law or agreed to in writing, software
11e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS,
12e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * See the License for the specific language governing permissions and
14e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * limitations under the License.
15e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */
16e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
17e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen///////////////////////////////////////////////////
18e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// ImageUtils.cpp
19e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// $Id: ImageUtils.cpp,v 1.12 2011/06/17 13:35:48 mbansal Exp $
20e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
21e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
22e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <stdio.h>
23e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <stdlib.h>
24e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <sys/time.h>
25e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
26e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "ImageUtils.h"
27e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
2841a2e9735136f372de95652d0828600282c8e967mbansalvoid ImageUtils::rgba2yvu(ImageType out, ImageType in, int width, int height)
2941a2e9735136f372de95652d0828600282c8e967mbansal{
3041a2e9735136f372de95652d0828600282c8e967mbansal  int r,g,b, a;
3141a2e9735136f372de95652d0828600282c8e967mbansal  ImageType yimg = out;
3241a2e9735136f372de95652d0828600282c8e967mbansal  ImageType vimg = yimg + width*height;
3341a2e9735136f372de95652d0828600282c8e967mbansal  ImageType uimg = vimg + width*height;
3441a2e9735136f372de95652d0828600282c8e967mbansal  ImageType image = in;
3541a2e9735136f372de95652d0828600282c8e967mbansal
3641a2e9735136f372de95652d0828600282c8e967mbansal  for (int ii = 0; ii < height; ii++) {
3741a2e9735136f372de95652d0828600282c8e967mbansal    for (int ij = 0; ij < width; ij++) {
3841a2e9735136f372de95652d0828600282c8e967mbansal      r = (*image++);
3941a2e9735136f372de95652d0828600282c8e967mbansal      g = (*image++);
4041a2e9735136f372de95652d0828600282c8e967mbansal      b = (*image++);
4141a2e9735136f372de95652d0828600282c8e967mbansal      a = (*image++);
4241a2e9735136f372de95652d0828600282c8e967mbansal
4341a2e9735136f372de95652d0828600282c8e967mbansal      if (r < 0) r = 0;
4441a2e9735136f372de95652d0828600282c8e967mbansal      if (r > 255) r = 255;
4541a2e9735136f372de95652d0828600282c8e967mbansal      if (g < 0) g = 0;
4641a2e9735136f372de95652d0828600282c8e967mbansal      if (g > 255) g = 255;
4741a2e9735136f372de95652d0828600282c8e967mbansal      if (b < 0) b = 0;
4841a2e9735136f372de95652d0828600282c8e967mbansal      if (b > 255) b = 255;
4941a2e9735136f372de95652d0828600282c8e967mbansal
5041a2e9735136f372de95652d0828600282c8e967mbansal      int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16;
5141a2e9735136f372de95652d0828600282c8e967mbansal      if (val < 0) val = 0;
5241a2e9735136f372de95652d0828600282c8e967mbansal      if (val > 255) val = 255;
5341a2e9735136f372de95652d0828600282c8e967mbansal      *(yimg) = val;
5441a2e9735136f372de95652d0828600282c8e967mbansal
5541a2e9735136f372de95652d0828600282c8e967mbansal      val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128;
5641a2e9735136f372de95652d0828600282c8e967mbansal      if (val < 0) val = 0;
5741a2e9735136f372de95652d0828600282c8e967mbansal      if (val > 255) val = 255;
5841a2e9735136f372de95652d0828600282c8e967mbansal      *(vimg) = val;
5941a2e9735136f372de95652d0828600282c8e967mbansal
6041a2e9735136f372de95652d0828600282c8e967mbansal      val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128;
6141a2e9735136f372de95652d0828600282c8e967mbansal      if (val < 0) val = 0;
6241a2e9735136f372de95652d0828600282c8e967mbansal      if (val > 255) val = 255;
6341a2e9735136f372de95652d0828600282c8e967mbansal      *(uimg) = val;
6441a2e9735136f372de95652d0828600282c8e967mbansal
6541a2e9735136f372de95652d0828600282c8e967mbansal      yimg++;
6641a2e9735136f372de95652d0828600282c8e967mbansal      uimg++;
6741a2e9735136f372de95652d0828600282c8e967mbansal      vimg++;
6841a2e9735136f372de95652d0828600282c8e967mbansal    }
6941a2e9735136f372de95652d0828600282c8e967mbansal  }
7041a2e9735136f372de95652d0828600282c8e967mbansal}
7141a2e9735136f372de95652d0828600282c8e967mbansal
7241a2e9735136f372de95652d0828600282c8e967mbansal
73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid ImageUtils::rgb2yvu(ImageType out, ImageType in, int width, int height)
74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
75e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int r,g,b;
76e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType yimg = out;
77e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType vimg = yimg + width*height;
78e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType uimg = vimg + width*height;
79e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType image = in;
80e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
81e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  for (int ii = 0; ii < height; ii++) {
82e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int ij = 0; ij < width; ij++) {
83e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      r = (*image++);
84e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      g = (*image++);
85e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      b = (*image++);
86e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
87e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r < 0) r = 0;
88e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r > 255) r = 255;
89e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g < 0) g = 0;
90e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g > 255) g = 255;
91e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b < 0) b = 0;
92e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b > 255) b = 255;
93e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
94e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16;
95e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (val < 0) val = 0;
96e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (val > 255) val = 255;
97e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(yimg) = val;
98e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
99e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128;
100e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (val < 0) val = 0;
101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (val > 255) val = 255;
102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(vimg) = val;
103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128;
105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (val < 0) val = 0;
106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (val > 255) val = 255;
107e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(uimg) = val;
108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      yimg++;
110e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      uimg++;
111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      vimg++;
112e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
115e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType ImageUtils::rgb2gray(ImageType in, int width, int height)
117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int r,g,b, nr, ng, nb, val;
119e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType gray = NULL;
120e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType image = in;
121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType out = ImageUtils::allocateImage(width, height, 1);
122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType outCopy = out;
123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  for (int ii = 0; ii < height; ii++) {
125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int ij = 0; ij < width; ij++) {
126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      r = (*image++);
127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      g = (*image++);
128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      b = (*image++);
129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r < 0) r = 0;
131e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r > 255) r = 255;
132e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g < 0) g = 0;
133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g > 255) g = 255;
134e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b < 0) b = 0;
135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b > 255) b = 255;
136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b);
138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
139e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      outCopy++;
140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  return out;
144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType ImageUtils::rgb2gray(ImageType out, ImageType in, int width, int height)
147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int r,g,b, nr, ng, nb, val;
149e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType gray = out;
150e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType image = in;
151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType outCopy = out;
152e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
153e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  for (int ii = 0; ii < height; ii++) {
154e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int ij = 0; ij < width; ij++) {
155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      r = (*image++);
156e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      g = (*image++);
157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      b = (*image++);
158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r < 0) r = 0;
160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r > 255) r = 255;
161e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g < 0) g = 0;
162e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g > 255) g = 255;
163e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b < 0) b = 0;
164e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b > 255) b = 255;
165e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
166e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b);
167e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      outCopy++;
169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
171e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  return out;
173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
174e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
175e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
176e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType *ImageUtils::imageTypeToRowPointers(ImageType in, int width, int height)
177e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
178e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int i;
179e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int m_h = height;
180e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int m_w = width;
181e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
182e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType *m_rows = new ImageType[m_h];
183e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
184e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  for (i=0;i<m_h;i++) {
185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_rows[i] = &in[(m_w)*i];
186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
187e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  return m_rows;
188e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
189e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
190e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid ImageUtils::yvu2rgb(ImageType out, ImageType in, int width, int height)
191e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
192e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int y,v,u, r, g, b;
193e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *yimg = in;
194e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *vimg = yimg + width*height;
195e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *uimg = vimg + width*height;
196e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *image = out;
197e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
198e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  for (int i = 0; i < height; i++) {
199e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int j = 0; j < width; j++) {
200e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
201e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      y = (*yimg);
202e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      v = (*vimg);
203e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      u = (*uimg);
204e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
205e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (y < 0) y = 0;
206e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (y > 255) y = 255;
207e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (u < 0) u = 0;
208e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (u > 255) u = 255;
209e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (v < 0) v = 0;
210e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (v > 255) v = 255;
211e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
212e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      b = (int) ( 1.164*(y - 16) + 2.018*(u-128));
213e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128));
214e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      r = (int) ( 1.164*(y - 16) + 1.596*(v-128));
215e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
216e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r < 0) r = 0;
217e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r > 255) r = 255;
218e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g < 0) g = 0;
219e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g > 255) g = 255;
220e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b < 0) b = 0;
221e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b > 255) b = 255;
222e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
223e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(image++) = r;
224e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(image++) = g;
225e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(image++) = b;
226e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
227e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      yimg++;
228e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      uimg++;
229e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      vimg++;
230e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
231e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
233e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
234e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
235e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid ImageUtils::yvu2bgr(ImageType out, ImageType in, int width, int height)
236e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int y,v,u, r, g, b;
238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *yimg = in;
239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *vimg = yimg + width*height;
240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *uimg = vimg + width*height;
241e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned char *image = out;
242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  for (int i = 0; i < height; i++) {
244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int j = 0; j < width; j++) {
245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      y = (*yimg);
247e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      v = (*vimg);
248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      u = (*uimg);
249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
250e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (y < 0) y = 0;
251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (y > 255) y = 255;
252e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (u < 0) u = 0;
253e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (u > 255) u = 255;
254e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (v < 0) v = 0;
255e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (v > 255) v = 255;
256e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
257e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      b = (int) ( 1.164*(y - 16) + 2.018*(u-128));
258e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128));
259e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      r = (int) ( 1.164*(y - 16) + 1.596*(v-128));
260e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
261e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r < 0) r = 0;
262e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (r > 255) r = 255;
263e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g < 0) g = 0;
264e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (g > 255) g = 255;
265e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b < 0) b = 0;
266e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      if (b > 255) b = 255;
267e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
268e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(image++) = b;
269e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(image++) = g;
270e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      *(image++) = r;
271e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
272e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      yimg++;
273e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      uimg++;
274e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      vimg++;
275e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
276e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
277e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
278e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
279e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
280e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
281e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType ImageUtils::readBinaryPPM(const char *filename, int &width, int &height)
282e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
283e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
284e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  FILE *imgin = NULL;
285e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int mval=0, format=0, eret;
286e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType ret = IMAGE_TYPE_NOIMAGE;
287e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
288e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  imgin = fopen(filename, "r");
289e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (imgin == NULL) {
290e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fprintf(stderr, "Error: Filename %s not found\n", filename);
291e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return ret;
292e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
293e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
294e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  eret = fscanf(imgin, "P%d\n", &format);
295e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (format != 6) {
296e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fprintf(stderr, "Error: readBinaryPPM only supports PPM format (P6)\n");
297e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return ret;
298e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
299e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
300e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  eret = fscanf(imgin, "%d %d\n", &width, &height);
301e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  eret = fscanf(imgin, "%d\n", &mval);
302e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ret  = allocateImage(width, height, IMAGE_TYPE_NUM_CHANNELS);
303e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  eret = fread(ret, sizeof(ImageTypeBase), IMAGE_TYPE_NUM_CHANNELS*width*height, imgin);
304e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
305e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  fclose(imgin);
306e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
307e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  return ret;
308e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
309e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
310e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
311e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid ImageUtils::writeBinaryPPM(ImageType image, const char *filename, int width, int height, int numChannels)
312e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
313e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  FILE *imgout = fopen(filename, "w");
314e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
315e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (imgout == NULL) {
316e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fprintf(stderr, "Error: Filename %s could not be opened for writing\n", filename);
317e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return;
318e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
319e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
320e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (numChannels == 3) {
321e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fprintf(imgout, "P6\n%d %d\n255\n", width, height);
322e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  } else if (numChannels == 1) {
323e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fprintf(imgout, "P5\n%d %d\n255\n", width, height);
324e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  } else {
325e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fprintf(stderr, "Error: writeBinaryPPM: Unsupported number of channels\n");
326e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
327e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  fwrite(image, sizeof(ImageTypeBase), numChannels*width*height, imgout);
328e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
329e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  fclose(imgout);
330e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
331e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
332e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
333e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType ImageUtils::allocateImage(int width, int height, int numChannels, short int border)
334e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
335e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int overallocation = 256;
336e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return (ImageType) calloc(width*height*numChannels+overallocation, sizeof(ImageTypeBase));
337e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
338e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
339e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
340e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid ImageUtils::freeImage(ImageType image)
341e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
342e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  free(image);
343e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
344e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
345e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
346e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// allocation of one color image used for tmp buffers, etc.
347e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// format of contiguous memory block:
348e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen//    YUVInfo struct (type + BimageInfo for Y,U, and V),
349e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen//    Y row pointers
350e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen//    U row pointers
351e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen//    V row pointers
352e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen//    Y image pixels
353e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen//    U image pixels
354e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen//    V image pixels
355e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenYUVinfo *YUVinfo::allocateImage(unsigned short width, unsigned short height)
356e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
357e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    unsigned short heightUV, widthUV;
358e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
359e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    widthUV = width;
360e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    heightUV = height;
361e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
362e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // figure out how much space to hold all pixels...
36389b9c07b5bbcc2de25dd5f61c28de4575b4df996Wei-Ta Chen    int size = ((width * height * 3) + 8);
364e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    unsigned char *position = 0;
365e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
366e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // VC 8 does not like calling free on yuv->Y.ptr since it is in
367e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // the middle of a block.  So rearrange the memory layout so after
368e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // calling mapYUVInforToImage yuv->Y.ptr points to the begginning
369e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // of the calloc'ed block.
370e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    YUVinfo *yuv = (YUVinfo *) calloc(sizeof(YUVinfo), 1);
371e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (yuv) {
372e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->Y.width  = yuv->Y.pitch = width;
373e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->Y.height = height;
374e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->Y.border = yuv->U.border = yuv->V.border = (unsigned short) 0;
375e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->U.width  = yuv->U.pitch = yuv->V.width = yuv->V.pitch = widthUV;
376e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->U.height = yuv->V.height = heightUV;
377e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
378e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        unsigned char* block = (unsigned char*) calloc(
379e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                sizeof(unsigned char *) * (height + heightUV + heightUV) +
380e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                sizeof(unsigned char) * size, 1);
381e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
382e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        position = block;
383e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        unsigned char **y = (unsigned char **) (block + size);
384e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
385e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        /* Initialize and assign row pointers */
386e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->Y.ptr = y;
387e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->V.ptr = &y[height];
388e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        yuv->U.ptr = &y[height + heightUV];
389e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
390e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (size)
391e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mapYUVInfoToImage(yuv, position);
392e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return yuv;
393e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
394e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
395e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// wrap YUVInfo row pointers around 3 contiguous image (color component) planes.
396e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// position = starting pixel in image.
397e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid YUVinfo::mapYUVInfoToImage(YUVinfo *img, unsigned char *position)
398e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
399e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int i;
400e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (i = 0; i < img->Y.height; i++, position += img->Y.width)
401e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        img->Y.ptr[i] = position;
402e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (i = 0; i < img->V.height; i++, position += img->V.width)
403e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        img->V.ptr[i] = position;
404e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (i = 0; i < img->U.height; i++, position += img->U.width)
405e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        img->U.ptr[i] = position;
406e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
407e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
408e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
409