diff --git a/pipi/Makefile.am b/pipi/Makefile.am index d1bce5b..45b069f 100644 --- a/pipi/Makefile.am +++ b/pipi/Makefile.am @@ -81,7 +81,8 @@ filter_sources = \ filter/transform.c \ filter/median.c \ filter/dilate.c \ - filter/wave.c + filter/wave.c \ + filter/yuv.c quantize_sources = \ quantize/reduce.c diff --git a/pipi/context.c b/pipi/context.c index 2f07fe2..b312d12 100644 --- a/pipi/context.c +++ b/pipi/context.c @@ -94,6 +94,8 @@ pipi_command_t const *pipi_get_command_list(void) { "line", 1 }, { "sine", 1 }, { "wave", 1 }, + { "rgb2yuv", 0 }, + { "yuv2rgb", 0 }, /* End marker */ { NULL, 0 } @@ -708,6 +710,22 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) pipi_free(src); ctx->images[ctx->nimages - 1] = dst; } + else if(!strcmp(cmd, "rgb2yuv") || !strcmp(cmd, "yuv2rgb")) + { + pipi_image_t *src, *dst = NULL; + if(ctx->nimages < 1) + return -1; + src = ctx->images[ctx->nimages - 1]; + switch (cmd[0]) + { + case 'r': dst = pipi_rgb2yuv(src); break; + case 'y': dst = pipi_yuv2rgb(src); break; + } + if(dst == NULL) + return -1; + pipi_free(src); + ctx->images[ctx->nimages - 1] = dst; + } else { return -1; diff --git a/pipi/filter/yuv.c b/pipi/filter/yuv.c new file mode 100644 index 0000000..273e84d --- /dev/null +++ b/pipi/filter/yuv.c @@ -0,0 +1,124 @@ +/* + * libpipi Pathetic image processing interface 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. + */ + +/* + * yuv.c: YUV conversion functions + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "pipi.h" +#include "pipi_internals.h" + +pipi_image_t *pipi_rgb2yuv(pipi_image_t *src) +{ + pipi_image_t *dst; + pipi_pixels_t *srcp, *dstp; + float *srcdata, *dstdata; + int x, y, w, h, gray; + + w = src->w; + h = src->h; + + 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; + + for(y = 0; y < h; y++) + { + for(x = 0; x < w; x++) + { + double r, g, b, a, yp, u, v; + int d = 4 * (y * w + x); + + r = srcdata[d]; + g = srcdata[d + 1]; + b = srcdata[d + 2]; + a = srcdata[d + 3]; + + yp = 0.299 * r + 0.587 * g + 0.114 * b; + u = 0.5 - 0.14713 * r - 0.28886 * g + 0.436 * b; + if (u < 0.0) u = 0.0; + if (u > 1.0) u = 1.0; + v = 0.5 + 0.615 * r - 0.51499 * g - 0.10001 * b; + if (v < 0.0) v = 0.0; + if (v > 1.0) v = 1.0; + + dstdata[d] = v; + dstdata[d + 1] = yp; + dstdata[d + 2] = u; + dstdata[d + 3] = a; + } + } + + return dst; +} + +pipi_image_t *pipi_yuv2rgb(pipi_image_t *src) +{ + pipi_image_t *dst; + pipi_pixels_t *srcp, *dstp; + float *srcdata, *dstdata; + int x, y, w, h, gray; + + w = src->w; + h = src->h; + + 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; + + for(y = 0; y < h; y++) + { + for(x = 0; x < w; x++) + { + double r, g, b, a, yp, u, v; + int d = 4 * (y * w + x); + + v = srcdata[d] - 0.5; + yp = srcdata[d + 1]; + u = srcdata[d + 2] - 0.5; + a = srcdata[d + 3]; + + r = yp + 1.13983 * v; + if (r < 0.0) r = 0.0; + if (r > 1.0) r = 1.0; + g = yp - 0.39465 * u - 0.58060 * v; + if (g < 0.0) g = 0.0; + if (g > 1.0) g = 1.0; + b = yp + 2.03211 * u; + if (b < 0.0) b = 0.0; + if (b > 1.0) b = 1.0; + + dstdata[d] = r; + dstdata[d + 1] = g; + dstdata[d + 2] = b; + dstdata[d + 3] = a; + } + } + + return dst; +} + diff --git a/pipi/pipi.h b/pipi/pipi.h index 25881d2..3b6485e 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -209,6 +209,8 @@ __extern pipi_image_t *pipi_sine(pipi_image_t *, double, double, double, double); __extern pipi_image_t *pipi_wave(pipi_image_t *, double, double, double, double); +__extern pipi_image_t *pipi_rgb2yuv(pipi_image_t *); +__extern pipi_image_t *pipi_yuv2rgb(pipi_image_t *); __extern pipi_image_t *pipi_order(pipi_image_t *);