Browse Source

image: reimplement most image merge operations (overlay, screen, etc.).

undefined
Sam Hocevar 10 years ago
parent
commit
6526c8c904
10 changed files with 173 additions and 609 deletions
  1. +0
    -5
      TODO
  2. +1
    -1
      src/Makefile.am
  3. +155
    -0
      src/image/combine.cpp
  4. +0
    -86
      src/image/combine/merge.cpp
  5. +0
    -123
      src/image/combine/minmax.cpp
  6. +0
    -221
      src/image/combine/mulscreen.cpp
  7. +0
    -173
      src/image/combine/subadd.cpp
  8. +13
    -0
      src/lol/image/image.h
  9. +1
    -0
      src/lolcore.vcxproj
  10. +3
    -0
      src/lolcore.vcxproj.filters

+ 0
- 5
TODO View File

@@ -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


+ 1
- 1
src/Makefile.am View File

@@ -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 \


+ 155
- 0
src/image/combine.cpp View File

@@ -0,0 +1,155 @@
//
// Lol Engine
//
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// 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<PixelFormat FORMAT, MergeMode MODE>
static Image GenericMerge(Image &src1, Image &src2, float alpha)
{
typedef typename PixelType<FORMAT>::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<FORMAT>();
pixel_t const *src2p = src2.Lock<FORMAT>();
pixel_t *dstp = dst.Lock<FORMAT>();

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<MergeMode MODE>
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<PixelFormat::Y_F32, MODE>(src1, src2, alpha);
else
return GenericMerge<PixelFormat::RGBA_F32, MODE>(src1, src2, alpha);

}

Image Image::Merge(Image &src1, Image &src2, float alpha)
{
return GenericMerge<MergeMode::Mix>(src1, src2, alpha);
}

Image Image::Mean(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Mix>(src1, src2, 0.5f);
}

Image Image::Min(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Min>(src1, src2, 0.0f);
}

Image Image::Max(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Max>(src1, src2, 0.0f);
}

Image Image::Overlay(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Overlay>(src1, src2, 0.0f);
}

Image Image::Screen(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Screen>(src1, src2, 0.0f);
}

Image Image::Divide(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Divide>(src1, src2, 0.0f);
}

Image Image::Multiply(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Multiply>(src1, src2, 0.0f);
}

Image Image::Add(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Add>(src1, src2, 0.0f);
}

Image Image::Sub(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Sub>(src1, src2, 0.0f);
}

Image Image::Difference(Image &src1, Image &src2)
{
return GenericMerge<MergeMode::Difference>(src1, src2, 0.0f);
}

} /* namespace lol */


+ 0
- 86
src/image/combine/merge.cpp View File

@@ -1,86 +0,0 @@
/*
* libpipi Pathetic image processing interface 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.
*/

/*
* mean.c: Mean computation function
*/

#include "config.h"

#include <stdlib.h>

#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);
}


+ 0
- 123
src/image/combine/minmax.cpp View File

@@ -1,123 +0,0 @@
/*
* libpipi Pathetic image processing interface 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.
*/

/*
* minmax.c: min and max computation functions
*/

#include "config.h"

#include <stdlib.h>

#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;
}


+ 0
- 221
src/image/combine/mulscreen.cpp View File

@@ -1,221 +0,0 @@
/*
* libpipi Pathetic image processing interface 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.
*/

/*
* mulscreen.c: multiply and screen computation functions
*/

#include "config.h"

#include <stdlib.h>

#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;
}


+ 0
- 173
src/image/combine/subadd.cpp View File

@@ -1,173 +0,0 @@
/*
* libpipi Pathetic image processing interface 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.
*/

/*
* subadd.c: sub, add and difference computation functions
*/

#include "config.h"

#include <stdlib.h>
#include <math.h>

#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;
}


+ 13
- 0
src/lol/image/image.h View File

@@ -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;
};


+ 1
- 0
src/lolcore.vcxproj View File

@@ -161,6 +161,7 @@
<ClCompile Include="image\dither\ostromoukhov.cpp" />
<ClCompile Include="image\dither\random.cpp" />
<ClCompile Include="image\crop.cpp" />
<ClCompile Include="image\combine.cpp" />
<ClCompile Include="image\image.cpp" />
<ClCompile Include="image\kernel.cpp" />
<ClCompile Include="image\noise.cpp" />


+ 3
- 0
src/lolcore.vcxproj.filters View File

@@ -309,6 +309,9 @@
<ClCompile Include="image\color\color.cpp">
<Filter>image\color</Filter>
</ClCompile>
<ClCompile Include="image\combine.cpp">
<Filter>image</Filter>
</ClCompile>
<ClCompile Include="math\geometry.cpp">
<Filter>math</Filter>
</ClCompile>


Loading…
Cancel
Save