/* * effect.c -- image effect routine * (C)Copyright 1999 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Wed Aug 9 07:31:52 2000. * $Id: effect.c,v 1.7 2000/08/09 22:26:21 sian Exp $ * * Enfle 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. * * Enfle 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include "enfle.h" static unsigned char * magnify_generic8(unsigned char *s, int width, int height, int dwidth, int dheight) { unsigned char *d; int x, y, t, t2; if ((d = malloc(dwidth * dheight)) == NULL) return NULL; if (dwidth >= width) if (dheight >= height) { unsigned char *dd = d; for (y = 0; y < dheight; y++) { t = y * height / dheight * width; for (x = 0; x < dwidth; x++) *dd++ = s[x * width / dwidth + t]; } } else for (y = 0; y < height; y++) { t = y * dheight / height * dwidth; t2 = y * width; for (x = 0; x < dwidth; x++) d[x + t] = s[x * width / dwidth + t2]; } else if (dheight >= height) for (y = 0; y < dheight; y++) { t = y * dwidth; t2 = y * height / dheight * width; for (x = 0; x < width; x++) d[x * dwidth / width + t] = s[x + t2]; } else for (y = 0; y < height; y++) { t = y * dheight / height * dwidth; for (x = 0; x < width; x++) d[x * dwidth / width + t] = *s++; } return d; } static unsigned short * magnify_generic16(unsigned short *s, int width, int height, int dwidth, int dheight) { unsigned short *d; int x, y, t, t2; if ((d = malloc(dwidth * dheight * 2)) == NULL) return NULL; if (dwidth >= width) if (dheight >= height) { unsigned short *dd = d; for (y = 0; y < dheight; y++) { t = y * height / dheight * width; for (x = 0; x < dwidth; x++) *dd++ = s[x * width / dwidth + t]; } } else for (y = 0; y < height; y++) { t = y * dheight / height * dwidth; t2 = y * width; for (x = 0; x < dwidth; x++) d[x + t] = s[x * width / dwidth + t2]; } else if (dheight >= height) for (y = 0; y < dheight; y++) { t = y * dwidth; t2 = y * height / dheight * width; for (x = 0; x < width; x++) d[x * dwidth / width + t] = s[x + t2]; } else for (y = 0; y < height; y++) { t = y * dheight / height * dwidth; for (x = 0; x < width; x++) d[x * dwidth / width + t] = *s++; } return d; } static unsigned char * magnify_generic24(unsigned char *s, int width, int height, int dwidth, int dheight, Interpolate_method method) { unsigned char *d; int i, x, y, t, t2, t3, t4; if ((d = malloc(dwidth * dheight * 3)) == NULL) return NULL; if (dwidth >= width) if (dheight >= height) { if (method == _BILINEAR) { unsigned char *dd = d; double dx, dy; int yt; yt = (height - 1) * width; for (y = 0; y < dheight; y++) { dy = (double)y * (double)height / (double)dheight; t = (int)dy; dy -= t; t = y * height / dheight * width; for (x = 0; x < dwidth; x++) { dx = (double)x * (double)width / (double)dwidth; t3 = (int)dx; dx -= t3; if (t < yt) { /* bilinear interpolation */ for (i = 0; i < 3; i++) *dd++ = s[(t + t3 ) * 3 + i] * (1.0 - dx) * (1.0 - dy) + s[(t + (t3 + 1)) * 3 + i] * dx * (1.0 - dy) + s[(t + width + t3 ) * 3 + i] * (1.0 - dx) * dy + s[(t + width + (t3 + 1)) * 3 + i] * dx * dy; } else { for (i = 0; i < 3; i++) *dd++ = s[(t + t3 ) * 3 + i] * (1.0 - dx) + s[(t + (t3 + 1)) * 3 + i] * dx; } } } } else { unsigned char *dd = d; for (y = 0; y < dheight; y++) { t = y * height / dheight * width; for (x = 0; x < dwidth; x++) { t3 = x * width / dwidth + t; for (i = 0; i < 3; i++) *dd++ = s[t3 * 3 + i]; } } } } else for (y = 0; y < height; y++) { t = y * dheight / height * dwidth; t2 = y * width; for (x = 0; x < dwidth; x++) { t4 = x * width / dwidth + t2; for (i = 0; i < 3; i++) d[(x + t) * 3 + i] = s[t4 * 3 + i]; } } else if (dheight >= height) for (y = 0; y < dheight; y++) { t = y * dwidth; t2 = y * height / dheight * width; for (x = 0; x < width; x++) { t3 = x * dwidth / width + t; for (i = 0; i < 3; i++) d[t3 * 3 + i] = s[(x + t2) * 3 + i]; } } else for (y = 0; y < height; y++) { t = y * dheight / height * dwidth; for (x = 0; x < width; x++) { t3 = x * dwidth / width + t; for (i = 0; i < 3; i++) d[t3 * 3 + i] = *s++; } } return d; } void * magnify_generic(Image *p, int dwidth, int dheight, Interpolate_method method) { switch (p->type) { case _GRAY: case _INDEX: return magnify_generic8(p->image, p->width, p->height, dwidth, dheight); case _RGB16: return magnify_generic16((unsigned short *)p->image, p->width, p->height, dwidth, dheight); case _RGB24: return magnify_generic24(p->image, p->width, p->height, dwidth, dheight, method); default: fprintf(stderr, "magnify_generic: unsupported image type %d\n", (int)p->type); return NULL; } } void * magnify(Image *p, int m, Interpolate_method method) { switch (p->type) { case _GRAY: case _INDEX: return magnify_generic8(p->image, p->width, p->height, p->width * m, p->height * m); case _RGB16: return magnify_generic16((unsigned short *)p->image, p->width, p->height, p->width * m, p->height * m); case _RGB24: return magnify_generic24(p->image, p->width, p->height, p->width * m, p->height * m, method); default: fprintf(stderr, "magnify: unsupported image type %d\n", (int)p->type); return NULL; } } static unsigned char * effect_generic8(unsigned char *s, int width, int height, int a11, int a12, int a21, int a22) { unsigned char *d; int x, y; int dwidth, dheight; if ((d = malloc(width * height)) == NULL) return NULL; dwidth = abs(a11 * width + a12 * height); dheight = abs(a21 * width + a22 * height); for (y = 0; y < height; y++) for (x = 0; x < width; x++) { int dx, dy; dx = a11 * x + a12 * y; dy = a21 * x + a22 * y; if (a11 < 0 || a12 < 0) dx = dwidth + dx - 1; if (a21 < 0 || a22 < 0) dy = dheight + dy - 1; d[dx + dy * dwidth] = s[x + y * width]; } return d; } static unsigned short * effect_generic16(unsigned short *s, int width, int height, int a11, int a12, int a21, int a22) { unsigned short *d; int x, y; int dwidth, dheight; if ((d = malloc(width * height * 2)) == NULL) return NULL; dwidth = abs(a11 * width + a12 * height); dheight = abs(a21 * width + a22 * height); for (y = 0; y < height; y++) for (x = 0; x < width; x++) { int dx, dy; dx = a11 * x + a12 * y; dy = a21 * x + a22 * y; if (a11 < 0 || a12 < 0) dx = dwidth + dx - 1; if (a21 < 0 || a22 < 0) dy = dheight + dy - 1; d[dx + dy * dwidth] = s[x + y * width]; } return d; } static unsigned char * effect_generic24(unsigned char *s, int width, int height, int a11, int a12, int a21, int a22) { unsigned char *d; int x, y; int dwidth, dheight; if ((d = malloc(width * height * 3)) == NULL) return NULL; dwidth = abs(a11 * width + a12 * height); dheight = abs(a21 * width + a22 * height); for (y = 0; y < height; y++) for (x = 0; x < width; x++) { int dx, dy; dx = a11 * x + a12 * y; dy = a21 * x + a22 * y; if (a11 < 0 || a12 < 0) dx = dwidth + dx - 1; if (a21 < 0 || a22 < 0) dy = dheight + dy - 1; d[(dx + dy * dwidth) * 3 + 0] = s[(x + y * width) * 3 + 0]; d[(dx + dy * dwidth) * 3 + 1] = s[(x + y * width) * 3 + 1]; d[(dx + dy * dwidth) * 3 + 2] = s[(x + y * width) * 3 + 2]; } return d; } /* flip image horizontally */ void * flip_horizontal(Image *p) { switch (p->type) { case _INDEX: return effect_generic8(p->image, p->width, p->height, -1, 0, 0, 1); case _RGB16: return effect_generic16((unsigned short *)p->image, p->width, p->height, -1, 0, 0, 1); case _RGB24: return effect_generic24(p->image, p->width, p->height, -1, 0, 0, 1); default: fprintf(stderr, "flip_horizontal: unsupported image type: %d\n", (int)p->type); return NULL; } } /* flip image vertically */ void * flip_vertical(Image *p) { switch (p->type) { case _INDEX: return effect_generic8(p->image, p->width, p->height, 1, 0, 0, -1); case _RGB16: return effect_generic16((unsigned short *)p->image, p->width, p->height, 1, 0, 0, -1); case _RGB24: return effect_generic24(p->image, p->width, p->height, 1, 0, 0, -1); default: fprintf(stderr, "flip_vertical: unsupported image type: %d\n", (int)p->type); return NULL; } }