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
remotes/tiles
| @@ -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 | |||
| @@ -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); | |||
| } | |||
| @@ -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); | |||
| } | |||
| @@ -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); | |||
| } | |||
| @@ -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 | |||
| } | |||
| @@ -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; | |||
| } | |||
| } | |||
| @@ -0,0 +1,40 @@ | |||
| /* | |||
| * libpipi Proper image processing implementation library | |||
| * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org> | |||
| * 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 <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "pipi.h" | |||
| #include "pipi_internals.h" | |||
| /* | |||
| static int init = 0; | |||
| void _pipi_init(void) | |||
| { | |||
| if(init) | |||
| return; | |||
| _pipi_init_pixels(); | |||
| } | |||
| */ | |||
| @@ -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 *); | |||
| @@ -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 | |||
| @@ -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]; | |||
| } | |||
| @@ -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); | |||
| @@ -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; | |||
| } | |||
| } | |||
| } | |||