|
- //
- // 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 <lol/main.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 */
|