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 Mosaic::Mosaic()
     30 {
     31     initialized = false;
     32     imageMosaicYVU = NULL;
     33     frames_size = 0;
     34     max_frames = 200;
     35 }
     36 
     37 Mosaic::~Mosaic()
     38 {
     39     for (int i = 0; i < frames_size; i++)
     40     {
     41         if (frames[i])
     42             delete frames[i];
     43     }
     44     delete frames;
     45     delete rframes;
     46 
     47     for (int j = 0; j < owned_size; j++)
     48         delete owned_frames[j];
     49     delete owned_frames;
     50 
     51     if (aligner != NULL)
     52         delete aligner;
     53     if (blender != NULL)
     54         delete blender;
     55 }
     56 
     57 int Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still)
     58 {
     59     this->blendingType = blendingType;
     60 
     61     // TODO: Review this logic if enabling FULL or PAN mode
     62     if (blendingType == Blend::BLEND_TYPE_FULL ||
     63             blendingType == Blend::BLEND_TYPE_PAN)
     64     {
     65         stripType = Blend::STRIP_TYPE_THIN;
     66     }
     67 
     68     this->stripType = stripType;
     69     this->width = width;
     70     this->height = height;
     71 
     72 
     73     mosaicWidth = mosaicHeight = 0;
     74     imageMosaicYVU = NULL;
     75 
     76     frames = new MosaicFrame *[max_frames];
     77     rframes = new MosaicFrame *[max_frames];
     78 
     79     if(nframes>-1)
     80     {
     81         for(int i=0; i<nframes; i++)
     82         {
     83             frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data
     84         }
     85     }
     86     else
     87     {
     88         for(int i=0; i<max_frames; i++)
     89         {
     90             frames[i] = NULL;
     91         }
     92     }
     93 
     94     owned_frames = new ImageType[max_frames];
     95     owned_size = 0;
     96 
     97     aligner = new Align();
     98     aligner->initialize(width, height,quarter_res,thresh_still);
     99 
    100     if (blendingType == Blend::BLEND_TYPE_FULL ||
    101             blendingType == Blend::BLEND_TYPE_PAN ||
    102             blendingType == Blend::BLEND_TYPE_CYLPAN ||
    103             blendingType == Blend::BLEND_TYPE_HORZ) {
    104         blender = new Blend();
    105         blender->initialize(blendingType, stripType, width, height);
    106     } else {
    107         blender = NULL;
    108         return MOSAIC_RET_ERROR;
    109     }
    110 
    111     initialized = true;
    112 
    113     return MOSAIC_RET_OK;
    114 }
    115 
    116 int Mosaic::addFrameRGB(ImageType imageRGB)
    117 {
    118     ImageType imageYVU;
    119     // Convert to YVU24 which is used by blending
    120     imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
    121     ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height);
    122 
    123     int existing_frames_size = frames_size;
    124     int ret = addFrame(imageYVU);
    125 
    126     if (frames_size > existing_frames_size)
    127         owned_frames[owned_size++] = imageYVU;
    128     else
    129         ImageUtils::freeImage(imageYVU);
    130 
    131     return ret;
    132 }
    133 
    134 int Mosaic::addFrame(ImageType imageYVU)
    135 {
    136     if(frames[frames_size]==NULL)
    137         frames[frames_size] = new MosaicFrame(this->width,this->height,false);
    138 
    139     MosaicFrame *frame = frames[frames_size];
    140 
    141     frame->image = imageYVU;
    142 
    143     // Add frame to aligner
    144     int ret = MOSAIC_RET_ERROR;
    145     if (aligner != NULL)
    146     {
    147         // Note aligner takes in RGB images
    148         int align_flag = Align::ALIGN_RET_OK;
    149         align_flag = aligner->addFrame(frame->image);
    150         aligner->getLastTRS(frame->trs);
    151 
    152         if (frames_size >= max_frames)
    153         {
    154             return MOSAIC_RET_ERROR;
    155         }
    156 
    157         switch (align_flag)
    158         {
    159             case Align::ALIGN_RET_OK:
    160                 frames_size++;
    161                 ret = MOSAIC_RET_OK;
    162                 break;
    163             case Align::ALIGN_RET_FEW_INLIERS:
    164                 frames_size++;
    165                 ret = MOSAIC_RET_FEW_INLIERS;
    166                 break;
    167             case Align::ALIGN_RET_LOW_TEXTURE:
    168                 ret = MOSAIC_RET_LOW_TEXTURE;
    169                 break;
    170             case Align::ALIGN_RET_ERROR:
    171                 ret = MOSAIC_RET_ERROR;
    172                 break;
    173             default:
    174                 break;
    175         }
    176     }
    177 
    178     return ret;
    179 }
    180 
    181 
    182 int Mosaic::createMosaic(float &progress, bool &cancelComputation)
    183 {
    184     if (frames_size <= 0)
    185     {
    186         // Haven't accepted any frame in aligner. No need to do blending.
    187         progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND
    188                 + TIME_PERCENT_FINAL;
    189         return MOSAIC_RET_OK;
    190     }
    191 
    192     if (blendingType == Blend::BLEND_TYPE_PAN)
    193     {
    194 
    195         balanceRotations();
    196 
    197     }
    198 
    199     int ret = Blend::BLEND_RET_ERROR;
    200 
    201     // Blend the mosaic (alignment has already been done)
    202     if (blender != NULL)
    203     {
    204         ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes,
    205                 frames_size, imageMosaicYVU,
    206                 mosaicWidth, mosaicHeight, progress, cancelComputation);
    207     }
    208 
    209     switch(ret)
    210     {
    211         case Blend::BLEND_RET_ERROR:
    212         case Blend::BLEND_RET_ERROR_MEMORY:
    213             ret = MOSAIC_RET_ERROR;
    214             break;
    215         case Blend::BLEND_RET_CANCELLED:
    216             ret = MOSAIC_RET_CANCELLED;
    217             break;
    218         case Blend::BLEND_RET_OK:
    219             ret = MOSAIC_RET_OK;
    220     }
    221     return ret;
    222 }
    223 
    224 ImageType Mosaic::getMosaic(int &width, int &height)
    225 {
    226     width = mosaicWidth;
    227     height = mosaicHeight;
    228 
    229     return imageMosaicYVU;
    230 }
    231 
    232 
    233 
    234 int Mosaic::balanceRotations()
    235 {
    236     // Normalize to the mean angle of rotation (Smiley face)
    237     double sineAngle = 0.0;
    238 
    239     for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
    240     sineAngle /= frames_size;
    241     // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
    242     double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
    243     double m[3][3] = {
    244         { cosineAngle, -sineAngle, 0 },
    245         { sineAngle, cosineAngle, 0},
    246         { 0, 0, 1}};
    247     double tmp[3][3];
    248 
    249     for (int i = 0; i < frames_size; i++) {
    250         memcpy(tmp, frames[i]->trs, sizeof(tmp));
    251         mult33d(frames[i]->trs, m, tmp);
    252     }
    253 
    254     return MOSAIC_RET_OK;
    255 }
    256