Home | History | Annotate | Download | only in mosaic
      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