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-862c8a59935fremotes/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; | |||
} | |||
} | |||
} | |||