| @@ -2,12 +2,16 @@ | |||||
| Large projects | 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 | Engine classes | ||||
| ---------------- | ---------------- | ||||
| Scene: | |||||
| - Remove uses of g_scene | |||||
| - Maybe make Camera a world object instead? | |||||
| Image: | Image: | ||||
| - Handle pitch in SDL codec (and all others, actually) | - Handle pitch in SDL codec (and all others, actually) | ||||
| - Fix the Floyd-Steinberg ode in pixels.cpp | - Fix the Floyd-Steinberg ode in pixels.cpp | ||||
| @@ -31,10 +35,7 @@ Image: | |||||
| · crop.cpp | · crop.cpp | ||||
| · dither.cpp | · dither.cpp | ||||
| · dither/dbs.cpp | · dither/dbs.cpp | ||||
| · dither/ediff.cpp | |||||
| · dither/ordered.cpp | · dither/ordered.cpp | ||||
| · dither/ostromoukhov.cpp | |||||
| · dither/random.cpp | |||||
| · filter/blur.cpp | · filter/blur.cpp | ||||
| · filter/color.cpp | · filter/color.cpp | ||||
| · filter/convolution.cpp | · filter/convolution.cpp | ||||
| @@ -116,6 +116,8 @@ liblolcore_sources = \ | |||||
| image/codec/zed-image.cpp image/codec/zed-palette-image.cpp \ | image/codec/zed-image.cpp image/codec/zed-palette-image.cpp \ | ||||
| image/codec/dummy-image.cpp \ | image/codec/dummy-image.cpp \ | ||||
| image/color/cie1931.cpp image/color/color.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/filter/autocontrast.cpp \ | ||||
| image/render/noise.cpp image/render/screen.cpp \ | image/render/noise.cpp image/render/screen.cpp \ | ||||
| \ | \ | ||||
| @@ -1,25 +1,25 @@ | |||||
| /* | |||||
| * 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. | |||||
| */ | |||||
| // | |||||
| // 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" | |||||
| /* | /* | ||||
| * 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 | /* Perform a generic error diffusion dithering. The first non-zero | ||||
| * element in ker is treated as the current pixel. All other 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 | * Making the matrix generic is not terribly slower: the performance | ||||
| * hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the | * hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the | ||||
| * benefit of a lot less code. */ | * 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<PixelFormat::Y_F32>(); | |||||
| int w = dst.GetSize().x; | |||||
| int h = dst.GetSize().y; | |||||
| float *kerdata = kernel.Lock<PixelFormat::Y_F32>(); | |||||
| int kw = kernel.GetSize().x; | |||||
| int kh = kernel.GetSize().y; | |||||
| int kx; | |||||
| for (kx = 0; kx < kw; kx++) | |||||
| if (kerdata[kx] > 0.f) | |||||
| break; | 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 x2 = reverse ? w - 1 - x : x; | ||||
| int s = reverse ? -1 : 1; | 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; | continue; | ||||
| if(x + i - kx < 0 || x + i - kx >= w) | |||||
| if (x + i - kx < 0 || x + i - kx >= w) | |||||
| continue; | continue; | ||||
| dstdata[(y + j) * w + x2 + (i - kx) * s] | |||||
| pixels[(y + j) * w + x2 + (i - kx) * s] | |||||
| += e * kerdata[j * kw + i]; | += e * kerdata[j * kw + i]; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| kernel.Unlock(kerdata); | |||||
| dst.Unlock(pixels); | |||||
| return dst; | return dst; | ||||
| } | } | ||||
| } /* namespace lol */ | |||||
| @@ -1,117 +1,116 @@ | |||||
| /* | |||||
| * 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. | |||||
| */ | |||||
| // | |||||
| // 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" | |||||
| /* | /* | ||||
| * ostromoukhov.c: Ostromoukhov dithering functions | |||||
| * Ostromoukhov dithering functions | |||||
| * | * | ||||
| * This module implements Ostromoukhov's simple error diffusion algorithm, | * This module implements Ostromoukhov's simple error diffusion algorithm, | ||||
| * as introduced in the paper "A Simple and Efficient Error-Diffusion | * as introduced in the paper "A Simple and Efficient Error-Diffusion | ||||
| * Algorithm", Proceedings of SIGGRAPH 2001, in ACM Computer Graphics, | * Algorithm", Proceedings of SIGGRAPH 2001, in ACM Computer Graphics, | ||||
| * Annual Conference Series, pp. 567--572, 2001. | * 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<PixelFormat::Y_F32>(); | |||||
| 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) | 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(y < h - 1) | ||||
| { | { | ||||
| if(x > 0) | 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; | return dst; | ||||
| } | } | ||||
| } /* namespace lol */ | |||||
| @@ -1,60 +1,42 @@ | |||||
| /* | |||||
| * 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. | |||||
| */ | |||||
| // | |||||
| // 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" | |||||
| /* | /* | ||||
| * 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<PixelFormat::Y_F32>(); | |||||
| 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; | return dst; | ||||
| } | } | ||||
| } /* namespace lol */ | |||||
| @@ -1,7 +1,7 @@ | |||||
| // | // | ||||
| // Lol Engine | // Lol Engine | ||||
| // | // | ||||
| // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | // 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 | // modify it under the terms of the Do What The Fuck You Want To | ||||
| // Public License, Version 2, as published by Sam Hocevar. See | // Public License, Version 2, as published by Sam Hocevar. See | ||||
| @@ -26,11 +26,16 @@ class ImageData | |||||
| public: | public: | ||||
| ImageData() | ImageData() | ||||
| : m_size(0, 0), | : m_size(0, 0), | ||||
| m_wrap_x(WrapMode::Clamp), | |||||
| m_wrap_y(WrapMode::Clamp), | |||||
| m_format(PixelFormat::Unknown) | m_format(PixelFormat::Unknown) | ||||
| {} | {} | ||||
| ivec2 m_size; | ivec2 m_size; | ||||
| /* The wrap modes for pixel access */ | |||||
| WrapMode m_wrap_x, m_wrap_y; | |||||
| /* A map of the various available bitplanes */ | /* A map of the various available bitplanes */ | ||||
| Map<int, void *> m_pixels; | Map<int, void *> m_pixels; | ||||
| /* The last bitplane being accessed for writing */ | /* The last bitplane being accessed for writing */ | ||||
| @@ -124,7 +124,7 @@ Image::~Image() | |||||
| { | { | ||||
| for (int k : m_data->m_pixels.Keys()) | 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; | m_data->m_pixels[k] = nullptr; | ||||
| } | } | ||||
| delete m_data; | 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 */ | /* The Lock() method */ | ||||
| template<PixelFormat T> typename PixelType<T>::type *Image::Lock() | template<PixelFormat T> typename PixelType<T>::type *Image::Lock() | ||||
| { | { | ||||
| @@ -43,13 +43,26 @@ PixelFormat Image::GetFormat() const | |||||
| void Image::SetFormat(PixelFormat fmt) | 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 */ | /* Set the new active pixel format */ | ||||
| PixelFormat old_fmt = m_data->m_format; | |||||
| m_data->m_format = fmt; | 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 | /* If we never used this format, allocate a new buffer: we will | ||||
| * obviously need it. */ | * obviously need it. */ | ||||
| if (m_data->m_pixels[(int)fmt] == nullptr) | 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) | if (fmt == old_fmt || old_fmt == PixelFormat::Unknown) | ||||
| return; | 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 */ | /* Convert pixels */ | ||||
| if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGBA_F32) | if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGBA_F32) | ||||
| { | { | ||||
| @@ -1,7 +1,7 @@ | |||||
| // | // | ||||
| // Lol Engine | // Lol Engine | ||||
| // | // | ||||
| // Copyright: (c) 2004-2013 Sam Hocevar <sam@hocevar.net> | |||||
| // Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | // 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 | // modify it under the terms of the Do What The Fuck You Want To | ||||
| // Public License, Version 2, as published by Sam Hocevar. See | // 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")) | if (!strcmp(name + 6, "fs")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 1., 7./16, | 0., 1., 7./16, | ||||
| 3./16, 5./16, 1./16, | 3./16, 5./16, 1./16, | ||||
| @@ -68,7 +68,7 @@ bool Image::Stock(char const *name) | |||||
| } | } | ||||
| else if (!strcmp(name + 6, "jajuni")) | else if (!strcmp(name + 6, "jajuni")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 1., 7./48, 5./48, | 0., 0., 1., 7./48, 5./48, | ||||
| 3./48, 5./48, 7./48, 5./48, 3./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")) | else if (!strcmp(name + 6, "atkinson")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 1., 1./8, 1./8, | 0., 1., 1./8, 1./8, | ||||
| 1./8, 1./8, 1./8, 0., | 1./8, 1./8, 1./8, 0., | ||||
| @@ -88,7 +88,7 @@ bool Image::Stock(char const *name) | |||||
| } | } | ||||
| else if (!strcmp(name + 6, "fan")) | else if (!strcmp(name + 6, "fan")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 1., 7./16, | 0., 0., 1., 7./16, | ||||
| 1./16, 3./16, 5./16, 0., | 1./16, 3./16, 5./16, 0., | ||||
| @@ -97,7 +97,7 @@ bool Image::Stock(char const *name) | |||||
| } | } | ||||
| else if (!strcmp(name + 6, "shiaufan")) | else if (!strcmp(name + 6, "shiaufan")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 1., 1./2, | 0., 0., 1., 1./2, | ||||
| 1./8, 1./8, 1./4, 0., | 1./8, 1./8, 1./4, 0., | ||||
| @@ -106,7 +106,7 @@ bool Image::Stock(char const *name) | |||||
| } | } | ||||
| else if (!strcmp(name + 6, "shiaufan2")) | else if (!strcmp(name + 6, "shiaufan2")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 0., 1., 1./2, | 0., 0., 0., 1., 1./2, | ||||
| 1./16, 1./16, 1./8, 1./4, 0., | 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")) | else if (!strcmp(name + 6, "stucki")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 1., 8./42, 4./42, | 0., 0., 1., 8./42, 4./42, | ||||
| 2./42, 4./42, 8./42, 4./42, 2./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")) | else if (!strcmp(name + 6, "burkes")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 1., 4./16, 2./16, | 0., 0., 1., 4./16, 2./16, | ||||
| 1./16, 2./16, 4./16, 2./16, 1./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")) | else if (!strcmp(name + 6, "sierra")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 1., 5./32, 3./32, | 0., 0., 1., 5./32, 3./32, | ||||
| 2./32, 4./32, 5./32, 4./32, 2./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")) | else if (!strcmp(name + 6, "sierra2")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 0., 1., 4./16, 3./16, | 0., 0., 1., 4./16, 3./16, | ||||
| 1./16, 2./16, 3./16, 2./16, 1./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")) | else if (!strcmp(name + 6, "lite")) | ||||
| { | { | ||||
| float const myker[] = | |||||
| static float const myker[] = | |||||
| { | { | ||||
| 0., 1., 1./2, | 0., 1., 1./2, | ||||
| 1./4, 1./4, 0., | 1./4, 1./4, 0., | ||||
| @@ -1,7 +1,7 @@ | |||||
| // | // | ||||
| // Lol Engine | // Lol Engine | ||||
| // | // | ||||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | // 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 | // modify it under the terms of the Do What The Fuck You Want To | ||||
| // Public License, Version 2, as published by Sam Hocevar. See | // Public License, Version 2, as published by Sam Hocevar. See | ||||
| @@ -29,6 +29,18 @@ template<> struct PixelType<PixelFormat::Y_F32> { typedef float type; }; | |||||
| template<> struct PixelType<PixelFormat::RGB_F32> { typedef vec3 type; }; | template<> struct PixelType<PixelFormat::RGB_F32> { typedef vec3 type; }; | ||||
| template<> struct PixelType<PixelFormat::RGBA_F32> { typedef vec4 type; }; | template<> struct PixelType<PixelFormat::RGBA_F32> { typedef vec4 type; }; | ||||
| enum class WrapMode : uint8_t | |||||
| { | |||||
| Clamp, | |||||
| Repeat, | |||||
| }; | |||||
| enum class ScanMode : uint8_t | |||||
| { | |||||
| Raster, | |||||
| Serpentine, | |||||
| }; | |||||
| class Image | class Image | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -53,6 +65,10 @@ public: | |||||
| PixelFormat GetFormat() const; | PixelFormat GetFormat() const; | ||||
| void SetFormat(PixelFormat fmt); | void SetFormat(PixelFormat fmt); | ||||
| WrapMode GetWrapX() const; | |||||
| WrapMode GetWrapY() const; | |||||
| void SetWrap(WrapMode wrap_x, WrapMode wrap_y); | |||||
| template<PixelFormat T = PixelFormat::Unknown> | template<PixelFormat T = PixelFormat::Unknown> | ||||
| typename PixelType<T>::type *Lock(); | typename PixelType<T>::type *Lock(); | ||||
| void Unlock(void const *pixels); | void Unlock(void const *pixels); | ||||
| @@ -67,6 +83,9 @@ public: | |||||
| /* Image processing */ | /* Image processing */ | ||||
| Image AutoContrast() const; | Image AutoContrast() const; | ||||
| Image DitherRandom() const; | |||||
| Image DitherEdiff(Image &kernel, ScanMode scan = ScanMode::Raster) const; | |||||
| Image DitherOstromoukhov(ScanMode scan = ScanMode::Raster) const; | |||||
| private: | private: | ||||
| class ImageData *m_data; | class ImageData *m_data; | ||||