From 1dc1c0583a268bdca3e9a8c5946c630fbfdbf446 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Tue, 17 Jun 2014 15:14:26 +0000 Subject: [PATCH] image: port some error diffusion dithering algorithms. --- TODO | 11 +- src/Makefile.am | 2 + src/image/dither/ediff.cpp | 100 +++++++++--------- src/image/dither/ostromoukhov.cpp | 169 +++++++++++++++--------------- src/image/dither/random.cpp | 74 +++++-------- src/image/image-private.h | 7 +- src/image/image.cpp | 19 +++- src/image/pixels.cpp | 31 +++--- src/image/stock.cpp | 24 ++--- src/lol/image/image.h | 21 +++- 10 files changed, 241 insertions(+), 217 deletions(-) diff --git a/TODO b/TODO index 736427ff..5bc77884 100644 --- a/TODO +++ b/TODO @@ -2,12 +2,16 @@ Large projects ---------------- - - Add scripting support (lua?). - - Tiler and Forge are almost the same, try to refactor them. + - Add scripting support (lua?). + - Tiler and Forge are almost the same, try to refactor them. Engine classes ---------------- +Scene: + - Remove uses of g_scene + - Maybe make Camera a world object instead? + Image: - Handle pitch in SDL codec (and all others, actually) - Fix the Floyd-Steinberg ode in pixels.cpp @@ -31,10 +35,7 @@ Image: · crop.cpp · dither.cpp · dither/dbs.cpp - · dither/ediff.cpp · dither/ordered.cpp - · dither/ostromoukhov.cpp - · dither/random.cpp · filter/blur.cpp · filter/color.cpp · filter/convolution.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 508a6ca3..3226004a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -116,6 +116,8 @@ liblolcore_sources = \ image/codec/zed-image.cpp image/codec/zed-palette-image.cpp \ image/codec/dummy-image.cpp \ image/color/cie1931.cpp image/color/color.cpp \ + image/dither/random.cpp image/dither/ediff.cpp \ + image/dither/ostromoukhov.cpp \ image/filter/autocontrast.cpp \ image/render/noise.cpp image/render/screen.cpp \ \ diff --git a/src/image/dither/ediff.cpp b/src/image/dither/ediff.cpp index efd259c1..e4bbecb8 100644 --- a/src/image/dither/ediff.cpp +++ b/src/image/dither/ediff.cpp @@ -1,25 +1,25 @@ -/* - * 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. - */ +// +// 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" /* - * ed.c: generic error diffusion functions + * Generic error diffusion functions */ -#include "config.h" - -#include "pipi.h" -#include "pipi-internals.h" +namespace lol +{ /* Perform a generic error diffusion dithering. The first non-zero * element in ker is treated as the current pixel. All other non-zero @@ -27,60 +27,58 @@ * Making the matrix generic is not terribly slower: the performance * hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the * benefit of a lot less code. */ -pipi_image_t *pipi_dither_ediff(pipi_image_t *img, pipi_image_t *ker, - pipi_scan_t scan) +Image Image::DitherEdiff(Image &kernel, ScanMode scan) const { - pipi_image_t *dst; - pipi_pixels_t *dstp, *kerp; - float *dstdata, *kerdata; - int x, y, w, h, i, j, kx, kw, kh; - - w = img->w; - h = img->h; - kw = ker->w; - kh = ker->h; - - dst = pipi_copy(img); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_Y_F32); - dstdata = (float *)dstp->pixels; - - kerp = pipi_get_pixels(ker, PIPI_PIXELS_Y_F32); - kerdata = (float *)kerp->pixels; - for(kx = 0; kx < kw; kx++) - if(kerdata[kx] > 0) + Image dst = *this; + + float *pixels = dst.Lock(); + int w = dst.GetSize().x; + int h = dst.GetSize().y; + + float *kerdata = kernel.Lock(); + int kw = kernel.GetSize().x; + int kh = kernel.GetSize().y; + + int kx; + for (kx = 0; kx < kw; kx++) + if (kerdata[kx] > 0.f) break; - for(y = 0; y < h; y++) + for (int y = 0; y < h; y++) { - int reverse = (y & 1) && (scan == PIPI_SCAN_SERPENTINE); + bool reverse = (y & 1) && (scan == ScanMode::Serpentine); - for(x = 0; x < w; x++) + for (int x = 0; x < w; x++) { - float p, q, e; int x2 = reverse ? w - 1 - x : x; int s = reverse ? -1 : 1; - p = dstdata[y * w + x2]; - q = p < 0.5 ? 0. : 1.; - dstdata[y * w + x2] = q; + float p = pixels[y * w + x2]; + float q = p < 0.5f ? 0.f : 1.f; + pixels[y * w + x2] = q; - e = (p - q); + float e = (p - q); - for(j = 0; j < kh && y < h - j; j++) - for(i = 0; i < kw; i++) + for (int j = 0; j < kh && y < h - j; j++) + for (int i = 0; i < kw; i++) { - if(j == 0 && i <= kx) + if (j == 0 && i <= kx) continue; - if(x + i - kx < 0 || x + i - kx >= w) + if (x + i - kx < 0 || x + i - kx >= w) continue; - dstdata[(y + j) * w + x2 + (i - kx) * s] + pixels[(y + j) * w + x2 + (i - kx) * s] += e * kerdata[j * kw + i]; } } } + kernel.Unlock(kerdata); + dst.Unlock(pixels); + return dst; } +} /* namespace lol */ + diff --git a/src/image/dither/ostromoukhov.cpp b/src/image/dither/ostromoukhov.cpp index a921addc..970dfec5 100644 --- a/src/image/dither/ostromoukhov.cpp +++ b/src/image/dither/ostromoukhov.cpp @@ -1,117 +1,116 @@ -/* - * 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. - */ +// +// 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" /* - * ostromoukhov.c: Ostromoukhov dithering functions + * Ostromoukhov dithering functions * * This module implements Ostromoukhov's simple error diffusion algorithm, * as introduced in the paper "A Simple and Efficient Error-Diffusion * Algorithm", Proceedings of SIGGRAPH 2001, in ACM Computer Graphics, * Annual Conference Series, pp. 567--572, 2001. * - * TODO: the table is actually a piecewise linear function, so it should - * be easy to change it into something that works perfectly with floats. + * Note: the authors initially provided a large data table, but we + * manually converted it to a piecewise linear function. */ -#include "config.h" - -#include "pipi.h" -#include "pipi-internals.h" - -static int const table[][3] = +namespace lol { - {13, 0, 5}, {13, 0, 5}, {21, 0, 10}, {7, 0, 4}, - {8, 0, 5}, {47, 3, 28}, {23, 3, 13}, {15, 3, 8}, - {22, 6, 11}, {43, 15, 20}, {7, 3, 3}, {501, 224, 211}, - {249, 116, 103}, {165, 80, 67}, {123, 62, 49}, {489, 256, 191}, - {81, 44, 31}, {483, 272, 181}, {60, 35, 22}, {53, 32, 19}, - {237, 148, 83}, {471, 304, 161}, {3, 2, 1}, {481, 314, 185}, - {354, 226, 155}, {1389, 866, 685}, {227, 138, 125}, {267, 158, 163}, - {327, 188, 220}, {61, 34, 45}, {627, 338, 505}, {1227, 638, 1075}, - {20, 10, 19}, {1937, 1000, 1767}, {977, 520, 855}, {657, 360, 551}, - {71, 40, 57}, {2005, 1160, 1539}, {337, 200, 247}, {2039, 1240, 1425}, - {257, 160, 171}, {691, 440, 437}, {1045, 680, 627}, {301, 200, 171}, - {177, 120, 95}, {2141, 1480, 1083}, {1079, 760, 513}, {725, 520, 323}, - {137, 100, 57}, {2209, 1640, 855}, {53, 40, 19}, {2243, 1720, 741}, - {565, 440, 171}, {759, 600, 209}, {1147, 920, 285}, {2311, 1880, 513}, - {97, 80, 19}, {335, 280, 57}, {1181, 1000, 171}, {793, 680, 95}, - {599, 520, 57}, {2413, 2120, 171}, {405, 360, 19}, {2447, 2200, 57}, - {11, 10, 0}, {158, 151, 3}, {178, 179, 7}, {1030, 1091, 63}, - {248, 277, 21}, {318, 375, 35}, {458, 571, 63}, {878, 1159, 147}, - {5, 7, 1}, {172, 181, 37}, {97, 76, 22}, {72, 41, 17}, - {119, 47, 29}, {4, 1, 1}, {4, 1, 1}, {4, 1, 1}, - {4, 1, 1}, {4, 1, 1}, {4, 1, 1}, {4, 1, 1}, - {4, 1, 1}, {4, 1, 1}, {65, 18, 17}, {95, 29, 26}, - {185, 62, 53}, {30, 11, 9}, {35, 14, 11}, {85, 37, 28}, - {55, 26, 19}, {80, 41, 29}, {155, 86, 59}, {5, 3, 2}, - {5, 3, 2}, {5, 3, 2}, {5, 3, 2}, {5, 3, 2}, - {5, 3, 2}, {5, 3, 2}, {5, 3, 2}, {5, 3, 2}, - {5, 3, 2}, {5, 3, 2}, {5, 3, 2}, {5, 3, 2}, - {305, 176, 119}, {155, 86, 59}, {105, 56, 39}, {80, 41, 29}, - {65, 32, 23}, {55, 26, 19}, {335, 152, 113}, {85, 37, 28}, - {115, 48, 37}, {35, 14, 11}, {355, 136, 109}, {30, 11, 9}, - {365, 128, 107}, {185, 62, 53}, {25, 8, 7}, {95, 29, 26}, - {385, 112, 103}, {65, 18, 17}, {395, 104, 101}, {4, 1, 1} -}; - -pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *img, pipi_scan_t scan) + +static inline vec3 GetDiffusion(float v) { - pipi_image_t *dst; - pipi_pixels_t *dstp; - float *dstdata; - int x, y, w, h; + static vec3 const table[] = + { + vec3(0.0000f, 0.2777f, 0.0000f), + vec3(0.0039f, 0.2777f, 0.0000f), + vec3(0.0117f, 0.3636f, 0.0000f), + vec3(0.0157f, 0.3846f, 0.0000f), + vec3(0.0392f, 0.2308f, 0.2308f), + vec3(0.0863f, 0.1667f, 0.3333f), + vec3(0.1255f, 0.3878f, 0.2041f), + vec3(0.2510f, 0.0000f, 0.4762f), + vec3(0.2824f, 0.0769f, 0.5385f), + vec3(0.3020f, 0.1667f, 0.1667f), + vec3(0.3333f, 0.1667f, 0.1667f), + vec3(0.3725f, 0.2000f, 0.3000f), + vec3(0.4196f, 0.2000f, 0.3000f), + vec3(0.4980f, 0.1667f, 0.1667f), + vec3(1.0000f, 0.1667f, 0.1667f), /* Safe value */ + }; - w = img->w; - h = img->h; + vec3 ret(0.1667f); - dst = pipi_copy(img); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_Y_F32); - dstdata = (float *)dstp->pixels; + if (v > 0.5f) + v = 1.f - v; + if (v < 0.f) + v = 0.f; - for(y = 0; y < h; y++) + for (int i = 1; i < sizeof(table) / sizeof(table[0]); ++i) { - int reverse = (y & 1) && (scan == PIPI_SCAN_SERPENTINE); - - for(x = 0; x < w; x++) + if (v <= table[i][0]) { - float p, q, e; - int x2, s, i; + ret[1] = lol::mix(table[i - 1][1], table[i][1], + (table[i][0] - v) / (table[i][0] - table[i - 1][0])); + ret[2] = lol::mix(table[i - 1][2], table[i][2], + (table[i][0] - v) / (table[i][0] - table[i - 1][0])); + break; + } + } + + ret[0] = 1.f - ret[1] - ret[2]; + return ret; +} - x2 = reverse ? w - 1 - x : x; - s = reverse ? -1 : 1; +Image Image::DitherOstromoukhov(ScanMode scan) const +{ + Image dst = *this; - p = dstdata[y * w + x2]; - q = p < 0.5 ? 0. : 1.; - dstdata[y * w + x2] = q; + float *pixels = dst.Lock(); + int w = dst.GetSize().x; + int h = dst.GetSize().y; - e = p - q; - i = p * 255.9999; - if(i > 127) i = 255 - i; - if(i < 0) i = 0; /* XXX: no "else" here */ - e /= table[i][0] + table[i][1] + table[i][2]; + for (int y = 0; y < h; y++) + { + bool reverse = (y & 1) && (scan == ScanMode::Serpentine); + + for (int x = 0; x < w; x++) + { + int x2 = reverse ? w - 1 - x : x; + int s = reverse ? -1 : 1; + + float p = pixels[y * w + x2]; + float q = p < 0.5f ? 0.f : 1.f; + pixels[y * w + x2] = q; + + vec3 e = (p - q) * GetDiffusion(p); if(x < w - 1) - dstdata[y * w + x2 + s] += e * table[i][0]; + pixels[y * w + x2 + s] += e[0]; if(y < h - 1) { if(x > 0) - dstdata[(y + 1) * w + x2 - s] += e * table[i][1]; - dstdata[(y + 1) * w + x2] += e * table[i][2]; + pixels[(y + 1) * w + x2 - s] += e[1]; + pixels[(y + 1) * w + x2] += e[2]; } } } + dst.Unlock(pixels); + return dst; } +} /* namespace lol */ + diff --git a/src/image/dither/random.cpp b/src/image/dither/random.cpp index b138e8ec..4e5106f6 100644 --- a/src/image/dither/random.cpp +++ b/src/image/dither/random.cpp @@ -1,60 +1,42 @@ -/* - * 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. - */ +// +// 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" /* - * random.c: random dithering functions + * Random dithering */ -#include "config.h" - -#include "pipi.h" -#include "pipi-internals.h" - -pipi_image_t *pipi_dither_random(pipi_image_t *img) +namespace lol { - pipi_image_t *dst; - pipi_pixels_t *dstp; - float *dstdata; - unsigned int ctx = 1; - int x, y, w, h; - w = img->w; - h = img->h; +Image Image::DitherRandom() const +{ + Image dst = *this; - dst = pipi_copy(img); - dstp = pipi_get_pixels(dst, PIPI_PIXELS_Y_F32); - dstdata = (float *)dstp->pixels; + float *pixels = dst.Lock(); + int count = GetSize().x * GetSize().y; - for(y = 0; y < h; y++) + for (int n = 0; n < count; ++n) { - for(x = 0; x < w; x++) - { - long hi, lo; - float p, q; - - hi = ctx / 12773L; - lo = ctx % 12773L; - ctx = 16807L * lo - 2836L * hi; - if(ctx <= 0) - ctx += 0x7fffffffL; - - p = dstdata[y * w + x]; - q = p > (double)((ctx % 65536) / 65535.) ? 1. : 0.; - dstdata[y * w + x] = q; - } + pixels[n] = (pixels[n] > lol::rand(0.5f)) ? 1.f : 0.f; } + dst.Unlock(pixels); + return dst; } +} /* namespace lol */ + diff --git a/src/image/image-private.h b/src/image/image-private.h index 165a4f72..434848f4 100644 --- a/src/image/image-private.h +++ b/src/image/image-private.h @@ -1,7 +1,7 @@ // // Lol Engine // -// Copyright: (c) 2010-2011 Sam Hocevar +// Copyright: (c) 2010-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 @@ -26,11 +26,16 @@ class ImageData public: ImageData() : m_size(0, 0), + m_wrap_x(WrapMode::Clamp), + m_wrap_y(WrapMode::Clamp), m_format(PixelFormat::Unknown) {} ivec2 m_size; + /* The wrap modes for pixel access */ + WrapMode m_wrap_x, m_wrap_y; + /* A map of the various available bitplanes */ Map m_pixels; /* The last bitplane being accessed for writing */ diff --git a/src/image/image.cpp b/src/image/image.cpp index 5644ed8e..dc498a98 100644 --- a/src/image/image.cpp +++ b/src/image/image.cpp @@ -124,7 +124,7 @@ Image::~Image() { for (int k : m_data->m_pixels.Keys()) { - delete[] m_data->m_pixels[k]; + delete[] (uint8_t *)m_data->m_pixels[k]; m_data->m_pixels[k] = nullptr; } delete m_data; @@ -170,6 +170,23 @@ void Image::SetSize(ivec2 size) } } +/* Wrap-around mode for some operations */ +WrapMode Image::GetWrapX() const +{ + return m_data->m_wrap_x; +} + +WrapMode Image::GetWrapY() const +{ + return m_data->m_wrap_y; +} + +void Image::SetWrap(WrapMode wrap_x, WrapMode wrap_y) +{ + m_data->m_wrap_x = wrap_x; + m_data->m_wrap_y = wrap_y; +} + /* The Lock() method */ template typename PixelType::type *Image::Lock() { diff --git a/src/image/pixels.cpp b/src/image/pixels.cpp index f6de0efc..cb1a01fd 100644 --- a/src/image/pixels.cpp +++ b/src/image/pixels.cpp @@ -43,13 +43,26 @@ PixelFormat Image::GetFormat() const void Image::SetFormat(PixelFormat fmt) { - ivec2 size = GetSize(); - int count = size.x * size.y; + PixelFormat old_fmt = m_data->m_format; + + /* Preliminary intermediate conversions */ + if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_F32) + SetFormat(PixelFormat::RGBA_F32); + else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_F32) + SetFormat(PixelFormat::RGBA_F32); + else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_8) + SetFormat(PixelFormat::RGBA_F32); + else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8) + SetFormat(PixelFormat::RGBA_F32); + + old_fmt = m_data->m_format; /* Set the new active pixel format */ - PixelFormat old_fmt = m_data->m_format; m_data->m_format = fmt; + ivec2 size = GetSize(); + int count = size.x * size.y; + /* If we never used this format, allocate a new buffer: we will * obviously need it. */ if (m_data->m_pixels[(int)fmt] == nullptr) @@ -62,18 +75,6 @@ void Image::SetFormat(PixelFormat fmt) if (fmt == old_fmt || old_fmt == PixelFormat::Unknown) return; -#if 0 - /* Preliminary conversions */ - if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_F32) - pipi_get_pixels(img, PixelFormat::RGBA_F32); - else if (old_fmt == PixelFormat::BGR_U8 && fmt == PixelFormat::Y_F32) - pipi_get_pixels(img, PixelFormat::RGBA_F32); - else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_8) - pipi_get_pixels(img, PixelFormat::RGBA_F32); - else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::BGR_U8) - pipi_get_pixels(img, PixelFormat::RGBA_F32); -#endif - /* Convert pixels */ if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGBA_F32) { diff --git a/src/image/stock.cpp b/src/image/stock.cpp index 383d55a1..59caf3fb 100644 --- a/src/image/stock.cpp +++ b/src/image/stock.cpp @@ -1,7 +1,7 @@ // // Lol Engine // -// Copyright: (c) 2004-2013 Sam Hocevar +// 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 @@ -59,7 +59,7 @@ bool Image::Stock(char const *name) if (!strcmp(name + 6, "fs")) { - float const myker[] = + static float const myker[] = { 0., 1., 7./16, 3./16, 5./16, 1./16, @@ -68,7 +68,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "jajuni")) { - float const myker[] = + static float const myker[] = { 0., 0., 1., 7./48, 5./48, 3./48, 5./48, 7./48, 5./48, 3./48, @@ -78,7 +78,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "atkinson")) { - float const myker[] = + static float const myker[] = { 0., 1., 1./8, 1./8, 1./8, 1./8, 1./8, 0., @@ -88,7 +88,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "fan")) { - float const myker[] = + static float const myker[] = { 0., 0., 1., 7./16, 1./16, 3./16, 5./16, 0., @@ -97,7 +97,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "shiaufan")) { - float const myker[] = + static float const myker[] = { 0., 0., 1., 1./2, 1./8, 1./8, 1./4, 0., @@ -106,7 +106,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "shiaufan2")) { - float const myker[] = + static float const myker[] = { 0., 0., 0., 1., 1./2, 1./16, 1./16, 1./8, 1./4, 0., @@ -115,7 +115,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "stucki")) { - float const myker[] = + static float const myker[] = { 0., 0., 1., 8./42, 4./42, 2./42, 4./42, 8./42, 4./42, 2./42, @@ -125,7 +125,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "burkes")) { - float const myker[] = + static float const myker[] = { 0., 0., 1., 4./16, 2./16, 1./16, 2./16, 4./16, 2./16, 1./16, @@ -134,7 +134,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "sierra")) { - float const myker[] = + static float const myker[] = { 0., 0., 1., 5./32, 3./32, 2./32, 4./32, 5./32, 4./32, 2./32, @@ -144,7 +144,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "sierra2")) { - float const myker[] = + static float const myker[] = { 0., 0., 1., 4./16, 3./16, 1./16, 2./16, 3./16, 2./16, 1./16, @@ -153,7 +153,7 @@ bool Image::Stock(char const *name) } else if (!strcmp(name + 6, "lite")) { - float const myker[] = + static float const myker[] = { 0., 1., 1./2, 1./4, 1./4, 0., diff --git a/src/lol/image/image.h b/src/lol/image/image.h index d9affb55..3b7acfbd 100644 --- a/src/lol/image/image.h +++ b/src/lol/image/image.h @@ -1,7 +1,7 @@ // // Lol Engine // -// Copyright: (c) 2010-2013 Sam Hocevar +// Copyright: (c) 2010-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 @@ -29,6 +29,18 @@ template<> struct PixelType { typedef float type; }; template<> struct PixelType { typedef vec3 type; }; template<> struct PixelType { typedef vec4 type; }; +enum class WrapMode : uint8_t +{ + Clamp, + Repeat, +}; + +enum class ScanMode : uint8_t +{ + Raster, + Serpentine, +}; + class Image { public: @@ -53,6 +65,10 @@ public: PixelFormat GetFormat() const; void SetFormat(PixelFormat fmt); + WrapMode GetWrapX() const; + WrapMode GetWrapY() const; + void SetWrap(WrapMode wrap_x, WrapMode wrap_y); + template typename PixelType::type *Lock(); void Unlock(void const *pixels); @@ -67,6 +83,9 @@ public: /* Image processing */ Image AutoContrast() const; + Image DitherRandom() const; + Image DitherEdiff(Image &kernel, ScanMode scan = ScanMode::Raster) const; + Image DitherOstromoukhov(ScanMode scan = ScanMode::Raster) const; private: class ImageData *m_data;