Files
scummvm/graphics/tinygl/image_util.cpp
T

151 lines
4.6 KiB
C++

/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
* which is licensed under the zlib-license (see LICENSE).
* It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
*/
#include "graphics/tinygl/zgl.h"
namespace TinyGL {
// linear interpolation with xf, yf normalized to 2^16
#define INTERP_NORM_BITS 16
#define INTERP_NORM (1 << INTERP_NORM_BITS)
static inline int interpolate(int v00, int v01, int v10, int xf, int yf) {
return v00 + (((v01 - v00) * xf + (v10 - v00) * yf) >> INTERP_NORM_BITS);
}
// TODO: more accurate resampling
void gl_resizeImage(unsigned char *dest, int xsize_dest, int ysize_dest,
unsigned char *src, int xsize_src, int ysize_src) {
unsigned char *pix, *pix_src;
int point1_offset = 0, point2_offset = 0, point3_offset = 0;
float x1, y1, x1inc, y1inc;
int xi, yi, xf, yf;
pix = dest;
pix_src = src;
x1inc = (float)(xsize_src - 1) / (float)(xsize_dest - 1);
y1inc = (float)(ysize_src - 1) / (float)(ysize_dest - 1);
y1 = 0;
for (int y = 0; y < ysize_dest; y++) {
x1 = 0;
for (int x = 0; x < xsize_dest; x++) {
xi = (int)x1;
yi = (int)y1;
xf = (int)((x1 - floor(x1)) * INTERP_NORM);
yf = (int)((y1 - floor(y1)) * INTERP_NORM);
if ((xf + yf) <= INTERP_NORM) {
for (int j = 0; j < 3; j++) {
point1_offset = (yi * xsize_src + xi) * 4 + j;
if ((xi + 1) < xsize_src)
point2_offset = (yi * xsize_src + xi + 1) * 4 + j;
else
point2_offset = point1_offset;
if ((yi + 1) < ysize_src)
point3_offset = ((yi + 1) * xsize_src + xi) * 4 + j;
else
point3_offset = point1_offset;
pix[j] = interpolate(pix_src[point1_offset], pix_src[point2_offset], pix_src[point3_offset], xf, yf);
}
pix[3] = pix_src[(yi * xsize_src + xi) * 4 + 3];
} else {
xf = INTERP_NORM - xf;
yf = INTERP_NORM - yf;
for (int j = 0; j < 3; j++) {
pix[j] = interpolate(pix_src[point1_offset], pix_src[point2_offset], pix_src[point3_offset], xf, yf);
if ((xi + 1) < xsize_src) {
if ((yi + 1) < ysize_src)
point1_offset = ((yi + 1) * xsize_src + xi + 1) * 4 + j;
else
point1_offset = (yi * xsize_src + xi + 1) * 4 + j;
} else {
if ((yi + 1) < ysize_src)
point1_offset = ((yi + 1) * xsize_src + xi) * 4 + j;
else
point1_offset = (yi * xsize_src + xi) * 4 + j;
}
if ((yi + 1) < ysize_src)
point2_offset = ((yi + 1) * xsize_src + xi) * 4 + j;
else
point2_offset = (yi * xsize_src + xi) * 4 + j;
if ((xi + 1) < xsize_src)
point3_offset = (yi * xsize_src + xi + 1) * 4 + j;
else
point3_offset = (yi * xsize_src + xi) * 4 + j;
pix[j] = interpolate(pix_src[point1_offset], pix_src[point2_offset], pix_src[point3_offset], xf, yf);
}
pix[3] = pix_src[(yi * xsize_src + xi) * 4 + 3];
}
pix += 4;
x1 += x1inc;
}
y1 += y1inc;
}
}
#define FRAC_BITS 16
// resizing with no interlating nor nearest pixel
void gl_resizeImageNoInterpolate(unsigned char *dest, int xsize_dest, int ysize_dest,
unsigned char *src, int xsize_src, int ysize_src) {
unsigned char *pix, *pix_src, *pix1;
int x1, y1, x1inc, y1inc;
int xi, yi;
pix = dest;
pix_src = src;
x1inc = (int)((float)((xsize_src) << FRAC_BITS) / (float)(xsize_dest));
y1inc = (int)((float)((ysize_src) << FRAC_BITS) / (float)(ysize_dest));
y1 = 0;
for (int y = 0; y < ysize_dest; y++) {
x1 = 0;
for (int x = 0; x < xsize_dest; x++) {
xi = x1 >> FRAC_BITS;
yi = y1 >> FRAC_BITS;
pix1 = pix_src + (yi * xsize_src + xi) * 4;
pix[0] = pix1[0];
pix[1] = pix1[1];
pix[2] = pix1[2];
pix[3] = pix1[3];
pix += 4;
x1 += x1inc;
}
y1 += y1inc;
}
}
} // end of namespace TinyGL