Skip to content

Commit

Permalink
Add a warping operator for point lists.
Browse files Browse the repository at this point in the history
  • Loading branch information
Philip Rideout committed Nov 15, 2015
1 parent dd932b6 commit e451c61
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 10 deletions.
7 changes: 7 additions & 0 deletions include/heman.h
Expand Up @@ -142,6 +142,9 @@ heman_image* heman_distance_create_cpcf(heman_image* seed);
// Convert a two-band coordinate field into an unsigned distance field.
heman_image* heman_distance_from_cpcf(heman_image* cf);

// Create a two-band CPCF where each texel contains its own coordinate.
heman_image* heman_distance_identity_cpcf(int width, int height);

// Create a single-channel floating point point image from bytes, such that
// [0, 255] map to the given [minval, maxval] range.
heman_image* heman_import_u8(int width, int height, int nbands,
Expand Down Expand Up @@ -203,6 +206,10 @@ void heman_ops_accumulate(heman_image* dst, heman_image* src);
// Use FBM and Perlin noise to warp the given image.
heman_image* heman_ops_warp(heman_image* src, int seed, int octaves);

// Same as ops_warp, but alos applies the warping operation to a point list.
heman_image* heman_ops_warp_points(heman_image* src, int seed, int octaves,
heman_points* pts);

// Consume a 3-band image and a color of interest; produce a 1-band image.
heman_image* heman_ops_extract_mask(heman_image* src, heman_color color, int invert);

Expand Down
22 changes: 14 additions & 8 deletions src/distance.c
Expand Up @@ -218,10 +218,22 @@ heman_image* heman_distance_create_df(heman_image* src)
return positive;
}

heman_image* heman_distance_identity_cpcf(int width, int height)
{
heman_image* retval = heman_image_create(width, height, 2);
HEMAN_FLOAT* cdata = retval->data;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
*cdata++ = x;
*cdata++ = y;
}
}
return retval;
}

heman_image* heman_distance_create_cpcf(heman_image* src)
{
heman_image* negative = heman_image_create(src->width, src->height, 1);
heman_image* coordfield = heman_image_create(src->width, src->height, 2);
int size = src->height * src->width;
HEMAN_FLOAT* nptr = negative->data;
HEMAN_FLOAT* sptr = src->data;
Expand All @@ -232,13 +244,7 @@ heman_image* heman_distance_create_cpcf(heman_image* src)
}
*nptr++ = val ? 0 : INF;
}
HEMAN_FLOAT* cdata = coordfield->data;
for (int y = 0; y < src->height; y++) {
for (int x = 0; x < src->width; x++) {
*cdata++ = x;
*cdata++ = y;
}
}
heman_image* coordfield = heman_distance_identity_cpcf(src->width, src->height);
transform_to_coordfield(negative, coordfield);
heman_image_destroy(negative);
return coordfield;
Expand Down
46 changes: 44 additions & 2 deletions src/ops.c
Expand Up @@ -200,14 +200,16 @@ heman_image* heman_ops_sobel(heman_image* img, heman_color rgb)
return result;
}

heman_image* heman_ops_warp(heman_image* img, int seed, int octaves)
heman_image* heman_ops_warp_core(heman_image* img, heman_image* secondary,
int seed, int octaves)
{
struct osn_context* ctx;
open_simplex_noise(seed, &ctx);
int width = img->width;
int height = img->height;
int nbands = img->nbands;
heman_image* result = heman_image_create(width, height, nbands);
heman_image* result2 = secondary ? heman_image_create(width, height, secondary->nbands) : 0;
HEMAN_FLOAT invw = 1.0 / width;
HEMAN_FLOAT invh = 1.0 / height;
HEMAN_FLOAT inv = MIN(invw, invh);
Expand Down Expand Up @@ -251,13 +253,53 @@ heman_image* heman_ops_warp(heman_image* img, int seed, int octaves)
for (int n = 0; n < nbands; n++) {
*dst++ = *src++;
}
if (secondary) {
src = heman_image_texel(secondary, x, y);
HEMAN_FLOAT* dst2 = heman_image_texel(result2, i, j);
for (int n = 0; n < secondary->nbands; n++) {
*dst2++ = *src++;
}
}
}
}

open_simplex_noise_free(ctx);
if (secondary) {
free(secondary->data);
secondary->data = result2->data;
free(result2);
}
return result;
}

heman_image* heman_ops_warp_points(heman_image* img, int seed, int octaves,
heman_points* pts)
{
int width = img->width;
int height = img->height;
heman_image* mapping = heman_distance_identity_cpcf(width, height);
heman_image* retval = heman_ops_warp_core(img, mapping, seed, octaves);
HEMAN_FLOAT* src = pts->data;
for (int k = 0; k < pts->width; k++, src += pts->nbands) {
HEMAN_FLOAT x = src[0];
HEMAN_FLOAT y = src[1];
int i = x * mapping->width;
int j = y * mapping->height;
if (i < 0 || i >= mapping->width || j < 0 || j >= mapping->height) {
continue;
}
HEMAN_FLOAT* texel = heman_image_texel(mapping, i, j);
src[0] = texel[0] / mapping->width;
src[1] = texel[1] / mapping->height;
}
heman_image_destroy(mapping);
return retval;
}

heman_image* heman_ops_warp(heman_image* img, int seed, int octaves)
{
return heman_ops_warp_core(img, 0, seed, octaves);
}

heman_image* heman_ops_extract_mask(heman_image* source, heman_color color, int invert)
{
assert(source->nbands == 3);
Expand Down

0 comments on commit e451c61

Please sign in to comment.