• 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 
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