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 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 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 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 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 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 234 ImageType Mosaic::getMosaic(int &width, int &height) 235 { 236 width = mosaicWidth; 237 height = mosaicHeight; 238 239 return imageMosaicYVU; 240 } 241 242 243 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