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; | ||||