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