mirror of https://github.com/aseprite/aseprite.git
167 lines
4.5 KiB
C
167 lines
4.5 KiB
C
/* ASE - Allegro Sprite Editor
|
|
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
|
|
*
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#ifndef USE_PRECOMPILED_HEADER
|
|
|
|
#include <allegro.h>
|
|
#include <math.h>
|
|
|
|
#include "core/core.h"
|
|
#include "modules/gui.h"
|
|
#include "modules/sprites.h"
|
|
#include "raster/image.h"
|
|
#include "raster/sprite.h"
|
|
#include "raster/undo.h"
|
|
#include "util/misc.h"
|
|
|
|
#endif
|
|
|
|
static void project(Image *image, int x, int y, double dmax, double *out_x, double *out_y)
|
|
{
|
|
int center_x = image->w/2; /* center point */
|
|
int center_y = image->h/2;
|
|
int u = (x - center_x); /* vector from center to current point */
|
|
int v = (y - center_y);
|
|
int r = MIN(image->w, image->h)/2; /* radius */
|
|
double d = sqrt(u*u + v*v); /* distance from center */
|
|
double a = atan2(-v, u); /* angle with center */
|
|
|
|
#if 1
|
|
/* sphere */
|
|
double s = sin(PI*MIN(d, r)/r); /* scale factor for effect */
|
|
/* double s = cos(PI/2*MIN(d, r)/r); /\* scale factor for effect *\/ */
|
|
double howmuch = 32;
|
|
/* *out_x = s * (cos(a)*howmuch*(dmax-d)/dmax); */
|
|
/* *out_y = s * (sin(a)*howmuch*(dmax-d)/dmax); */
|
|
*out_x = s * (cos(a)*howmuch*d/dmax);
|
|
*out_y = s * (sin(a)*howmuch*d/dmax);
|
|
|
|
#elif 0
|
|
|
|
/* rotation CCW */
|
|
*out_x = (u + v);
|
|
*out_y = (u - v);
|
|
|
|
#elif 1
|
|
|
|
/* twist */
|
|
/* double s = sin(PI*4*MIN(d, r)/r); /\* scale factor for effect *\/ */
|
|
/* *out_x = s * (cos(a)*8); */
|
|
/* *out_y = s * (sin(a)*8); */
|
|
/* double twist_angle = 2*PI; */
|
|
|
|
/* *out_x = cos(PI/2*MIN(d,r)/r) * (d); */
|
|
/* *out_y = cos(PI/2*MIN(d,r)/r) * (d); */
|
|
|
|
#endif
|
|
}
|
|
|
|
/* original code from 2xSaI by Derek Liauw Kie Fa and Robert J
|
|
Ohannessian */
|
|
static unsigned long bilinear4 (unsigned long A, unsigned long B,
|
|
unsigned long C, unsigned long D,
|
|
fixed x, fixed y)
|
|
{
|
|
unsigned long xy, areaA, areaB, areaC, areaD;
|
|
unsigned long res_r, res_g, res_b, res_a;
|
|
|
|
x = (x >> 11) & 0x1f;
|
|
y = (y >> 11) & 0x1f;
|
|
xy = (x*y) >> 5;
|
|
|
|
/* A = (A & redblueMask) | ((A & greenMask) << 16); */
|
|
/* B = (B & redblueMask) | ((B & greenMask) << 16); */
|
|
/* C = (C & redblueMask) | ((C & greenMask) << 16); */
|
|
/* D = (D & redblueMask) | ((D & greenMask) << 16); */
|
|
|
|
areaA = 0x20 + xy - x - y;
|
|
areaB = x - xy;
|
|
areaC = y - xy;
|
|
areaD = xy;
|
|
|
|
#define CHANNEL(channel) \
|
|
res_##channel = ((areaA * _rgba_get##channel(A)) + \
|
|
(areaB * _rgba_get##channel(B)) + \
|
|
(areaC * _rgba_get##channel(C)) + \
|
|
(areaD * _rgba_get##channel(D))) >> 5
|
|
|
|
CHANNEL(r);
|
|
CHANNEL(g);
|
|
CHANNEL(b);
|
|
CHANNEL(a);
|
|
|
|
return _rgba(res_r, res_g, res_b, res_a);
|
|
}
|
|
|
|
static int image_getpixel4 (Image *image, double x, double y)
|
|
{
|
|
int x1, y1, x2, y2, a, b, c, d;
|
|
|
|
x1 = floor(x);
|
|
y1 = floor(y);
|
|
x2 = ceil(x);
|
|
y2 = ceil(y);
|
|
|
|
a = image_getpixel(image, MID(0, x1, image->w-1), MID(0, y1, image->h-1));
|
|
b = image_getpixel(image, MID(0, x2, image->w-1), MID(0, y1, image->h-1));
|
|
c = image_getpixel(image, MID(0, x1, image->w-1), MID(0, y2, image->h-1));
|
|
d = image_getpixel(image, MID(0, x2, image->w-1), MID(0, y2, image->h-1));
|
|
|
|
return bilinear4(a, b, c, d, ftofix(x), ftofix(y));
|
|
}
|
|
|
|
void dialogs_vector_map(void)
|
|
{
|
|
#define PROJECT() project(image, x, y, dmax, &u, &v)
|
|
|
|
Sprite *sprite = current_sprite;
|
|
Image *image, *image_copy;
|
|
double u, v, dmax;
|
|
int c, x, y;
|
|
|
|
if (!is_interactive () || !sprite)
|
|
return;
|
|
|
|
image = GetImage();
|
|
if (!image)
|
|
return;
|
|
|
|
image_copy = image_new_copy(image);
|
|
if (!image_copy)
|
|
return;
|
|
|
|
/* undo stuff */
|
|
if (undo_is_enabled(sprite->undo))
|
|
undo_image(sprite->undo, image, 0, 0, image->w, image->h);
|
|
|
|
dmax = sqrt(image->w/2*image->w/2 + image->h/2*image->h/2);
|
|
for (y=0; y<image->h; y++) {
|
|
for (x=0; x<image->w; x++) {
|
|
PROJECT();
|
|
c = image_getpixel4 (image_copy, x-u, y+v);
|
|
image_putpixel(image, x, y, c);
|
|
}
|
|
}
|
|
|
|
image_free(image_copy);
|
|
|
|
update_screen_for_sprite(sprite);
|
|
}
|