18bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling/*
28bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Copyright (C) 2011 The Android Open Source Project
38bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
48bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License");
58bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * you may not use this file except in compliance with the License.
68bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * You may obtain a copy of the License at
78bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
88bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *      http://www.apache.org/licenses/LICENSE-2.0
98bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
108bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Unless required by applicable law or agreed to in writing, software
118bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS,
128bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * See the License for the specific language governing permissions and
148bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * limitations under the License.
158bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling */
168bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
178bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling///////////////////////////////////////////////////
188bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling// Mosaic.pp
198bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling// S.O. # :
208bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling// Author(s): zkira
218bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling// $Id: Mosaic.cpp,v 1.20 2011/06/24 04:22:14 mbansal Exp $
228bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
238bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include <stdio.h>
248bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include <string.h>
258bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
268bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include "Mosaic.h"
278bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include "trsMatrix.h"
288bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
298bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include "Log.h"
308bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#define LOG_TAG "MOSAIC"
318bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
328bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha HaeberlingMosaic::Mosaic()
338bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
348bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    initialized = false;
358bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    imageMosaicYVU = NULL;
368bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    frames_size = 0;
378bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    max_frames = 200;
388bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
398bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
408bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha HaeberlingMosaic::~Mosaic()
418bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
428bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    for (int i = 0; i < frames_size; i++)
438bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
448bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        if (frames[i])
458bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            delete frames[i];
468bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
478bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    delete frames;
488bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    delete rframes;
498bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
508bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    for (int j = 0; j < owned_size; j++)
518bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        delete owned_frames[j];
528bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    delete owned_frames;
538bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
548bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (aligner != NULL)
558bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        delete aligner;
568bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (blender != NULL)
578bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        delete blender;
588bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
598bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
608bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingint Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still)
618bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
628bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    this->blendingType = blendingType;
638bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
648bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    // TODO: Review this logic if enabling FULL or PAN mode
658bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (blendingType == Blend::BLEND_TYPE_FULL ||
668bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            blendingType == Blend::BLEND_TYPE_PAN)
678bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
688bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        stripType = Blend::STRIP_TYPE_THIN;
698bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
708bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
718bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    this->stripType = stripType;
728bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    this->width = width;
738bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    this->height = height;
748bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
758bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
768bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    mosaicWidth = mosaicHeight = 0;
778bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    imageMosaicYVU = NULL;
788bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
798bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    frames = new MosaicFrame *[max_frames];
808bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    rframes = new MosaicFrame *[max_frames];
818bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
828bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if(nframes>-1)
838bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
848bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        for(int i=0; i<nframes; i++)
858bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        {
868bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data
878bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        }
888bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
898bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    else
908bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
918bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        for(int i=0; i<max_frames; i++)
928bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        {
938bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            frames[i] = NULL;
948bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        }
958bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
968bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
978bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    owned_frames = new ImageType[max_frames];
988bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    owned_size = 0;
998bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1008bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    LOGV("Initialize %d %d", width, height);
1018bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    LOGV("Frame width %d,%d", width, height);
1028bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    LOGV("Max num frames %d", max_frames);
1038bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1048bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    aligner = new Align();
1058bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    aligner->initialize(width, height,quarter_res,thresh_still);
1068bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1078bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (blendingType == Blend::BLEND_TYPE_FULL ||
1088bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            blendingType == Blend::BLEND_TYPE_PAN ||
1098bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            blendingType == Blend::BLEND_TYPE_CYLPAN ||
1108bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            blendingType == Blend::BLEND_TYPE_HORZ) {
1118bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        blender = new Blend();
1128bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        blender->initialize(blendingType, stripType, width, height);
1138bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    } else {
1148bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        blender = NULL;
1158bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        LOGE("Error: Unknown blending type %d",blendingType);
1168bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        return MOSAIC_RET_ERROR;
1178bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
1188bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1198bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    initialized = true;
1208bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1218bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    return MOSAIC_RET_OK;
1228bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1238bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1248bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingint Mosaic::addFrameRGB(ImageType imageRGB)
1258bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1268bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    ImageType imageYVU;
1278bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    // Convert to YVU24 which is used by blending
1288bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
1298bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height);
1308bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1318bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    int existing_frames_size = frames_size;
1328bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    int ret = addFrame(imageYVU);
1338bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1348bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (frames_size > existing_frames_size)
1358bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        owned_frames[owned_size++] = imageYVU;
1368bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    else
1378bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        ImageUtils::freeImage(imageYVU);
1388bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1398bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    return ret;
1408bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1418bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1428bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingint Mosaic::addFrame(ImageType imageYVU)
1438bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1448bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if(frames[frames_size]==NULL)
1458bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        frames[frames_size] = new MosaicFrame(this->width,this->height,false);
1468bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1478bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    MosaicFrame *frame = frames[frames_size];
1488bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1498bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    frame->image = imageYVU;
1508bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1518bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    // Add frame to aligner
1528bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    int ret = MOSAIC_RET_ERROR;
1538bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (aligner != NULL)
1548bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
1558bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        // Note aligner takes in RGB images
1568bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        int align_flag = Align::ALIGN_RET_OK;
1578bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        align_flag = aligner->addFrame(frame->image);
1588bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        aligner->getLastTRS(frame->trs);
1598bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1608bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        if (frames_size >= max_frames)
1618bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        {
1628bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            LOGV("WARNING: More frames than preallocated, ignoring."
1638bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                 "Increase maximum number of frames (-f <max_frames>) to avoid this");
1648bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            return MOSAIC_RET_ERROR;
1658bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        }
1668bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1678bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        switch (align_flag)
1688bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        {
1698bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            case Align::ALIGN_RET_OK:
1708bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                frames_size++;
1718bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                ret = MOSAIC_RET_OK;
1728bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                break;
1738bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            case Align::ALIGN_RET_FEW_INLIERS:
1748bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                frames_size++;
1758bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                ret = MOSAIC_RET_FEW_INLIERS;
1768bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                break;
1778bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            case Align::ALIGN_RET_LOW_TEXTURE:
1788bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                ret = MOSAIC_RET_LOW_TEXTURE;
1798bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                break;
1808bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            case Align::ALIGN_RET_ERROR:
1818bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                ret = MOSAIC_RET_ERROR;
1828bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                break;
1838bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            default:
1848bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                break;
1858bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        }
1868bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
1878bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1888bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    return ret;
1898bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1908bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1918bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1928bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingint Mosaic::createMosaic(float &progress, bool &cancelComputation)
1938bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1948bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (frames_size <= 0)
1958bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
1968bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        // Haven't accepted any frame in aligner. No need to do blending.
1978bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND
1988bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                + TIME_PERCENT_FINAL;
1998bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        return MOSAIC_RET_OK;
2008bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
2018bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2028bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (blendingType == Blend::BLEND_TYPE_PAN)
2038bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
2048bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2058bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        balanceRotations();
2068bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2078bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
2088bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2098bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    int ret = Blend::BLEND_RET_ERROR;
2108bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2118bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    // Blend the mosaic (alignment has already been done)
2128bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    if (blender != NULL)
2138bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
2148bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes,
2158bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                frames_size, imageMosaicYVU,
2168bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                mosaicWidth, mosaicHeight, progress, cancelComputation);
2178bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
2188bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2198bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    switch(ret)
2208bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    {
2218bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        case Blend::BLEND_RET_ERROR:
2228bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        case Blend::BLEND_RET_ERROR_MEMORY:
2238bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            ret = MOSAIC_RET_ERROR;
2248bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            break;
2258bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        case Blend::BLEND_RET_CANCELLED:
2268bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            ret = MOSAIC_RET_CANCELLED;
2278bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            break;
2288bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        case Blend::BLEND_RET_OK:
2298bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling            ret = MOSAIC_RET_OK;
2308bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
2318bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    return ret;
2328bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
2338bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2348bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha HaeberlingImageType Mosaic::getMosaic(int &width, int &height)
2358bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
2368bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    width = mosaicWidth;
2378bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    height = mosaicHeight;
2388bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2398bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    return imageMosaicYVU;
2408bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
2418bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2428bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2438bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2448bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingint Mosaic::balanceRotations()
2458bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
2468bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    // Normalize to the mean angle of rotation (Smiley face)
2478bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    double sineAngle = 0.0;
2488bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2498bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
2508bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    sineAngle /= frames_size;
2518bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
2528bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
2538bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    double m[3][3] = {
2548bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        { cosineAngle, -sineAngle, 0 },
2558bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        { sineAngle, cosineAngle, 0},
2568bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        { 0, 0, 1}};
2578bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    double tmp[3][3];
2588bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2598bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    for (int i = 0; i < frames_size; i++) {
2608bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        memcpy(tmp, frames[i]->trs, sizeof(tmp));
2618bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling        mult33d(frames[i]->trs, m, tmp);
2628bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    }
2638bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2648bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling    return MOSAIC_RET_OK;
2658bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
266