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     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