Bläddra i källkod

Implement bicubic resampling. Lacks some blurring in the pre-pass, maybe.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@4696 92316355-f0b4-4df1-b90c-862c8a59935f
master
sam 14 år sedan
förälder
incheckning
3f31901de2
8 ändrade filer med 162 tillägg och 10 borttagningar
  1. +1
    -1
      genethumb/genethumb.c
  2. +17
    -3
      pipi-php/php_pipi.c
  3. +2
    -1
      pipi/Makefile.am
  4. +1
    -1
      pipi/codec/oric.c
  5. +2
    -2
      pipi/context.c
  6. +2
    -1
      pipi/pipi.h
  7. +136
    -0
      pipi/resample/bicubic.c
  8. +1
    -1
      pipi/resample/bresenham.c

+ 1
- 1
genethumb/genethumb.c Visa fil

@@ -95,7 +95,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}

dst = pipi_resize(src, w, h);
dst = pipi_resize_bicubic(src, w, h);
if(bpp == 16)
pipi_dither_24to16(dst);
pipi_save(dst, dstname);


+ 17
- 3
pipi-php/php_pipi.c Visa fil

@@ -37,7 +37,8 @@ static function_entry pipi_functions[] = {
PHP_FE(pipi_get_format_name, NULL)
PHP_FE(pipi_measure_msd, 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_bayer, NULL)
PHP_FE(pipi_render_halftone, NULL)
@@ -339,7 +340,7 @@ PHP_FUNCTION(pipi_measure_rmsd) {
RETURN_LONG(pipi_measure_rmsd(img1, img2));
}

PHP_FUNCTION(pipi_resize) {
PHP_FUNCTION(pipi_resize_bicubic) {
zval *_zval;
long width, height = 0;
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;
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);
}



+ 2
- 1
pipi/Makefile.am Visa fil

@@ -51,7 +51,8 @@ codec_sources = \
codec/oric.c

resample_sources = \
resample/bresenham.c
resample/bresenham.c \
resample/bicubic.c

paint_sources = \
paint/floodfill.c \


+ 1
- 1
pipi/codec/oric.c Visa fil

@@ -141,7 +141,7 @@ int pipi_save_oric(pipi_image_t *img, char const *name)
fwrite("\x00", 1, 1, fp);

if(img->w != WIDTH || img->h != HEIGHT)
tmp = pipi_resize(img, WIDTH, HEIGHT);
tmp = pipi_resize_bicubic(img, WIDTH, HEIGHT);
else
tmp = img;
p = pipi_get_pixels(tmp, PIPI_PIXELS_RGBA_F32);


+ 2
- 2
pipi/context.c Visa fil

@@ -295,7 +295,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...)
src = ctx->images[ctx->nimages - 1];
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;
}
if(dst == NULL)
@@ -322,7 +322,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...)
h = (int)(scale * src->h + 0.5);
if(w <= 0 || h <= 0)
return -1;
dst = pipi_resize(src, w, h);
dst = pipi_resize_bicubic(src, w, h);
if(dst == NULL)
return -1;
pipi_free(src);


+ 2
- 1
pipi/pipi.h Visa fil

@@ -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_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_render_random(int, int);


+ 136
- 0
pipi/resample/bicubic.c Visa fil

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


+ 1
- 1
pipi/resample/bresenham.c Visa fil

@@ -31,7 +31,7 @@
/* FIXME: the algorithm does not handle alpha components properly. Resulting
* alpha should be the mean alpha value of the neightbouring pixels, but
* 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;
pipi_image_t *dst;


Laddar…
Avbryt
Spara