diff options
Diffstat (limited to 'jni/feature_mos/src/mosaic/Mosaic.cpp')
-rw-r--r-- | jni/feature_mos/src/mosaic/Mosaic.cpp | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/jni/feature_mos/src/mosaic/Mosaic.cpp b/jni/feature_mos/src/mosaic/Mosaic.cpp new file mode 100644 index 000000000..7b96fa5c5 --- /dev/null +++ b/jni/feature_mos/src/mosaic/Mosaic.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/////////////////////////////////////////////////// +// Mosaic.pp +// S.O. # : +// Author(s): zkira +// $Id: Mosaic.cpp,v 1.20 2011/06/24 04:22:14 mbansal Exp $ + +#include <stdio.h> +#include <string.h> + +#include "Mosaic.h" +#include "trsMatrix.h" + +#include "Log.h" +#define LOG_TAG "MOSAIC" + +Mosaic::Mosaic() +{ + initialized = false; + imageMosaicYVU = NULL; + frames_size = 0; + max_frames = 200; +} + +Mosaic::~Mosaic() +{ + for (int i = 0; i < frames_size; i++) + { + if (frames[i]) + delete frames[i]; + } + delete frames; + delete rframes; + + for (int j = 0; j < owned_size; j++) + delete owned_frames[j]; + delete owned_frames; + + if (aligner != NULL) + delete aligner; + if (blender != NULL) + delete blender; +} + +int Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still) +{ + this->blendingType = blendingType; + + // TODO: Review this logic if enabling FULL or PAN mode + if (blendingType == Blend::BLEND_TYPE_FULL || + blendingType == Blend::BLEND_TYPE_PAN) + { + stripType = Blend::STRIP_TYPE_THIN; + } + + this->stripType = stripType; + this->width = width; + this->height = height; + + + mosaicWidth = mosaicHeight = 0; + imageMosaicYVU = NULL; + + frames = new MosaicFrame *[max_frames]; + rframes = new MosaicFrame *[max_frames]; + + if(nframes>-1) + { + for(int i=0; i<nframes; i++) + { + frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data + } + } + else + { + for(int i=0; i<max_frames; i++) + { + frames[i] = NULL; + } + } + + owned_frames = new ImageType[max_frames]; + owned_size = 0; + + LOGV("Initialize %d %d", width, height); + LOGV("Frame width %d,%d", width, height); + LOGV("Max num frames %d", max_frames); + + aligner = new Align(); + aligner->initialize(width, height,quarter_res,thresh_still); + + if (blendingType == Blend::BLEND_TYPE_FULL || + blendingType == Blend::BLEND_TYPE_PAN || + blendingType == Blend::BLEND_TYPE_CYLPAN || + blendingType == Blend::BLEND_TYPE_HORZ) { + blender = new Blend(); + blender->initialize(blendingType, stripType, width, height); + } else { + blender = NULL; + LOGE("Error: Unknown blending type %d",blendingType); + return MOSAIC_RET_ERROR; + } + + initialized = true; + + return MOSAIC_RET_OK; +} + +int Mosaic::addFrameRGB(ImageType imageRGB) +{ + ImageType imageYVU; + // Convert to YVU24 which is used by blending + imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS); + ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height); + + int existing_frames_size = frames_size; + int ret = addFrame(imageYVU); + + if (frames_size > existing_frames_size) + owned_frames[owned_size++] = imageYVU; + else + ImageUtils::freeImage(imageYVU); + + return ret; +} + +int Mosaic::addFrame(ImageType imageYVU) +{ + if(frames[frames_size]==NULL) + frames[frames_size] = new MosaicFrame(this->width,this->height,false); + + MosaicFrame *frame = frames[frames_size]; + + frame->image = imageYVU; + + // Add frame to aligner + int ret = MOSAIC_RET_ERROR; + if (aligner != NULL) + { + // Note aligner takes in RGB images + int align_flag = Align::ALIGN_RET_OK; + align_flag = aligner->addFrame(frame->image); + aligner->getLastTRS(frame->trs); + + if (frames_size >= max_frames) + { + LOGV("WARNING: More frames than preallocated, ignoring." + "Increase maximum number of frames (-f <max_frames>) to avoid this"); + return MOSAIC_RET_ERROR; + } + + switch (align_flag) + { + case Align::ALIGN_RET_OK: + frames_size++; + ret = MOSAIC_RET_OK; + break; + case Align::ALIGN_RET_FEW_INLIERS: + frames_size++; + ret = MOSAIC_RET_FEW_INLIERS; + break; + case Align::ALIGN_RET_LOW_TEXTURE: + ret = MOSAIC_RET_LOW_TEXTURE; + break; + case Align::ALIGN_RET_ERROR: + ret = MOSAIC_RET_ERROR; + break; + default: + break; + } + } + + return ret; +} + + +int Mosaic::createMosaic(float &progress, bool &cancelComputation) +{ + if (frames_size <= 0) + { + // Haven't accepted any frame in aligner. No need to do blending. + progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND + + TIME_PERCENT_FINAL; + return MOSAIC_RET_OK; + } + + if (blendingType == Blend::BLEND_TYPE_PAN) + { + + balanceRotations(); + + } + + int ret = Blend::BLEND_RET_ERROR; + + // Blend the mosaic (alignment has already been done) + if (blender != NULL) + { + ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes, + frames_size, imageMosaicYVU, + mosaicWidth, mosaicHeight, progress, cancelComputation); + } + + switch(ret) + { + case Blend::BLEND_RET_ERROR: + case Blend::BLEND_RET_ERROR_MEMORY: + ret = MOSAIC_RET_ERROR; + break; + case Blend::BLEND_RET_CANCELLED: + ret = MOSAIC_RET_CANCELLED; + break; + case Blend::BLEND_RET_OK: + ret = MOSAIC_RET_OK; + } + return ret; +} + +ImageType Mosaic::getMosaic(int &width, int &height) +{ + width = mosaicWidth; + height = mosaicHeight; + + return imageMosaicYVU; +} + + + +int Mosaic::balanceRotations() +{ + // Normalize to the mean angle of rotation (Smiley face) + double sineAngle = 0.0; + + for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1]; + sineAngle /= frames_size; + // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle + double cosineAngle = sqrt(1.0 - sineAngle*sineAngle); + double m[3][3] = { + { cosineAngle, -sineAngle, 0 }, + { sineAngle, cosineAngle, 0}, + { 0, 0, 1}}; + double tmp[3][3]; + + for (int i = 0; i < frames_size; i++) { + memcpy(tmp, frames[i]->trs, sizeof(tmp)); + mult33d(frames[i]->trs, m, tmp); + } + + return MOSAIC_RET_OK; +} |