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 44b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansalint Blend::initialize(int blendingType, int stripType, 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; 49b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal this->m_wb.stripType = stripType; 50e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 51e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.blendRange = m_wb.blendRangeUV = BLEND_RANGE_DEFAULT; 52e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.nlevs = m_wb.blendRange; 53e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.nlevsC = m_wb.blendRangeUV; 54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.nlevs <= 0) m_wb.nlevs = 1; // Need levels for YUV processing 56e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.nlevsC > m_wb.nlevs) m_wb.nlevsC = m_wb.nlevs; 57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.roundoffOverlap = 1.5; 59e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 60e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pFrameYPyr = NULL; 61e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pFrameUPyr = NULL; 62e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pFrameVPyr = NULL; 63e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 64e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pFrameYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs, (unsigned short) width, (unsigned short) height, BORDER); 65e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pFrameUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER); 66e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pFrameVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER); 67e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 68e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (!m_pFrameYPyr || !m_pFrameUPyr || !m_pFrameVPyr) 69e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 70274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGE("Error: Could not allocate pyramids for blending"); 71e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR_MEMORY; 72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_OK; 75e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 76e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 776c5b20113ba9f91352f32e5a53df66aec0ec761ambansalinline double max(double a, double b) { return a > b ? a : b; } 786c5b20113ba9f91352f32e5a53df66aec0ec761ambansalinline double min(double a, double b) { return a < b ? a : b; } 796c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 801e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid Blend::AlignToMiddleFrame(MosaicFrame **frames, int frames_size) 811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{ 821e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal // Unwarp this frame and Warp the others to match 831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal MosaicFrame *mb = NULL; 841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal MosaicFrame *ref = frames[int(frames_size/2)]; // Middle frame 851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal double invtrs[3][3]; 871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal inv33d(ref->trs, invtrs); 881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal for(int mfit = 0; mfit < frames_size; mfit++) 901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal { 911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal mb = frames[mfit]; 921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal double temp[3][3]; 931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal mult33d(temp, invtrs, mb->trs); 941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal memcpy(mb->trs, temp, sizeof(temp)); 951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal normProjMat33d(mb->trs); 961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal } 971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal} 981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 99b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansalint Blend::runBlend(MosaicFrame **oframes, MosaicFrame **rframes, 100b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal int frames_size, 10150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal ImageType &imageMosaicYVU, int &mosaicWidth, int &mosaicHeight, 102e1178a73fd5756771d25d0b8375452450f509e99mbansal float &progress, bool &cancelComputation) 103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int ret; 105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int numCenters; 106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 107b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal MosaicFrame **frames; 108b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 109b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // For THIN strip mode, accept all frames for blending 110b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal if (m_wb.stripType == STRIP_TYPE_THIN) 111b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 112b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal frames = oframes; 113b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 114b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal else // For WIDE strip mode, first select the relevant frames to blend. 115b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 116b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal SelectRelevantFrames(oframes, frames_size, rframes, frames_size); 117b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal frames = rframes; 118b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 119b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 120fa45108679c51623e716acbc3301b1e4535c3267Wei-Ta Chen ComputeBlendParameters(frames, frames_size, true); 121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen numCenters = frames_size; 122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (numCenters == 0) 124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 125274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGE("Error: No frames to blend"); 126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR; 127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (!(m_AllSites = m_Triangulator.allocMemory(numCenters))) 130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 131e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR_MEMORY; 132e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1346c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // Bounding rectangle (real numbers) of the final mosaic computed by projecting 1356c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // each input frame into the mosaic coordinate system. 136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BlendRect global_rect; 137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen global_rect.lft = global_rect.bot = 2e30; // min values 139e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen global_rect.rgt = global_rect.top = -2e30; // max values 140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicFrame *mb = NULL; 141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double halfwidth = width / 2.0; 142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double halfheight = height / 2.0; 143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double z, x0, y0, x1, y1, x2, y2, x3, y3; 145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 146a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal // Corners of the left-most and right-most frames respectively in the 147a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal // mosaic coordinate system. 148a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal double xLeftCorners[2] = {2e30, 2e30}; 149a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal double xRightCorners[2] = {-2e30, -2e30}; 1506c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 151ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal // Corners of the top-most and bottom-most frames respectively in the 152ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal // mosaic coordinate system. 153ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal double yTopCorners[2] = {2e30, 2e30}; 154ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal double yBottomCorners[2] = {-2e30, -2e30}; 155ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 156ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Determine the extents of the final mosaic 158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen CSite *csite = m_AllSites ; 159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for(int mfit = 0; mfit < frames_size; mfit++) 160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 161e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mb = frames[mfit]; 162e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 163e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Compute clipping for this frame's rect 164e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaicRect(mb->width, mb->height, mb->trs, mb->brect); 165e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Clip global rect using this frame's rect 166e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ClipRect(mb->brect, global_rect); 167e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Calculate the corner points 169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(mb->trs, 0.0, 0.0, x0, y0); 170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(mb->trs, 0.0, mb->height-1.0, x1, y1); 171e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(mb->trs, mb->width-1.0, mb->height-1.0, x2, y2); 172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(mb->trs, mb->width-1.0, 0.0, x3, y3); 173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 174a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal if(x0 < xLeftCorners[0] || x1 < xLeftCorners[1]) // If either of the left corners is lower 1756c5b20113ba9f91352f32e5a53df66aec0ec761ambansal { 176a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal xLeftCorners[0] = x0; 177a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal xLeftCorners[1] = x1; 1786c5b20113ba9f91352f32e5a53df66aec0ec761ambansal } 1796c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 180a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal if(x3 > xRightCorners[0] || x2 > xRightCorners[1]) // If either of the right corners is higher 1816c5b20113ba9f91352f32e5a53df66aec0ec761ambansal { 182a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal xRightCorners[0] = x3; 183a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal xRightCorners[1] = x2; 1846c5b20113ba9f91352f32e5a53df66aec0ec761ambansal } 1856c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 186ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if(y0 < yTopCorners[0] || y3 < yTopCorners[1]) // If either of the top corners is lower 187ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 188ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal yTopCorners[0] = y0; 189ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal yTopCorners[1] = y3; 190ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 191ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 192ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if(y1 > yBottomCorners[0] || y2 > yBottomCorners[1]) // If either of the bottom corners is higher 193ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 194ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal yBottomCorners[0] = y1; 195ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal yBottomCorners[1] = y2; 196ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 197ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 198ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 199e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Compute the centroid of the warped region 200e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FindQuadCentroid(x0, y0, x1, y1, x2, y2, x3, y3, csite->getVCenter().x, csite->getVCenter().y); 201e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 202e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen csite->setMb(mb); 203e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen csite++; 204e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 205e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 206e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Get origin and sizes 2076c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 2086c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // Bounding rectangle (int numbers) of the final mosaic computed by projecting 2096c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // each input frame into the mosaic coordinate system. 210e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicRect fullRect; 211e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 212e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen fullRect.left = (int) floor(global_rect.lft); // min-x 213e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen fullRect.top = (int) floor(global_rect.bot); // min-y 214e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen fullRect.right = (int) ceil(global_rect.rgt); // max-x 215e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen fullRect.bottom = (int) ceil(global_rect.top);// max-y 216e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Mwidth = (unsigned short) (fullRect.right - fullRect.left + 1); 217e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Mheight = (unsigned short) (fullRect.bottom - fullRect.top + 1); 218e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 219a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal int xLeftMost, xRightMost; 220ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal int yTopMost, yBottomMost; 2216c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 222a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal // Rounding up, so that we don't include the gray border. 223a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal xLeftMost = max(0, max(xLeftCorners[0], xLeftCorners[1]) - fullRect.left + 1); 224a369cd3153170975a5e5bd6fa5544dcd6f22ee85mbansal xRightMost = min(Mwidth - 1, min(xRightCorners[0], xRightCorners[1]) - fullRect.left - 1); 2256c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 226ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal yTopMost = max(0, max(yTopCorners[0], yTopCorners[1]) - fullRect.top + 1); 227ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal yBottomMost = min(Mheight - 1, min(yBottomCorners[0], yBottomCorners[1]) - fullRect.top - 1); 228ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 2290a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen if (xRightMost <= xLeftMost || yBottomMost <= yTopMost) 2300a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen { 2310a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen LOGE("RunBlend: aborting -consistency check failed," 2320a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen "(xLeftMost, xRightMost, yTopMost, yBottomMost): (%d, %d, %d, %d)", 2330a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen xLeftMost, xRightMost, yTopMost, yBottomMost); 2340a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return BLEND_RET_ERROR; 2350a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen } 2360a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen 237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Make sure image width is multiple of 4 238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Mwidth = (unsigned short) ((Mwidth + 3) & ~3); 239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Mheight = (unsigned short) ((Mheight + 3) & ~3); // Round up. 240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 2410a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen ret = MosaicSizeCheck(LIMIT_SIZE_MULTIPLIER, LIMIT_HEIGHT_MULTIPLIER); 2420a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen if (ret != BLEND_RET_OK) 243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 2440a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen LOGE("RunBlend: aborting - mosaic size check failed, " 2450a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen "(frame_width, frame_height) vs (mosaic_width, mosaic_height): " 2460a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen "(%d, %d) vs (%d, %d)", width, height, Mwidth, Mheight); 2470a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return ret; 248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 25089b9c07b5bbcc2de25dd5f61c28de4575b4df996Wei-Ta Chen LOGI("Allocate mosaic image for blending - size: %d x %d", Mwidth, Mheight); 251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen YUVinfo *imgMos = YUVinfo::allocateImage(Mwidth, Mheight); 252e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (imgMos == NULL) 253e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 254274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGE("RunBlend: aborting - couldn't alloc %d x %d mosaic image", Mwidth, Mheight); 255e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR_MEMORY; 256e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 257e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 258e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Set the Y image to 255 so we can distinguish when frame idx are written to it 259e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen memset(imgMos->Y.ptr[0], 255, (imgMos->Y.width * imgMos->Y.height)); 260e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Set the v and u images to black 261e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen memset(imgMos->V.ptr[0], 128, (imgMos->V.width * imgMos->V.height) << 1); 262e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 263e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Do the triangulation. It returns a sorted list of edges 264e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen SEdgeVector *edge; 265e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int n = m_Triangulator.triangulate(&edge, numCenters, width, height); 266e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_Triangulator.linkNeighbors(edge, n, numCenters); 267e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 2686c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // Bounding rectangle that determines the positioning of the rectangle that is 2696c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // cropped out of the computed mosaic to get rid of the gray borders. 270e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicRect cropping_rect; 271e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 272ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (m_wb.horizontal) 273ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 274ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.left = xLeftMost; 275ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.right = xRightMost; 276ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 277ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal else 278ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 279ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.top = yTopMost; 280ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.bottom = yBottomMost; 281ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 2826c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 283e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Do merging and blending : 28450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal ret = DoMergeAndBlend(frames, numCenters, width, height, *imgMos, fullRect, 285e1178a73fd5756771d25d0b8375452450f509e99mbansal cropping_rect, progress, cancelComputation); 286e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 287e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.blendingType == BLEND_TYPE_HORZ) 288e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen CropFinalMosaic(*imgMos, cropping_rect); 289e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 290e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 291e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_Triangulator.freeMemory(); // note: can be called even if delaunay_alloc() wasn't successful 292e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 293e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen imageMosaicYVU = imgMos->Y.ptr[0]; 294e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 295e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 296e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.blendingType == BLEND_TYPE_HORZ) 297e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 298e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mosaicWidth = cropping_rect.right - cropping_rect.left + 1; 299e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mosaicHeight = cropping_rect.bottom - cropping_rect.top + 1; 300e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 301e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 302e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 303e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mosaicWidth = Mwidth; 304e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mosaicHeight = Mheight; 305e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 306e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 307e1178a73fd5756771d25d0b8375452450f509e99mbansal return ret; 308e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 309e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 3100a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chenint Blend::MosaicSizeCheck(float sizeMultiplier, float heightMultiplier) { 3110a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen if (Mwidth < width || Mheight < height) { 3120a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return BLEND_RET_ERROR; 3130a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen } 3140a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen 3150a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen if ((Mwidth * Mheight) > (width * height * sizeMultiplier)) { 3160a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return BLEND_RET_ERROR; 3170a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen } 3180a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen 3190a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen // We won't do blending for the cases where users swing the device too much 3200a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen // in the secondary direction. We use a short side to determine the 3210a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen // secondary direction because users may hold the device in landsape 3220a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen // or portrait. 3230a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen int shortSide = min(Mwidth, Mheight); 3240a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen if (shortSide > height * heightMultiplier) { 3250a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return BLEND_RET_ERROR; 3260a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen } 3270a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen 3280a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return BLEND_RET_OK; 3290a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen} 330e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 331e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Blend::FillFramePyramid(MosaicFrame *mb) 332e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 333e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageType mbY, mbU, mbV; 334e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Lay this image, centered into the temporary buffer 335e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mbY = mb->image; 336e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mbU = mb->getU(); 337e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mbV = mb->getV(); 338e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 339e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int h, w; 340e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 341e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for(h=0; h<height; h++) 342e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 343e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort yptr = m_pFrameYPyr->ptr[h]; 344e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort uptr = m_pFrameUPyr->ptr[h]; 345e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort vptr = m_pFrameVPyr->ptr[h]; 346e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 347e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for(w=0; w<width; w++) 348e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 349e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yptr[w] = (short) ((*(mbY++)) << 3); 350e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen uptr[w] = (short) ((*(mbU++)) << 3); 351e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen vptr[w] = (short) ((*(mbV++)) << 3); 352e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 353e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 354e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 355e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Spread the image through the border 356e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort::BorderSpread(m_pFrameYPyr, BORDER, BORDER, BORDER, BORDER); 357e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort::BorderSpread(m_pFrameUPyr, BORDER, BORDER, BORDER, BORDER); 358e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort::BorderSpread(m_pFrameVPyr, BORDER, BORDER, BORDER, BORDER); 359e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 360e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Generate Laplacian pyramids 361e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (!PyramidShort::BorderReduce(m_pFrameYPyr, m_wb.nlevs) || !PyramidShort::BorderExpand(m_pFrameYPyr, m_wb.nlevs, -1) || 362e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen !PyramidShort::BorderReduce(m_pFrameUPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameUPyr, m_wb.nlevsC, -1) || 363e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen !PyramidShort::BorderReduce(m_pFrameVPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameVPyr, m_wb.nlevsC, -1)) 364e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 365274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGE("Error: Could not generate Laplacian pyramids"); 366e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR; 367e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 368e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 369e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 370e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_OK; 371e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 372e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 373e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 374e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Blend::DoMergeAndBlend(MosaicFrame **frames, int nsite, 37550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal int width, int height, YUVinfo &imgMos, MosaicRect &rect, 376e1178a73fd5756771d25d0b8375452450f509e99mbansal MosaicRect &cropping_rect, float &progress, bool &cancelComputation) 377e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 378e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pMosaicYPyr = NULL; 379e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pMosaicUPyr = NULL; 380e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pMosaicVPyr = NULL; 381e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 382e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pMosaicYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER); 383e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pMosaicUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER); 384e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_pMosaicVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER); 385e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (!m_pMosaicYPyr || !m_pMosaicUPyr || !m_pMosaicVPyr) 386e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 387274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGE("Error: Could not allocate pyramids for blending"); 388e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR_MEMORY; 389e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 390e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 391e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicFrame *mb; 392e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 393e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen CSite *esite = m_AllSites + nsite; 394e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int site_idx; 395e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 396e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // First go through each frame and for each mosaic pixel determine which frame it should come from 397e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen site_idx = 0; 398e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for(CSite *csite = m_AllSites; csite < esite; csite++) 399e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 400e1178a73fd5756771d25d0b8375452450f509e99mbansal if(cancelComputation) 401e1178a73fd5756771d25d0b8375452450f509e99mbansal { 402e1178a73fd5756771d25d0b8375452450f509e99mbansal if (m_pMosaicVPyr) free(m_pMosaicVPyr); 403e1178a73fd5756771d25d0b8375452450f509e99mbansal if (m_pMosaicUPyr) free(m_pMosaicUPyr); 404e1178a73fd5756771d25d0b8375452450f509e99mbansal if (m_pMosaicYPyr) free(m_pMosaicYPyr); 405e1178a73fd5756771d25d0b8375452450f509e99mbansal return BLEND_RET_CANCELLED; 406e1178a73fd5756771d25d0b8375452450f509e99mbansal } 407e1178a73fd5756771d25d0b8375452450f509e99mbansal 408e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mb = csite->getMb(); 409e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 410e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mb->vcrect = mb->brect; 411e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ClipBlendRect(csite, mb->vcrect); 412e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 413e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ComputeMask(csite, mb->vcrect, mb->brect, rect, imgMos, site_idx); 414e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 415e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen site_idx++; 416e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 417e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 418b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal ////////// imgMos.Y, imgMos.V, imgMos.U are used as follows ////////////// 419b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal ////////////////////// THIN STRIP MODE /////////////////////////////////// 420b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 421b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // imgMos.Y is used to store the index of the image from which each pixel 422b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // in the output mosaic can be read out for the thin-strip mode. Thus, 423b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // there is no special handling for pixels around the seam. Also, imgMos.Y 424b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // is set to 255 wherever we can't get its value from any input image e.g. 425b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // in the gray border areas. imgMos.V and imgMos.U are set to 128 for the 426b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // thin-strip mode. 427b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 428b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal ////////////////////// WIDE STRIP MODE /////////////////////////////////// 429b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 430b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // imgMos.Y is used the same way as the thin-strip mode. 431b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // imgMos.V is used to store the index of the neighboring image which 432b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // should contribute to the color of an output pixel in a band around 433b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // the seam. Thus, in this band, we will crossfade between the color values 434b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // from the image index imgMos.Y and image index imgMos.V. imgMos.U is 435b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // used to store the weight (multiplied by 100) that each image will 436b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // contribute to the blending process. Thus, we start at 99% contribution 437b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // from the first image, then go to 50% contribution from each image at 438b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // the seam. Then, the contribution from the second image goes up to 99%. 439b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 440b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // For WIDE mode, set the pixel masks to guide the blender to cross-fade 441b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // between the images on either side of each seam: 442b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal if (m_wb.stripType == STRIP_TYPE_WIDE) 443b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 444ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if(m_wb.horizontal) 445b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 446ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal // Set the number of pixels around the seam to cross-fade between 447ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal // the two component images, 4488252bf716c798a1007e7869569b35815d2df3c6cmbansal int tw = STRIP_CROSS_FADE_WIDTH_PXLS; 449ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 450d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Proceed with the image index calculation for cross-fading 451d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // only if the cross-fading width is larger than 0 452d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen if (tw > 0) 453b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 454d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for(int y = 0; y < imgMos.Y.height; y++) 455b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 456d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Since we compare two adjecant pixels to determine 457d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // whether there is a seam, the termination condition of x 458d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // is set to imgMos.Y.width - tw, so that x+1 below 459d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // won't exceed the imgMos' boundary. 460d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for(int x = tw; x < imgMos.Y.width - tw; ) 461b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 462d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Determine where the seam is... 463d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen if (imgMos.Y.ptr[y][x] != imgMos.Y.ptr[y][x+1] && 464d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.Y.ptr[y][x] != 255 && 465d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.Y.ptr[y][x+1] != 255) 466ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 467d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Find the image indices on both sides of the seam 468d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen unsigned char idx1 = imgMos.Y.ptr[y][x]; 469d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen unsigned char idx2 = imgMos.Y.ptr[y][x+1]; 470d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen 471d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for (int o = tw; o >= 0; o--) 472d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen { 473d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the image index to use for cross-fading 474d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.V.ptr[y][x - o] = idx2; 475d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the intensity weights to use for cross-fading 476d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.U.ptr[y][x - o] = 50 + (99 - 50) * o / tw; 477d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen } 478d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen 479d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for (int o = 1; o <= tw; o++) 480d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen { 481d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the image index to use for cross-fading 482d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.V.ptr[y][x + o] = idx1; 483d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the intensity weights to use for cross-fading 484d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.U.ptr[y][x + o] = imgMos.U.ptr[y][x - o]; 485d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen } 486d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen 487d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen x += (tw + 1); 488ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 489d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen else 490ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 491d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen x++; 492ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 493b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 494b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 495ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 496ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 497ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal else 498ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 499ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal // Set the number of pixels around the seam to cross-fade between 500ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal // the two component images, 5018252bf716c798a1007e7869569b35815d2df3c6cmbansal int tw = STRIP_CROSS_FADE_WIDTH_PXLS; 502ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 503d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Proceed with the image index calculation for cross-fading 504d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // only if the cross-fading width is larger than 0 505d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen if (tw > 0) 506ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 507d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for(int x = 0; x < imgMos.Y.width; x++) 508b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 509d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Since we compare two adjecant pixels to determine 510d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // whether there is a seam, the termination condition of y 511d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // is set to imgMos.Y.height - tw, so that y+1 below 512d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // won't exceed the imgMos' boundary. 513d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for(int y = tw; y < imgMos.Y.height - tw; ) 514ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 515d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Determine where the seam is... 516d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen if (imgMos.Y.ptr[y][x] != imgMos.Y.ptr[y+1][x] && 517d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.Y.ptr[y][x] != 255 && 518d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.Y.ptr[y+1][x] != 255) 519ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 520d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Find the image indices on both sides of the seam 521d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen unsigned char idx1 = imgMos.Y.ptr[y][x]; 522d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen unsigned char idx2 = imgMos.Y.ptr[y+1][x]; 523d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen 524d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for (int o = tw; o >= 0; o--) 525d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen { 526d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the image index to use for cross-fading 527d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.V.ptr[y - o][x] = idx2; 528d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the intensity weights to use for cross-fading 529d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.U.ptr[y - o][x] = 50 + (99 - 50) * o / tw; 530d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen } 531d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen 532d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen for (int o = 1; o <= tw; o++) 533d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen { 534d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the image index to use for cross-fading 535d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.V.ptr[y + o][x] = idx1; 536d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen // Set the intensity weights to use for cross-fading 537d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen imgMos.U.ptr[y + o][x] = imgMos.U.ptr[y - o][x]; 538d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen } 539d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen 540d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen y += (tw + 1); 541ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 542d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen else 543ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 544d97245f738813db9e55e5ae34b01eb7ecd4381e0Wei-Ta Chen y++; 545ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 546ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 547b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 548b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 549b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 550ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 551b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 552b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 553e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Now perform the actual blending using the frame assignment determined above 554e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen site_idx = 0; 555e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for(CSite *csite = m_AllSites; csite < esite; csite++) 556e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 557e1178a73fd5756771d25d0b8375452450f509e99mbansal if(cancelComputation) 558e1178a73fd5756771d25d0b8375452450f509e99mbansal { 559e1178a73fd5756771d25d0b8375452450f509e99mbansal if (m_pMosaicVPyr) free(m_pMosaicVPyr); 560e1178a73fd5756771d25d0b8375452450f509e99mbansal if (m_pMosaicUPyr) free(m_pMosaicUPyr); 561e1178a73fd5756771d25d0b8375452450f509e99mbansal if (m_pMosaicYPyr) free(m_pMosaicYPyr); 562e1178a73fd5756771d25d0b8375452450f509e99mbansal return BLEND_RET_CANCELLED; 563e1178a73fd5756771d25d0b8375452450f509e99mbansal } 564e1178a73fd5756771d25d0b8375452450f509e99mbansal 565e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mb = csite->getMb(); 566e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 567e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 568e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if(FillFramePyramid(mb)!=BLEND_RET_OK) 569e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR; 570e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 571e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ProcessPyramidForThisFrame(csite, mb->vcrect, mb->brect, rect, imgMos, mb->trs, site_idx); 572e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 57350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal progress += TIME_PERCENT_BLEND/nsite; 57450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 575e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen site_idx++; 576e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 577e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 578e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 579e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Blend 580e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PerformFinalBlending(imgMos, cropping_rect); 581e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 582e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_pMosaicVPyr) free(m_pMosaicVPyr); 583e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_pMosaicUPyr) free(m_pMosaicUPyr); 584e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_pMosaicYPyr) free(m_pMosaicYPyr); 585e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 58650b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal progress += TIME_PERCENT_FINAL; 58750b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 588e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_OK; 589e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 590e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 591e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::CropFinalMosaic(YUVinfo &imgMos, MosaicRect &cropping_rect) 592e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 593e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int i, j, k; 594e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageType yimg; 595e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageType uimg; 596e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageType vimg; 597e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 598e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 599e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yimg = imgMos.Y.ptr[0]; 600e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen uimg = imgMos.U.ptr[0]; 601e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen vimg = imgMos.V.ptr[0]; 602e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 603e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen k = 0; 604e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (j = cropping_rect.top; j <= cropping_rect.bottom; j++) 605e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 606e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (i = cropping_rect.left; i <= cropping_rect.right; i++) 607e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 608e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yimg[k] = yimg[j*imgMos.Y.width+i]; 609e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen k++; 610e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 611e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 612e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (j = cropping_rect.top; j <= cropping_rect.bottom; j++) 613e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 614e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (i = cropping_rect.left; i <= cropping_rect.right; i++) 615e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 616e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yimg[k] = vimg[j*imgMos.Y.width+i]; 617e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen k++; 618e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 619e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 620e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (j = cropping_rect.top; j <= cropping_rect.bottom; j++) 621e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 622e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (i = cropping_rect.left; i <= cropping_rect.right; i++) 623e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 624e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yimg[k] = uimg[j*imgMos.Y.width+i]; 625e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen k++; 626e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 627e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 628e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 629e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 630e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect) 631e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 632e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (!PyramidShort::BorderExpand(m_pMosaicYPyr, m_wb.nlevs, 1) || !PyramidShort::BorderExpand(m_pMosaicUPyr, m_wb.nlevsC, 1) || 633e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen !PyramidShort::BorderExpand(m_pMosaicVPyr, m_wb.nlevsC, 1)) 634e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 635274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGE("Error: Could not BorderExpand!"); 636e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_ERROR; 637e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 638e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 639e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort myimg; 640e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort muimg; 641e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort mvimg; 642e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageType yimg; 643e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageType uimg; 644e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageType vimg; 645e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 646e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int cx = (int)imgMos.Y.width/2; 647e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int cy = (int)imgMos.Y.height/2; 648e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 6496c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // 2D boolean array that contains true wherever the mosaic image data is 6506c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // invalid (i.e. in the gray border). 6516c5b20113ba9f91352f32e5a53df66aec0ec761ambansal bool **b = new bool*[imgMos.Y.height]; 6526c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 6536c5b20113ba9f91352f32e5a53df66aec0ec761ambansal for(int j=0; j<imgMos.Y.height; j++) 6546c5b20113ba9f91352f32e5a53df66aec0ec761ambansal { 6556c5b20113ba9f91352f32e5a53df66aec0ec761ambansal b[j] = new bool[imgMos.Y.width]; 6566c5b20113ba9f91352f32e5a53df66aec0ec761ambansal } 657e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 658e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Copy the resulting image into the full image using the mask 659e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int i, j; 660e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 661e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yimg = imgMos.Y.ptr[0]; 662e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen uimg = imgMos.U.ptr[0]; 663e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen vimg = imgMos.V.ptr[0]; 664e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 665e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (j = 0; j < imgMos.Y.height; j++) 666e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 667e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen myimg = m_pMosaicYPyr->ptr[j]; 668e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen muimg = m_pMosaicUPyr->ptr[j]; 669e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mvimg = m_pMosaicVPyr->ptr[j]; 670e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 6716c5b20113ba9f91352f32e5a53df66aec0ec761ambansal for (i = 0; i<imgMos.Y.width; i++) 672e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 673e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // A final mask was set up previously, 674e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // if the value is zero skip it, otherwise replace it. 675e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (*yimg <255) 676e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 677e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen short value = (short) ((*myimg) >> 3); 678e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (value < 0) value = 0; 679e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (value > 255) value = 255; 680e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *yimg = (unsigned char) value; 681e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 682e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen value = (short) ((*muimg) >> 3); 683e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (value < 0) value = 0; 684e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (value > 255) value = 255; 685e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *uimg = (unsigned char) value; 686e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 687e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen value = (short) ((*mvimg) >> 3); 688e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (value < 0) value = 0; 689e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (value > 255) value = 255; 690e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *vimg = (unsigned char) value; 691e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 6926c5b20113ba9f91352f32e5a53df66aec0ec761ambansal b[j][i] = false; 6936c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 694e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 695e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 696e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { // set border color in here 697e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *yimg = (unsigned char) 96; 6986c5b20113ba9f91352f32e5a53df66aec0ec761ambansal *uimg = (unsigned char) 128; 6996c5b20113ba9f91352f32e5a53df66aec0ec761ambansal *vimg = (unsigned char) 128; 7006c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 7016c5b20113ba9f91352f32e5a53df66aec0ec761ambansal b[j][i] = true; 702e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 703e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 704e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yimg++; 705e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen uimg++; 706e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen vimg++; 707e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen myimg++; 708e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen muimg++; 709e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mvimg++; 710e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 711e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 712e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 713ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if(m_wb.horizontal) 714e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 715ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal //Scan through each row and increment top if the row contains any gray 716ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (j = 0; j < imgMos.Y.height; j++) 717e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 718ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (i = cropping_rect.left; i < cropping_rect.right; i++) 719e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 720ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (b[j][i]) 721ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 722ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; // to next row 723ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 724ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 725ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 726ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (i == cropping_rect.right) //no gray pixel in this row! 727ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 728ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.top = j; 729ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; 730e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 731e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 732e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 733ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal //Scan through each row and decrement bottom if the row contains any gray 734ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (j = imgMos.Y.height-1; j >= 0; j--) 7356c5b20113ba9f91352f32e5a53df66aec0ec761ambansal { 736ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (i = cropping_rect.left; i < cropping_rect.right; i++) 737ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 738ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (b[j][i]) 739ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 740ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; // to next row 741ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 742ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 743ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 744ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (i == cropping_rect.right) //no gray pixel in this row! 745ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 746ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.bottom = j; 747ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; 748ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 7496c5b20113ba9f91352f32e5a53df66aec0ec761ambansal } 750e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 751ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal else // Vertical Mosaic 752e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 753ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal //Scan through each column and increment left if the column contains any gray 754ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (i = 0; i < imgMos.Y.width; i++) 755e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 756ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (j = cropping_rect.top; j < cropping_rect.bottom; j++) 757ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 758ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (b[j][i]) 759ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 760ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; // to next column 761ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 762ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 763ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 764ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (j == cropping_rect.bottom) //no gray pixel in this column! 765e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 766ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.left = i; 767ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; 768e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 769e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 770e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 771ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal //Scan through each column and decrement right if the column contains any gray 772ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (i = imgMos.Y.width-1; i >= 0; i--) 7736c5b20113ba9f91352f32e5a53df66aec0ec761ambansal { 774ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal for (j = cropping_rect.top; j < cropping_rect.bottom; j++) 775ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 776ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (b[j][i]) 777ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 778ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; // to next column 779ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 780ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 781ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal 782ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal if (j == cropping_rect.bottom) //no gray pixel in this column! 783ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal { 784ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal cropping_rect.right = i; 785ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal break; 786ff1c641693cf537703fef3949ccf15898c3ad5d0mbansal } 7876c5b20113ba9f91352f32e5a53df66aec0ec761ambansal } 7886c5b20113ba9f91352f32e5a53df66aec0ec761ambansal } 789e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 7906c5b20113ba9f91352f32e5a53df66aec0ec761ambansal for(int j=0; j<imgMos.Y.height; j++) 7916c5b20113ba9f91352f32e5a53df66aec0ec761ambansal { 7926c5b20113ba9f91352f32e5a53df66aec0ec761ambansal delete b[j]; 793e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 794e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 7956c5b20113ba9f91352f32e5a53df66aec0ec761ambansal delete b; 796e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 797e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return BLEND_RET_OK; 798e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 799e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 800e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx) 801e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 802e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *dptr = m_pMosaicYPyr; 803e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 804e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int nC = m_wb.nlevsC; 805e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int l = (int) ((vcrect.lft - rect.left)); 806e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int b = (int) ((vcrect.bot - rect.top)); 807e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int r = (int) ((vcrect.rgt - rect.left)); 808e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int t = (int) ((vcrect.top - rect.top)); 809e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 810e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.lft == brect.lft) 811e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen l = (l <= 0) ? -BORDER : l - BORDER; 812e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (l < -BORDER) 813e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen l = -BORDER; 814e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 815e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.bot == brect.bot) 816e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen b = (b <= 0) ? -BORDER : b - BORDER; 817e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (b < -BORDER) 818e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen b = -BORDER; 819e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 820e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.rgt == brect.rgt) 821e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER; 822e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (r >= dptr->width + BORDER) 823e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen r = dptr->width + BORDER - 1; 824e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 825e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.top == brect.top) 826e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER; 827e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (t >= dptr->height + BORDER) 828e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen t = dptr->height + BORDER - 1; 829e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 830e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Walk the Region of interest and populate the pyramid 831e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int j = b; j <= t; j++) 832e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 833e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int jj = j; 834e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double sj = jj + rect.top; 835e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 836e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int i = l; i <= r; i++) 837e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 838e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int ii = i; 839e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // project point and then triangulate to neighbors 840e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double si = ii + rect.left; 841e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 842e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double dself = hypotSq(csite->getVCenter().x - si, csite->getVCenter().y - sj); 843e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int inMask = ((unsigned) ii < imgMos.Y.width && 844e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (unsigned) jj < imgMos.Y.height) ? 1 : 0; 845e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 846e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if(!inMask) 847e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen continue; 848e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 849e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // scan the neighbors to see if this is a valid position 850e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char mask = (unsigned char) 255; 851e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen SEdgeVector *ce; 852e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int ecnt; 853e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++) 854e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 855e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double d1 = hypotSq(m_AllSites[ce->second].getVCenter().x - si, 856e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_AllSites[ce->second].getVCenter().y - sj); 857e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (d1 < dself) 858e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 859e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen break; 860e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 861e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 862e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 863e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (ecnt >= 0) continue; 864e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 865e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen imgMos.Y.ptr[jj][ii] = (unsigned char)site_idx; 866e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 867e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 868e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 869e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 870e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ProcessPyramidForThisFrame(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, double trs[3][3], int site_idx) 871e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 872e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Put the Region of interest (for all levels) into m_pMosaicYPyr 873e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double inv_trs[3][3]; 874e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen inv33d(trs, inv_trs); 875e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 876e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Process each pyramid level 877e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *sptr = m_pFrameYPyr; 878e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *suptr = m_pFrameUPyr; 879e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *svptr = m_pFrameVPyr; 880e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 881e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *dptr = m_pMosaicYPyr; 882e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *duptr = m_pMosaicUPyr; 883e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *dvptr = m_pMosaicVPyr; 884e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 885e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int dscale = 0; // distance scale for the current level 886e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int nC = m_wb.nlevsC; 887e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int n = m_wb.nlevs; n--; dscale++, dptr++, sptr++, dvptr++, duptr++, svptr++, suptr++, nC--) 888e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 889e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int l = (int) ((vcrect.lft - rect.left) / (1 << dscale)); 890e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int b = (int) ((vcrect.bot - rect.top) / (1 << dscale)); 891e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int r = (int) ((vcrect.rgt - rect.left) / (1 << dscale) + .5); 892e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int t = (int) ((vcrect.top - rect.top) / (1 << dscale) + .5); 893e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 894e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.lft == brect.lft) 895e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen l = (l <= 0) ? -BORDER : l - BORDER; 896e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (l < -BORDER) 897e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen l = -BORDER; 898e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 899e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.bot == brect.bot) 900e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen b = (b <= 0) ? -BORDER : b - BORDER; 901e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (b < -BORDER) 902e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen b = -BORDER; 903e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 904e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.rgt == brect.rgt) 905e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER; 906e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (r >= dptr->width + BORDER) 907e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen r = dptr->width + BORDER - 1; 908e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 909e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (vcrect.top == brect.top) 910e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER; 911e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (t >= dptr->height + BORDER) 912e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen t = dptr->height + BORDER - 1; 913e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 914e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Walk the Region of interest and populate the pyramid 915e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int j = b; j <= t; j++) 916e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 917e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int jj = (j << dscale); 918e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double sj = jj + rect.top; 919e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 920e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int i = l; i <= r; i++) 921e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 922e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int ii = (i << dscale); 923e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // project point and then triangulate to neighbors 924e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double si = ii + rect.left; 925e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 926e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int inMask = ((unsigned) ii < imgMos.Y.width && 927e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (unsigned) jj < imgMos.Y.height) ? 1 : 0; 928e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 929b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal if(inMask && imgMos.Y.ptr[jj][ii] != site_idx && 930b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal imgMos.V.ptr[jj][ii] != site_idx && 931b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal imgMos.Y.ptr[jj][ii] != 255) 932e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen continue; 933e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 934b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // Setup weights for cross-fading 935b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // Weight of the intensity already in the output pixel 936b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double wt0 = 0.0; 937b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // Weight of the intensity from the input pixel (current frame) 938b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double wt1 = 1.0; 939b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 940b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal if (m_wb.stripType == STRIP_TYPE_WIDE) 941b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 942b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal if(inMask && imgMos.Y.ptr[jj][ii] != 255) 943b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 9448252bf716c798a1007e7869569b35815d2df3c6cmbansal // If not on a seam OR pyramid level exceeds 9458252bf716c798a1007e7869569b35815d2df3c6cmbansal // maximum level for cross-fading. 9468252bf716c798a1007e7869569b35815d2df3c6cmbansal if((imgMos.V.ptr[jj][ii] == 128) || 9478252bf716c798a1007e7869569b35815d2df3c6cmbansal (dscale > STRIP_CROSS_FADE_MAX_PYR_LEVEL)) 948b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 949b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt0 = 0.0; 950b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt1 = 1.0; 951b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 952b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal else 953b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 954b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt0 = 1.0; 955b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt1 = ((imgMos.Y.ptr[jj][ii] == site_idx) ? 956b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal (double)imgMos.U.ptr[jj][ii] / 100.0 : 957b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 1.0 - (double)imgMos.U.ptr[jj][ii] / 100.0); 958b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 959b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 960b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 961b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 962e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Project this mosaic point into the original frame coordinate space 963e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xx, yy; 964e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 965e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicToFrame(inv_trs, si, sj, xx, yy); 966e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 967e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (xx < 0.0 || yy < 0.0 || xx > width - 1.0 || yy > height - 1.0) 968e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 969e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if(inMask) 970e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 971e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen imgMos.Y.ptr[jj][ii] = 255; 972b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt0 = 0.0f; 973b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt1 = 1.0f; 974e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 975e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 976e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 977e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xx /= (1 << dscale); 978e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yy /= (1 << dscale); 979e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 980e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 981e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int x1 = (xx >= 0.0) ? (int) xx : (int) floor(xx); 982e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int y1 = (yy >= 0.0) ? (int) yy : (int) floor(yy); 983e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 984e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Final destination in extended pyramid 985e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#ifndef LINEAR_INTERP 986b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal if(inSegment(x1, sptr->width, BORDER-1) && 987b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal inSegment(y1, sptr->height, BORDER-1)) 988e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 989e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xfrac = xx - x1; 990e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double yfrac = yy - y1; 991b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal dptr->ptr[j][i] = (short) (wt0 * dptr->ptr[j][i] + .5 + 992b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt1 * ciCalc(sptr, x1, y1, xfrac, yfrac)); 993e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dvptr >= m_pMosaicVPyr && nC > 0) 994e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 995b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal duptr->ptr[j][i] = (short) (wt0 * duptr->ptr[j][i] + .5 + 996b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt1 * ciCalc(suptr, x1, y1, xfrac, yfrac)); 997b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal dvptr->ptr[j][i] = (short) (wt0 * dvptr->ptr[j][i] + .5 + 998b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt1 * ciCalc(svptr, x1, y1, xfrac, yfrac)); 999e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1000e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1001e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#else 1002e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if(inSegment(x1, sptr->width, BORDER) && inSegment(y1, sptr->height, BORDER)) 1003e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1004e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int x2 = x1 + 1; 1005e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int y2 = y1 + 1; 1006e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xfrac = xx - x1; 1007e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double yfrac = yy - y1; 1008e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double y1val = sptr->ptr[y1][x1] + 1009e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (sptr->ptr[y1][x2] - sptr->ptr[y1][x1]) * xfrac; 1010e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double y2val = sptr->ptr[y2][x1] + 1011e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (sptr->ptr[y2][x2] - sptr->ptr[y2][x1]) * xfrac; 1012e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val)); 1013e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1014e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dvptr >= m_pMosaicVPyr && nC > 0) 1015e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1016e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen y1val = suptr->ptr[y1][x1] + 1017e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (suptr->ptr[y1][x2] - suptr->ptr[y1][x1]) * xfrac; 1018e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen y2val = suptr->ptr[y2][x1] + 1019e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (suptr->ptr[y2][x2] - suptr->ptr[y2][x1]) * xfrac; 1020e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1021e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen duptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val)); 1022e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1023e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen y1val = svptr->ptr[y1][x1] + 1024e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (svptr->ptr[y1][x2] - svptr->ptr[y1][x1]) * xfrac; 1025e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen y2val = svptr->ptr[y2][x1] + 1026e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (svptr->ptr[y2][x2] - svptr->ptr[y2][x1]) * xfrac; 1027e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1028e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dvptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val)); 1029e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1030e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1031e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#endif 1032e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1033e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1034e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen clipToSegment(x1, sptr->width, BORDER); 1035e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen clipToSegment(y1, sptr->height, BORDER); 1036e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1037b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal dptr->ptr[j][i] = (short) (wt0 * dptr->ptr[j][i] + 0.5 + 1038b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal wt1 * sptr->ptr[y1][x1] ); 1039e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dvptr >= m_pMosaicVPyr && nC > 0) 1040e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1041b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal dvptr->ptr[j][i] = (short) (wt0 * dvptr->ptr[j][i] + 1042b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 0.5 + wt1 * svptr->ptr[y1][x1] ); 1043b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal duptr->ptr[j][i] = (short) (wt0 * duptr->ptr[j][i] + 1044b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 0.5 + wt1 * suptr->ptr[y1][x1] ); 1045e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1046e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1047e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1048e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1049e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1050e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 1051e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1052e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::MosaicToFrame(double trs[3][3], double x, double y, double &wx, double &wy) 1053e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 1054e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double X, Y, z; 1055e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.theta == 0.0) 1056e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1057e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen X = x; 1058e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Y = y; 1059e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1060e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (m_wb.horizontal) 1061e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1062e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double alpha = x * m_wb.direction / m_wb.width; 1063e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double length = (y - alpha * m_wb.correction) * m_wb.direction + m_wb.radius; 1064e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaTheta = m_wb.theta * alpha; 1065e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double sinTheta = sin(deltaTheta); 1066e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction; 1067e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen X = length * sinTheta + m_wb.x; 1068e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Y = length * cosTheta + m_wb.y; 1069e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1070e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1071e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1072e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double alpha = y * m_wb.direction / m_wb.width; 1073e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double length = (x - alpha * m_wb.correction) * m_wb.direction + m_wb.radius; 1074e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaTheta = m_wb.theta * alpha; 1075e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double sinTheta = sin(deltaTheta); 1076e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction; 1077e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Y = length * sinTheta + m_wb.y; 1078e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen X = length * cosTheta + m_wb.x; 1079e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1080e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen z = ProjZ(trs, X, Y, 1.0); 1081e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wx = ProjX(trs, X, Y, z, 1.0); 1082e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wy = ProjY(trs, X, Y, z, 1.0); 1083e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 1084e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1085e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::FrameToMosaic(double trs[3][3], double x, double y, double &wx, double &wy) 1086e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 1087e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Project into the intermediate Mosaic coordinate system 1088e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double z = ProjZ(trs, x, y, 1.0); 1089e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double X = ProjX(trs, x, y, z, 1.0); 1090e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double Y = ProjY(trs, x, y, z, 1.0); 1091e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1092e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.theta == 0.0) 1093e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1094e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // No rotation, then this is all we need to do. 1095e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wx = X; 1096e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wy = Y; 1097e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1098e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (m_wb.horizontal) 1099e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1100e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaX = X - m_wb.x; 1101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaY = Y - m_wb.y; 1102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double length = sqrt(deltaX * deltaX + deltaY * deltaY); 1103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaTheta = asin(deltaX / length); 1104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double alpha = deltaTheta / m_wb.theta; 1105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wx = alpha * m_wb.width * m_wb.direction; 1106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wy = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction; 1107e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1110e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaX = X - m_wb.x; 1111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaY = Y - m_wb.y; 1112e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double length = sqrt(deltaX * deltaX + deltaY * deltaY); 1113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaTheta = asin(deltaY / length); 1114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double alpha = deltaTheta / m_wb.theta; 1115e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wy = alpha * m_wb.width * m_wb.direction; 1116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen wx = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction; 1117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 1119e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1120e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Clip the region of interest as small as possible by using the Voronoi edges of 1123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// the neighbors 1124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ClipBlendRect(CSite *csite, BlendRect &brect) 1125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 1126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen SEdgeVector *ce; 1127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int ecnt; 1128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++) 1129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // calculate the Voronoi bisector intersection 1131e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen const double epsilon = 1e-5; 1132e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double dx = (m_AllSites[ce->second].getVCenter().x - m_AllSites[ce->first].getVCenter().x); 1133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double dy = (m_AllSites[ce->second].getVCenter().y - m_AllSites[ce->first].getVCenter().y); 1134e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xmid = m_AllSites[ce->first].getVCenter().x + dx/2.0; 1135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double ymid = m_AllSites[ce->first].getVCenter().y + dy/2.0; 1136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double inter; 1137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dx > epsilon) 1139e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // neighbor is on right 1141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if ((inter = m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) < brect.rgt) 1142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen brect.rgt = inter; 1143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (dx < -epsilon) 1145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // neighbor is on left 1147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if ((inter = -m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) > brect.lft) 1148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen brect.lft = inter; 1149e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1150e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dy > epsilon) 1151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1152e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // neighbor is above 1153e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if ((inter = m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) < brect.top) 1154e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen brect.top = inter; 1155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1156e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (dy < -epsilon) 1157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // neighbor is below 1159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if ((inter = -m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) > brect.bot) 1160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen brect.bot = inter; 1161e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1162e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1163e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 1164e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1165e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect &brect) 1166e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 1167e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // We need to walk the perimeter since the borders can be bent. 1168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen brect.lft = brect.bot = 2e30; 1169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen brect.rgt = brect.top = -2e30; 1170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xpos, ypos; 1171e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double lasty = height - 1.0; 1172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double lastx = width - 1.0; 1173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int i; 1174e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1175e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (i = width; i--;) 1176e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1177e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1178e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(trs, (double) i, 0.0, xpos, ypos); 1179e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ClipRect(xpos, ypos, brect); 1180e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(trs, (double) i, lasty, xpos, ypos); 1181e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ClipRect(xpos, ypos, brect); 1182e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1183e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (i = height; i--;) 1184e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(trs, 0.0, (double) i, xpos, ypos); 1186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ClipRect(xpos, ypos, brect); 1187e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen FrameToMosaic(trs, lastx, (double) i, xpos, ypos); 1188e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ClipRect(xpos, ypos, brect); 1189e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1190e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 1191e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1192b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansalvoid Blend::SelectRelevantFrames(MosaicFrame **frames, int frames_size, 1193b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal MosaicFrame **relevant_frames, int &relevant_frames_size) 1194b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal{ 1195b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal MosaicFrame *first = frames[0]; 1196b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal MosaicFrame *last = frames[frames_size-1]; 1197b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal MosaicFrame *mb; 1198b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 1199b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double fxpos = first->trs[0][2], fypos = first->trs[1][2]; 1200b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 1201b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double midX = last->width / 2.0; 1202b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double midY = last->height / 2.0; 1203b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double z = ProjZ(first->trs, midX, midY, 1.0); 1204b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double firstX, firstY; 1205b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double prevX = firstX = ProjX(first->trs, midX, midY, z, 1.0); 1206b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double prevY = firstY = ProjY(first->trs, midX, midY, z, 1.0); 1207b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 1208b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal relevant_frames[0] = first; // Add first frame by default 1209b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal relevant_frames_size = 1; 1210b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 1211b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal for (int i = 0; i < frames_size - 1; i++) 1212b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 1213b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal mb = frames[i]; 1214b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double currX, currY; 1215b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal z = ProjZ(mb->trs, midX, midY, 1.0); 1216b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal currX = ProjX(mb->trs, midX, midY, z, 1.0); 1217b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal currY = ProjY(mb->trs, midX, midY, z, 1.0); 1218b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double deltaX = currX - prevX; 1219b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double deltaY = currY - prevY; 1220b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal double center2centerDist = sqrt(deltaY * deltaY + deltaX * deltaX); 1221b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 12228252bf716c798a1007e7869569b35815d2df3c6cmbansal if (fabs(deltaX) > STRIP_SEPARATION_THRESHOLD_PXLS || 12238252bf716c798a1007e7869569b35815d2df3c6cmbansal fabs(deltaY) > STRIP_SEPARATION_THRESHOLD_PXLS) 1224b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal { 1225b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal relevant_frames[relevant_frames_size] = mb; 1226b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal relevant_frames_size++; 1227b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal 1228b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal prevX = currX; 1229b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal prevY = currY; 1230b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 1231b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal } 1232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1233b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal // Add last frame by default 1234b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal relevant_frames[relevant_frames_size] = last; 1235b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal relevant_frames_size++; 1236b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal} 1237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is360) 1239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 12406c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // For FULL and PAN modes, we do not unwarp the mosaic into a rectangular coordinate system 12416c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // and so we set the theta to 0 and return. 1242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.blendingType != BLEND_TYPE_CYLPAN && m_wb.blendingType != BLEND_TYPE_HORZ) 1243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.theta = 0.0; 1245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return; 1246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1247e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicFrame *first = frames[0]; 1249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicFrame *last = frames[frames_size-1]; 1250e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen MosaicFrame *mb; 1251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 12521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal double lxpos = last->trs[0][2], lypos = last->trs[1][2]; 12531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal double fxpos = first->trs[0][2], fypos = first->trs[1][2]; 1254e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1255e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Calculate warp to produce proper stitching. 1256e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // get x, y displacement 1257e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double midX = last->width / 2.0; 1258e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double midY = last->height / 2.0; 1259e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double z = ProjZ(first->trs, midX, midY, 1.0); 1260e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double firstX, firstY; 1261e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double prevX = firstX = ProjX(first->trs, midX, midY, z, 1.0); 1262e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double prevY = firstY = ProjY(first->trs, midX, midY, z, 1.0); 1263e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1264e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double arcLength, lastTheta; 1265e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.theta = lastTheta = arcLength = 0.0; 12666c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 12676c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // Step through all the frames to compute the total arc-length of the cone 12686c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // swept while capturing the mosaic (in the original conical coordinate system). 1269e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int i = 0; i < frames_size; i++) 1270e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1271e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mb = frames[i]; 1272e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double currX, currY; 1273e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen z = ProjZ(mb->trs, midX, midY, 1.0); 1274e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen currX = ProjX(mb->trs, midX, midY, z, 1.0); 1275e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen currY = ProjY(mb->trs, midX, midY, z, 1.0); 1276e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaX = currX - prevX; 1277e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaY = currY - prevY; 12786c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 12796c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // The arcLength is computed by summing the lengths of the chords 12806c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // connecting the pairwise projected image centers of the input image frames. 1281e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen arcLength += sqrt(deltaY * deltaY + deltaX * deltaX); 12826c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 1283e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (!is360) 1284e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1285e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double thisTheta = asin(mb->trs[1][0]); 1286e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.theta += thisTheta - lastTheta; 1287e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen lastTheta = thisTheta; 1288e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 12896c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 1290e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevX = currX; 1291e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevY = currY; 1292e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1293e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 12946c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // Stretch this to end at the proper alignment i.e. the width of the 12956c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // rectangle is determined by the arcLength computed above and the cone 12966c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // sector angle is determined using the rotation of the last frame. 1297e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.width = arcLength; 1298e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (is360) m_wb.theta = asin(last->trs[1][0]); 1299e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1300e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // If there is no rotation, we're done. 1301e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.theta != 0.0) 1302e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1303e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double dx = prevX - firstX; 1304e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double dy = prevY - firstY; 13056c5b20113ba9f91352f32e5a53df66aec0ec761ambansal 13066c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // If the mosaic was captured by sweeping horizontally 1307e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (abs(lxpos - fxpos) > abs(lypos - fypos)) 1308e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1309e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.horizontal = 1; 1310e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Calculate radius position to make ends exactly the same Y offset 1311e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double radiusTheta = dx / cos(3.14159 / 2.0 - m_wb.theta); 1312e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.radius = dy + radiusTheta * cos(m_wb.theta); 1313e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius; 1314e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1315e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1316e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1317e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.horizontal = 0; 1318e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Calculate radius position to make ends exactly the same Y offset 1319e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double radiusTheta = dy / cos(3.14159 / 2.0 - m_wb.theta); 1320e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.radius = dx + radiusTheta * cos(m_wb.theta); 1321e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius; 1322e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1323e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1324e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Determine major direction 1325e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (m_wb.horizontal) 1326e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1327e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Horizontal strip 13286c5b20113ba9f91352f32e5a53df66aec0ec761ambansal // m_wb.x,y record the origin of the rectangle coordinate system. 1329e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (is360) m_wb.x = firstX; 1330e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1331e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1332e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (lxpos - fxpos < 0) 1333e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1334e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.x = firstX + midX; 1335e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen z = ProjZ(last->trs, 0.0, midY, 1.0); 1336e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevX = ProjX(last->trs, 0.0, midY, z, 1.0); 1337e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevY = ProjY(last->trs, 0.0, midY, z, 1.0); 1338e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1339e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1340e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1341e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.x = firstX - midX; 1342e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen z = ProjZ(last->trs, last->width - 1.0, midY, 1.0); 1343e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevX = ProjX(last->trs, last->width - 1.0, midY, z, 1.0); 1344e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevY = ProjY(last->trs, last->width - 1.0, midY, z, 1.0); 1345e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1346e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1347e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dy = prevY - firstY; 1348e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dy < 0.0) m_wb.direction = 1.0; 1349e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else m_wb.direction = -1.0; 1350e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.y = firstY - m_wb.radius * m_wb.direction; 1351e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dy * m_wb.theta > 0.0) m_wb.width = -m_wb.width; 1352e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1353e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1354e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1355e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Vertical strip 1356e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (is360) m_wb.y = firstY; 1357e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1358e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1359e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (lypos - fypos < 0) 1360e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1361e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.x = firstY + midY; 1362e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen z = ProjZ(last->trs, midX, 0.0, 1.0); 1363e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevX = ProjX(last->trs, midX, 0.0, z, 1.0); 1364e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevY = ProjY(last->trs, midX, 0.0, z, 1.0); 1365e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1366e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 1367e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 1368e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.x = firstX - midX; 1369e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen z = ProjZ(last->trs, midX, last->height - 1.0, 1.0); 1370e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevX = ProjX(last->trs, midX, last->height - 1.0, z, 1.0); 1371e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen prevY = ProjY(last->trs, midX, last->height - 1.0, z, 1.0); 1372e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1373e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1374e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dx = prevX - firstX; 1375e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dx < 0.0) m_wb.direction = 1.0; 1376e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else m_wb.direction = -1.0; 1377e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.x = firstX - m_wb.radius * m_wb.direction; 1378e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (dx * m_wb.theta > 0.0) m_wb.width = -m_wb.width; 1379e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1380e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 1381e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Calculate the correct correction factor 1382e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaX = prevX - m_wb.x; 1383e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaY = prevY - m_wb.y; 1384e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double length = sqrt(deltaX * deltaX + deltaY * deltaY); 1385e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double deltaTheta = (m_wb.horizontal) ? deltaX : deltaY; 1386e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen deltaTheta = asin(deltaTheta / length); 1387e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen m_wb.correction = ((m_wb.radius - length) * m_wb.direction) / 1388e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (deltaTheta / m_wb.theta); 1389e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 1390e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 1391