From ad07a2da5116f1aa220685ec6ffa42310b586ada Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 May 2015 16:34:37 -0400 Subject: [PATCH 1/5] Added colormap attribute to af::Window This attribute will affect rendering of images currently. --- include/af/defines.h | 11 +++++++++++ include/af/graphics.h | 3 +++ src/api/c/image.cpp | 1 + src/api/cpp/graphics.cpp | 19 ++++++++++++------- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/include/af/defines.h b/include/af/defines.h index 7439a5216e..7af55c3f9f 100644 --- a/include/af/defines.h +++ b/include/af/defines.h @@ -272,6 +272,16 @@ typedef enum { AF_MAT_BLOCK_DIAG = 8192 ///< Matrix is block diagonal } af_mat_prop; +typedef enum { + AF_COLORMAP_DEFAULT = 0, ///< Default grayscale map + AF_COLORMAP_SPECTRUM= 1, ///< Spectrum map + AF_COLORMAP_COLORS = 2, ///< Colors + AF_COLORMAP_RED = 3, ///< Red hue map + AF_COLORMAP_MOOD = 4, ///< Mood map + AF_COLORMAP_HEAT = 5, ///< Heat map + AF_COLORMAP_BLUE = 6 ///< Blue hue map +} af_colormap; + // Below enum is purely added for example purposes // it doesn't and shoudn't be used anywhere in the // code. No Guarantee's provided if it is used. @@ -296,6 +306,7 @@ namespace af typedef af_conv_mode convMode; typedef af_conv_domain convDomain; typedef af_mat_prop matProp; + typedef af_colormap ColorMap; } #endif diff --git a/include/af/graphics.h b/include/af/graphics.h index 9e0820d36b..64343f5613 100644 --- a/include/af/graphics.h +++ b/include/af/graphics.h @@ -18,6 +18,7 @@ typedef struct { int row; int col; const char* title; + af_colormap cmap; } af_cell; #ifdef __cplusplus @@ -32,6 +33,7 @@ class AFAPI Window { * cell in the grid is being rendered currently */ int _r; int _c; + ColorMap _cmap; void initWindow(const int width, const int height, const char* const title); @@ -45,6 +47,7 @@ class AFAPI Window { af_window get() const { return wnd; } void setPos(const unsigned x, const unsigned y); void setTitle(const char* const title); + void setColorMap(const ColorMap cmap); void image(const array& in, const char* title=NULL); void plot(const array& X, const array& Y, const char* const title=NULL); diff --git a/src/api/c/image.cpp b/src/api/c/image.cpp index b823c9fc57..d51ac9c0cf 100644 --- a/src/api/c/image.cpp +++ b/src/api/c/image.cpp @@ -81,6 +81,7 @@ af_err af_draw_image(const af_window wind, const af_array in, const af_cell* con default: TYPE_ERROR(1, type); } + window->setColorMap((fg::ColorMap)props->cmap); if (props->col>-1 && props->row>-1) window->draw(props->col, props->row, *image, props->title); else diff --git a/src/api/cpp/graphics.cpp b/src/api/cpp/graphics.cpp index cbc8995b81..6e4f3aa559 100644 --- a/src/api/cpp/graphics.cpp +++ b/src/api/cpp/graphics.cpp @@ -20,25 +20,25 @@ void Window::initWindow(const int width, const int height, const char* const tit } Window::Window() - : wnd(0), _r(-1), _c(-1) + : wnd(0), _r(-1), _c(-1), _cmap(AF_COLORMAP_DEFAULT) { initWindow(1280, 720, "ArrayFire"); } Window::Window(const char* const title) - : wnd(0), _r(-1), _c(-1) + : wnd(0), _r(-1), _c(-1), _cmap(AF_COLORMAP_DEFAULT) { initWindow(1280, 720, title); } Window::Window(const int width, const int height, const char* const title) - : wnd(0), _r(-1), _c(-1) + : wnd(0), _r(-1), _c(-1), _cmap(AF_COLORMAP_DEFAULT) { initWindow(width, height, title); } Window::Window(const af_window window) - : wnd(window), _r(-1), _c(-1) + : wnd(window), _r(-1), _c(-1), _cmap(AF_COLORMAP_DEFAULT) { } @@ -57,21 +57,26 @@ void Window::setTitle(const char* const title) AF_THROW(af_set_title(get(), title)); } +void Window::setColorMap(const ColorMap cmap) +{ + _cmap = cmap; +} + void Window::image(const array& in, const char* const title) { - af_cell temp{_r, _c, title}; + af_cell temp{_r, _c, title, _cmap}; AF_THROW(af_draw_image(get(), in.get(), &temp)); } void Window::plot(const array& X, const array& Y, const char* const title) { - af_cell temp{_r, _c, title}; + af_cell temp{_r, _c, title, AF_COLORMAP_DEFAULT}; AF_THROW(af_draw_plot(get(), X.get(), Y.get(), &temp)); } void Window::hist(const array& X, const double minval, const double maxval, const char* const title) { - af_cell temp{_r, _c, title}; + af_cell temp{_r, _c, title, AF_COLORMAP_DEFAULT}; AF_THROW(af_draw_hist(get(), X.get(), minval, maxval, &temp)); } From db329f1f049668f84300f0ddea3830f1b7758467 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 May 2015 16:35:27 -0400 Subject: [PATCH 2/5] Added colormap option to examples to make them look pretty --- examples/graphics/conway_pretty.cpp | 4 +++- examples/graphics/fractal.cpp | 3 ++- examples/image_processing/brain_segmentation.cpp | 1 + examples/image_processing/optical_flow.cpp | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/graphics/conway_pretty.cpp b/examples/graphics/conway_pretty.cpp index cd9257b0a8..5b40990745 100644 --- a/examples/graphics/conway_pretty.cpp +++ b/examples/graphics/conway_pretty.cpp @@ -40,6 +40,8 @@ int main(int argc, char *argv[]) af::Window simpleWindow(512, 512, "Conway's Game Of Life - Current State"); af::Window prettyWindow(512, 512, "Conway's Game Of Life - Visualizing States"); + simpleWindow.setPos(25, 25); + prettyWindow.setPos(125, 15); int frame_count = 0; @@ -50,7 +52,7 @@ int main(int argc, char *argv[]) array display = tile(state, 1, 1, 3, 1); - while(!simpleWindow.close() || !prettyWindow.close()) { + while(!simpleWindow.close() && !prettyWindow.close()) { af::timer delay = timer::start(); if(!simpleWindow.close()) simpleWindow.image(state); diff --git a/examples/graphics/fractal.cpp b/examples/graphics/fractal.cpp index ba4519bf18..a68f1c16e3 100644 --- a/examples/graphics/fractal.cpp +++ b/examples/graphics/fractal.cpp @@ -73,10 +73,11 @@ int main(int argc, char **argv) info(); printf("** ArrayFire Fractals Demo **\n"); af::Window wnd("Fractal Demo"); + wnd.setColorMap(AF_COLORMAP_SPECTRUM); float center[] = {-0.5, 0}; // Keep zomming out for each frame - for (int zoom = 1000; zoom > 10; zoom -= 5) { + for (int zoom = 1000; zoom > 100; zoom -= 1) { // Generate the grid at the current zoom factor array c = complex_grid(WIDTH, HEIGHT, zoom, center); diff --git a/examples/image_processing/brain_segmentation.cpp b/examples/image_processing/brain_segmentation.cpp index af6dc987e3..92c29bdd90 100644 --- a/examples/image_processing/brain_segmentation.cpp +++ b/examples/image_processing/brain_segmentation.cpp @@ -91,6 +91,7 @@ array segment_volume(array A, int k) void brain_seg(bool console) { af::Window wnd("Brain Segmentation Demo"); + wnd.setColorMap(AF_COLORMAP_HEAT); double time_total = 30; // run for N seconds diff --git a/examples/image_processing/optical_flow.cpp b/examples/image_processing/optical_flow.cpp index 190bd9cce5..5c4b60b33e 100644 --- a/examples/image_processing/optical_flow.cpp +++ b/examples/image_processing/optical_flow.cpp @@ -38,6 +38,7 @@ static void diffs(array& Ix, array& Iy, array& It, array I1, array I2) static void optical_flow_demo(bool console) { af::Window wnd("Horn-Schunck Optical Flow Demo"); + wnd.setColorMap(AF_COLORMAP_COLORS); double time_total = 10; // run for N seconds From c8da0c3a8cc760c1ac107d7dd86ada65b473e489 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 May 2015 16:39:20 -0400 Subject: [PATCH 3/5] Corrected doxygen group tag for matchTemplate C++ API --- include/af/image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/af/image.h b/include/af/image.h index 6ad44c34f5..56bf58c183 100644 --- a/include/af/image.h +++ b/include/af/image.h @@ -320,7 +320,7 @@ AFAPI array regions(const array& in, const af::connectivity connectivity=AF_CONN \note If \p search_img is 3d array, a batch operation will be performed. - \ingroup image_func_match_template + \ingroup cv_func_match_template */ AFAPI array matchTemplate(const array &searchImg, const array &templateImg, const matchType mType=AF_SAD); From 545971655725ebdf4925d18ee54bcf394b8ea82b Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 May 2015 18:28:57 -0400 Subject: [PATCH 4/5] Documentation for af::Window class and graphics C API --- docs/details/graphics.dox | 23 ++++ include/af/graphics.h | 254 +++++++++++++++++++++++++++++++++++++- include/arrayfire.h | 15 +++ 3 files changed, 288 insertions(+), 4 deletions(-) create mode 100644 docs/details/graphics.dox diff --git a/docs/details/graphics.dox b/docs/details/graphics.dox new file mode 100644 index 0000000000..5fa083fc4c --- /dev/null +++ b/docs/details/graphics.dox @@ -0,0 +1,23 @@ +/** + +\addtogroup graphics_func +@{ + +A list of graphics functions to visualize data + +\defgroup gfx_func_window Window Functions +@{ + +Window creation, modification and destruction functions. + +@} + +\defgroup gfx_func_draw Rendering Functions +@{ + +Rendering functions to draw images, plots etc. + +@} + +@} +*/ diff --git a/include/af/graphics.h b/include/af/graphics.h index 64343f5613..675082d654 100644 --- a/include/af/graphics.h +++ b/include/af/graphics.h @@ -25,7 +25,13 @@ typedef struct { namespace af { - // FIXME handle copying properly +/** + \class Window + + \brief Window object to render af::arrays + + \ingroup graphics_func + */ class AFAPI Window { private: af_window wnd; @@ -38,25 +44,137 @@ class AFAPI Window { void initWindow(const int width, const int height, const char* const title); public: + /** + Creates a window object with default width + and height with title set to "ArrayFire" + */ Window(); + + /** + Creates a window object with default width + and height using the title provided by the user + + \param[in] title is the window title + */ Window(const char* const title); + + /** + Creates a window object using the parameters + provided by the user + + \param[in] width is the window width + \param[in] height is the window height + \param[in] title is the window title with default value as "ArrayFire" + */ Window(const int width, const int height, const char* const title="ArrayFire"); + + /** + Creates a window object with default width + and height with title set to "ArrayFire" + + \param[in] wnd is an \ref af_window handle which can be retrieved by + doing a get call on any \ref Window object + */ Window(const af_window wnd); + /** + Destroys the window handle + */ ~Window(); + // FIXME handle copying properly + + /** + \return Returns the \ref af_window window handle. + */ af_window get() const { return wnd; } + + /** + Set the start position where the window will appear + + \param[in] x is horizontal coordinate + \param[in] y is vertical coordinate + */ void setPos(const unsigned x, const unsigned y); + + /** + Set the window title + + \param[in] title is the window title + */ void setTitle(const char* const title); + + /** + Set the colormap to be used for subsequent rendering calls + + \param[in] cmap should be one of the enum values from \ref ColorMap + */ void setColorMap(const ColorMap cmap); + /** + Renders the input array as an image to the window + + \param[in] in is an \ref array + \param[in] title parameter is used when this function is called in grid mode + + \note \p in should be 2d array or 3d array with 3 channels. + */ void image(const array& in, const char* title=NULL); + + /** + Renders the input arrays as a 2D plot to the window + + \param[in] X is an \ref array with the x-axis data points + \param[in] Y is an \ref array with the y-axis data points + \param[in] title parameter is used when this function is called in grid mode + + \note \p X and \p Y should be vectors. + */ void plot(const array& X, const array& Y, const char* const title=NULL); + + /** + Renders the input array as a histogram to the window + + \param[in] X is the data frequency \ref array + \param[in] minval is the value of the minimum data point of the array whose histogram(\p X) is going to be rendered. + \param[in] maxval is the value of the maximum data point of the array whose histogram(\p X) is going to be rendered. + + \note \p X should be a vector. + */ void hist(const array& X, const double minval, const double maxval, const char* const title=NULL); + + /** + Setup grid layout for multiview mode in a window + + \param[in] rows is number of rows you want to show in a window + \param[in] cols is number of coloumns you want to show in a window + */ void grid(const int rows, const int cols); + + /** + This function swaps the background buffer to current view + and polls for any key strokes while the window was in focus + */ void show(); + /** + To check if window is marked for close. This usually + happens when user presses ESC key while the window is in focus. + + \return \ref AF_SUCCESS if window show is successful, otherwise an appropriate error code + is returned. + */ bool close(); + /** + This function is used to keep track of which cell in the grid mode is + being currently rendered. When a user does Window(0,0), we internally + store the cell coordinates and return an reference to the very object that + called upon this function. This reference can be used later to issue + draw calls using rendering functions. + + \return returns a reference to the object pointed by this + to enable cascading this call with rendering functions. + */ inline Window& operator()(const int r, const int c) { _r = r; _c = c; return *this; @@ -70,24 +188,152 @@ class AFAPI Window { extern "C" { #endif +/** + C Interface wrapper for creating a window + + \param[out] out is the handle to the created window + \param[in] width is the width of the window that will be created + \param[in] height is the height of the window that will be created + \param[in] title is the window title + + \return \ref AF_SUCCESS if window creation is successful, otherwise an appropriate error code + is returned. + + \ingroup gfx_window_func +*/ AFAPI af_err af_create_window(af_window *out, const int width, const int height, const char* const title); +/** + C Interface wrapper for setting the start position when window display + + \param[in] wind is the window handle + \param[in] x is horizontal start coordinate + \param[in] y is vertical start coordinate + + \return \ref AF_SUCCESS if set position for window is successful, otherwise an appropriate error code + is returned. + + \ingroup gfx_func_window +*/ AFAPI af_err af_set_position(const af_window wind, const unsigned x, const unsigned y); +/** + C Interface wrapper for setting window title + + \param[in] wind is the window handle + \param[in] title is title of the window + + \return \ref AF_SUCCESS if set title for window is successful, otherwise an appropriate error code + is returned. + + \ingroup gfx_func_window +*/ AFAPI af_err af_set_title(const af_window wind, const char* const title); +/** + C Interface wrapper for drawing an array as an image + + \param[in] wind is the window handle + \param[in] in is an \ref af_array + \param[in] props is structure \ref af_cell that has the properties that are used + for the current rendering. + + \return \ref AF_SUCCESS if rendering is successful, otherwise an appropriate error code + is returned. + + \note \p in should be 2d array or 3d array with 3 channels. + + \ingroup gfx_func_draw +*/ AFAPI af_err af_draw_image(const af_window wind, const af_array in, const af_cell* const props); +/** + C Interface wrapper for drawing an array as a plot + + \param[in] wind is the window handle + \param[in] X is an \ref af_array with the x-axis data points + \param[in] Y is an \ref af_array with the y-axis data points + \param[in] props is structure \ref af_cell that has the properties that are used + for the current rendering. + + \return \ref AF_SUCCESS if rendering is successful, otherwise an appropriate error code + is returned. + + \note \p X and \p Y should be vectors. + + \ingroup gfx_func_draw +*/ AFAPI af_err af_draw_plot(const af_window wind, const af_array X, const af_array Y, const af_cell* const props); -AFAPI af_err af_draw_hist(const af_window window, const af_array X, const double minval, const double maxval, const af_cell* const props); +/** + C Interface wrapper for drawing an array as a histogram + + \param[in] wind is the window handle + \param[in] X is the data frequency \ref af_array + \param[in] minval is the value of the minimum data point of the array whose histogram(\p X) is going to be rendered. + \param[in] maxval is the value of the maximum data point of the array whose histogram(\p X) is going to be rendered. + \param[in] props is structure \ref af_cell that has the properties that are used + for the current rendering. + \return \ref AF_SUCCESS if rendering is successful, otherwise an appropriate error code + is returned. + + \note \p X should be a vector. + + \ingroup gfx_func_draw +*/ +AFAPI af_err af_draw_hist(const af_window wind, const af_array X, const double minval, const double maxval, const af_cell* const props); + +/** + C Interface wrapper for grid setup in a window + + \param[in] wind is the window handle + \param[in] rows is number of rows you want to show in a window + \param[in] cols is number of coloumns you want to show in a window + + \return \ref AF_SUCCESS if grid setup for window is successful, otherwise an appropriate error code + is returned. + + \ingroup gfx_func_window +*/ AFAPI af_err af_grid(const af_window wind, const int rows, const int cols); -AFAPI af_err af_show(const af_window window); +/** + C Interface wrapper for showing a window + + \param[in] wind is the window handle + + \return \ref AF_SUCCESS if window show is successful, otherwise an appropriate error code + is returned. + + \ingroup gfx_func_window +*/ +AFAPI af_err af_show(const af_window wind); + +/** + C Interface wrapper for checking if window is marked for close + + \param[out] out is a boolean which indicates whether window is marked for close. This usually + happens when user presses ESC key while the window is in focus. + \param[in] wind is the window handle + + \return \ref AF_SUCCESS if \p wind show is successful, otherwise an appropriate error code + is returned. + + \ingroup gfx_func_window +*/ +AFAPI af_err af_is_window_closed(bool *out, const af_window wind); + +/** + C Interface wrapper for destroying a window handle + + \param[in] wind is the window handle -AFAPI af_err af_is_window_closed(bool *out, const af_window window); + \return \ref AF_SUCCESS if window destroy is successful, otherwise an appropriate error code + is returned. + \ingroup gfx_func_window +*/ AFAPI af_err af_destroy_window(const af_window wind); #ifdef __cplusplus diff --git a/include/arrayfire.h b/include/arrayfire.h index 3b16cf271b..63a6ce015e 100644 --- a/include/arrayfire.h +++ b/include/arrayfire.h @@ -15,6 +15,10 @@ @{ @} +\defgroup graphics_func Graphics +@{ +@} + @defgroup func_categories ArrayFire Functions by Category @{ @@ -222,6 +226,17 @@ \example rbm.cpp \example deep_belief_net.cpp \example logistic_regression.cpp +\example conway.cpp +\example conway_pretty.cpp +\example fractal.cpp +\example histogram.cpp +\example plot2d.cpp +\example brain_segmentation.cpp +\example image_demo.cpp +\example morphing.cpp +\example optical_flow.cpp +\example pyramids.cpp +\example edge.cpp */ #include "af/compatible.h" From a8dfa172502542dc0039770f37a06f29b8600357 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 May 2015 20:26:19 -0400 Subject: [PATCH 5/5] BUGFIX in jit opencl cl::Program and cl::Kernel are created on heap instead of stack. Having them created on stack is causing issues on windows for Intel OpenCL devices. --- src/backend/opencl/jit.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/backend/opencl/jit.cpp b/src/backend/opencl/jit.cpp index d232ff9611..a00bfba378 100644 --- a/src/backend/opencl/jit.cpp +++ b/src/backend/opencl/jit.cpp @@ -129,8 +129,8 @@ static Kernel getKernel(Node *node, bool is_linear) string funcName = getFuncName(node, is_linear, &is_dbl); typedef struct { - Program prog; - Kernel ker; + Program* prog; + Kernel* ker; } kc_entry_t; typedef std::map kc_t; @@ -145,16 +145,17 @@ static Kernel getKernel(Node *node, bool is_linear) const char *ker_strs[] = {jit_cl, jit_ker.c_str()}; const int ker_lens[] = {jit_cl_len, (int)jit_ker.size()}; - - buildProgram(entry.prog, 2, ker_strs, ker_lens, is_dbl ? string(" -D USE_DOUBLE") : string("")); - entry.ker = Kernel(entry.prog, funcName.c_str()); + cl::Program prog; + buildProgram(prog, 2, ker_strs, ker_lens, is_dbl ? string(" -D USE_DOUBLE") : string("")); + entry.prog = new cl::Program(prog); + entry.ker = new Kernel(*entry.prog, funcName.c_str()); kernelCaches[device][funcName] = entry; } else { entry = idx->second; } - return entry.ker; + return *entry.ker; } void evalNodes(Param &out, Node *node)