Browse Source

image: add YUV filter, median filter, and image cropping.

undefined
Sam Hocevar 10 years ago
parent
commit
6b9f3b66c1
10 changed files with 275 additions and 356 deletions
  1. +0
    -4
      TODO
  2. +2
    -0
      src/Makefile.am
  3. +49
    -48
      src/image/crop.cpp
  4. +0
    -93
      src/image/dither.cpp
  5. +121
    -98
      src/image/filter/median.cpp
  6. +36
    -112
      src/image/filter/yuv.cpp
  7. +39
    -0
      src/lol/image/color.h
  8. +7
    -1
      src/lol/image/image.h
  9. +3
    -0
      src/lolcore.vcxproj
  10. +18
    -0
      src/lolcore.vcxproj.filters

+ 0
- 4
TODO View File

@@ -32,18 +32,14 @@ Image:
· combine/rgb.cpp
· combine/subadd.cpp
· context.cpp
· crop.cpp
· dither.cpp
· dither/dbs.cpp
· filter/blur.cpp
· filter/color.cpp
· filter/dilate.cpp
· filter/median.cpp
· filter/rotate.cpp
· filter/sharpen.cpp
· filter/transform.cpp
· filter/wave.cpp
· filter/yuv.cpp
· paint/bezier.cpp
· paint/floodfill.cpp
· paint/line.cpp


+ 2
- 0
src/Makefile.am View File

@@ -111,6 +111,7 @@ liblolcore_sources = \
sys/thread.cpp sys/threadbase.h \
\
image/image.cpp image/image-private.h image/stock.cpp image/pixels.cpp \
image/crop.cpp \
image/codec/gdiplus-image.cpp image/codec/imlib2-image.cpp \
image/codec/sdl-image.cpp image/codec/ios-image.cpp \
image/codec/zed-image.cpp image/codec/zed-palette-image.cpp \
@@ -119,6 +120,7 @@ liblolcore_sources = \
image/dither/random.cpp image/dither/ediff.cpp \
image/dither/ostromoukhov.cpp image/dither/ordered.cpp \
image/filter/autocontrast.cpp image/filter/convolution.cpp \
image/filter/median.cpp image/filter/yuv.cpp \
image/render/noise.cpp \
\
loldebug.h \


+ 49
- 48
src/image/crop.cpp View File

@@ -1,68 +1,69 @@
/*
* libpipi Pathetic image processing interface library
* Copyright (c) 2004-2009 Sam Hocevar <sam@hocevar.net>
* 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.
//

/*
* crop.c: image cropping functions
*/
#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include "config.h"
#include "core.h"
#include "image-private.h"

#include <stdlib.h>
#include <string.h>
/*
* Image cropping functions
*/

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

pipi_image_t *pipi_crop(pipi_image_t *src, int w, int h, int dx, int dy)
Image Image::Crop(ibox2 box) const
{
float *srcdata, *dstdata;
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
int y, off, len;
ivec2 const srcsize = GetSize();
ivec2 const dstsize = box.B - box.A;

srcp = pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32);
srcdata = (float *)srcp->pixels;
Image dst(dstsize);
PixelFormat format = GetFormat();

dst = pipi_new(w, h);
dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32);
dstdata = (float *)dstp->pixels;
if (format != PixelFormat::Unknown)
{
dst.SetFormat(format);
uint8_t const *srcp = (uint8_t const *)m_data->m_pixels[(int)format];
uint8_t *dstp = (uint8_t *)dst.m_data->m_pixels[(int)format];
uint8_t bpp = BytesPerPixel(format);

off = dx;
len = w;
int len = dstsize.x;

if(dx < 0)
{
len += dx;
dx = 0;
}
if (box.A.x < 0)
{
len += box.A.x;
box.A.x = 0;
}

if(dx + len > srcp->w)
len = srcp->w - dx;
if (box.A.x + len > srcsize.x)
len = srcsize.x - box.A.x;

if(len > 0)
{
for(y = 0; y < h; y++)
if (len > 0)
{
if(y + dy < 0 || y + dy >= srcp->h)
continue;
for (int y = 0; y < dstsize.y; y++)
{
if (y + box.A.y < 0 || y + box.A.y >= srcsize.y)
continue;

memcpy(dstdata + y * w * 4,
srcdata + ((y + dy) * srcp->w + dx) * 4,
len * 4 * sizeof(float));
memcpy(dstp + y * dstsize.x * bpp,
srcp + ((y + box.A.y) * srcsize.x + box.A.x) * bpp,
len * bpp);
}
}
}

return dst;
}

} /* namespace lol */


+ 0
- 93
src/image/dither.cpp View File

@@ -1,93 +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.
*/

/*
* dither.c: dithering functions
*/

#include "config.h"

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

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

/* FIXME: this is not the right place for this... see pixels.c instead */
void pipi_dither_24to16(pipi_image_t *img)
{
int *error, *nexterror;
pipi_pixels_t *p;
uint32_t *p32;
int x, y;

error = malloc(sizeof(int) * 3 * (img->w + 2));
nexterror = malloc(sizeof(int) * 3 * (img->w + 2));
p = pipi_get_pixels(img, PIPI_PIXELS_RGBA_U8);
p32 = (uint32_t *)p->pixels;

memset(error, 0, sizeof(int) * 3 * (img->w + 2));

for(y = 0; y < img->h; y++)
{
int er = 0, eg = 0, eb = 0;

memset(nexterror, 0, sizeof(int) * 3 * (img->w + 2));

for(x = 0; x < img->w; x++)
{
int r, g, b, a, r2, g2, b2;
r = p32[y * img->w + x] & 0xff;
g = (p32[y * img->w + x] >> 8) & 0xff;
b = (p32[y * img->w + x] >> 16) & 0xff;
a = (p32[y * img->w + x] >> 24) & 0xff;
r += er + error[x * 3 + 3];
g += eg + error[x * 3 + 4];
b += eb + error[x * 3 + 5];
r2 = r / 8 * 8; g2 = g / 4 * 4; b2 = b / 8 * 8;
if(r2 < 0) r2 = 0; if(r2 > 0xf8) r2 = 0xf8;
if(g2 < 0) g2 = 0; if(g2 > 0xfc) g2 = 0xfc;
if(b2 < 0) b2 = 0; if(b2 > 0xf8) b2 = 0xf8;
/* hack */
if(r2 == 0x88 && g2 == 0x88 && b2 == 0x88) g2 = 0x84;
/* hack */
p32[y * img->w + x] = (a << 24) | (b2 << 16) | (g2 << 8) | r2;

er = r - (r2 / 8 * 255 / 31);
eg = g - (g2 / 4 * 255 / 63);
eb = b - (b2 / 8 * 255 / 31);
nexterror[x * 3 + 0] += er * 3 / 8;
nexterror[x * 3 + 1] += eg * 3 / 8;
nexterror[x * 3 + 2] += eb * 3 / 8;
nexterror[x * 3 + 3] += er * 5 / 8;
nexterror[x * 3 + 4] += eg * 5 / 8;
nexterror[x * 3 + 5] += eb * 5 / 8;
nexterror[x * 3 + 6] += er * 1 / 8;
nexterror[x * 3 + 7] += eg * 1 / 8;
nexterror[x * 3 + 8] += eb * 1 / 8;
er -= er * 3 / 8 + er * 7 / 8 + er * 1 / 8;
eg -= eg * 3 / 8 + eg * 7 / 8 + eg * 1 / 8;
eb -= eb * 3 / 8 + eb * 7 / 8 + eb * 1 / 8;
}

memcpy(error, nexterror, sizeof(int) * 3 * (img->w + 2));
}

pipi_release_pixels(img, p);

free(error);
free(nexterror);
}


+ 121
- 98
src/image/filter/median.cpp View File

@@ -1,134 +1,157 @@
/*
* 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"

/*
* median.c: median filter functions
* Median filter functions
*/

#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
/* FIXME: this is in desperate want of optimisation. Here is what could
* be done to improve the performance:
* - prefetch the neighbourhood; most neighbours are the same as the
* previous pixels.
* - use a better sort algorithm; bubble sort is ridiculous
* - even better, use state-of-the art median selection, ie. O(3n), for
* most common combinations (9, 25, 49, 81). */

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

static int cmpdouble(void const *i1, void const *i2)
static int cmpfloat(void const *i1, void const *i2)
{
double a = *(double const *)i1;
double b = *(double const *)i2;
float a = *(float const *)i1;
float b = *(float const *)i2;

return (a > b) - (a < b);
}

pipi_image_t *pipi_median(pipi_image_t *src, int radius)
Image Image::Median(ivec2 ksize) const
{
return pipi_median_ext(src, radius, radius);
}
ivec2 const size = GetSize();
Image tmp = *this;
Image ret(size);

/* FIXME: this is in desperate want of optimisation. Here is what could
* be done to improve the performance:
* - prefetch the neighbourhood; most neighbours are the same as the
* previous pixels.
* - use a better sort algorithm; bubble sort is ridiculous
* - even better, use state-of-the art median selection, ie. O(3n), for
* most common combinations (9, 25, 49, 81). */
pipi_image_t *pipi_median_ext(pipi_image_t *src, int rx, int ry)
{
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
double *list;
int x, y, w, h, i, j, size, gray;
if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
{
ivec2 const lsize = 2 * ksize + ivec2(1);
Array2D<float> list(lsize);

float *srcp = tmp.Lock<PixelFormat::Y_F32>();
float *dstp = ret.Lock<PixelFormat::Y_F32>();

w = src->w;
h = src->h;
size = (2 * rx + 1) * (2 * ry + 1);
for (int y = 0; y < size.y; y++)
{
for (int x = 0; x < size.x; x++)
{
/* Make a list of neighbours */
for (int j = -ksize.y; j <= ksize.y; j++)
{
int y2 = y + j;
if (y2 < 0) y2 = size.y - 1 - ((-y2 - 1) % size.y);
else if (y2 > 0) y2 = y2 % size.y;

gray = (src->last_modified == PIPI_PIXELS_Y_F32);
for (int i = -ksize.x; i <= ksize.x; i++)
{
int x2 = x + i;
if (x2 < 0) x2 = size.x - 1 - ((-x2 - 1) % size.x);
else if (x2 > 0) x2 = x2 % size.x;

srcp = gray ? pipi_get_pixels(src, PIPI_PIXELS_Y_F32)
: pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32);
srcdata = (float *)srcp->pixels;
list[i + ksize.x][j + ksize.y] = srcp[y2 * size.x + x2];
}
}

dst = pipi_new(w, h);
dstp = gray ? pipi_get_pixels(dst, PIPI_PIXELS_Y_F32)
: pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32);
dstdata = (float *)dstp->pixels;
/* Sort the list */
qsort(&list[0][0], lsize.x * lsize.y, sizeof(float), cmpfloat);

list = malloc(size * (gray ? 1 : 4) * sizeof(double));
/* Store the median value */
dstp[y * size.x + x] = *(&list[0][0] + lsize.x * lsize.y / 2);
}
}

for(y = 0; y < h; y++)
tmp.Unlock(srcp);
ret.Unlock(dstp);
}
else
{
for(x = 0; x < w; x++)
{
double *parser = list;
ivec2 const lsize = 2 * ksize + ivec2(1);
Array2D<vec3> list(lsize);

/* Make a list of neighbours */
for(j = -ry; j <= ry; j++)
{
int y2 = y + j;
if(y2 < 0) y2 = h - 1 - ((-y2 - 1) % h);
else if(y2 > 0) y2 = y2 % h;
vec4 *srcp = tmp.Lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.Lock<PixelFormat::RGBA_F32>();

for(i = -rx; i <= rx; i++)
for (int y = 0; y < size.y; y++)
{
for (int x = 0; x < size.x; x++)
{
/* Make a list of neighbours */
for (int j = -ksize.y; j <= ksize.y; j++)
{
int x2 = x + i;
if(x2 < 0) x2 = w - 1 - ((-x2 - 1) % w);
else if(x2 > 0) x2 = x2 % w;
int y2 = y + j;
if (y2 < 0) y2 = size.y - 1 - ((-y2 - 1) % size.y);
else if (y2 > 0) y2 = y2 % size.y;

if(gray)
for (int i = -ksize.x; i <= ksize.x; i++)
{
*parser++ = srcdata[y2 * w + x2];
int x2 = x + i;
if (x2 < 0) x2 = size.x - 1 - ((-x2 - 1) % size.x);
else if (x2 > 0) x2 = x2 % size.x;

list[i + ksize.x][j + ksize.y] = srcp[y2 * size.x + x2].rgb;
}
else
}

/* Algorithm constants, empirically chosen */
int const N = 5;
float const K = 1.5f;

/* Iterate using Weiszfeld’s algorithm */
vec3 oldmed(0.f), median(0.f);
for (int iter = 0; ; ++iter)
{
oldmed = median;
vec3 s1(0.f);
float s2 = 0.f;
for (int j = 0; j < lsize.y; ++j)
for (int i = 0; i < lsize.x; ++i)
{
float d = 1.0f / (1e-10f + distance(median, list[i][j]));
s1 += list[i][j] * d;
s2 += d;
}
median = s1 / s2;

if (iter > 1 && iter < N)
{
parser[0] = srcdata[4 * (y2 * w + x2)];
parser[size * 1] = srcdata[4 * (y2 * w + x2) + 1];
parser[size * 2] = srcdata[4 * (y2 * w + x2) + 2];
parser[size * 3] = srcdata[4 * (y2 * w + x2) + 3];
parser++;
median += K * (median - oldmed);
}
}
}

/* Sort the list */
qsort(list, size, sizeof(double), cmpdouble);
if(!gray)
{
qsort(list + size, size, sizeof(double), cmpdouble);
qsort(list + 2 * size, size, sizeof(double), cmpdouble);
qsort(list + 3 * size, size, sizeof(double), cmpdouble);
}
if (iter > 3 && distance(oldmed, median) < 1.e-5f)
break;
}

/* Store the median value */
if(gray)
{
dstdata[y * w + x] = list[size / 2];
}
else
{
dstdata[4 * (y * w + x)] = list[size / 2];
dstdata[4 * (y * w + x) + 1] = list[size / 2 + size * 1];
dstdata[4 * (y * w + x) + 2] = list[size / 2 + size * 2];
dstdata[4 * (y * w + x) + 3] = list[size / 2 + size * 3];
/* Store the median value */
dstp[y * size.x + x] = vec4(median, srcp[y * size.x + x].a);
}
}

tmp.Unlock(srcp);
ret.Unlock(dstp);
}

return dst;
return ret;
}

} /* namespace lol */


+ 36
- 112
src/image/filter/yuv.cpp View File

@@ -1,127 +1,51 @@
/*
* 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"

/*
* yuv.c: YUV conversion functions
* YUV conversion functions
*/

#include "config.h"

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

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

pipi_image_t *pipi_rgb2yuv(pipi_image_t *src)
namespace lol
{
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
int x, y, w, h;

w = src->w;
h = src->h;

srcp = pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32);
srcdata = (float *)srcp->pixels;

dst = pipi_new(w, h);
dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32);
dstdata = (float *)dstp->pixels;

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
double r, g, b, a, yp, u, v;
int d = 4 * (y * w + x);

r = srcdata[d];
g = srcdata[d + 1];
b = srcdata[d + 2];
a = srcdata[d + 3];

yp = 0.299 * r + 0.587 * g + 0.114 * b;
yp = (yp * 220.0 + 16.0) / 255.0;

u = 0.5 - 0.14713 * r - 0.28886 * g + 0.436 * b;
if (u < 0.0) u = 0.0;
if (u > 1.0) u = 1.0;

v = 0.5 + 0.615 * r - 0.51499 * g - 0.10001 * b;
if (v < 0.0) v = 0.0;
if (v > 1.0) v = 1.0;
Image Image::YUVToRGB() const
{
Image ret = *this;
int count = GetSize().x * GetSize().y;

dstdata[d] = yp;
dstdata[d + 1] = u;
dstdata[d + 2] = v;
dstdata[d + 3] = a;
}
}
vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n)
pixels[n] = Color::YUVToRGB(pixels[n]);
ret.Unlock(pixels);

return dst;
return ret;
}

pipi_image_t *pipi_yuv2rgb(pipi_image_t *src)
Image Image::RGBToYUV() const
{
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
int x, y, w, h;

w = src->w;
h = src->h;

srcp = pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32);
srcdata = (float *)srcp->pixels;
Image ret = *this;
int count = GetSize().x * GetSize().y;

dst = pipi_new(w, h);
dstp = pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32);
dstdata = (float *)dstp->pixels;
vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n)
pixels[n] = Color::RGBToYUV(pixels[n]);
ret.Unlock(pixels);

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
double r, g, b, a, yp, u, v;
int d = 4 * (y * w + x);

yp = (srcdata[d] * 255.0 - 16.0) / 220.0;
u = srcdata[d + 1] - 0.5;
v = srcdata[d + 2] - 0.5;
a = srcdata[d + 3];

r = yp + 1.13983 * v;
if (r < 0.0) r = 0.0;
if (r > 1.0) r = 1.0;
g = yp - 0.39465 * u - 0.58060 * v;
if (g < 0.0) g = 0.0;
if (g > 1.0) g = 1.0;
b = yp + 2.03211 * u;
if (b < 0.0) b = 0.0;
if (b > 1.0) b = 1.0;

dstdata[d] = r;
dstdata[d + 1] = g;
dstdata[d + 2] = b;
dstdata[d + 3] = a;
}
}

return dst;
return ret;
}

} /* namespace lol */


+ 39
- 0
src/lol/image/color.h View File

@@ -65,6 +65,45 @@ public:
return vec4(sRGBToLinearRGB(src.rgb), src.a);
}

/*
* Convert linear RGB to YUV
*/
static vec3 RGBToYUV(vec3 src)
{
mat3 m(vec3(0.299f, -0.14713f, 0.615f),
vec3(0.587f, -0.28886f, -0.51499f),
vec3(0.114f, 0.436f, -0.10001f));
vec3 tmp = m * src;
tmp.r = (tmp.r * 220.f + 16.f) / 255.f;
tmp.g += 0.5f;
tmp.b += 0.5f;
return clamp(tmp, 0.f, 1.f);
}

static vec4 RGBToYUV(vec4 src)
{
return vec4(RGBToYUV(src.rgb), src.a);
}

/*
* Convert YUV to linear RGB
*/
static vec3 YUVToRGB(vec3 src)
{
src.r = (src.r * 255.f - 16.f) / 220.f;
src.g -= 0.5f;
src.b -= 0.5f;
mat3 m(vec3(1.f, 1.f, 1.f),
vec3(0.f, -0.39465f, 2.03211f),
vec3(1.13983f, -0.58060f, 0.f));
return clamp(m * src, 0.f, 1.f);
}

static vec4 YUVToRGB(vec4 src)
{
return vec4(YUVToRGB(src.rgb), src.a);
}

/*
* Convert linear HSV to linear RGB
*/


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

@@ -95,7 +95,9 @@ public:
static Array2D<float> HalftoneKernel(ivec2 size);
static Array2D<float> EdiffKernel(EdiffAlgorithm algorithm);
static Array2D<float> NormalizeKernel(Array2D<float> const &kernel);
static Array2D<float> GaussianKernel(vec2 radius, float angle, vec2 delta);
static Array2D<float> GaussianKernel(vec2 radius,
float angle = 0.f,
vec2 delta = vec2(0.f, 0.f));

/* Rendering */
bool Stock(char const *desc);
@@ -104,6 +106,10 @@ public:
/* Image processing */
Image AutoContrast() const;
Image Convolution(Array2D<float> const &kernel);
Image Crop(ibox2 box) const;
Image Median(ivec2 radii) const;
Image YUVToRGB() const;
Image RGBToYUV() const;

Image DitherRandom() const;
Image DitherEdiff(Array2D<float> const &kernel,


+ 3
- 0
src/lolcore.vcxproj View File

@@ -151,10 +151,13 @@
<ClCompile Include="image\color\color.cpp" />
<ClCompile Include="image\filter\autocontrast.cpp" />
<ClCompile Include="image\filter\convolution.cpp" />
<ClCompile Include="image\filter\median.cpp" />
<ClCompile Include="image\filter\yuv.cpp" />
<ClCompile Include="image\dither\ediff.cpp" />
<ClCompile Include="image\dither\ordered.cpp" />
<ClCompile Include="image\dither\ostromoukhov.cpp" />
<ClCompile Include="image\dither\random.cpp" />
<ClCompile Include="image\crop.cpp" />
<ClCompile Include="image\image.cpp" />
<ClCompile Include="image\pixels.cpp" />
<ClCompile Include="image\render\noise.cpp" />


+ 18
- 0
src/lolcore.vcxproj.filters View File

@@ -88,11 +88,17 @@
<Filter Include="image\dither">
<UniqueIdentifier>{63e63eea-c96e-4d37-81f6-f3f17e18b751}</UniqueIdentifier>
</Filter>
<Filter Include="image\filter">
<UniqueIdentifier>{3f420a7d-0538-463a-925b-3f8968bf628e}</UniqueIdentifier>
</Filter>
<Filter Include="image\render">
<UniqueIdentifier>{23655fca-56e5-48ec-8cf0-a71322f4cc89}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="image\crop.cpp">
<Filter>image</Filter>
</ClCompile>
<ClCompile Include="image\image.cpp">
<Filter>image</Filter>
</ClCompile>
@@ -355,6 +361,18 @@
<ClCompile Include="sys\thread.cpp">
<Filter>sys</Filter>
</ClCompile>
<ClCompile Include="image\filter\autocontrast.cpp">
<Filter>image\filter</Filter>
</ClCompile>
<ClCompile Include="image\filter\convolution.cpp">
<Filter>image\filter</Filter>
</ClCompile>
<ClCompile Include="image\filter\median.cpp">
<Filter>image\filter</Filter>
</ClCompile>
<ClCompile Include="image\filter\yuv.cpp">
<Filter>image\filter</Filter>
</ClCompile>
<ClCompile Include="image\dither\ediff.cpp">
<Filter>image\dither</Filter>
</ClCompile>


Loading…
Cancel
Save