/* * 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. */ /* * pixels.c: pixel-level image manipulation */ #include "config.h" #include "common.h" #include #include #include #include #include "pipi.h" #include "pipi_internals.h" #define GAMMA 2.2 static void init_tables(void); static float u8tof32_table[256]; static inline float u8tof32(uint8_t p) { return u8tof32_table[(int)p]; } /* Return a direct pointer to an image's pixels. */ pipi_pixels_t *pipi_getpixels(pipi_image_t *img, pipi_format_t type) { size_t bytes = 0; int x, y, i; if(type < 0 || type >= PIPI_PIXELS_MAX) return NULL; if(img->last_modified == type) return &img->p[type]; /* 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); } /* 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; init_tables(); 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] = u8tof32(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; init_tables(); for(y = 0; y < img->h; y++) for(x = 0; x < img->w; x++) for(i = 0; i < 4; i++) { double p, e; uint8_t d; p = src[4 * (y * img->w + x) + i]; d = (int)(255.999 * pow(p, 1. / GAMMA)); dest[4 * (y * img->w + x) + i] = d; e = p - u8tof32(d); if(x < img->w - 1) src[4 * (y * img->w + x + 1) + i] += e * .4375; if(y < img->h - 1) { if(x < img->w - 1) src[4 * ((y + 1) * img->w + x - 1) + i] += e * .1875; src[4 * ((y + 1) * img->w + x) + i] += e * .3125; if(x < img->w - 1) src[4 * ((y + 1) * img->w + x + 1) + i] += e * .0625; } } } else { memset(img->p[type].pixels, 0, bytes); } img->last_modified = type; return &img->p[type]; } static void init_tables(void) { static int done = 0; int i; if(done) return; for(i = 0; i < 256; i++) u8tof32_table[i] = pow((double)i / 255., GAMMA); done = 1; }