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