Mosaic.cpp revision b28b9c0fa991bc97e8aa11da83d27f71fdfef6da
1e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*
2e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Copyright (C) 2011 The Android Open Source Project
3e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
4e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License");
5e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * you may not use this file except in compliance with the License.
6e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * You may obtain a copy of the License at
7e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
8e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *      http://www.apache.org/licenses/LICENSE-2.0
9e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
10e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Unless required by applicable law or agreed to in writing, software
11e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS,
12e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * See the License for the specific language governing permissions and
14e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * limitations under the License.
15e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */
16e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
17e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen///////////////////////////////////////////////////
18e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Mosaic.pp
19e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// S.O. # :
20e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Author(s): zkira
21e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// $Id: Mosaic.cpp,v 1.20 2011/06/24 04:22:14 mbansal Exp $
22e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
23e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <stdio.h>
24e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <string.h>
25e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
26e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "Mosaic.h"
27e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "trsMatrix.h"
28e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
29274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include "Log.h"
30274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#define LOG_TAG "MOSAIC"
31274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen
32e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenMosaic::Mosaic()
33e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
34e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    initialized = false;
35e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageMosaicYVU = NULL;
36e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frames_size = 0;
37e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    max_frames = 200;
38e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
39e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
40e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenMosaic::~Mosaic()
41e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
42e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++)
43e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
44e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (frames[i])
45e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            delete frames[i];
46e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
47e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    delete frames;
48b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    delete rframes;
49e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
50e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (aligner != NULL)
51e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        delete aligner;
52e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blender != NULL)
53e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        delete blender;
54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
56b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansalint Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still)
57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->blendingType = blendingType;
59b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
60b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    // TODO: Review this logic if enabling FULL or PAN mode
61b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    if (blendingType == Blend::BLEND_TYPE_FULL ||
62b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal            blendingType == Blend::BLEND_TYPE_PAN)
63b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    {
64b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        stripType = Blend::STRIP_TYPE_THIN;
65b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    }
66b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
67b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    this->stripType = stripType;
68e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->width = width;
69e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->height = height;
70e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
71b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    mosaicWidth = mosaicHeight = 0;
73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageMosaicYVU = NULL;
74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
75e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frames = new MosaicFrame *[max_frames];
76b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    rframes = new MosaicFrame *[max_frames];
77e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
78e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if(nframes>-1)
79e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
80e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for(int i=0; i<nframes; i++)
81e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
82e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data
83e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
84e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
85e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
86e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
87e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for(int i=0; i<max_frames; i++)
88e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
89e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            frames[i] = NULL;
90e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
91e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
92e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
93e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
94e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
95274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Initialize %d %d", width, height);
96274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Frame width %d,%d", width, height);
97274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Max num frames %d", max_frames);
98e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
99274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    aligner = new Align();
100274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    aligner->initialize(width, height,quarter_res,thresh_still);
101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blendingType == Blend::BLEND_TYPE_FULL ||
103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_PAN ||
104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_CYLPAN ||
105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_HORZ) {
106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        blender = new Blend();
107b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        blender->initialize(blendingType, stripType, width, height);
108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    } else {
109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        blender = NULL;
110274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("Error: Unknown blending type %d",blendingType);
111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return MOSAIC_RET_ERROR;
112e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    initialized = true;
115e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return MOSAIC_RET_OK;
117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
119e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::addFrameRGB(ImageType imageRGB)
120e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType imageYVU;
122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Convert to YVU24 which is used by blending
123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height);
125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return addFrame(imageYVU);
127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::addFrame(ImageType imageYVU)
130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
131e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if(frames[frames_size]==NULL)
132e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        frames[frames_size] = new MosaicFrame(this->width,this->height,false);
133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
134e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *frame = frames[frames_size];
135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frame->image = imageYVU;
137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int align_flag = Align::ALIGN_RET_OK;
139e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Add frame to aligner
141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (aligner != NULL)
142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Note aligner takes in RGB images
144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        printf("Adding frame to aligner...\n");
145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        align_flag = aligner->addFrame(frame->image);
146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        aligner->getLastTRS(frame->trs);
147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        printf("Frame width %d,%d\n", frame->width, frame->height);
149e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (frames_size >= max_frames)
150e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            fprintf(stderr, "WARNING: More frames than preallocated, ignoring.  Increase maximum number of frames (-f <max_frames>) to avoid this\n");
152e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            return MOSAIC_RET_ERROR;
153e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
154e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else if(align_flag == Align::ALIGN_RET_OK)
155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
156e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            frames_size++;
157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            return MOSAIC_RET_OK;
158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else
160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
161e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            return MOSAIC_RET_ERROR;
162e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
163e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
164e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
165e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
166e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return MOSAIC_RET_ERROR;
167e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
171e1178a73fd5756771d25d0b8375452450f509e99mbansalint Mosaic::createMosaic(float &progress, bool &cancelComputation)
172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    printf("Creating mosaic\n");
174e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
17550f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    if (frames_size <= 0)
17650f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    {
17750f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        // Haven't accepted any frame in aligner. No need to do blending.
17850f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND
17950f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen                + TIME_PERCENT_FINAL;
18050f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        return MOSAIC_RET_OK;
18150f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    }
18250f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen
183e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blendingType == Blend::BLEND_TYPE_PAN)
184e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        balanceRotations();
187e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
188e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
189e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
190274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    int ret = Blend::BLEND_RET_ERROR;
191e1178a73fd5756771d25d0b8375452450f509e99mbansal
192e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Blend the mosaic (alignment has already been done)
193e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blender != NULL)
194e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
195b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes,
196b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal                frames_size, imageMosaicYVU,
197e1178a73fd5756771d25d0b8375452450f509e99mbansal                mosaicWidth, mosaicHeight, progress, cancelComputation);
198e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
199e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
200e1178a73fd5756771d25d0b8375452450f509e99mbansal    switch(ret)
201e1178a73fd5756771d25d0b8375452450f509e99mbansal    {
202e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_ERROR:
203e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_ERROR_MEMORY:
204e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_ERROR;
205e1178a73fd5756771d25d0b8375452450f509e99mbansal            break;
206e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_CANCELLED:
207e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_CANCELLED;
208e1178a73fd5756771d25d0b8375452450f509e99mbansal            break;
209e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_OK:
210e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_OK;
211e1178a73fd5756771d25d0b8375452450f509e99mbansal    }
212e1178a73fd5756771d25d0b8375452450f509e99mbansal    return ret;
213e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
214e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
215e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType Mosaic::getMosaic(int &width, int &height)
216e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
217e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    width = mosaicWidth;
218e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    height = mosaicHeight;
219e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
220e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return imageMosaicYVU;
221e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
222e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
223e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
224e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
225e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::balanceRotations()
226e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
227e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Normalize to the mean angle of rotation (Smiley face)
228e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double sineAngle = 0.0;
229e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
230e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
231e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    sineAngle /= frames_size;
232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
233e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
234e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double m[3][3] = {
235e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { cosineAngle, -sineAngle, 0 },
236e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { sineAngle, cosineAngle, 0},
237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { 0, 0, 1}};
238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double tmp[3][3];
239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++) {
241e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        memcpy(tmp, frames[i]->trs, sizeof(tmp));
242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mult33d(frames[i]->trs, m, tmp);
243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return MOSAIC_RET_OK;
246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
247