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 Mosaic::Mosaic() 30 { 31 initialized = false; 32 imageMosaicYVU = NULL; 33 frames_size = 0; 34 max_frames = 200; 35 } 36 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 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 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 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 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 224 ImageType Mosaic::getMosaic(int &width, int &height) 225 { 226 width = mosaicWidth; 227 height = mosaicHeight; 228 229 return imageMosaicYVU; 230 } 231 232 233 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