From 6526c8c9040afda6c319d8e932bf0c2cc523b8ac Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Thu, 26 Jun 2014 20:20:54 +0000 Subject: [PATCH] image: reimplement most image merge operations (overlay, screen, etc.). --- TODO | 5 - src/Makefile.am | 2 +- src/image/combine.cpp | 155 ++++++++++++++++++++++ src/image/combine/merge.cpp | 86 ------------- src/image/combine/minmax.cpp | 123 ------------------ src/image/combine/mulscreen.cpp | 221 -------------------------------- src/image/combine/subadd.cpp | 173 ------------------------- src/lol/image/image.h | 13 ++ src/lolcore.vcxproj | 1 + src/lolcore.vcxproj.filters | 3 + 10 files changed, 173 insertions(+), 609 deletions(-) create mode 100644 src/image/combine.cpp delete mode 100644 src/image/combine/merge.cpp delete mode 100644 src/image/combine/minmax.cpp delete mode 100644 src/image/combine/mulscreen.cpp delete mode 100644 src/image/combine/subadd.cpp diff --git a/TODO b/TODO index 1bd67595..a0d789fb 100644 --- a/TODO +++ b/TODO @@ -18,17 +18,12 @@ Image: - Add gamma handling in pixels.cpp - Make some Image::Lock2D method that returns an Array2D - port libpipi files: - · analysis/histogram.cpp · analysis/measure.cpp · codec/coreimage.cpp · codec/coreimage.h · codec/jpeg.cpp · combine/blit.cpp - · combine/merge.cpp - · combine/minmax.cpp - · combine/mulscreen.cpp · combine/rgb.cpp - · combine/subadd.cpp · context.cpp · filter/blur.cpp · filter/rotate.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 0e448a5c..cd7fb243 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,7 +111,7 @@ liblolcore_sources = \ sys/thread.cpp sys/threadbase.h \ \ image/image.cpp image/image-private.h image/kernel.cpp image/pixel.cpp \ - image/crop.cpp image/resample.cpp image/noise.cpp \ + image/crop.cpp image/resample.cpp image/noise.cpp image/combine.cpp \ image/codec/gdiplus-image.cpp image/codec/imlib2-image.cpp \ image/codec/sdl-image.cpp image/codec/ios-image.cpp \ image/codec/zed-image.cpp image/codec/zed-palette-image.cpp \ diff --git a/src/image/combine.cpp b/src/image/combine.cpp new file mode 100644 index 00000000..3c3fc73c --- /dev/null +++ b/src/image/combine.cpp @@ -0,0 +1,155 @@ +// +// Lol Engine +// +// Copyright: (c) 2004-2014 Sam Hocevar +// This program is free software; 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://www.wtfpl.net/ for more details. +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include "core.h" + +/* + * Image merge operations: merge, min/max, overlay, screen, multiply, + * divide, add, sub, difference + */ + +namespace lol +{ + +enum class MergeMode +{ + Mix, + Min, + Max, + Overlay, + Screen, + Divide, + Multiply, + Add, + Sub, + Difference, +}; + +template +static Image GenericMerge(Image &src1, Image &src2, float alpha) +{ + typedef typename PixelType::type pixel_t; + + ASSERT(src1.GetSize() == src2.GetSize()); + int const count = src1.GetSize().x * src2.GetSize().y; + + Image dst(src1.GetSize()); + + pixel_t const *src1p = src1.Lock(); + pixel_t const *src2p = src2.Lock(); + pixel_t *dstp = dst.Lock(); + + for (int n = 0; n < count; ++n) + { + if (MODE == MergeMode::Mix) + dstp[n] = lol::mix(src1p[n], src2p[n], alpha); + else if (MODE == MergeMode::Min) + dstp[n] = lol::min(src1p[n], src2p[n]); + else if (MODE == MergeMode::Max) + dstp[n] = lol::max(src1p[n], src2p[n]); + else if (MODE == MergeMode::Overlay) + dstp[n] = src1p[n] * (src1p[n] + 2.f * src2p[n] + * (pixel_t(1.f) - src1p[n])); + else if (MODE == MergeMode::Screen) + dstp[n] = src1p[n] + src2p[n] - src1p[n] * src2p[n]; + else if (MODE == MergeMode::Divide) + dstp[n] = src1p[n] / (lol::max(src1p[n], src2p[n]) + pixel_t(1e-8f)); + else if (MODE == MergeMode::Multiply) + dstp[n] = src1p[n] * src2p[n]; + else if (MODE == MergeMode::Add) + dstp[n] = lol::min(src1p[n] + src2p[n], pixel_t(1.f)); + else if (MODE == MergeMode::Sub) + dstp[n] = lol::max(src1p[n] - src2p[n], pixel_t(0.f)); + else if (MODE == MergeMode::Difference) + dstp[n] = lol::abs(src1p[n] - src2p[n]); + } + + src1.Unlock(src1p); + src2.Unlock(src2p); + dst.Unlock(dstp); + + return dst; +} + +template +static Image GenericMerge(Image &src1, Image &src2, float alpha) +{ + bool gray1 = src1.GetFormat() == PixelFormat::Y_8 + || src1.GetFormat() == PixelFormat::Y_F32; + bool gray2 = src2.GetFormat() == PixelFormat::Y_8 + || src2.GetFormat() == PixelFormat::Y_F32; + if (gray1 && gray2) + return GenericMerge(src1, src2, alpha); + else + return GenericMerge(src1, src2, alpha); + +} + +Image Image::Merge(Image &src1, Image &src2, float alpha) +{ + return GenericMerge(src1, src2, alpha); +} + +Image Image::Mean(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.5f); +} + +Image Image::Min(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Max(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Overlay(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Screen(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Divide(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Multiply(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Add(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Sub(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +Image Image::Difference(Image &src1, Image &src2) +{ + return GenericMerge(src1, src2, 0.0f); +} + +} /* namespace lol */ + diff --git a/src/image/combine/merge.cpp b/src/image/combine/merge.cpp deleted file mode 100644 index beeab483..00000000 --- a/src/image/combine/merge.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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. - */ - -/* - * mean.c: Mean computation function - */ - -#include "config.h" - -#include - -#include "pipi.h" -#include "pipi-internals.h" - -pipi_image_t *pipi_merge(pipi_image_t *img1, pipi_image_t *img2, double t) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - if(t < 0.0) - t = 0.0; - else if(t > 1.0) - t = 1.0; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - double t1 = t * img2data[4 * (y * w + x) + 3]; - double t2 = 1.0 - t1; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = t2 * p + t1 * q; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = t2 * p + t1 * q; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = t2 * p + t1 * q; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = t2 * p + t1 * q; - } - } - - return dst; -} - -pipi_image_t *pipi_mean(pipi_image_t *img1, pipi_image_t *img2) -{ - return pipi_merge(img1, img2, 0.5); -} - diff --git a/src/image/combine/minmax.cpp b/src/image/combine/minmax.cpp deleted file mode 100644 index 780c03a4..00000000 --- a/src/image/combine/minmax.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -/* - * minmax.c: min and max computation functions - */ - -#include "config.h" - -#include - -#include "pipi.h" -#include "pipi-internals.h" - -pipi_image_t *pipi_min(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = p < q ? p : q; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = p < q ? p : q; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = p < q ? p : q; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = p < q ? p : q; - } - } - - return dst; -} - -pipi_image_t *pipi_max(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = p > q ? p : q; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = p > q ? p : q; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = p > q ? p : q; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = p > q ? p : q; - } - } - - return dst; -} - diff --git a/src/image/combine/mulscreen.cpp b/src/image/combine/mulscreen.cpp deleted file mode 100644 index d50e8ccc..00000000 --- a/src/image/combine/mulscreen.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* - * 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. - */ - -/* - * mulscreen.c: multiply and screen computation functions - */ - -#include "config.h" - -#include - -#include "pipi.h" -#include "pipi-internals.h" - -pipi_image_t *pipi_multiply(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = p * q; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = p * q; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = p * q; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = p * q; - } - } - - return dst; -} - -pipi_image_t *pipi_divide(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = p >= q ? 1. : p / q; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = p >= q ? 1. : p / q; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = p >= q ? 1. : p / q; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = p >= q ? 1. : p / q; - } - } - - return dst; -} - -pipi_image_t *pipi_screen(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = p + q - p * q; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = p + q - p * q; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = p + q - p * q; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = p + q - p * q; - } - } - - return dst; -} - -pipi_image_t *pipi_overlay(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = p * (p + 2. * q * (1. - p)); - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = p * (p + 2. * q * (1. - p)); - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = p * (p + 2. * q * (1. - p)); - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = p * (p + 2. * q * (1. - p)); - } - } - - return dst; -} - diff --git a/src/image/combine/subadd.cpp b/src/image/combine/subadd.cpp deleted file mode 100644 index f3e07786..00000000 --- a/src/image/combine/subadd.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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. - */ - -/* - * subadd.c: sub, add and difference computation functions - */ - -#include "config.h" - -#include -#include - -#include "pipi.h" -#include "pipi-internals.h" - -pipi_image_t *pipi_add(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = (p + q < 1.) ? p + q : 1.; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = (p + q < 1.) ? p + q : 1.; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = (p + q < 1.) ? p + q : 1.; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = (p + q < 1.) ? p + q : 1.; - } - } - - return dst; -} - -pipi_image_t *pipi_sub(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = p < q ? 0 : p - q; - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = p < q ? 0 : p - q; - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = p < q ? 0 : p - q; - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = p < q ? 0 : p - q; - } - } - - return dst; -} - -pipi_image_t *pipi_difference(pipi_image_t *img1, pipi_image_t *img2) -{ - pipi_image_t *dst; - pipi_pixels_t *img1p, *img2p, *dstp; - float *img1data, *img2data, *dstdata; - int x, y, w, h; - - if(img1->w != img2->w || img1->h != img2->h) - return NULL; - - w = img1->w; - h = img1->h; - - dst = pipi_new(w, h); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); - dstdata = (float *)dstp->pixels; - - img1p = pipi_get_pixels(img1, PIPI_PIXELS_RGBA_F32); - img1data = (float *)img1p->pixels; - img2p = pipi_get_pixels(img2, PIPI_PIXELS_RGBA_F32); - img2data = (float *)img2p->pixels; - - for(y = 0; y < h; y++) - { - for(x = 0; x < w; x++) - { - float p, q; - - p = img1data[4 * (y * w + x)]; - q = img2data[4 * (y * w + x)]; - dstdata[4 * (y * w + x)] = fabsf(p - q); - - p = img1data[4 * (y * w + x) + 1]; - q = img2data[4 * (y * w + x) + 1]; - dstdata[4 * (y * w + x) + 1] = fabsf(p - q); - - p = img1data[4 * (y * w + x) + 2]; - q = img2data[4 * (y * w + x) + 2]; - dstdata[4 * (y * w + x) + 2] = fabsf(p - q); - - p = img1data[4 * (y * w + x) + 3]; - q = img2data[4 * (y * w + x) + 3]; - dstdata[4 * (y * w + x) + 3] = fabsf(p - q); - } - } - - return dst; -} - diff --git a/src/lol/image/image.h b/src/lol/image/image.h index f63c63ee..28bfab0f 100644 --- a/src/lol/image/image.h +++ b/src/lol/image/image.h @@ -134,6 +134,19 @@ public: Image DitherHalftone(float radius, float angle) const; Image DitherDbs() const; + /* Combine images */ + static Image Merge(Image &src1, Image &src2, float alpha); + static Image Mean(Image &src1, Image &src2); + static Image Min(Image &src1, Image &src2); + static Image Max(Image &src1, Image &src2); + static Image Overlay(Image &src1, Image &src2); + static Image Screen(Image &src1, Image &src2); + static Image Multiply(Image &src1, Image &src2); + static Image Divide(Image &src1, Image &src2); + static Image Add(Image &src1, Image &src2); + static Image Sub(Image &src1, Image &src2); + static Image Difference(Image &src1, Image &src2); + private: class ImageData *m_data; }; diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index ec7f5edd..be86a707 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -161,6 +161,7 @@ + diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters index 5eed2457..659ae78b 100644 --- a/src/lolcore.vcxproj.filters +++ b/src/lolcore.vcxproj.filters @@ -309,6 +309,9 @@ image\color + + image + math