| @@ -18,17 +18,12 @@ Image: | |||||
| - Add gamma handling in pixels.cpp | - Add gamma handling in pixels.cpp | ||||
| - Make some Image::Lock2D method that returns an Array2D | - Make some Image::Lock2D method that returns an Array2D | ||||
| - port libpipi files: | - port libpipi files: | ||||
| · analysis/histogram.cpp | |||||
| · analysis/measure.cpp | · analysis/measure.cpp | ||||
| · codec/coreimage.cpp | · codec/coreimage.cpp | ||||
| · codec/coreimage.h | · codec/coreimage.h | ||||
| · codec/jpeg.cpp | · codec/jpeg.cpp | ||||
| · combine/blit.cpp | · combine/blit.cpp | ||||
| · combine/merge.cpp | |||||
| · combine/minmax.cpp | |||||
| · combine/mulscreen.cpp | |||||
| · combine/rgb.cpp | · combine/rgb.cpp | ||||
| · combine/subadd.cpp | |||||
| · context.cpp | · context.cpp | ||||
| · filter/blur.cpp | · filter/blur.cpp | ||||
| · filter/rotate.cpp | · filter/rotate.cpp | ||||
| @@ -111,7 +111,7 @@ liblolcore_sources = \ | |||||
| sys/thread.cpp sys/threadbase.h \ | sys/thread.cpp sys/threadbase.h \ | ||||
| \ | \ | ||||
| image/image.cpp image/image-private.h image/kernel.cpp image/pixel.cpp \ | 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/gdiplus-image.cpp image/codec/imlib2-image.cpp \ | ||||
| image/codec/sdl-image.cpp image/codec/ios-image.cpp \ | image/codec/sdl-image.cpp image/codec/ios-image.cpp \ | ||||
| image/codec/zed-image.cpp image/codec/zed-palette-image.cpp \ | image/codec/zed-image.cpp image/codec/zed-palette-image.cpp \ | ||||
| @@ -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 */ | |||||
| @@ -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); | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| @@ -134,6 +134,19 @@ public: | |||||
| Image DitherHalftone(float radius, float angle) const; | Image DitherHalftone(float radius, float angle) const; | ||||
| Image DitherDbs() 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: | private: | ||||
| class ImageData *m_data; | class ImageData *m_data; | ||||
| }; | }; | ||||
| @@ -161,6 +161,7 @@ | |||||
| <ClCompile Include="image\dither\ostromoukhov.cpp" /> | <ClCompile Include="image\dither\ostromoukhov.cpp" /> | ||||
| <ClCompile Include="image\dither\random.cpp" /> | <ClCompile Include="image\dither\random.cpp" /> | ||||
| <ClCompile Include="image\crop.cpp" /> | <ClCompile Include="image\crop.cpp" /> | ||||
| <ClCompile Include="image\combine.cpp" /> | |||||
| <ClCompile Include="image\image.cpp" /> | <ClCompile Include="image\image.cpp" /> | ||||
| <ClCompile Include="image\kernel.cpp" /> | <ClCompile Include="image\kernel.cpp" /> | ||||
| <ClCompile Include="image\noise.cpp" /> | <ClCompile Include="image\noise.cpp" /> | ||||
| @@ -309,6 +309,9 @@ | |||||
| <ClCompile Include="image\color\color.cpp"> | <ClCompile Include="image\color\color.cpp"> | ||||
| <Filter>image\color</Filter> | <Filter>image\color</Filter> | ||||
| </ClCompile> | </ClCompile> | ||||
| <ClCompile Include="image\combine.cpp"> | |||||
| <Filter>image</Filter> | |||||
| </ClCompile> | |||||
| <ClCompile Include="math\geometry.cpp"> | <ClCompile Include="math\geometry.cpp"> | ||||
| <Filter>math</Filter> | <Filter>math</Filter> | ||||
| </ClCompile> | </ClCompile> | ||||