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