Blend.cpp revision 6c5b20113ba9f91352f32e5a53df66aec0ec761a
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// Blend.cpp
19e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// $Id: Blend.cpp,v 1.22 2011/06/24 04:22:14 mbansal Exp $
20e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
21e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <string.h>
22e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
23e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "Interp.h"
24e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "Blend.h"
25e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
26e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "Geometry.h"
27e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "trsMatrix.h"
28e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
29274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include "Log.h"
30274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#define LOG_TAG "BLEND"
31274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen
32e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenBlend::Blend()
33e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
34e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  m_wb.blendingType = BLEND_TYPE_NONE;
35e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
36e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
37e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenBlend::~Blend()
38e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
39e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_pFrameVPyr) free(m_pFrameVPyr);
40e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_pFrameUPyr) free(m_pFrameUPyr);
41e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_pFrameYPyr) free(m_pFrameYPyr);
42e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
43e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
44e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Blend::initialize(int blendingType, int frame_width, int frame_height)
45e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
46e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->width = frame_width;
47e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->height = frame_height;
48e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->m_wb.blendingType = blendingType;
49e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
50e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_wb.blendRange = m_wb.blendRangeUV = BLEND_RANGE_DEFAULT;
51e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_wb.nlevs = m_wb.blendRange;
52e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_wb.nlevsC = m_wb.blendRangeUV;
53e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.nlevs <= 0) m_wb.nlevs = 1; // Need levels for YUV processing
55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.nlevsC > m_wb.nlevs) m_wb.nlevsC = m_wb.nlevs;
56e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_wb.roundoffOverlap = 1.5;
58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
59e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pFrameYPyr = NULL;
60e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pFrameUPyr = NULL;
61e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pFrameVPyr = NULL;
62e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
63e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pFrameYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs, (unsigned short) width, (unsigned short) height, BORDER);
64e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pFrameUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER);
65e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pFrameVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER);
66e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
67e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (!m_pFrameYPyr || !m_pFrameUPyr || !m_pFrameVPyr)
68e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
69274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("Error: Could not allocate pyramids for blending");
70e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return BLEND_RET_ERROR_MEMORY;
71e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return BLEND_RET_OK;
74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
75e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
766c5b20113ba9f91352f32e5a53df66aec0ec761ambansalinline double max(double a, double b) { return a > b ? a : b; }
776c5b20113ba9f91352f32e5a53df66aec0ec761ambansalinline double min(double a, double b) { return a < b ? a : b; }
786c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Blend::AlignToMiddleFrame(MosaicFrame **frames, int frames_size)
801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{
811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    // Unwarp this frame and Warp the others to match
821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    MosaicFrame *mb = NULL;
831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    MosaicFrame *ref = frames[int(frames_size/2)];    // Middle frame
841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    double invtrs[3][3];
861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    inv33d(ref->trs, invtrs);
871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    for(int mfit = 0; mfit < frames_size; mfit++)
891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    {
901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mb = frames[mfit];
911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        double temp[3][3];
921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        mult33d(temp, invtrs, mb->trs);
931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        memcpy(mb->trs, temp, sizeof(temp));
941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal        normProjMat33d(mb->trs);
951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    }
961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal}
971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal
9850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansalint Blend::runBlend(MosaicFrame **frames, int frames_size,
9950b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal        ImageType &imageMosaicYVU, int &mosaicWidth, int &mosaicHeight,
100e1178a73fd5756771d25d0b8375452450f509e99mbansal        float &progress, bool &cancelComputation)
101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int ret;
103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int numCenters;
104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
105fa45108679c51623e716acbc3301b1e4535c3267Wei-Ta Chen    ComputeBlendParameters(frames, frames_size, true);
106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    numCenters = frames_size;
107e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (numCenters == 0)
109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
110274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("Error: No frames to blend");
111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return BLEND_RET_ERROR;
112e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (!(m_AllSites = m_Triangulator.allocMemory(numCenters)))
115e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return BLEND_RET_ERROR_MEMORY;
117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
1196c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // Bounding rectangle (real numbers) of the final mosaic computed by projecting
1206c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // each input frame into the mosaic coordinate system.
121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    BlendRect global_rect;
122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    global_rect.lft = global_rect.bot = 2e30; // min values
124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    global_rect.rgt = global_rect.top = -2e30; // max values
125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *mb = NULL;
126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double halfwidth = width / 2.0;
127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double halfheight = height / 2.0;
128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double z, x0, y0, x1, y1, x2, y2, x3, y3;
130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
1316c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // Corners of the first and last frames in mosaic coordinate system
1326c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    double xf[4] = {0.0, 0.0, 0.0, 0.0};
1336c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    double xl[4] = {0.0, 0.0, 0.0, 0.0};
1346c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Determine the extents of the final mosaic
136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    CSite *csite = m_AllSites ;
137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for(int mfit = 0; mfit < frames_size; mfit++)
138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
139e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mb = frames[mfit];
140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Compute clipping for this frame's rect
142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaicRect(mb->width, mb->height, mb->trs, mb->brect);
143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Clip global rect using this frame's rect
144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ClipRect(mb->brect, global_rect);
145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Calculate the corner points
147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(mb->trs, 0.0,             0.0,            x0, y0);
148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(mb->trs, 0.0,             mb->height-1.0, x1, y1);
149e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(mb->trs, mb->width-1.0,   mb->height-1.0, x2, y2);
150e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(mb->trs, mb->width-1.0,   0.0,            x3, y3);
151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
1526c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        if(mfit == 0)
1536c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        {
1546c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xf[0] = x0;
1556c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xf[1] = x1;
1566c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xf[2] = x3;
1576c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xf[3] = x2;
1586c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        }
1596c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
1606c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        if(mfit==frames_size-1)
1616c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        {
1626c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xl[0] = x0;
1636c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xl[1] = x1;
1646c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xl[2] = x3;
1656c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            xl[3] = x2;
1666c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        }
1676c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Compute the centroid of the warped region
169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FindQuadCentroid(x0, y0, x1, y1, x2, y2, x3, y3, csite->getVCenter().x, csite->getVCenter().y);
170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
171e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        csite->setMb(mb);
172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        csite++;
173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
174e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
175e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Get origin and sizes
1766c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
1776c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // Bounding rectangle (int numbers) of the final mosaic computed by projecting
1786c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // each input frame into the mosaic coordinate system.
179e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicRect fullRect;
180e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
181e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fullRect.left = (int) floor(global_rect.lft); // min-x
182e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fullRect.top = (int) floor(global_rect.bot);  // min-y
183e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fullRect.right = (int) ceil(global_rect.rgt); // max-x
184e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    fullRect.bottom = (int) ceil(global_rect.top);// max-y
185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    Mwidth = (unsigned short) (fullRect.right - fullRect.left + 1);
186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    Mheight = (unsigned short) (fullRect.bottom - fullRect.top + 1);
187e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
1886c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    int xlt, xrt;
1896c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
1906c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    if(frames[0]->trs[0][2] < frames[frames_size-1]->trs[0][2]) //left->right mosaic
1916c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    {
1926c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        xlt = max(xf[0],xf[1]) - fullRect.left;
1936c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        xrt = min(xl[2],xl[3]) - fullRect.left;
1946c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    }
1956c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    else
1966c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    {
1976c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        xlt = max(xl[0],xl[1]) - fullRect.left;
1986c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        xrt = min(xf[2],xf[3]) - fullRect.left;
1996c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    }
2006c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
2016c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
202e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Make sure image width is multiple of 4
203e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    Mwidth = (unsigned short) ((Mwidth + 3) & ~3);
204e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    Mheight = (unsigned short) ((Mheight + 3) & ~3);    // Round up.
205e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
206e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (Mwidth < width || Mheight < height)
207e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
208274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("RunBlend: aborting - consistency check failed, w=%d, h=%d", Mwidth, Mheight);
209e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return BLEND_RET_ERROR;
210e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
211e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
212e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    YUVinfo *imgMos = YUVinfo::allocateImage(Mwidth, Mheight);
213e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (imgMos == NULL)
214e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
215274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("RunBlend: aborting - couldn't alloc %d x %d mosaic image", Mwidth, Mheight);
216e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return BLEND_RET_ERROR_MEMORY;
217e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
218e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
219e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Set the Y image to 255 so we can distinguish when frame idx are written to it
220e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    memset(imgMos->Y.ptr[0], 255, (imgMos->Y.width * imgMos->Y.height));
221e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Set the v and u images to black
222e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    memset(imgMos->V.ptr[0], 128, (imgMos->V.width * imgMos->V.height) << 1);
223e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
224e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Do the triangulation.  It returns a sorted list of edges
225e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    SEdgeVector *edge;
226e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int n = m_Triangulator.triangulate(&edge, numCenters, width, height);
227e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_Triangulator.linkNeighbors(edge, n, numCenters);
228e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
2296c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // Bounding rectangle that determines the positioning of the rectangle that is
2306c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // cropped out of the computed mosaic to get rid of the gray borders.
231e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicRect cropping_rect;
232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
2336c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    cropping_rect.left = xlt;
2346c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    cropping_rect.right = xrt;
2356c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
236e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Do merging and blending :
23750b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal    ret = DoMergeAndBlend(frames, numCenters, width, height, *imgMos, fullRect,
238e1178a73fd5756771d25d0b8375452450f509e99mbansal            cropping_rect, progress, cancelComputation);
239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.blendingType == BLEND_TYPE_HORZ)
241e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        CropFinalMosaic(*imgMos, cropping_rect);
242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_Triangulator.freeMemory();    // note: can be called even if delaunay_alloc() wasn't successful
245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageMosaicYVU = imgMos->Y.ptr[0];
247e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.blendingType == BLEND_TYPE_HORZ)
250e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mosaicWidth = cropping_rect.right - cropping_rect.left + 1;
252e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mosaicHeight = cropping_rect.bottom - cropping_rect.top + 1;
253e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
254e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
255e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
256e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mosaicWidth = Mwidth;
257e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mosaicHeight = Mheight;
258e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
259e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
260e1178a73fd5756771d25d0b8375452450f509e99mbansal    return ret;
261e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
262e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
263e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
264e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Blend::FillFramePyramid(MosaicFrame *mb)
265e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
266e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType mbY, mbU, mbV;
267e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Lay this image, centered into the temporary buffer
268e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    mbY = mb->image;
269e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    mbU = mb->getU();
270e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    mbV = mb->getV();
271e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
272e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int h, w;
273e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
274e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for(h=0; h<height; h++)
275e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
276e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ImageTypeShort yptr = m_pFrameYPyr->ptr[h];
277e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ImageTypeShort uptr = m_pFrameUPyr->ptr[h];
278e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ImageTypeShort vptr = m_pFrameVPyr->ptr[h];
279e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
280e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for(w=0; w<width; w++)
281e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
282e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            yptr[w] = (short) ((*(mbY++)) << 3);
283e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            uptr[w] = (short) ((*(mbU++)) << 3);
284e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            vptr[w] = (short) ((*(mbV++)) << 3);
285e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
286e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
287e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
288e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Spread the image through the border
289e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort::BorderSpread(m_pFrameYPyr, BORDER, BORDER, BORDER, BORDER);
290e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort::BorderSpread(m_pFrameUPyr, BORDER, BORDER, BORDER, BORDER);
291e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort::BorderSpread(m_pFrameVPyr, BORDER, BORDER, BORDER, BORDER);
292e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
293e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Generate Laplacian pyramids
294e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (!PyramidShort::BorderReduce(m_pFrameYPyr, m_wb.nlevs) || !PyramidShort::BorderExpand(m_pFrameYPyr, m_wb.nlevs, -1) ||
295e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            !PyramidShort::BorderReduce(m_pFrameUPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameUPyr, m_wb.nlevsC, -1) ||
296e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            !PyramidShort::BorderReduce(m_pFrameVPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameVPyr, m_wb.nlevsC, -1))
297e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
298274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("Error: Could not generate Laplacian pyramids");
299e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return BLEND_RET_ERROR;
300e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
301e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
302e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
303e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return BLEND_RET_OK;
304e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
305e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
306e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
307e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Blend::DoMergeAndBlend(MosaicFrame **frames, int nsite,
30850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal             int width, int height, YUVinfo &imgMos, MosaicRect &rect,
309e1178a73fd5756771d25d0b8375452450f509e99mbansal             MosaicRect &cropping_rect, float &progress, bool &cancelComputation)
310e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
311e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pMosaicYPyr = NULL;
312e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pMosaicUPyr = NULL;
313e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pMosaicVPyr = NULL;
314e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
315e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pMosaicYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER);
316e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pMosaicUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER);
317e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_pMosaicVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER);
318e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (!m_pMosaicYPyr || !m_pMosaicUPyr || !m_pMosaicVPyr)
319e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
320274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen      LOGE("Error: Could not allocate pyramids for blending");
321e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      return BLEND_RET_ERROR_MEMORY;
322e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
323e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
324e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *mb;
325e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
326e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    CSite *esite = m_AllSites + nsite;
327e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int site_idx;
328e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
329e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // First go through each frame and for each mosaic pixel determine which frame it should come from
330e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    site_idx = 0;
331e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for(CSite *csite = m_AllSites; csite < esite; csite++)
332e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
333e1178a73fd5756771d25d0b8375452450f509e99mbansal        if(cancelComputation)
334e1178a73fd5756771d25d0b8375452450f509e99mbansal        {
335e1178a73fd5756771d25d0b8375452450f509e99mbansal            if (m_pMosaicVPyr) free(m_pMosaicVPyr);
336e1178a73fd5756771d25d0b8375452450f509e99mbansal            if (m_pMosaicUPyr) free(m_pMosaicUPyr);
337e1178a73fd5756771d25d0b8375452450f509e99mbansal            if (m_pMosaicYPyr) free(m_pMosaicYPyr);
338e1178a73fd5756771d25d0b8375452450f509e99mbansal            return BLEND_RET_CANCELLED;
339e1178a73fd5756771d25d0b8375452450f509e99mbansal        }
340e1178a73fd5756771d25d0b8375452450f509e99mbansal
341e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mb = csite->getMb();
342e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
343e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mb->vcrect = mb->brect;
344e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ClipBlendRect(csite, mb->vcrect);
345e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
346e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ComputeMask(csite, mb->vcrect, mb->brect, rect, imgMos, site_idx);
347e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
348e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        site_idx++;
349e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
350e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
351e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Now perform the actual blending using the frame assignment determined above
352e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    site_idx = 0;
353e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for(CSite *csite = m_AllSites; csite < esite; csite++)
354e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
355e1178a73fd5756771d25d0b8375452450f509e99mbansal        if(cancelComputation)
356e1178a73fd5756771d25d0b8375452450f509e99mbansal        {
357e1178a73fd5756771d25d0b8375452450f509e99mbansal            if (m_pMosaicVPyr) free(m_pMosaicVPyr);
358e1178a73fd5756771d25d0b8375452450f509e99mbansal            if (m_pMosaicUPyr) free(m_pMosaicUPyr);
359e1178a73fd5756771d25d0b8375452450f509e99mbansal            if (m_pMosaicYPyr) free(m_pMosaicYPyr);
360e1178a73fd5756771d25d0b8375452450f509e99mbansal            return BLEND_RET_CANCELLED;
361e1178a73fd5756771d25d0b8375452450f509e99mbansal        }
362e1178a73fd5756771d25d0b8375452450f509e99mbansal
363e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mb = csite->getMb();
364e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
365e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
366e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if(FillFramePyramid(mb)!=BLEND_RET_OK)
367e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            return BLEND_RET_ERROR;
368e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
369e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ProcessPyramidForThisFrame(csite, mb->vcrect, mb->brect, rect, imgMos, mb->trs, site_idx);
370e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
37150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal        progress += TIME_PERCENT_BLEND/nsite;
37250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal
373e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        site_idx++;
374e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
375e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
376e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
377e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Blend
378e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PerformFinalBlending(imgMos, cropping_rect);
379e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
380e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_pMosaicVPyr) free(m_pMosaicVPyr);
381e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_pMosaicUPyr) free(m_pMosaicUPyr);
382e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_pMosaicYPyr) free(m_pMosaicYPyr);
383e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
38450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal    progress += TIME_PERCENT_FINAL;
38550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal
386e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return BLEND_RET_OK;
387e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
388e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
389e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::CropFinalMosaic(YUVinfo &imgMos, MosaicRect &cropping_rect)
390e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
391e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int i, j, k;
392e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType yimg;
393e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType uimg;
394e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType vimg;
395e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
396e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
397e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    yimg = imgMos.Y.ptr[0];
398e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    uimg = imgMos.U.ptr[0];
399e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    vimg = imgMos.V.ptr[0];
400e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
401e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    k = 0;
402e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (j = cropping_rect.top; j <= cropping_rect.bottom; j++)
403e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
404e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for (i = cropping_rect.left; i <= cropping_rect.right; i++)
405e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
406e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            yimg[k] = yimg[j*imgMos.Y.width+i];
407e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            k++;
408e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
409e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
410e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (j = cropping_rect.top; j <= cropping_rect.bottom; j++)
411e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
412e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen       for (i = cropping_rect.left; i <= cropping_rect.right; i++)
413e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
414e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            yimg[k] = vimg[j*imgMos.Y.width+i];
415e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            k++;
416e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
417e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
418e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (j = cropping_rect.top; j <= cropping_rect.bottom; j++)
419e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
420e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen       for (i = cropping_rect.left; i <= cropping_rect.right; i++)
421e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
422e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            yimg[k] = uimg[j*imgMos.Y.width+i];
423e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            k++;
424e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
425e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
426e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
427e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
428e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect)
429e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
430e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (!PyramidShort::BorderExpand(m_pMosaicYPyr, m_wb.nlevs, 1) || !PyramidShort::BorderExpand(m_pMosaicUPyr, m_wb.nlevsC, 1) ||
431e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        !PyramidShort::BorderExpand(m_pMosaicVPyr, m_wb.nlevsC, 1))
432e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
433274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen      LOGE("Error: Could not BorderExpand!");
434e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      return BLEND_RET_ERROR;
435e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
436e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
437e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageTypeShort myimg;
438e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageTypeShort muimg;
439e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageTypeShort mvimg;
440e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType yimg;
441e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType uimg;
442e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType vimg;
443e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
444e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int cx = (int)imgMos.Y.width/2;
445e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int cy = (int)imgMos.Y.height/2;
446e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
4476c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // 2D boolean array that contains true wherever the mosaic image data is
4486c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // invalid (i.e. in the gray border).
4496c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    bool **b = new bool*[imgMos.Y.height];
4506c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
4516c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    for(int j=0; j<imgMos.Y.height; j++)
4526c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    {
4536c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        b[j] = new bool[imgMos.Y.width];
4546c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    }
455e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
456e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Copy the resulting image into the full image using the mask
457e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int i, j;
458e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
459e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    yimg = imgMos.Y.ptr[0];
460e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    uimg = imgMos.U.ptr[0];
461e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    vimg = imgMos.V.ptr[0];
462e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
463e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (j = 0; j < imgMos.Y.height; j++)
464e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
465e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        myimg = m_pMosaicYPyr->ptr[j];
466e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        muimg = m_pMosaicUPyr->ptr[j];
467e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mvimg = m_pMosaicVPyr->ptr[j];
468e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
4696c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        for (i = 0; i<imgMos.Y.width; i++)
470e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
471e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // A final mask was set up previously,
472e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // if the value is zero skip it, otherwise replace it.
473e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (*yimg <255)
474e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {
475e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                short value = (short) ((*myimg) >> 3);
476e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if (value < 0) value = 0;
477e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                else if (value > 255) value = 255;
478e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                *yimg = (unsigned char) value;
479e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
480e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                value = (short) ((*muimg) >> 3);
481e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if (value < 0) value = 0;
482e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                else if (value > 255) value = 255;
483e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                *uimg = (unsigned char) value;
484e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
485e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                value = (short) ((*mvimg) >> 3);
486e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if (value < 0) value = 0;
487e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                else if (value > 255) value = 255;
488e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                *vimg = (unsigned char) value;
489e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
4906c5b20113ba9f91352f32e5a53df66aec0ec761ambansal                b[j][i] = false;
4916c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
492e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
493e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            else
494e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {   // set border color in here
495e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                *yimg = (unsigned char) 96;
4966c5b20113ba9f91352f32e5a53df66aec0ec761ambansal                *uimg = (unsigned char) 128;
4976c5b20113ba9f91352f32e5a53df66aec0ec761ambansal                *vimg = (unsigned char) 128;
4986c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
4996c5b20113ba9f91352f32e5a53df66aec0ec761ambansal                b[j][i] = true;
500e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
501e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
502e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            yimg++;
503e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            uimg++;
504e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            vimg++;
505e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            myimg++;
506e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            muimg++;
507e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            mvimg++;
508e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
509e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
510e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
5116c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    //Scan through each row and increment top if the row contains any gray
512e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (j = 0; j < imgMos.Y.height; j++)
513e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
5146c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        for (i = cropping_rect.left; i < cropping_rect.right; i++)
515e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
5166c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            if (b[j][i])
517e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {
5186c5b20113ba9f91352f32e5a53df66aec0ec761ambansal                break; // to next row
519e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
520e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
521e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
5226c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        if (i == cropping_rect.right)   //no gray pixel in this row!
5236c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        {
5246c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            cropping_rect.top = j;
5256c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            break;
5266c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        }
527e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
528e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
5296c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    //Scan through each row and decrement bottom if the row contains any gray
5306c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    for (j = imgMos.Y.height-1; j >= 0; j--)
531e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
5326c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        for (i = cropping_rect.left; i < cropping_rect.right; i++)
533e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
5346c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            if (b[j][i])
535e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {
5366c5b20113ba9f91352f32e5a53df66aec0ec761ambansal                break; // to next row
537e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
538e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
539e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
5406c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        if (i == cropping_rect.right)   //no gray pixel in this row!
5416c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        {
5426c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            cropping_rect.bottom = j;
5436c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            break;
5446c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        }
5456c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    }
546e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
5476c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    for(int j=0; j<imgMos.Y.height; j++)
5486c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    {
5496c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        delete b[j];
550e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
551e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
5526c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    delete b;
553e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
554e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return BLEND_RET_OK;
555e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
556e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
557e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx)
558e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
559e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort *dptr = m_pMosaicYPyr;
560e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
561e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int nC = m_wb.nlevsC;
562e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int l = (int) ((vcrect.lft - rect.left));
563e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int b = (int) ((vcrect.bot - rect.top));
564e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int r = (int) ((vcrect.rgt - rect.left));
565e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int t = (int) ((vcrect.top - rect.top));
566e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
567e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (vcrect.lft == brect.lft)
568e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        l = (l <= 0) ? -BORDER : l - BORDER;
569e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else if (l < -BORDER)
570e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        l = -BORDER;
571e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
572e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (vcrect.bot == brect.bot)
573e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        b = (b <= 0) ? -BORDER : b - BORDER;
574e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else if (b < -BORDER)
575e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        b = -BORDER;
576e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
577e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (vcrect.rgt == brect.rgt)
578e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER;
579e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else if (r >= dptr->width + BORDER)
580e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        r = dptr->width + BORDER - 1;
581e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
582e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (vcrect.top == brect.top)
583e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER;
584e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else if (t >= dptr->height + BORDER)
585e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        t = dptr->height + BORDER - 1;
586e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
587e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Walk the Region of interest and populate the pyramid
588e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int j = b; j <= t; j++)
589e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
590e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        int jj = j;
591e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double sj = jj + rect.top;
592e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
593e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for (int i = l; i <= r; i++)
594e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
595e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            int ii = i;
596e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // project point and then triangulate to neighbors
597e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            double si = ii + rect.left;
598e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
599e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            double dself = hypotSq(csite->getVCenter().x - si, csite->getVCenter().y - sj);
600e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            int inMask = ((unsigned) ii < imgMos.Y.width &&
601e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    (unsigned) jj < imgMos.Y.height) ? 1 : 0;
602e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
603e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if(!inMask)
604e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                continue;
605e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
606e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // scan the neighbors to see if this is a valid position
607e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            unsigned char mask = (unsigned char) 255;
608e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            SEdgeVector *ce;
609e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            int ecnt;
610e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++)
611e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {
612e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                double d1 = hypotSq(m_AllSites[ce->second].getVCenter().x - si,
613e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        m_AllSites[ce->second].getVCenter().y - sj);
614e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if (d1 < dself)
615e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
616e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    break;
617e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
618e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
619e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
620e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (ecnt >= 0) continue;
621e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
622e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            imgMos.Y.ptr[jj][ii] = (unsigned char)site_idx;
623e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
624e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
625e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
626e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
627e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ProcessPyramidForThisFrame(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, double trs[3][3], int site_idx)
628e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
629e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Put the Region of interest (for all levels) into m_pMosaicYPyr
630e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double inv_trs[3][3];
631e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    inv33d(trs, inv_trs);
632e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
633e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Process each pyramid level
634e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort *sptr = m_pFrameYPyr;
635e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort *suptr = m_pFrameUPyr;
636e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort *svptr = m_pFrameVPyr;
637e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
638e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort *dptr = m_pMosaicYPyr;
639e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort *duptr = m_pMosaicUPyr;
640e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    PyramidShort *dvptr = m_pMosaicVPyr;
641e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
642e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int dscale = 0; // distance scale for the current level
643e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int nC = m_wb.nlevsC;
644e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int n = m_wb.nlevs; n--; dscale++, dptr++, sptr++, dvptr++, duptr++, svptr++, suptr++, nC--)
645e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
646e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        int l = (int) ((vcrect.lft - rect.left) / (1 << dscale));
647e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        int b = (int) ((vcrect.bot - rect.top) / (1 << dscale));
648e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        int r = (int) ((vcrect.rgt - rect.left) / (1 << dscale) + .5);
649e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        int t = (int) ((vcrect.top - rect.top) / (1 << dscale) + .5);
650e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
651e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (vcrect.lft == brect.lft)
652e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            l = (l <= 0) ? -BORDER : l - BORDER;
653e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else if (l < -BORDER)
654e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            l = -BORDER;
655e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
656e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (vcrect.bot == brect.bot)
657e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            b = (b <= 0) ? -BORDER : b - BORDER;
658e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else if (b < -BORDER)
659e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            b = -BORDER;
660e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
661e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (vcrect.rgt == brect.rgt)
662e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER;
663e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else if (r >= dptr->width + BORDER)
664e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            r = dptr->width + BORDER - 1;
665e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
666e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (vcrect.top == brect.top)
667e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER;
668e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else if (t >= dptr->height + BORDER)
669e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            t = dptr->height + BORDER - 1;
670e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
671e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Walk the Region of interest and populate the pyramid
672e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for (int j = b; j <= t; j++)
673e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
674e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            int jj = (j << dscale);
675e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            double sj = jj + rect.top;
676e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
677e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            for (int i = l; i <= r; i++)
678e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {
679e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                int ii = (i << dscale);
680e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                // project point and then triangulate to neighbors
681e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                double si = ii + rect.left;
682e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
683e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                int inMask = ((unsigned) ii < imgMos.Y.width &&
684e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        (unsigned) jj < imgMos.Y.height) ? 1 : 0;
685e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
686e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if(inMask && imgMos.Y.ptr[jj][ii]!=site_idx && imgMos.Y.ptr[jj][ii]!=255)
687e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    continue;
688e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
689e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                // Project this mosaic point into the original frame coordinate space
690e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                double xx, yy;
691e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
692e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                MosaicToFrame(inv_trs, si, sj, xx, yy);
693e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
694e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if (xx < 0.0 || yy < 0.0 || xx > width - 1.0 || yy > height - 1.0)
695e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
696e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    if(inMask)
697e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    {
698e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        imgMos.Y.ptr[jj][ii] = 255;
699e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    }
700e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
701e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
702e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                xx /= (1 << dscale);
703e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                yy /= (1 << dscale);
704e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
705e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
706e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                int x1 = (xx >= 0.0) ? (int) xx : (int) floor(xx);
707e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                int y1 = (yy >= 0.0) ? (int) yy : (int) floor(yy);
708e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
709e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                // Final destination in extended pyramid
710e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#ifndef LINEAR_INTERP
711e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if(inSegment(x1, sptr->width, BORDER-1) && inSegment(y1, sptr->height, BORDER-1))
712e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
713e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    double xfrac = xx - x1;
714e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    double yfrac = yy - y1;
715e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    dptr->ptr[j][i] = (short) (.5 + ciCalc(sptr, x1, y1, xfrac, yfrac));
716e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    if (dvptr >= m_pMosaicVPyr && nC > 0)
717e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    {
718e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        duptr->ptr[j][i] = (short) (.5 + ciCalc(suptr, x1, y1, xfrac, yfrac));
719e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        dvptr->ptr[j][i] = (short) (.5 + ciCalc(svptr, x1, y1, xfrac, yfrac));
720e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    }
721e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
722e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#else
723e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if(inSegment(x1, sptr->width, BORDER) && inSegment(y1, sptr->height, BORDER))
724e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
725e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    int x2 = x1 + 1;
726e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    int y2 = y1 + 1;
727e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    double xfrac = xx - x1;
728e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    double yfrac = yy - y1;
729e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    double y1val = sptr->ptr[y1][x1] +
730e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        (sptr->ptr[y1][x2] - sptr->ptr[y1][x1]) * xfrac;
731e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    double y2val = sptr->ptr[y2][x1] +
732e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        (sptr->ptr[y2][x2] - sptr->ptr[y2][x1]) * xfrac;
733e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    dptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val));
734e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
735e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    if (dvptr >= m_pMosaicVPyr && nC > 0)
736e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    {
737e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        y1val = suptr->ptr[y1][x1] +
738e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                            (suptr->ptr[y1][x2] - suptr->ptr[y1][x1]) * xfrac;
739e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        y2val = suptr->ptr[y2][x1] +
740e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                            (suptr->ptr[y2][x2] - suptr->ptr[y2][x1]) * xfrac;
741e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
742e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        duptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val));
743e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
744e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        y1val = svptr->ptr[y1][x1] +
745e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                            (svptr->ptr[y1][x2] - svptr->ptr[y1][x1]) * xfrac;
746e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        y2val = svptr->ptr[y2][x1] +
747e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                            (svptr->ptr[y2][x2] - svptr->ptr[y2][x1]) * xfrac;
748e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
749e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        dvptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val));
750e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    }
751e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
752e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#endif
753e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                else
754e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
755e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    clipToSegment(x1, sptr->width, BORDER);
756e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    clipToSegment(y1, sptr->height, BORDER);
757e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
758e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    dptr->ptr[j][i] = sptr->ptr[y1][x1];
759e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    if (dvptr >= m_pMosaicVPyr && nC > 0)
760e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    {
761e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        dvptr->ptr[j][i] = svptr->ptr[y1][x1];
762e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                        duptr->ptr[j][i] = suptr->ptr[y1][x1];
763e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    }
764e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
765e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
766e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
767e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
768e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
769e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
770e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::MosaicToFrame(double trs[3][3], double x, double y, double &wx, double &wy)
771e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
772e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double X, Y, z;
773e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.theta == 0.0)
774e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
775e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        X = x;
776e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        Y = y;
777e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
778e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else if (m_wb.horizontal)
779e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
780e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double alpha = x * m_wb.direction / m_wb.width;
781e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double length = (y - alpha * m_wb.correction) * m_wb.direction + m_wb.radius;
782e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaTheta = m_wb.theta * alpha;
783e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double sinTheta = sin(deltaTheta);
784e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction;
785e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        X = length * sinTheta + m_wb.x;
786e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        Y = length * cosTheta + m_wb.y;
787e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
788e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
789e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
790e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double alpha = y * m_wb.direction / m_wb.width;
791e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double length = (x - alpha * m_wb.correction) * m_wb.direction + m_wb.radius;
792e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaTheta = m_wb.theta * alpha;
793e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double sinTheta = sin(deltaTheta);
794e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction;
795e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        Y = length * sinTheta + m_wb.y;
796e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        X = length * cosTheta + m_wb.x;
797e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
798e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    z = ProjZ(trs, X, Y, 1.0);
799e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    wx = ProjX(trs, X, Y, z, 1.0);
800e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    wy = ProjY(trs, X, Y, z, 1.0);
801e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
802e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
803e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::FrameToMosaic(double trs[3][3], double x, double y, double &wx, double &wy)
804e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
805e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Project into the intermediate Mosaic coordinate system
806e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double z = ProjZ(trs, x, y, 1.0);
807e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double X = ProjX(trs, x, y, z, 1.0);
808e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double Y = ProjY(trs, x, y, z, 1.0);
809e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
810e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.theta == 0.0)
811e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
812e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // No rotation, then this is all we need to do.
813e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        wx = X;
814e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        wy = Y;
815e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
816e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else if (m_wb.horizontal)
817e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
818e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaX = X - m_wb.x;
819e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaY = Y - m_wb.y;
820e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double length = sqrt(deltaX * deltaX + deltaY * deltaY);
821e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaTheta = asin(deltaX / length);
822e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double alpha = deltaTheta / m_wb.theta;
823e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        wx = alpha * m_wb.width * m_wb.direction;
824e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        wy = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction;
825e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
826e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
827e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
828e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaX = X - m_wb.x;
829e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaY = Y - m_wb.y;
830e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double length = sqrt(deltaX * deltaX + deltaY * deltaY);
831e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaTheta = asin(deltaY / length);
832e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double alpha = deltaTheta / m_wb.theta;
833e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        wy = alpha * m_wb.width * m_wb.direction;
834e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        wx = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction;
835e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
836e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
837e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
838e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
839e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
840e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Clip the region of interest as small as possible by using the Voronoi edges of
841e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// the neighbors
842e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ClipBlendRect(CSite *csite, BlendRect &brect)
843e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
844e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      SEdgeVector *ce;
845e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      int ecnt;
846e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++)
847e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      {
848e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // calculate the Voronoi bisector intersection
849e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        const double epsilon = 1e-5;
850e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double dx = (m_AllSites[ce->second].getVCenter().x - m_AllSites[ce->first].getVCenter().x);
851e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double dy = (m_AllSites[ce->second].getVCenter().y - m_AllSites[ce->first].getVCenter().y);
852e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double xmid = m_AllSites[ce->first].getVCenter().x + dx/2.0;
853e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double ymid = m_AllSites[ce->first].getVCenter().y + dy/2.0;
854e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double inter;
855e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
856e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (dx > epsilon)
857e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
858e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          // neighbor is on right
859e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          if ((inter = m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) < brect.rgt)
860e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            brect.rgt = inter;
861e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
862e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else if (dx < -epsilon)
863e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
864e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          // neighbor is on left
865e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          if ((inter = -m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) > brect.lft)
866e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            brect.lft = inter;
867e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
868e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (dy > epsilon)
869e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
870e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          // neighbor is above
871e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          if ((inter = m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) < brect.top)
872e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            brect.top = inter;
873e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
874e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else if (dy < -epsilon)
875e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
876e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          // neighbor is below
877e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen          if ((inter = -m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) > brect.bot)
878e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            brect.bot = inter;
879e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
880e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen      }
881e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
882e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
883e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect &brect)
884e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
885e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // We need to walk the perimeter since the borders can be bent.
886e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    brect.lft = brect.bot = 2e30;
887e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    brect.rgt = brect.top = -2e30;
888e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double xpos, ypos;
889e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double lasty = height - 1.0;
890e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double lastx = width - 1.0;
891e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    int i;
892e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
893e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (i = width; i--;)
894e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
895e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
896e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(trs, (double) i, 0.0, xpos, ypos);
897e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ClipRect(xpos, ypos, brect);
898e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(trs, (double) i, lasty, xpos, ypos);
899e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ClipRect(xpos, ypos, brect);
900e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
901e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (i = height; i--;)
902e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
903e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(trs, 0.0, (double) i, xpos, ypos);
904e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ClipRect(xpos, ypos, brect);
905e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        FrameToMosaic(trs, lastx, (double) i, xpos, ypos);
906e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        ClipRect(xpos, ypos, brect);
907e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
908e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
909e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
910e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
911e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
912e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is360)
913e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
9146c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // For FULL and PAN modes, we do not unwarp the mosaic into a rectangular coordinate system
9156c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // and so we set the theta to 0 and return.
916e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.blendingType != BLEND_TYPE_CYLPAN && m_wb.blendingType != BLEND_TYPE_HORZ)
917e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
918e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        m_wb.theta = 0.0;
919e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return;
920e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
921e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
922e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *first = frames[0];
923e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *last = frames[frames_size-1];
924e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *mb;
925e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
9261e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    double lxpos = last->trs[0][2], lypos = last->trs[1][2];
9271e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal    double fxpos = first->trs[0][2], fypos = first->trs[1][2];
928e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
929e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Calculate warp to produce proper stitching.
930e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // get x, y displacement
931e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double midX = last->width / 2.0;
932e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double midY = last->height / 2.0;
933e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double z = ProjZ(first->trs, midX, midY, 1.0);
934e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double firstX, firstY;
935e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double prevX = firstX = ProjX(first->trs, midX, midY, z, 1.0);
936e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double prevY = firstY = ProjY(first->trs, midX, midY, z, 1.0);
937e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
938e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double arcLength, lastTheta;
939e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_wb.theta = lastTheta = arcLength = 0.0;
9406c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
9416c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // Step through all the frames to compute the total arc-length of the cone
9426c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // swept while capturing the mosaic (in the original conical coordinate system).
943e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++)
944e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
945e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mb = frames[i];
946e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double currX, currY;
947e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        z = ProjZ(mb->trs, midX, midY, 1.0);
948e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        currX = ProjX(mb->trs, midX, midY, z, 1.0);
949e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        currY = ProjY(mb->trs, midX, midY, z, 1.0);
950e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaX = currX - prevX;
951e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaY = currY - prevY;
9526c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
9536c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        // The arcLength is computed by summing the lengths of the chords
9546c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        // connecting the pairwise projected image centers of the input image frames.
955e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        arcLength += sqrt(deltaY * deltaY + deltaX * deltaX);
9566c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
957e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (!is360)
958e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
959e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            double thisTheta = asin(mb->trs[1][0]);
960e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            m_wb.theta += thisTheta - lastTheta;
961e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            lastTheta = thisTheta;
962e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
9636c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
964e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        prevX = currX;
965e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        prevY = currY;
966e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
967e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
9686c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // Stretch this to end at the proper alignment i.e. the width of the
9696c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // rectangle is determined by the arcLength computed above and the cone
9706c5b20113ba9f91352f32e5a53df66aec0ec761ambansal    // sector angle is determined using the rotation of the last frame.
971e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    m_wb.width = arcLength;
972e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (is360) m_wb.theta = asin(last->trs[1][0]);
973e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
974e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // If there is no rotation, we're done.
975e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (m_wb.theta != 0.0)
976e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
977e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double dx = prevX - firstX;
978e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double dy = prevY - firstY;
9796c5b20113ba9f91352f32e5a53df66aec0ec761ambansal
9806c5b20113ba9f91352f32e5a53df66aec0ec761ambansal        // If the mosaic was captured by sweeping horizontally
981e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (abs(lxpos - fxpos) > abs(lypos - fypos))
982e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
983e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            m_wb.horizontal = 1;
984e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // Calculate radius position to make ends exactly the same Y offset
985e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            double radiusTheta = dx / cos(3.14159 / 2.0 - m_wb.theta);
986e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            m_wb.radius = dy + radiusTheta * cos(m_wb.theta);
987e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius;
988e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
989e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else
990e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
991e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            m_wb.horizontal = 0;
992e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // Calculate radius position to make ends exactly the same Y offset
993e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            double radiusTheta = dy / cos(3.14159 / 2.0 - m_wb.theta);
994e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            m_wb.radius = dx + radiusTheta * cos(m_wb.theta);
995e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius;
996e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
997e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
998e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Determine major direction
999e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (m_wb.horizontal)
1000e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
1001e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // Horizontal strip
10026c5b20113ba9f91352f32e5a53df66aec0ec761ambansal            // m_wb.x,y record the origin of the rectangle coordinate system.
1003e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (is360) m_wb.x = firstX;
1004e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            else
1005e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {
1006e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if (lxpos - fxpos < 0)
1007e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
1008e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    m_wb.x = firstX + midX;
1009e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    z = ProjZ(last->trs, 0.0, midY, 1.0);
1010e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevX = ProjX(last->trs, 0.0, midY, z, 1.0);
1011e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevY = ProjY(last->trs, 0.0, midY, z, 1.0);
1012e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
1013e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                else
1014e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
1015e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    m_wb.x = firstX - midX;
1016e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    z = ProjZ(last->trs, last->width - 1.0, midY, 1.0);
1017e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevX = ProjX(last->trs, last->width - 1.0, midY, z, 1.0);
1018e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevY = ProjY(last->trs, last->width - 1.0, midY, z, 1.0);
1019e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
1020e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
1021e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            dy = prevY - firstY;
1022e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (dy < 0.0) m_wb.direction = 1.0;
1023e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            else m_wb.direction = -1.0;
1024e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            m_wb.y = firstY - m_wb.radius * m_wb.direction;
1025e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (dy * m_wb.theta > 0.0) m_wb.width = -m_wb.width;
1026e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
1027e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        else
1028e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
1029e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            // Vertical strip
1030e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (is360) m_wb.y = firstY;
1031e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            else
1032e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            {
1033e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                if (lypos - fypos < 0)
1034e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
1035e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    m_wb.x = firstY + midY;
1036e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    z = ProjZ(last->trs, midX, 0.0, 1.0);
1037e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevX = ProjX(last->trs, midX, 0.0, z, 1.0);
1038e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevY = ProjY(last->trs, midX, 0.0, z, 1.0);
1039e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
1040e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                else
1041e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                {
1042e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    m_wb.x = firstX - midX;
1043e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    z = ProjZ(last->trs, midX, last->height - 1.0, 1.0);
1044e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevX = ProjX(last->trs, midX, last->height - 1.0, z, 1.0);
1045e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                    prevY = ProjY(last->trs, midX, last->height - 1.0, z, 1.0);
1046e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen                }
1047e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            }
1048e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            dx = prevX - firstX;
1049e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (dx < 0.0) m_wb.direction = 1.0;
1050e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            else m_wb.direction = -1.0;
1051e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            m_wb.x = firstX - m_wb.radius * m_wb.direction;
1052e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            if (dx * m_wb.theta > 0.0) m_wb.width = -m_wb.width;
1053e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
1054e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
1055e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Calculate the correct correction factor
1056e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaX = prevX - m_wb.x;
1057e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaY = prevY - m_wb.y;
1058e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double length = sqrt(deltaX * deltaX + deltaY * deltaY);
1059e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        double deltaTheta = (m_wb.horizontal) ? deltaX : deltaY;
1060e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        deltaTheta = asin(deltaTheta / length);
1061e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        m_wb.correction = ((m_wb.radius - length) * m_wb.direction) /
1062e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            (deltaTheta / m_wb.theta);
1063e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
1064e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
1065