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// pyramid.cpp 18e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 19e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <stdio.h> 20e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <string.h> 21e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 22e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "Pyramid.h" 23e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 24e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// We allocate the entire pyramid into one contiguous storage. This makes 25e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// cleanup easier than fragmented stuff. In addition, we added a "pitch" 26e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// field, so pointer manipulation is much simpler when it would be faster. 27e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenPyramidShort *PyramidShort::allocatePyramidPacked(real levels, 28e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen real width, real height, real border) 29e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 30e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen real border2 = (real) (border << 1); 31e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int lines, size = calcStorage(width, height, border2, levels, &lines); 32e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 33e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *img = (PyramidShort *) calloc(sizeof(PyramidShort) * levels 34e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen + sizeof(short *) * lines + 35e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen + sizeof(short) * size, 1); 36e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 37e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (img) { 38e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *curr, *last; 39e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort *y = (ImageTypeShort *) &img[levels]; 40e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort position = (ImageTypeShort) &y[lines]; 41e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (last = (curr = img) + levels; curr < last; curr++) { 42e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen curr->width = width; 43e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen curr->height = height; 44e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen curr->border = border; 45e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen curr->pitch = (real) (width + border2); 46e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen curr->ptr = y + border; 47e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 48e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Assign row pointers 49e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int j = height + border2; j--; y++, position += curr->pitch) { 50e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *y = position + border; 51e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 52e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 53e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen width >>= 1; 54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen height >>= 1; 55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 56e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return img; 59e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 60e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 61e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Allocate an image of type short 62e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenPyramidShort *PyramidShort::allocateImage(real width, real height, real border) 63e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 64e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen real border2 = (real) (border << 1); 65e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *img = (PyramidShort *) 66e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen calloc(sizeof(PyramidShort) + sizeof(short *) * (height + border2) + 67e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen sizeof(short) * (width + border2) * (height + border2), 1); 68e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 69e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (img) { 70e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen short **y = (short **) &img[1]; 71e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen short *position = (short *) &y[height + border2]; 72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen img->width = width; 73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen img->height = height; 74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen img->border = border; 75e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen img->pitch = (real) (width + border2); 76e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen img->ptr = y + border; 77e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen position += border; // Move position down to origin of real image 78e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 79e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Assign row pointers 80e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int j = height + border2; j--; y++, position += img->pitch) { 81e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *y = position; 82e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 83e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 84e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 85e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return img; 86e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 87e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 88e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Free the images 89e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid PyramidShort::freeImage(PyramidShort *image) 90e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 91e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (image != NULL) 92e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen free(image); 93e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 94e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 95e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Calculate amount of storage needed taking into account the borders, etc. 96e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenunsigned int PyramidShort::calcStorage(real width, real height, real border2, int levels, int *lines) 97e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 98e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int size; 99e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 100e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *lines = size = 0; 101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen while(levels--) { 103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen size += (width + border2) * (height + border2); 104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *lines += height + border2; 105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen width >>= 1; 106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen height >>= 1; 107e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return size; 110e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 112e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid PyramidShort::BorderSpread(PyramidShort *pyr, int left, int right, 113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int top, int bot) 114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 115e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int off, off2, height, h, w; 116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShort base; 117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (left || right) { 119e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen off = pyr->border - left; 120e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen off2 = pyr->width + off + pyr->border - right - 1; 121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen h = pyr->border - top; 122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen height = pyr->height + (h << 1); 123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen base = pyr->ptr[-h] - off; 124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // spread in X 126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (h = height; h--; base += pyr->pitch) { 127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (w = left; w--;) 128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen base[-1 - w] = base[0]; 129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (w = right; w--;) 130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen base[off2 + w + 1] = base[off2]; 131e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 132e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 134e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (top || bot) { 135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // spread in Y 136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen base = pyr->ptr[top - pyr->border] - pyr->border; 137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (h = top; h--; base -= pyr->pitch) { 138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen memcpy(base - pyr->pitch, base, pyr->pitch * sizeof(short)); 139e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen base = pyr->ptr[pyr->height + pyr->border - bot] - pyr->border; 142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (h = bot; h--; base += pyr->pitch) { 143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen memcpy(base, base - pyr->pitch, pyr->pitch * sizeof(short)); 144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid PyramidShort::BorderExpandOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr, 149e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int mode) 150e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int i,j; 152e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int off = in->border / 2; 153e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 154e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Vertical Filter 155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (j = -off; j < in->height + off; j++) { 156e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int j2 = j * 2; 157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (i = -scr->border; i < scr->width + scr->border; i++) { 158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->ptr[j2][i] = (short) 159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ((6 * in->ptr[j][i] + (in->ptr[j-1][i] + in->ptr[j+1][i]) + 4) >> 3); 160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->ptr[j2+1][i] = (short)((in->ptr[j][i] + in->ptr[j+1][i] + 1) >> 1); 161e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 162e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 163e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 164e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BorderSpread(scr, 0, 0, 3, 3); 165e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 166e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Horizontal Filter 167e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (i = -off; i < scr->width + off; i++) { 168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int i2 = i * 2; 169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (j = -out->border; j < out->height + out->border; j++) { 170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen out->ptr[j][i2] = (short) (out->ptr[j][i2] + 171e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (mode * ((6 * scr->ptr[j][i] + 172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->ptr[j][i-1] + scr->ptr[j][i+1] + 4) >> 3))); 173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen out->ptr[j][i2+1] = (short) (out->ptr[j][i2+1] + 174e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen (mode * ((scr->ptr[j][i] + scr->ptr[j][i+1] + 1) >> 1))); 175e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 176e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 177e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 178e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 179e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 180e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint PyramidShort::BorderExpand(PyramidShort *pyr, int nlev, int mode) 181e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 182e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *tpyr = pyr + nlev - 1; 183e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *scr = allocateImage(pyr[1].width, pyr[0].height, pyr->border); 184e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (scr == NULL) return 0; 185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (mode > 0) { 187e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Expand and add (reconstruct from Laplacian) 188e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (; tpyr > pyr; tpyr--) { 189e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->width = tpyr[0].width; 190e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->height = tpyr[-1].height; 191e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BorderExpandOdd(tpyr, tpyr - 1, scr, 1); 192e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 193e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 194e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else if (mode < 0) { 195e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Expand and subtract (build Laplacian) 196e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen while ((pyr++) < tpyr) { 197e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->width = pyr[0].width; 198e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->height = pyr[-1].height; 199e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BorderExpandOdd(pyr, pyr - 1, scr, -1); 200e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 201e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 202e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 203e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen freeImage(scr); 204e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return 1; 205e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 206e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 207e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenvoid PyramidShort::BorderReduceOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr) 208e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 209e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ImageTypeShortBase *s, *ns, *ls, *p, *np; 210e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 211e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int off = scr->border - 2; 212e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen s = scr->ptr[-scr->border] - (off >> 1); 213e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ns = s + scr->pitch; 214e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ls = scr->ptr[scr->height + scr->border - 1] + scr->pitch - (off >> 1); 215e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int width = scr->width + scr->border; 216e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen p = in->ptr[-scr->border] - off; 217e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen np = p + in->pitch; 218e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 219e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // treat it as if the whole thing were the image 220e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (; s < ls; s = ns, ns += scr->pitch, p = np, np += in->pitch) { 221e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int w = width; w--; s++, p += 2) { 222e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *s = (short)((((int) p[-2]) + ((int) p[2]) + 8 + // 1 223e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ((((int) p[-1]) + ((int) p[1])) << 2) + // 4 224e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ((int) *p) * 6) >> 4); // 6 225e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 226e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 227e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 228e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BorderSpread(scr, 5, 4 + ((in->width ^ 1) & 1), 0, 0); // 229e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 230e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen s = out->ptr[-(off >> 1)] - out->border; 231e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ns = s + out->pitch; 232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ls = s + out->pitch * (out->height + off); 233e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen p = scr->ptr[-off] - out->border; 234e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int pitch = scr->pitch; 235e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int pitch2 = pitch << 1; 236e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen np = p + pitch2; 237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (; s < ls; s = ns, ns += out->pitch, p = np, np += pitch2) { 238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for (int w = out->pitch; w--; s++, p++) { 239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *s = (short)((((int) p[-pitch2]) + ((int) p[pitch2]) + 8 + // 1 240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ((((int) p[-pitch]) + ((int) p[pitch])) << 2) + // 4 241e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ((int) *p) * 6) >> 4); // 6 242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BorderSpread(out, 0, 0, 5, 5); 245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 247e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint PyramidShort::BorderReduce(PyramidShort *pyr, int nlev) 249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 250e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen PyramidShort *scr = allocateImage(pyr[1].width, pyr[0].height, pyr->border); 251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (scr == NULL) 252e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return 0; 253e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 254e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BorderSpread(pyr, pyr->border, pyr->border, pyr->border, pyr->border); 255e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen while (--nlev) { 256e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen BorderReduceOdd(pyr, pyr + 1, scr); 257e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen pyr++; 258e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->width = pyr[1].width; 259e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen scr->height = pyr[0].height; 260e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 261e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 262e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen freeImage(scr); 263e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return 1; 264e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 265