From 31328a14aa7772b93dab0f7dfede7e5a6a180b47 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 28 Jul 2008 23:01:29 +0000 Subject: [PATCH] * Big API reorganisation. Now libpipi can transparently convert between colour spaces for a given image. For instance, if pipi_gaussian_blur is applied to a 32-bpp image, it is automatically converted to gamma-corrected 32-bit floats beforehands, then converted back to normal. * TODO: clipping, regions of interest, more formats, getpixel macros... git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2605 92316355-f0b4-4df1-b90c-862c8a59935f --- pipi/codec.c | 17 -------- pipi/codec/imlib.c | 43 ++++++++++++------- pipi/codec/opencv.c | 43 ++++++++++++------- pipi/codec/sdl.c | 47 +++++++++++++-------- pipi/dither.c | 3 ++ pipi/filter/blur.c | 30 +++++++++----- pipi/pipi.c | 40 ++++++++++++++++++ pipi/pipi.h | 43 +++++++++++++------ pipi/pipi_internals.h | 18 +++++--- pipi/pixels.c | 96 +++++++++++++++++++++++++------------------ pipi/resize.c | 47 ++++++++++++--------- pipi/test.c | 19 +++++++-- 12 files changed, 293 insertions(+), 153 deletions(-) diff --git a/pipi/codec.c b/pipi/codec.c index 7af7cd7..66d9a43 100644 --- a/pipi/codec.c +++ b/pipi/codec.c @@ -49,23 +49,6 @@ pipi_image_t *pipi_new(int width, int height) #endif } -pipi_image_t *pipi_copy(pipi_image_t const *img) -{ - pipi_image_t *dst; - int x, y; - dst = pipi_new(img->width, img->height); - for(y = 0; y < img->height; y++) - { - for(x = 0; x < img->width; x++) - { - double r, g, b; - pipi_getpixel(img, x, y, &r, &g, &b); - pipi_setpixel(dst, x, y, r, g, b); - } - } - return dst; -} - void pipi_free(pipi_image_t *img) { #if USE_SDL diff --git a/pipi/codec/imlib.c b/pipi/codec/imlib.c index d10138e..49bf476 100644 --- a/pipi/codec/imlib.c +++ b/pipi/codec/imlib.c @@ -37,13 +37,20 @@ pipi_image_t *pipi_load_imlib2(const char *name) return NULL; img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); + memset(img, 0, sizeof(pipi_image_t)); + imlib_context_set_image(priv); - img->width = imlib_image_get_width(); - img->height = imlib_image_get_height(); - img->pitch = 4 * imlib_image_get_width(); - img->channels = 4; - img->pixels = (char *)imlib_image_get_data(); - img->priv = (void *)priv; + img->w = imlib_image_get_width(); + img->h = imlib_image_get_height(); + + img->p[PIPI_PIXELS_RGBA32].pixels = imlib_image_get_data(); + img->p[PIPI_PIXELS_RGBA32].w = imlib_image_get_width(); + img->p[PIPI_PIXELS_RGBA32].h = imlib_image_get_height(); + img->p[PIPI_PIXELS_RGBA32].pitch = 4 * imlib_image_get_width(); + img->last_modified = PIPI_PIXELS_RGBA32; + + img->codec_priv = (void *)priv; + img->codec_format = PIPI_PIXELS_RGBA32; return img; } @@ -57,20 +64,27 @@ pipi_image_t *pipi_new_imlib2(int width, int height) return NULL; img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); + memset(img, 0, sizeof(pipi_image_t)); + imlib_context_set_image(priv); - img->width = imlib_image_get_width(); - img->height = imlib_image_get_height(); - img->pitch = 4 * imlib_image_get_width(); - img->channels = 4; - img->pixels = (char *)imlib_image_get_data(); - img->priv = (void *)priv; + img->w = imlib_image_get_width(); + img->h = imlib_image_get_height(); + + img->p[PIPI_PIXELS_RGBA32].pixels = imlib_image_get_data(); + img->p[PIPI_PIXELS_RGBA32].w = imlib_image_get_width(); + img->p[PIPI_PIXELS_RGBA32].h = imlib_image_get_height(); + img->p[PIPI_PIXELS_RGBA32].pitch = 4 * imlib_image_get_width(); + img->last_modified = PIPI_PIXELS_RGBA32; + + img->codec_priv = (void *)priv; + img->codec_format = PIPI_PIXELS_RGBA32; return img; } void pipi_free_imlib2(pipi_image_t *img) { - imlib_context_set_image(img->priv); + imlib_context_set_image(img->codec_priv); imlib_free_image(); free(img); @@ -78,7 +92,8 @@ void pipi_free_imlib2(pipi_image_t *img) void pipi_save_imlib2(pipi_image_t *img, const char *name) { - imlib_context_set_image(img->priv); + pipi_getpixels(img, img->codec_format); + imlib_context_set_image(img->codec_priv); imlib_save_image(name); } diff --git a/pipi/codec/opencv.c b/pipi/codec/opencv.c index d9f33ad..e061dd0 100644 --- a/pipi/codec/opencv.c +++ b/pipi/codec/opencv.c @@ -38,12 +38,19 @@ pipi_image_t *pipi_load_opencv(const char *name) return NULL; img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); - img->width = priv->width; - img->height = priv->height; - img->pitch = priv->widthStep; - img->channels = priv->nChannels; - img->pixels = priv->imageData; - img->priv = (void *)priv; + memset(img, 0, sizeof(pipi_image_t)); + + img->w = priv->width; + img->h = priv->height; + + img->p[PIPI_PIXELS_RGBA32].pixels = priv->imageData; + img->p[PIPI_PIXELS_RGBA32].w = priv->width; + img->p[PIPI_PIXELS_RGBA32].h = priv->height; + img->p[PIPI_PIXELS_RGBA32].pitch = priv->widthStep; + img->last_modified = PIPI_PIXELS_RGBA32; + + img->codec_priv = (void *)priv; + img->codec_format = PIPI_PIXELS_RGBA32; return img; } @@ -57,12 +64,19 @@ pipi_image_t *pipi_new_opencv(int width, int height) return NULL; img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); - img->width = priv->width; - img->height = priv->height; - img->pitch = priv->widthStep; - img->channels = priv->nChannels; - img->pixels = priv->imageData; - img->priv = (void *)priv; + memset(img, 0, sizeof(pipi_image_t)); + + img->w = priv->width; + img->h = priv->height; + + img->p[PIPI_PIXELS_RGBA32].pixels = priv->imageData; + img->p[PIPI_PIXELS_RGBA32].w = priv->width; + img->p[PIPI_PIXELS_RGBA32].h = priv->height; + img->p[PIPI_PIXELS_RGBA32].pitch = priv->widthStep; + img->last_modified = PIPI_PIXELS_RGBA32; + + img->codec_priv = (void *)priv; + img->codec_format = PIPI_PIXELS_RGBA32; return img; } @@ -70,7 +84,7 @@ pipi_image_t *pipi_new_opencv(int width, int height) void pipi_free_opencv(pipi_image_t *img) { IplImage *iplimg; - iplimg = (IplImage *)img->priv; + iplimg = (IplImage *)img->codec_priv; cvReleaseImage(&iplimg); free(img); @@ -78,6 +92,7 @@ void pipi_free_opencv(pipi_image_t *img) void pipi_save_opencv(pipi_image_t *img, const char *name) { - cvSaveImage(name, img->priv); + pipi_getpixels(img, img->codec_format); + cvSaveImage(name, img->codec_priv); } diff --git a/pipi/codec/sdl.c b/pipi/codec/sdl.c index fdd6d93..010affe 100644 --- a/pipi/codec/sdl.c +++ b/pipi/codec/sdl.c @@ -36,21 +36,28 @@ pipi_image_t *pipi_load_sdl(const char *name) if(!priv) return NULL; - if(priv->format->BytesPerPixel == 1) + if(priv->format->BytesPerPixel != 4) { img = pipi_new(priv->w, priv->h); - SDL_BlitSurface(priv, NULL, img->priv, NULL); + SDL_BlitSurface(priv, NULL, img->codec_priv, NULL); SDL_FreeSurface(priv); return img; } img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); - img->width = priv->w; - img->height = priv->h; - img->pitch = priv->pitch; - img->channels = priv->format->BytesPerPixel; - img->pixels = priv->pixels; - img->priv = (void *)priv; + memset(img, 0, sizeof(pipi_image_t)); + + img->w = priv->w; + img->h = priv->h; + + img->p[PIPI_PIXELS_RGBA32].pixels = priv->pixels; + img->p[PIPI_PIXELS_RGBA32].w = priv->w; + img->p[PIPI_PIXELS_RGBA32].h = priv->h; + img->p[PIPI_PIXELS_RGBA32].pitch = priv->pitch; + img->last_modified = PIPI_PIXELS_RGBA32; + + img->codec_priv = (void *)priv; + img->codec_format = PIPI_PIXELS_RGBA32; return img; } @@ -78,25 +85,33 @@ pipi_image_t *pipi_new_sdl(int width, int height) return NULL; img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); - img->width = priv->w; - img->height = priv->h; - img->pitch = priv->pitch; - img->channels = priv->format->BytesPerPixel; - img->pixels = priv->pixels; - img->priv = (void *)priv; + memset(img, 0, sizeof(pipi_image_t)); + + img->w = priv->w; + img->h = priv->h; + + img->p[PIPI_PIXELS_RGBA32].pixels = priv->pixels; + img->p[PIPI_PIXELS_RGBA32].w = priv->w; + img->p[PIPI_PIXELS_RGBA32].h = priv->h; + img->p[PIPI_PIXELS_RGBA32].pitch = priv->pitch; + img->last_modified = PIPI_PIXELS_RGBA32; + + img->codec_priv = (void *)priv; + img->codec_format = PIPI_PIXELS_RGBA32; return img; } void pipi_free_sdl(pipi_image_t *img) { - SDL_FreeSurface(img->priv); + SDL_FreeSurface(img->codec_priv); free(img); } void pipi_save_sdl(pipi_image_t *img, const char *name) { - SDL_SaveBMP(img->priv, name); + pipi_getpixels(img, img->codec_format); + SDL_SaveBMP(img->codec_priv, name); } diff --git a/pipi/dither.c b/pipi/dither.c index a2f9ec4..7b4a07b 100644 --- a/pipi/dither.c +++ b/pipi/dither.c @@ -28,6 +28,8 @@ void pipi_dither_24to16(pipi_image_t *img) { +/* XXX: disabled because this is not the right place... see pixels.c instead */ +#if 0 int *error, *nexterror; uint32_t *p32; int x, y; @@ -84,5 +86,6 @@ void pipi_dither_24to16(pipi_image_t *img) free(error); free(nexterror); +#endif } diff --git a/pipi/filter/blur.c b/pipi/filter/blur.c index ac6b28f..3c5fc9f 100644 --- a/pipi/filter/blur.c +++ b/pipi/filter/blur.c @@ -27,15 +27,24 @@ #include "pipi.h" #include "pipi_internals.h" -pipi_image_t *pipi_gaussian_blur(pipi_image_t const *src, float radius) +pipi_image_t *pipi_gaussian_blur(pipi_image_t *src, float radius) { pipi_image_t *dst; + pipi_pixels_t *srcp, *dstp; + float *srcdata, *dstdata; double *kernel; double K, L, t = 0.; int x, y, i, j, w, h, kr, kw; - w = src->width; - h = src->height; + w = src->w; + h = src->h; + + srcp = pipi_getpixels(src, PIPI_PIXELS_RGBA_F); + srcdata = (float *)srcp->pixels; + + dst = pipi_new(w, h); + dstp = pipi_getpixels(dst, PIPI_PIXELS_RGBA_F); + dstdata = (float *)dstp->pixels; kr = (int)(3. * radius + 0.99999); kw = 2 * kr + 1; @@ -52,8 +61,6 @@ pipi_image_t *pipi_gaussian_blur(pipi_image_t const *src, float radius) for(i = -kr; i <= kr; i++) kernel[(j + kr) * kw + (i + kr)] /= t; - dst = pipi_new(w, h); - for(y = 0; y < h; y++) { for(x = 0; x < w; x++) @@ -63,15 +70,16 @@ pipi_image_t *pipi_gaussian_blur(pipi_image_t const *src, float radius) for(j = -kr; j <= kr; j++) for(i = -kr; i <= kr; i++) { - double r, g, b, f = kernel[(j + kr) * kw + (i + kr)]; + double f = kernel[(j + kr) * kw + (i + kr)]; - pipi_getpixel(src, x + i, y + j, &r, &g, &b); - R += f * r; - G += f * g; - B += f * b; + R += f * srcdata[((y + j) * w + x + i) * 4]; + G += f * srcdata[((y + j) * w + x + i) * 4 + 1]; + B += f * srcdata[((y + j) * w + x + i) * 4 + 2]; } - pipi_setpixel(dst, x, y, R, G, B); + dstdata[(y * w + x) * 4] = R; + dstdata[(y * w + x) * 4 + 1] = G; + dstdata[(y * w + x) * 4 + 2] = B; } } diff --git a/pipi/pipi.c b/pipi/pipi.c index e69de29..24d1aa8 100644 --- a/pipi/pipi.c +++ b/pipi/pipi.c @@ -0,0 +1,40 @@ +/* + * libpipi Proper image processing implementation library + * Copyright (c) 2004-2008 Sam Hocevar + * 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. + */ + +/* + * pipi.c: core library routines + */ + +#include "config.h" +#include "common.h" + +#include +#include +#include + +#include "pipi.h" +#include "pipi_internals.h" + +/* +static int init = 0; + +void _pipi_init(void) +{ + if(init) + return; + + _pipi_init_pixels(); +} +*/ + diff --git a/pipi/pipi.h b/pipi/pipi.h index b4f2303..58bbeb5 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -24,25 +24,42 @@ extern "C" { #endif +/* pipi_format_t: this enum is a list of all possible pixel formats for + * our internal images. RGBA32 is the most usual format when an image has + * just been loaded, but RGBA_F is a lot better for complex operations. */ +typedef enum +{ + PIPI_PIXELS_RGBA32 = 0, + PIPI_PIXELS_RGBA_F = 1, + + PIPI_PIXELS_MAX = 2 +} +pipi_format_t; + +/* pipi_pixels_t: this structure stores a pixel view of an image. */ +typedef struct +{ + void *pixels; + int w, h, pitch; +} +pipi_pixels_t; + +/* pipi_image_t: the main image type */ typedef struct pipi_image pipi_image_t; -extern pipi_image_t *pipi_load(const char *name); -extern pipi_image_t *pipi_new(int width, int height); -extern pipi_image_t *pipi_copy(const pipi_image_t *img); -extern void pipi_free(pipi_image_t *img); -extern void pipi_save(pipi_image_t *img, const char *name); -extern int pipi_getgray(pipi_image_t const *img, int x, int y, int *g); -extern int pipi_getpixel(pipi_image_t const *img, - int x, int y, double *r, double *g, double *b); -extern int pipi_setpixel(pipi_image_t *img, int x, int y, - double r, double g, double b); +extern pipi_image_t *pipi_load(const char *); +extern pipi_image_t *pipi_new(int, int); +extern void pipi_free(pipi_image_t *); +extern void pipi_save(pipi_image_t *, const char *); + +extern pipi_pixels_t *pipi_getpixels(pipi_image_t *, pipi_format_t); -extern pipi_image_t *pipi_resize(pipi_image_t const *, int, int); +extern pipi_image_t *pipi_resize(pipi_image_t *, int, int); -extern pipi_image_t *pipi_gaussian_blur(pipi_image_t const *, float); +extern pipi_image_t *pipi_gaussian_blur(pipi_image_t *, float); -extern void pipi_dither_24to16(pipi_image_t *img); +extern void pipi_dither_24to16(pipi_image_t *); extern void pipi_test(pipi_image_t *); diff --git a/pipi/pipi_internals.h b/pipi/pipi_internals.h index bc0fd77..f5165d1 100644 --- a/pipi/pipi_internals.h +++ b/pipi/pipi_internals.h @@ -16,14 +16,22 @@ * pipi_internals.h: internal types */ -#ifndef __CACA_INTERNALS_H__ -#define __CACA_INTERNALS_H__ +#ifndef __PIPI_INTERNALS_H__ +#define __PIPI_INTERNALS_H__ +/* pipi_image_t: the image structure. This is probably going to be the most + * complex structure in the library, but right now it only has fairly normal + * stuff, like width and height and pointers to pixel areas. */ struct pipi_image { - int width, height, pitch, channels; - unsigned char *pixels; - void *priv; + int w, h, pitch; + pipi_format_t codec_format, last_modified; + + /* List of all possible pixel formats */ + pipi_pixels_t p[PIPI_PIXELS_MAX]; + + /* Private data used by the codec */ + void *codec_priv; }; #ifdef USE_IMLIB2 diff --git a/pipi/pixels.c b/pipi/pixels.c index 257be69..2af8ef6 100644 --- a/pipi/pixels.c +++ b/pipi/pixels.c @@ -31,52 +31,68 @@ #define C2I(p) (pow(((double)p)/255., 2.2)) #define I2C(p) ((int)255.999*pow(((double)p), 1./2.2)) -int pipi_getgray(pipi_image_t const *img, int x, int y, int *g) +/* Return a direct pointer to an image's pixels. */ +pipi_pixels_t *pipi_getpixels(pipi_image_t *img, pipi_format_t type) { - if(x < 0 || y < 0 || x >= img->width || y >= img->height) - { - *g = 255; - return -1; - } - - *g = (unsigned char)img->pixels[y * img->pitch + x * img->channels + 1]; + size_t bytes = 0; + int x, y, i; - return 0; -} - -int pipi_getpixel(pipi_image_t const *img, - int x, int y, double *r, double *g, double *b) -{ - uint8_t *pixel; + if(type < 0 || type >= PIPI_PIXELS_MAX) + return NULL; - if(x < 0) x = 0; - else if(x >= img->width) x = img->width - 1; - - if(y < 0) y = 0; - else if(y >= img->height) y = img->height - 1; - - pixel = img->pixels + y * img->pitch + x * img->channels; - - *b = C2I((unsigned char)pixel[0]); - *g = C2I((unsigned char)pixel[1]); - *r = C2I((unsigned char)pixel[2]); - - return 0; -} + if(img->last_modified == type) + return &img->p[type]; -int pipi_setpixel(pipi_image_t *img, int x, int y, double r, double g, double b) -{ - uint8_t *pixel; - - if(x < 0 || y < 0 || x >= img->width || y >= img->height) - return -1; + /* Allocate pixels if necessary */ + if(!img->p[type].pixels) + { + switch(type) + { + case PIPI_PIXELS_RGBA32: + bytes = img->w * img->h * 4 * sizeof(uint8_t); + break; + case PIPI_PIXELS_RGBA_F: + bytes = img->w * img->h * 4 * sizeof(float); + break; + default: + return NULL; + } + + img->p[type].pixels = malloc(bytes); + } - pixel = img->pixels + y * img->pitch + x * img->channels; + /* Convert pixels */ + if(img->last_modified == PIPI_PIXELS_RGBA32 + && type == PIPI_PIXELS_RGBA_F) + { + uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA32].pixels; + float *dest = (float *)img->p[type].pixels; + + for(y = 0; y < img->h; y++) + for(x = 0; x < img->w; x++) + for(i = 0; i < 4; i++) + dest[4 * (y * img->w + x) + i] + = C2I(src[4 * (y * img->w + x) + i]); + } + else if(img->last_modified == PIPI_PIXELS_RGBA_F + && type == PIPI_PIXELS_RGBA32) + { + float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels; + uint8_t *dest = (uint8_t *)img->p[type].pixels; + + for(y = 0; y < img->h; y++) + for(x = 0; x < img->w; x++) + for(i = 0; i < 4; i++) + dest[4 * (y * img->w + x) + i] + = I2C(src[4 * (y * img->w + x) + i]); + } + else + { + memset(img->p[type].pixels, 0, bytes); + } - pixel[0] = I2C(b); - pixel[1] = I2C(g); - pixel[2] = I2C(r); + img->last_modified = type; - return 0; + return &img->p[type]; } diff --git a/pipi/resize.c b/pipi/resize.c index 2cc1ea4..bfdc3c6 100644 --- a/pipi/resize.c +++ b/pipi/resize.c @@ -25,46 +25,54 @@ #include "pipi.h" #include "pipi_internals.h" -pipi_image_t *pipi_resize(pipi_image_t const *src, int w, int h) +pipi_image_t *pipi_resize(pipi_image_t *src, int w, int h) { - double *aline, *line; + float *srcdata, *dstdata, *aline, *line; pipi_image_t *dst; + pipi_pixels_t *srcp, *dstp; int x, y, x0, y0, sw, dw, sh, dh, remy; + srcp = pipi_getpixels(src, PIPI_PIXELS_RGBA_F); + srcdata = (float *)srcp->pixels; + dst = pipi_new(w, h); + dstp = pipi_getpixels(dst, PIPI_PIXELS_RGBA_F); + dstdata = (float *)dstp->pixels; - sw = src->width; sh = src->height; - dw = dst->width; dh = dst->height; + sw = src->w; sh = src->h; + dw = dst->w; dh = dst->h; - aline = malloc(3 * dw * sizeof(double)); - line = malloc(3 * dw * sizeof(double)); + aline = malloc(3 * dw * sizeof(float)); + line = malloc(3 * dw * sizeof(float)); - memset(line, 0, 3 * dw * sizeof(double)); + memset(line, 0, 3 * dw * sizeof(float)); remy = 0; - for(y = 0, y0 = 0; y < dst->height; y++) + for(y = 0, y0 = 0; y < dh; y++) { int toty = 0, ny; - memset(aline, 0, 3 * dw * sizeof(double)); + memset(aline, 0, 3 * dw * sizeof(float)); while(toty < sh) { if(remy == 0) { - double r = 0, g = 0, b = 0; + float r = 0, g = 0, b = 0; int remx = 0; - for(x = 0, x0 = 0; x < dst->width; x++) + for(x = 0, x0 = 0; x < dw; x++) { - double ar = 0, ag = 0, ab = 0; + float ar = 0, ag = 0, ab = 0; int totx = 0, nx; while(totx < sw) { if(remx == 0) { - pipi_getpixel(src, x0, y0, &r, &g, &b); + r = srcdata[(y0 * sw + x0) * 4]; + g = srcdata[(y0 * sw + x0) * 4 + 1]; + b = srcdata[(y0 * sw + x0) * 4 + 2]; x0++; remx = dw; } @@ -85,7 +93,7 @@ pipi_image_t *pipi_resize(pipi_image_t const *src, int w, int h) } ny = (toty + remy <= sh) ? remy : sh - toty; - for(x = 0; x < dst->width; x++) + for(x = 0; x < dw; x++) { aline[3 * x] += ny * line[3 * x]; aline[3 * x + 1] += ny * line[3 * x + 1]; @@ -95,11 +103,12 @@ pipi_image_t *pipi_resize(pipi_image_t const *src, int w, int h) remy -= ny; } - for(x = 0; x < dst->width; x++) - pipi_setpixel(dst, x, y, - aline[3 * x] / (sw * sh), - aline[3 * x + 1] / (sw * sh), - aline[3 * x + 2] / (sw * sh)); + for(x = 0; x < dw; x++) + { + dstdata[(y * dw + x) * 4] = aline[3 * x] / (sw * sh); + dstdata[(y * dw + x) * 4 + 1] = aline[3 * x + 1] / (sw * sh); + dstdata[(y * dw + x) * 4 + 2] = aline[3 * x + 2] / (sw * sh); + } } free(aline); diff --git a/pipi/test.c b/pipi/test.c index 9b150e3..5a45dfc 100644 --- a/pipi/test.c +++ b/pipi/test.c @@ -27,15 +27,23 @@ void pipi_test(pipi_image_t *img) { + pipi_pixels_t *pixels; + float *data; int x, y; - for(y = 0; y < img->height; y++) + pixels = pipi_getpixels(img, PIPI_PIXELS_RGBA_F); + data = (float *)pixels->pixels; + + for(y = 0; y < img->h; y++) { - for(x = 0; x < img->width; x++) + for(x = 0; x < img->w; x++) { double r = 0, g = 0, b = 0; - pipi_getpixel(img, x, y, &r, &g, &b); + r = data[(y * img->w + x) * 4]; + g = data[(y * img->w + x) * 4 + 1]; + b = data[(y * img->w + x) * 4 + 2]; + if(r + g + b == 0) r = g = b = 1. / 3; else if(r + g + b < 1.) @@ -53,7 +61,10 @@ void pipi_test(pipi_image_t *img) double d = (-1. - r + g + b) / 3; r += d; g -= d; b -= d; } - pipi_setpixel(img, x, y, r, g, b); + + data[(y * img->w + x) * 4] = r; + data[(y * img->w + x) * 4 + 1] = g; + data[(y * img->w + x) * 4 + 2] = b; } } }