1 /*
2 * Copyright (C) 2011 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 ///////////////////////////////////////////////////
18 // Mosaic.pp
19 // S.O. # :
20 // Author(s): zkira
21 // $Id: Mosaic.cpp,v 1.20 2011/06/24 04:22:14 mbansal Exp $
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "Mosaic.h"
27 #include "trsMatrix.h"
28
29 #include "Log.h"
30 #define LOG_TAG "MOSAIC"
31
Mosaic()32 Mosaic::Mosaic()
33 {
34 initialized = false;
35 imageMosaicYVU = NULL;
36 frames_size = 0;
37 max_frames = 200;
38 }
39
~Mosaic()40 Mosaic::~Mosaic()
41 {
42 for (int i = 0; i < frames_size; i++)
43 {
44 if (frames[i])
45 delete frames[i];
46 }
47 delete frames;
48 delete rframes;
49
50 for (int j = 0; j < owned_size; j++)
51 delete owned_frames[j];
52 delete owned_frames;
53
54 if (aligner != NULL)
55 delete aligner;
56 if (blender != NULL)
57 delete blender;
58 }
59
initialize(int blendingType,int stripType,int width,int height,int nframes,bool quarter_res,float thresh_still)60 int Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still)
61 {
62 this->blendingType = blendingType;
63
64 // TODO: Review this logic if enabling FULL or PAN mode
65 if (blendingType == Blend::BLEND_TYPE_FULL ||
66 blendingType == Blend::BLEND_TYPE_PAN)
67 {
68 stripType = Blend::STRIP_TYPE_THIN;
69 }
70
71 this->stripType = stripType;
72 this->width = width;
73 this->height = height;
74
75
76 mosaicWidth = mosaicHeight = 0;
77 imageMosaicYVU = NULL;
78
79 frames = new MosaicFrame *[max_frames];
80 rframes = new MosaicFrame *[max_frames];
81
82 if(nframes>-1)
83 {
84 for(int i=0; i<nframes; i++)
85 {
86 frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data
87 }
88 }
89 else
90 {
91 for(int i=0; i<max_frames; i++)
92 {
93 frames[i] = NULL;
94 }
95 }
96
97 owned_frames = new ImageType[max_frames];
98 owned_size = 0;
99
100 LOGV("Initialize %d %d", width, height);
101 LOGV("Frame width %d,%d", width, height);
102 LOGV("Max num frames %d", max_frames);
103
104 aligner = new Align();
105 aligner->initialize(width, height,quarter_res,thresh_still);
106
107 if (blendingType == Blend::BLEND_TYPE_FULL ||
108 blendingType == Blend::BLEND_TYPE_PAN ||
109 blendingType == Blend::BLEND_TYPE_CYLPAN ||
110 blendingType == Blend::BLEND_TYPE_HORZ) {
111 blender = new Blend();
112 blender->initialize(blendingType, stripType, width, height);
113 } else {
114 blender = NULL;
115 LOGE("Error: Unknown blending type %d",blendingType);
116 return MOSAIC_RET_ERROR;
117 }
118
119 initialized = true;
120
121 return MOSAIC_RET_OK;
122 }
123
addFrameRGB(ImageType imageRGB)124 int Mosaic::addFrameRGB(ImageType imageRGB)
125 {
126 ImageType imageYVU;
127 // Convert to YVU24 which is used by blending
128 imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
129 ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height);
130
131 int existing_frames_size = frames_size;
132 int ret = addFrame(imageYVU);
133
134 if (frames_size > existing_frames_size)
135 owned_frames[owned_size++] = imageYVU;
136 else
137 ImageUtils::freeImage(imageYVU);
138
139 return ret;
140 }
141
addFrame(ImageType imageYVU)142 int Mosaic::addFrame(ImageType imageYVU)
143 {
144 if(frames[frames_size]==NULL)
145 frames[frames_size] = new MosaicFrame(this->width,this->height,false);
146
147 MosaicFrame *frame = frames[frames_size];
148
149 frame->image = imageYVU;
150
151 // Add frame to aligner
152 int ret = MOSAIC_RET_ERROR;
153 if (aligner != NULL)
154 {
155 // Note aligner takes in RGB images
156 int align_flag = Align::ALIGN_RET_OK;
157 align_flag = aligner->addFrame(frame->image);
158 aligner->getLastTRS(frame->trs);
159
160 if (frames_size >= max_frames)
161 {
162 LOGV("WARNING: More frames than preallocated, ignoring."
163 "Increase maximum number of frames (-f <max_frames>) to avoid this");
164 return MOSAIC_RET_ERROR;
165 }
166
167 switch (align_flag)
168 {
169 case Align::ALIGN_RET_OK:
170 frames_size++;
171 ret = MOSAIC_RET_OK;
172 break;
173 case Align::ALIGN_RET_FEW_INLIERS:
174 frames_size++;
175 ret = MOSAIC_RET_FEW_INLIERS;
176 break;
177 case Align::ALIGN_RET_LOW_TEXTURE:
178 ret = MOSAIC_RET_LOW_TEXTURE;
179 break;
180 case Align::ALIGN_RET_ERROR:
181 ret = MOSAIC_RET_ERROR;
182 break;
183 default:
184 break;
185 }
186 }
187
188 return ret;
189 }
190
191
createMosaic(float & progress,bool & cancelComputation)192 int Mosaic::createMosaic(float &progress, bool &cancelComputation)
193 {
194 if (frames_size <= 0)
195 {
196 // Haven't accepted any frame in aligner. No need to do blending.
197 progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND
198 + TIME_PERCENT_FINAL;
199 return MOSAIC_RET_OK;
200 }
201
202 if (blendingType == Blend::BLEND_TYPE_PAN)
203 {
204
205 balanceRotations();
206
207 }
208
209 int ret = Blend::BLEND_RET_ERROR;
210
211 // Blend the mosaic (alignment has already been done)
212 if (blender != NULL)
213 {
214 ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes,
215 frames_size, imageMosaicYVU,
216 mosaicWidth, mosaicHeight, progress, cancelComputation);
217 }
218
219 switch(ret)
220 {
221 case Blend::BLEND_RET_ERROR:
222 case Blend::BLEND_RET_ERROR_MEMORY:
223 ret = MOSAIC_RET_ERROR;
224 break;
225 case Blend::BLEND_RET_CANCELLED:
226 ret = MOSAIC_RET_CANCELLED;
227 break;
228 case Blend::BLEND_RET_OK:
229 ret = MOSAIC_RET_OK;
230 }
231 return ret;
232 }
233
getMosaic(int & width,int & height)234 ImageType Mosaic::getMosaic(int &width, int &height)
235 {
236 width = mosaicWidth;
237 height = mosaicHeight;
238
239 return imageMosaicYVU;
240 }
241
242
243
balanceRotations()244 int Mosaic::balanceRotations()
245 {
246 // Normalize to the mean angle of rotation (Smiley face)
247 double sineAngle = 0.0;
248
249 for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
250 sineAngle /= frames_size;
251 // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
252 double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
253 double m[3][3] = {
254 { cosineAngle, -sineAngle, 0 },
255 { sineAngle, cosineAngle, 0},
256 { 0, 0, 1}};
257 double tmp[3][3];
258
259 for (int i = 0; i < frames_size; i++) {
260 memcpy(tmp, frames[i]->trs, sizeof(tmp));
261 mult33d(frames[i]->trs, m, tmp);
262 }
263
264 return MOSAIC_RET_OK;
265 }
266