Browse Source

image: port libpipi stock images, plus noise and screen rendering.

undefined
Sam Hocevar 10 years ago
parent
commit
347e6a0551
7 changed files with 247 additions and 276 deletions
  1. +36
    -40
      TODO
  2. +3
    -3
      src/Makefile.am
  3. +2
    -6
      src/image/image.cpp
  4. +41
    -47
      src/image/render/noise.cpp
  5. +64
    -82
      src/image/render/screen.cpp
  6. +89
    -97
      src/image/stock.cpp
  7. +12
    -1
      src/lol/image/image.h

+ 36
- 40
TODO View File

@@ -12,57 +12,53 @@ Image:
- Handle pitch in SDL codec (and all others, actually) - Handle pitch in SDL codec (and all others, actually)
- port libpipi files: - port libpipi files:
· accessors.cpp · accessors.cpp
· pipi-stubs.h
· render/noise.cpp
· render/screen.cpp
· tiles.cpp
· pipi-internals.h
· pipi-template.h
· paint/rectangle.cpp
· paint/line.cpp
· paint/floodfill.cpp
· paint/bezier.cpp
· paint/tile.cpp
· pipi-types.h
· stock.cpp
· context.cpp
· pipi.h
· dither.cpp
· colorstring.cpp
· analysis/histogram.cpp
· analysis/measure.cpp
· codec/coreimage.cpp · codec/coreimage.cpp
· codec/coreimage.h · codec/coreimage.h
· codec/oric.cpp
· codec.cpp
· codec/jpeg.cpp · codec/jpeg.cpp
· resample/bresenham.cpp
· resample/bicubic.cpp
· quantize/reduce.cpp
· analysis/histogram.cpp
· analysis/measure.cpp
· codec/oric.cpp
· colorstring.cpp
· combine/blit.cpp
· combine/merge.cpp
· combine/minmax.cpp
· combine/mulscreen.cpp
· combine/rgb.cpp
· combine/subadd.cpp
· context.cpp
· crop.cpp · crop.cpp
· pipi.cpp
· codec.cpp
· dither.cpp
· dither/dbs.cpp
· dither/ediff.cpp · dither/ediff.cpp
· dither/ordered.cpp
· dither/ostromoukhov.cpp · dither/ostromoukhov.cpp
· dither/random.cpp · dither/random.cpp
· dither/ordered.cpp
· dither/dbs.cpp
· sequence.cpp
· filter/autocontrast.cpp
· filter/blur.cpp
· filter/color.cpp
· filter/convolution.cpp · filter/convolution.cpp
· filter/wave.cpp
· filter/dilate.cpp · filter/dilate.cpp
· filter/color.cpp
· filter/blur.cpp
· filter/yuv.cpp
· filter/autocontrast.cpp
· filter/median.cpp · filter/median.cpp
· filter/rotate.cpp · filter/rotate.cpp
· filter/transform.cpp
· filter/sharpen.cpp · filter/sharpen.cpp
· combine/rgb.cpp
· combine/blit.cpp
· combine/minmax.cpp
· combine/subadd.cpp
· combine/merge.cpp
· combine/mulscreen.cpp
· filter/transform.cpp
· filter/wave.cpp
· filter/yuv.cpp
· paint/bezier.cpp
· paint/floodfill.cpp
· paint/line.cpp
· paint/rectangle.cpp
· paint/tile.cpp
· pipi.h
· pipi-internals.h
· pipi-stubs.h
· pipi-template.h
· pipi-types.h
· pixels.cpp · pixels.cpp
· quantize/reduce.cpp
· resample/bicubic.cpp
· resample/bresenham.cpp
· sequence.cpp
· tiles.cpp



+ 3
- 3
src/Makefile.am View File

@@ -110,13 +110,13 @@ liblolcore_sources = \
sys/init.cpp sys/timer.cpp sys/file.cpp \ sys/init.cpp sys/timer.cpp sys/file.cpp \
sys/thread.cpp sys/threadbase.h \ sys/thread.cpp sys/threadbase.h \
\ \
image/image.cpp image/image-private.h \
image/image.cpp image/image-private.h image/stock.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 \
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/render/noise.cpp image/render/screen.cpp \
\ \
loldebug.h \ loldebug.h \
debug/fps.cpp debug/fps.h debug/lines.cpp \ debug/fps.cpp debug/fps.h debug/lines.cpp \


+ 2
- 6
src/image/image.cpp View File

@@ -15,8 +15,6 @@
#include "core.h" #include "core.h"
#include "image-private.h" #include "image-private.h"


using namespace std;

namespace lol namespace lol
{ {


@@ -196,8 +194,7 @@ void Image::SetFormat(PixelFormat fmt)
} }


/* The Lock() method */ /* The Lock() method */
template<PixelFormat T>
typename PixelType<T>::type *Image::Lock()
template<PixelFormat T> typename PixelType<T>::type *Image::Lock()
{ {
SetFormat(T); SetFormat(T);


@@ -215,8 +212,7 @@ _T(PixelFormat::RGBA_F32);
#undef _T #undef _T


/* Special case for the "any" format: return the last active buffer */ /* Special case for the "any" format: return the last active buffer */
template<>
void *Image::Lock<PixelFormat::Unknown>()
template<> void *Image::Lock<PixelFormat::Unknown>()
{ {
ASSERT(m_data->m_format != PixelFormat::Unknown); ASSERT(m_data->m_format != PixelFormat::Unknown);




+ 41
- 47
src/image/render/noise.cpp View File

@@ -1,61 +1,55 @@
/*
* 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"


/* /*
* noise.c: noise rendering functions
* Noise rendering functions
*/ */


#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pipi.h"
#include "pipi-internals.h"
namespace lol
{


pipi_image_t *pipi_render_random(int w, int h)
bool Image::RenderRandom(ivec2 size)
{ {
pipi_image_t *ret;
pipi_pixels_t *pix;
float *data;
unsigned int ctx = 1; unsigned int ctx = 1;
int x, y, t;


ret = pipi_new(w, h);
pix = pipi_get_pixels(ret, PIPI_PIXELS_RGBA_F32);
data = (float *)pix->pixels;
SetSize(size);
vec4 *pixels = Lock<PixelFormat::RGBA_F32>();
int count = size.x * size.y;


for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
for (int n = 0; n < count; ++n)
{
for (int t : { 0, 1, 2 })
{ {
for(t = 0; t < 3; t++)
{
long hi, lo;

hi = ctx / 12773L;
lo = ctx % 12773L;
ctx = 16807L * lo - 2836L * hi;
if(ctx <= 0)
ctx += 0x7fffffffL;

data[4 * (y * w + x) + t]
= (double)((ctx % 65536) / 65535.);
}
data[4 * (y * w + x) + 3] = 1.0;
long hi, lo;

hi = ctx / 12773L;
lo = ctx % 12773L;
ctx = 16807L * lo - 2836L * hi;
if(ctx <= 0)
ctx += 0x7fffffffL;

pixels[n][t] = (float)((ctx % 65536) / 65535.);
} }
pixels[n][3] = 1.0f;
}


return ret;
Unlock(pixels);

return true;
} }


} /* namespace lol */


+ 64
- 82
src/image/render/screen.cpp View File

@@ -1,71 +1,59 @@
/*
* 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"


/* /*
* screen.c: halftoning screen functions
* Halftoning screen functions
*/ */


#include "config.h"

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

#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif

#include "pipi.h"
#include "pipi-internals.h"

pipi_image_t *pipi_render_bayer(int w, int h)
namespace lol
{ {
pipi_image_t *ret;
pipi_pixels_t *pix;
float *data;
int i, j, n;


if(w <= 0 || h <= 0)
return NULL;
bool Image::RenderBayer(ivec2 size)
{
if (size.x <= 0 || size.y <= 0)
return false;


for(n = 1; n < w || n < h; n *= 2)
;
int n = 1;
while (n < size.x || n < size.y)
n *= 2;


ret = pipi_new(w, h);
pix = pipi_get_pixels(ret, PIPI_PIXELS_Y_F32);
data = (float *)pix->pixels;
SetSize(size);
float *pixels = Lock<PixelFormat::Y_F32>();


for(j = 0; j < h; j++)
for(i = 0; i < w; i++)
for (int j = 0; j < size.y; j++)
for (int i = 0; i < size.x; i++)
{ {
int k, l, x = 0;
int x = 0;


for(k = 1, l = n * n / 4; k < n; k *= 2, l /= 4)
for (int k = 1, l = n * n / 4; k < n; k *= 2, l /= 4)
{ {
if((i & k) && (j & k))
if ((i & k) && (j & k))
x += l; x += l;
else if(i & k)
else if (i & k)
x += 3 * l; x += 3 * l;
else if(j & k)
else if (j & k)
x += 2 * l; x += 2 * l;
} }


data[j * w + i] = (double)(x + 1) / (n * n + 1);
pixels[j * size.x + i] = (float)(x + 1) / (n * n + 1);
} }


return ret;
Unlock(pixels);

return true;
} }


typedef struct typedef struct
@@ -80,49 +68,43 @@ static int cmpdot(const void *p1, const void *p2)
return ((dot_t const *)p1)->dist > ((dot_t const *)p2)->dist; return ((dot_t const *)p1)->dist > ((dot_t const *)p2)->dist;
} }


pipi_image_t *pipi_render_halftone(int w, int h)
bool Image::RenderHalftone(ivec2 size)
{ {
pipi_image_t *ret;
pipi_pixels_t *pix;
float *data;
dot_t *circle;
int x, y, n;

if(w <= 0 || h <= 0)
return NULL;
if (size.x <= 0 || size.y <= 0)
return false;


circle = malloc(w * h * sizeof(dot_t));
for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
Array<dot_t> circle;
circle.Resize(size.x * size.y);
for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++)
{ {
double dy = ((double)y + .07) / h - .5;
double dx = (double)x / w - .5;
double dy = ((double)y + .07) / size.y - .5;
double dx = (double)x / size.x - .5;
/* Using dx²+dy² here creates another interesting halftone. */ /* Using dx²+dy² here creates another interesting halftone. */
double r = - cos(M_PI * (dx - dy)) - cos(M_PI * (dx + dy)); double r = - cos(M_PI * (dx - dy)) - cos(M_PI * (dx + dy));
circle[y * w + x].x = x;
circle[y * w + x].y = y;
circle[y * w + x].dist = r;
circle[y * size.x + x].x = x;
circle[y * size.x + x].y = y;
circle[y * size.x + x].dist = r;
} }
qsort(circle, w * h, sizeof(dot_t), cmpdot);

ret = pipi_new(w * 2, h * 2);
pix = pipi_get_pixels(ret, PIPI_PIXELS_Y_F32);
data = (float *)pix->pixels;
std::qsort(circle.Data(), size.x * size.y, sizeof(dot_t), cmpdot);


for(n = 0; n < w * h; n++)
SetSize(2 * size);
float *pixels = Lock<PixelFormat::Y_F32>();
float mul = 1.f / (size.x * size.y * 4 + 1);
for (int n = 0; n < size.x * size.y; n++)
{ {
x = circle[n].x;
y = circle[n].y;
int x = circle[n].x;
int y = circle[n].y;


data[y * (2 * w) + x] = (float)(2 * n + 1) / (w * h * 4 + 1);
data[(y + h) * (2 * w) + x + w] = (float)(2 * n + 2) / (w * h * 4 + 1);
data[(y + h) * (2 * w) + x] = 1. - (float)(2 * n + 1) / (w * h * 4 + 1);
data[y * (2 * w) + x + w] = 1. - (float)(2 * n + 2) / (w * h * 4 + 1);
pixels[y * (2 * size.x) + x] = (float)(2 * n + 1) * mul;
pixels[(y + size.y) * (2 * size.x) + x + size.x] = (float)(2 * n + 2) * mul;
pixels[(y + size.y) * (2 * size.x) + x] = 1. - (float)(2 * n + 1) * mul;
pixels[y * (2 * size.x) + x + size.x] = 1. - (float)(2 * n + 2) * mul;
} }
Unlock(pixels);


free(circle);

return ret;
return true;
} }


} /* namespace lol */


+ 89
- 97
src/image/stock.cpp View File

@@ -1,201 +1,193 @@
/*
* 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-2013 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"


/* /*
* stock.c: stock images
* Stock images
*/ */


#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pipi.h"
#include "pipi-internals.h"

pipi_image_t *pipi_load_stock(char const *name)
namespace lol
{ {
pipi_image_t *ret;
pipi_pixels_t *pix;


bool Image::Stock(char const *name)
{
/* Generate a Bayer dithering pattern. */ /* Generate a Bayer dithering pattern. */
if(!strncmp(name, "bayer:", 6))
if (!strncmp(name, "bayer:", 6))
{ {
int w, h = 0;

w = atoi(name + 6);
ivec2 size(0);
size.x = atoi(name + 6);
name = strchr(name + 6, 'x'); name = strchr(name + 6, 'x');
if(name)
h = atoi(name + 1);
if(!h)
h = w;
if (name)
size.y = atoi(name + 1);
if (!size.y)
size.y = size.x;


return pipi_render_bayer(w, h);
return RenderBayer(size);
} }


/* Generate a clustered dithering pattern. */ /* Generate a clustered dithering pattern. */
if(!strncmp(name, "halftone:", 9))
if (!strncmp(name, "halftone:", 9))
{ {
int w, h = 0;

w = atoi(name + 9);
ivec2 size(0);
size.x = atoi(name + 9);
name = strchr(name + 9, 'x'); name = strchr(name + 9, 'x');
if(name)
h = atoi(name + 1);
if(!h)
h = w;
if (name)
size.y = atoi(name + 1);
if (!size.y)
size.y = size.x;


return pipi_render_halftone(w, h);
return RenderHalftone(size);
} }


/* Generate an error diffusion matrix. */ /* Generate an error diffusion matrix. */
if(!strncmp(name, "ediff:", 6))
if (!strncmp(name, "ediff:", 6))
{ {
float const *ker; float const *ker;
int w, h;
ivec2 size(0);


if(!strcmp(name + 6, "fs"))
if (!strcmp(name + 6, "fs"))
{ {
static float const myker[] =
float const myker[] =
{ {
0., 1., 7./16, 0., 1., 7./16,
3./16, 5./16, 1./16, 3./16, 5./16, 1./16,
}; };
ker = myker; w = 3; h = 2;
ker = myker; size = ivec2(3, 2);
} }
else if(!strcmp(name + 6, "jajuni"))
else if (!strcmp(name + 6, "jajuni"))
{ {
static float const myker[] =
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,
1./48, 3./48, 5./48, 3./48, 1./48, 1./48, 3./48, 5./48, 3./48, 1./48,
}; };
ker = myker; w = 5; h = 3;
ker = myker; size = ivec2(5, 3);
} }
else if(!strcmp(name + 6, "atkinson"))
else if (!strcmp(name + 6, "atkinson"))
{ {
static float const myker[] =
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.,
0., 1./8, 0., 0., 0., 1./8, 0., 0.,
}; };
ker = myker; w = 4; h = 3;
ker = myker; size = ivec2(4, 3);
} }
else if(!strcmp(name + 6, "fan"))
else if (!strcmp(name + 6, "fan"))
{ {
static float const myker[] =
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.,
}; };
ker = myker; w = 4; h = 2;
ker = myker; size = ivec2(4, 2);
} }
else if(!strcmp(name + 6, "shiaufan"))
else if (!strcmp(name + 6, "shiaufan"))
{ {
static float const myker[] =
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.,
}; };
ker = myker; w = 4; h = 2;
ker = myker; size = ivec2(4, 2);
} }
else if(!strcmp(name + 6, "shiaufan2"))
else if (!strcmp(name + 6, "shiaufan2"))
{ {
static float const myker[] =
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.,
}; };
ker = myker; w = 5; h = 2;
ker = myker; size = ivec2(5, 2);
} }
else if(!strcmp(name + 6, "stucki"))
else if (!strcmp(name + 6, "stucki"))
{ {
static float const myker[] =
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,
1./42, 2./42, 4./42, 2./42, 1./42, 1./42, 2./42, 4./42, 2./42, 1./42,
}; };
ker = myker; w = 5; h = 3;
ker = myker; size = ivec2(5, 3);
} }
else if(!strcmp(name + 6, "burkes"))
else if (!strcmp(name + 6, "burkes"))
{ {
static float const myker[] =
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,
}; };
ker = myker; w = 5; h = 2;
ker = myker; size = ivec2(5, 2);
} }
else if(!strcmp(name + 6, "sierra"))
else if (!strcmp(name + 6, "sierra"))
{ {
static float const myker[] =
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,
0., 2./32, 3./32, 2./32, 0., 0., 2./32, 3./32, 2./32, 0.,
}; };
ker = myker; w = 5; h = 3;
ker = myker; size = ivec2(5, 3);
} }
else if(!strcmp(name + 6, "sierra2"))
else if (!strcmp(name + 6, "sierra2"))
{ {
static float const myker[] =
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,
}; };
ker = myker; w = 5; h = 2;
ker = myker; size = ivec2(5, 2);
} }
else if(!strcmp(name + 6, "lite"))
else if (!strcmp(name + 6, "lite"))
{ {
static float const myker[] =
float const myker[] =
{ {
0., 1., 1./2, 0., 1., 1./2,
1./4, 1./4, 0., 1./4, 1./4, 0.,
}; };
ker = myker; w = 3; h = 2;
ker = myker; size = ivec2(3, 2);
} }
else
return NULL;


ret = pipi_new(w, h);
pix = pipi_get_pixels(ret, PIPI_PIXELS_Y_F32);
memcpy(pix->pixels, ker, w * h * sizeof(float));
SetSize(size);
float *pixels = Lock<PixelFormat::Y_F32>();
memcpy(pixels, ker, size.x * size.y * sizeof(float));
Unlock(pixels);


return ret;
return true;
} }


/* Generate a completely random image. */ /* Generate a completely random image. */
if(!strncmp(name, "random:", 7))
if (!strncmp(name, "random:", 7))
{ {
int w, h = 0;
ivec2 size(0);


w = atoi(name + 7);
size.x = atoi(name + 7);
name = strchr(name + 7, 'x'); name = strchr(name + 7, 'x');
if(name)
h = atoi(name + 1);
if(!h)
h = w;
if(w <= 0 || h <= 0)
return NULL;
return pipi_render_random(w, h);
if (name)
size.y = atoi(name + 1);
if (!size.y)
size.y = size.x;
if (size.x <= 0 || size.y <= 0)
return false;
return RenderRandom(size);
} }


return NULL;
return false;
} }


} /* namespace lol */


+ 12
- 1
src/lol/image/image.h View File

@@ -39,13 +39,14 @@ public:
Image(char const *path); Image(char const *path);


/* Rule of three */ /* Rule of three */
Image (Image const &other);
Image(Image const &other);
Image & operator =(Image other); Image & operator =(Image other);
~Image(); ~Image();


bool Load(char const *path); bool Load(char const *path);
bool Save(char const *path); bool Save(char const *path);


/* Low level access */
ivec2 GetSize() const; ivec2 GetSize() const;
void SetSize(ivec2); void SetSize(ivec2);


@@ -58,6 +59,16 @@ public:


bool RetrieveTiles(Array<ivec2, ivec2>& tiles) const; bool RetrieveTiles(Array<ivec2, ivec2>& tiles) const;


/* Rendering */
bool Stock(char const *desc);
bool RenderBayer(ivec2 size);
bool RenderHalftone(ivec2 size);
bool RenderRandom(ivec2 size);

/* Image processing */



private: private:
class ImageData *m_data; class ImageData *m_data;
}; };


Loading…
Cancel
Save