commit 01ca48f4f6411ad2fd26916927707e46297c92cb
parent 1ef0c178832b421e0d0ee96841192a24a54e1c70
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 3 Apr 2017 15:11:20 +0200
Add the ssol_image_sample function
Diffstat:
2 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -92,6 +92,16 @@ enum ssol_pixel_format {
SSOL_PIXEL_FORMATS_COUNT__
};
+enum ssol_filter_mode {
+ SSOL_FILTER_LINEAR,
+ SSOL_FILTER_NEAREST
+};
+
+enum ssol_address_mode {
+ SSOL_ADDRESS_CLAMP,
+ SSOL_ADDRESS_REPEAT
+};
+
enum ssol_quadric_type {
SSOL_QUADRIC_PLANE,
SSOL_QUADRIC_PARABOL,
@@ -517,6 +527,15 @@ SSOL_API res_T
ssol_image_unmap
(const struct ssol_image* image);
+SSOL_API res_T
+ssol_image_sample
+ (const struct ssol_image* image,
+ const enum ssol_filter_mode filter,
+ const enum ssol_address_mode address_u,
+ const enum ssol_address_mode address_v,
+ const double uv[2],
+ void* val);
+
/* Helper function that matches the `ssol_write_pixels_T' functor type */
SSOL_API res_T
ssol_image_write
diff --git a/src/ssol_image.c b/src/ssol_image.c
@@ -26,6 +26,26 @@
/*******************************************************************************
* Helper functions
******************************************************************************/
+static INLINE double
+map_address(const double address, const enum ssol_address_mode mode)
+{
+ double dbl;
+ double i;
+ switch(mode) {
+ case SSOL_ADDRESS_CLAMP: dbl = CLAMP(address, 0, 1); break;
+ case SSOL_ADDRESS_REPEAT: dbl = modf(address, &i); break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ return dbl;
+}
+
+static INLINE const char*
+get_pixel(const struct ssol_image* img, const size_t x, const size_t y)
+{
+ ASSERT(img && x < img->size[0] && y < img->size[1]);
+ return img->mem + y*img->pitch + x*ssol_sizeof_pixel_format(img->format);
+}
+
static void
image_release(ref_T* ref)
{
@@ -151,6 +171,57 @@ res_T ssol_image_unmap(const struct ssol_image* img)
}
res_T
+ssol_image_sample
+ (const struct ssol_image* img,
+ const enum ssol_filter_mode filter,
+ const enum ssol_address_mode address_u,
+ const enum ssol_address_mode address_v,
+ const double uv[2],
+ void* val)
+{
+ double* z00, *z01, *z10, *z11;
+ double x0, y0, x1, y1;
+ double texsz[2];
+ double s, t;
+ double* pix = val;
+ double integer;
+
+ if(!img || !uv || !val) return RES_BAD_ARG;
+
+ /* Only double3 pixel format is currently supported */
+ if(img->format != SSOL_PIXEL_DOUBLE3) return RES_BAD_ARG;
+
+ x0 = map_address(uv[0], address_u) * (double)img->size[0];
+ y0 = map_address(uv[1], address_v) * (double)img->size[1];
+
+ switch(filter) {
+ case SSOL_FILTER_NEAREST:
+ z00 = (double*)get_pixel(img, (size_t)x0, (size_t)y0);
+ pix[0] = z00[0];
+ pix[1] = z00[1];
+ pix[2] = z00[2];
+ break;
+ case SSOL_FILTER_LINEAR:
+ texsz[0] = 1.0/(double)img->size[0];
+ texsz[1] = 1.0/(double)img->size[1];
+ x1 = map_address(uv[0] + texsz[0], address_u) * (double)img->size[0];
+ y1 = map_address(uv[1] + texsz[1], address_v) * (double)img->size[1];
+ z00 = (double*)get_pixel(img, (size_t)x0, (size_t)y0);
+ z01 = (double*)get_pixel(img, (size_t)x0, (size_t)y1);
+ z10 = (double*)get_pixel(img, (size_t)x1, (size_t)y0);
+ z11 = (double*)get_pixel(img, (size_t)x1, (size_t)y1);
+ s = modf(x0, &integer);
+ t = modf(y0, &integer);
+ pix[0] = (1-s)*((1-t)*z00[0] + t*z01[0]) + s*((1-t)*z10[0] + t*z11[0]);
+ pix[1] = (1-s)*((1-t)*z00[1] + t*z01[1]) + s*((1-t)*z10[1] + t*z11[1]);
+ pix[2] = (1-s)*((1-t)*z00[2] + t*z01[2]) + s*((1-t)*z10[2] + t*z11[2]);
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ return RES_OK;
+}
+
+res_T
ssol_image_write
(void* image,
const size_t origin[2],