• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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