git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@4696 92316355-f0b4-4df1-b90c-862c8a59935fmaster
@@ -95,7 +95,7 @@ int main(int argc, char *argv[]) | |||||
return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
} | } | ||||
dst = pipi_resize(src, w, h); | |||||
dst = pipi_resize_bicubic(src, w, h); | |||||
if(bpp == 16) | if(bpp == 16) | ||||
pipi_dither_24to16(dst); | pipi_dither_24to16(dst); | ||||
pipi_save(dst, dstname); | pipi_save(dst, dstname); | ||||
@@ -37,7 +37,8 @@ static function_entry pipi_functions[] = { | |||||
PHP_FE(pipi_get_format_name, NULL) | PHP_FE(pipi_get_format_name, NULL) | ||||
PHP_FE(pipi_measure_msd, NULL) | PHP_FE(pipi_measure_msd, NULL) | ||||
PHP_FE(pipi_measure_rmsd, NULL) | PHP_FE(pipi_measure_rmsd, NULL) | ||||
PHP_FE(pipi_resize, NULL) | |||||
PHP_FE(pipi_resize_bicubic, NULL) | |||||
PHP_FE(pipi_resize_bresenham, NULL) | |||||
PHP_FE(pipi_render_random, NULL) | PHP_FE(pipi_render_random, NULL) | ||||
PHP_FE(pipi_render_bayer, NULL) | PHP_FE(pipi_render_bayer, NULL) | ||||
PHP_FE(pipi_render_halftone, NULL) | PHP_FE(pipi_render_halftone, NULL) | ||||
@@ -339,7 +340,7 @@ PHP_FUNCTION(pipi_measure_rmsd) { | |||||
RETURN_LONG(pipi_measure_rmsd(img1, img2)); | RETURN_LONG(pipi_measure_rmsd(img1, img2)); | ||||
} | } | ||||
PHP_FUNCTION(pipi_resize) { | |||||
PHP_FUNCTION(pipi_resize_bicubic) { | |||||
zval *_zval; | zval *_zval; | ||||
long width, height = 0; | long width, height = 0; | ||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &_zval, &width, &height) == FAILURE) { | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &_zval, &width, &height) == FAILURE) { | ||||
@@ -348,7 +349,20 @@ PHP_FUNCTION(pipi_resize) { | |||||
pipi_image_t *src, *result; | pipi_image_t *src, *result; | ||||
ZEND_FETCH_RESOURCE(src, pipi_image_t*, &_zval, -1, PHP_PIPI_IMAGE_RES_NAME, le_pipi_image); | ZEND_FETCH_RESOURCE(src, pipi_image_t*, &_zval, -1, PHP_PIPI_IMAGE_RES_NAME, le_pipi_image); | ||||
result = pipi_resize(src, width, height); | |||||
result = pipi_resize_bicubic(src, width, height); | |||||
ZEND_REGISTER_RESOURCE(return_value, result, le_pipi_image); | |||||
} | |||||
PHP_FUNCTION(pipi_resize_bresenham) { | |||||
zval *_zval; | |||||
long width, height = 0; | |||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &_zval, &width, &height) == FAILURE) { | |||||
RETURN_FALSE; | |||||
} | |||||
pipi_image_t *src, *result; | |||||
ZEND_FETCH_RESOURCE(src, pipi_image_t*, &_zval, -1, PHP_PIPI_IMAGE_RES_NAME, le_pipi_image); | |||||
result = pipi_resize_bresenham(src, width, height); | |||||
ZEND_REGISTER_RESOURCE(return_value, result, le_pipi_image); | ZEND_REGISTER_RESOURCE(return_value, result, le_pipi_image); | ||||
} | } | ||||
@@ -51,7 +51,8 @@ codec_sources = \ | |||||
codec/oric.c | codec/oric.c | ||||
resample_sources = \ | resample_sources = \ | ||||
resample/bresenham.c | |||||
resample/bresenham.c \ | |||||
resample/bicubic.c | |||||
paint_sources = \ | paint_sources = \ | ||||
paint/floodfill.c \ | paint/floodfill.c \ | ||||
@@ -141,7 +141,7 @@ int pipi_save_oric(pipi_image_t *img, char const *name) | |||||
fwrite("\x00", 1, 1, fp); | fwrite("\x00", 1, 1, fp); | ||||
if(img->w != WIDTH || img->h != HEIGHT) | if(img->w != WIDTH || img->h != HEIGHT) | ||||
tmp = pipi_resize(img, WIDTH, HEIGHT); | |||||
tmp = pipi_resize_bicubic(img, WIDTH, HEIGHT); | |||||
else | else | ||||
tmp = img; | tmp = img; | ||||
p = pipi_get_pixels(tmp, PIPI_PIXELS_RGBA_F32); | p = pipi_get_pixels(tmp, PIPI_PIXELS_RGBA_F32); | ||||
@@ -295,7 +295,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) | |||||
src = ctx->images[ctx->nimages - 1]; | src = ctx->images[ctx->nimages - 1]; | ||||
switch(cmd[0]) | switch(cmd[0]) | ||||
{ | { | ||||
case 'g': dst = pipi_resize(src, w, h); break; | |||||
case 'g': dst = pipi_resize_bicubic(src, w, h); break; | |||||
case 't': dst = pipi_tile(src, w, h); break; | case 't': dst = pipi_tile(src, w, h); break; | ||||
} | } | ||||
if(dst == NULL) | if(dst == NULL) | ||||
@@ -322,7 +322,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) | |||||
h = (int)(scale * src->h + 0.5); | h = (int)(scale * src->h + 0.5); | ||||
if(w <= 0 || h <= 0) | if(w <= 0 || h <= 0) | ||||
return -1; | return -1; | ||||
dst = pipi_resize(src, w, h); | |||||
dst = pipi_resize_bicubic(src, w, h); | |||||
if(dst == NULL) | if(dst == NULL) | ||||
return -1; | return -1; | ||||
pipi_free(src); | pipi_free(src); | ||||
@@ -159,7 +159,8 @@ __extern const char* pipi_get_format_name(int format); | |||||
__extern double pipi_measure_msd(pipi_image_t *, pipi_image_t *); | __extern double pipi_measure_msd(pipi_image_t *, pipi_image_t *); | ||||
__extern double pipi_measure_rmsd(pipi_image_t *, pipi_image_t *); | __extern double pipi_measure_rmsd(pipi_image_t *, pipi_image_t *); | ||||
__extern pipi_image_t *pipi_resize(pipi_image_t *, int, int); | |||||
__extern pipi_image_t *pipi_resize_bresenham(pipi_image_t *, int, int); | |||||
__extern pipi_image_t *pipi_resize_bicubic(pipi_image_t *, int, int); | |||||
__extern pipi_image_t *pipi_crop(pipi_image_t *, int, int, int, int); | __extern pipi_image_t *pipi_crop(pipi_image_t *, int, int, int, int); | ||||
__extern pipi_image_t *pipi_render_random(int, int); | __extern pipi_image_t *pipi_render_random(int, int); | ||||
@@ -0,0 +1,136 @@ | |||||
/* | |||||
* libpipi Pathetic image processing interface library | |||||
* Copyright (c) 2004-2010 Sam Hocevar <sam@hocevar.net> | |||||
* All Rights Reserved | |||||
* | |||||
* $Id$ | |||||
* | |||||
* This library is free software. It comes without any warranty, to | |||||
* the extent permitted by applicable law. You can redistribute it | |||||
* and/or modify it under the terms of the Do What The Fuck You Want | |||||
* To Public License, Version 2, as published by Sam Hocevar. See | |||||
* http://sam.zoy.org/wtfpl/COPYING for more details. | |||||
*/ | |||||
/* | |||||
* bicubic.c: Bicubic image resizing functions | |||||
*/ | |||||
#include "config.h" | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include "pipi.h" | |||||
#include "pipi_internals.h" | |||||
static inline int min_int(int a, int b) { return a < b ? a : b; } | |||||
static inline int max_int(int a, int b) { return a > b ? a : b; } | |||||
pipi_image_t *pipi_resize_bicubic(pipi_image_t *src, int w, int h) | |||||
{ | |||||
float *srcdata, *dstdata, *p0, *p1, *p2, *p3; | |||||
pipi_image_t *dst; | |||||
pipi_pixels_t *srcp, *dstp; | |||||
int x, y, i, sw, dw, sh, dh, i0, i1, i2, i3; | |||||
float scalex, scaley; | |||||
srcp = pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32); | |||||
srcdata = (float *)srcp->pixels; | |||||
dst = pipi_new(w, h); | |||||
dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); | |||||
dstdata = (float *)dstp->pixels; | |||||
sw = src->w; sh = src->h; | |||||
dw = dst->w; dh = dst->h; | |||||
scalex = dw > 1 ? (float)(sw - 1) / (dw - 1) : 1.0f; | |||||
scaley = dh > 1 ? (float)(sh - 1) / (dh - 1) : 1.0f; | |||||
for(y = 0; y < dh; y++) | |||||
{ | |||||
float yfloat = scaley * y; | |||||
int yint = (int)yfloat; | |||||
float y1 = yfloat - yint; | |||||
p0 = srcdata + 4 * sw * min_int(max_int(0, yint - 1), sh - 1); | |||||
p1 = srcdata + 4 * sw * min_int(max_int(0, yint ), sh - 1); | |||||
p2 = srcdata + 4 * sw * min_int(max_int(0, yint + 1), sh - 1); | |||||
p3 = srcdata + 4 * sw * min_int(max_int(0, yint + 2), sh - 1); | |||||
for (x = 0; x < dw; x++) | |||||
{ | |||||
float xfloat = scalex * x; | |||||
int xint = (int)xfloat; | |||||
float x1 = xfloat - xint; | |||||
i0 = 4 * min_int(max_int(0, xint - 1), sw - 1); | |||||
i1 = 4 * min_int(max_int(0, xint ), sw - 1); | |||||
i2 = 4 * min_int(max_int(0, xint + 1), sw - 1); | |||||
i3 = 4 * min_int(max_int(0, xint + 2), sw - 1); | |||||
for (i = 0; i < 4; i++, i0++, i1++, i2++, i3++) | |||||
{ | |||||
float a00 = p1[i1]; | |||||
float a01 = .5f * (p2[i1] - p0[i1]); | |||||
float a02 = p0[i1] - 2.5f * p1[i1] | |||||
+ 2.f * p2[i1] - .5f * p3[i1]; | |||||
float a03 = .5f * (p3[i1] - p0[i1]) + 1.5f * (p1[i1] - p2[i1]); | |||||
float a10 = .5f * (p1[i2] - p1[i0]); | |||||
float a11 = .25f * (p0[i0] - p2[i0] - p0[i2] + p2[i2]); | |||||
float a12 = .5f * (p0[i2] - p0[i0]) + 1.25f * (p1[i0] - p1[i2]) | |||||
+ .25f * (p3[i0] - p3[i2]) + p2[i2] - p2[i0]; | |||||
float a13 = .25f * (p0[i0] - p3[i0] - p0[i2] + p3[i2]) | |||||
+ .75f * (p2[i0] - p1[i0] + p1[i2] - p2[i2]); | |||||
float a20 = p1[i0] - 2.5f * p1[i1] | |||||
+ 2.f * p1[i2] - .5f * p1[i3]; | |||||
float a21 = .5f * (p2[i0] - p0[i0]) + 1.25f * (p0[i1] - p2[i1]) | |||||
+ .25f * (p0[i3] - p2[i3]) - p0[i2] + p2[i2]; | |||||
float a22 = p0[i0] - p3[i2] - 2.5f * (p1[i0] + p0[i1]) | |||||
+ 2.f * (p2[i0] + p0[i2]) - .5f * (p3[i0] + p0[i3]) | |||||
+ 6.25f * p1[i1] - 5.f * (p2[i1] + p1[i2]) | |||||
+ 1.25f * (p3[i1] + p1[i3]) | |||||
+ 4.f * p2[i2] - p2[i3] + .25f * p3[i3]; | |||||
float a23 = 1.5f * (p1[i0] - p2[i0]) + .5f * (p3[i0] - p0[i0]) | |||||
+ 1.25f * (p0[i1] - p3[i1]) | |||||
+ 3.75f * (p2[i1] - p1[i1]) + p3[i2] - p0[i2] | |||||
+ 3.f * (p1[i2] - p2[i2]) + .25f * (p0[i3] - p3[i3]) | |||||
+ .75f * (p2[i3] - p1[i3]); | |||||
float a30 = .5f * (p1[i3] - p1[i0]) + 1.5f * (p1[i1] - p1[i2]); | |||||
float a31 = .25f * (p0[i0] - p2[i0]) + .25f * (p2[i3] - p0[i3]) | |||||
+ .75f * (p2[i1] - p0[i1] + p0[i2] - p2[i2]); | |||||
float a32 = -.5f * p0[i0] + 1.25f * p1[i0] - p2[i0] | |||||
+ .25f * p3[i0] + 1.5f * p0[i1] - 3.75f * p1[i1] | |||||
+ 3.f * p2[i1] - .75f * p3[i1] - 1.5f * p0[i2] | |||||
+ 3.75f * p1[i2] - 3.f * p2[i2] + .75f * p3[i2] | |||||
+ .5f * p0[i3] - 1.25f * p1[i3] + p2[i3] | |||||
- .25f * p3[i3]; | |||||
float a33 = .25f * p0[i0] - .75f * p1[i0] + .75f * p2[i0] | |||||
- .25f * p3[i0] - .75f * p0[i1] + 2.25f * p1[i1] | |||||
- 2.25f * p2[i1] + .75f * p3[i1] + .75f * p0[i2] | |||||
- 2.25f * p1[i2] + 2.25f * p2[i2] - .75f * p3[i2] | |||||
- .25f * p0[i3] + .75f * p1[i3] - .75f * p2[i3] | |||||
+ .25f * p3[i3]; | |||||
float y2 = y1 * y1; float y3 = y2 * y1; | |||||
float x2 = x1 * x1; float x3 = x2 * x1; | |||||
float p = a00 + a01 * y1 + a02 * y2 + a03 * y3 + | |||||
+ a10 * x1 + a11 * x1 * y1 + a12 * x1 * y2 + a13 * x1 * y3 | |||||
+ a20 * x2 + a21 * x2 * y1 + a22 * x2 * y2 + a23 * x2 * y3 | |||||
+ a30 * x3 + a31 * x3 * y1 + a32 * x3 * y2 + a33 * x3 * y3; | |||||
if (p < 0.0f) p = 0.0f; | |||||
if (p > 1.0f) p = 1.0f; | |||||
dstdata[(y * dw + x) * 4 + i] = p; | |||||
} | |||||
} | |||||
} | |||||
return dst; | |||||
} | |||||
@@ -31,7 +31,7 @@ | |||||
/* FIXME: the algorithm does not handle alpha components properly. Resulting | /* FIXME: the algorithm does not handle alpha components properly. Resulting | ||||
* alpha should be the mean alpha value of the neightbouring pixels, but | * alpha should be the mean alpha value of the neightbouring pixels, but | ||||
* the colour components should be weighted with the alpha value. */ | * the colour components should be weighted with the alpha value. */ | ||||
pipi_image_t *pipi_resize(pipi_image_t *src, int w, int h) | |||||
pipi_image_t *pipi_resize_bresenham(pipi_image_t *src, int w, int h) | |||||
{ | { | ||||
float *srcdata, *dstdata, *aline, *line; | float *srcdata, *dstdata, *aline, *line; | ||||
pipi_image_t *dst; | pipi_image_t *dst; | ||||