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