# HG changeset patch # User Rik # Date 1398555560 25200 # Node ID 44f0d1a53eada384767b16005cba7ed13c5ea20b # Parent 8c537222f1e5941e19e30130b822906d615cb851 Add support for integer data types for image cdata. * gl-render.cc (draw_image): Add support for 'single' data type by converting FloatNDArray to GLfloat. * graphics.cc (convert_cdata_2): Change function signature to add is_real parameter. Convert data from 1-based indexing to 0-based indexing only if is_real is true. * graphics.cc (convert_cdata_1): Change function signature to add is_real parameter. Pass is_real through to convert_cdata_2. * graphics.cc (convert_cdata): Change CONVERT_CDATA_1 macro to support IS_REAL argument. Pass IS_REAL through to convert_cdata_1. Add support for uint16 data type. * image.m: Remove hack converting all integer cdata to single data type. diff -r 8c537222f1e5 -r 44f0d1a53ead libinterp/corefcn/gl-render.cc --- a/libinterp/corefcn/gl-render.cc Sat Apr 26 13:12:35 2014 -0700 +++ b/libinterp/corefcn/gl-render.cc Sat Apr 26 16:39:20 2014 -0700 @@ -2692,7 +2692,7 @@ glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0); // by default this is 4 - glPixelStorei (GL_UNPACK_ALIGNMENT,1); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // Expect RGB data if (dv.length () == 3 && dv(2) == 3) @@ -2716,6 +2716,44 @@ draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a); } + else if (cdata.is_single_type ()) + { + const FloatNDArray xcdata = cdata.float_array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + a[idx] = xcdata(i,j,0); + a[idx+1] = xcdata(i,j,1); + a[idx+2] = xcdata(i,j,2); + } + } + + draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a); + + } + else if (cdata.is_uint8_type ()) + { + const uint8NDArray xcdata = cdata.uint8_array_value (); + + OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + a[idx] = xcdata(i,j,0); + a[idx+1] = xcdata(i,j,1); + a[idx+2] = xcdata(i,j,2); + } + } + + draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a); + + } else if (cdata.is_uint16_type ()) { const uint16NDArray xcdata = cdata.uint16_array_value (); @@ -2735,26 +2773,8 @@ draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a); } - else if (cdata.is_uint8_type ()) - { - const uint8NDArray xcdata = cdata.uint8_array_value (); - - OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - a[idx] = xcdata(i,j,0); - a[idx+1] = xcdata(i,j,1); - a[idx+2] = xcdata(i,j,2); - } - } - - draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a); - } else - warning ("opengl_renderer: invalid image data type (expected double, uint8, or uint16)"); + warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)"); } else warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)"); diff -r 8c537222f1e5 -r 44f0d1a53ead libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Sat Apr 26 13:12:35 2014 -0700 +++ b/libinterp/corefcn/graphics.cc Sat Apr 26 16:39:20 2014 -0700 @@ -748,13 +748,13 @@ } static void -convert_cdata_2 (bool is_scaled, double clim_0, double clim_1, +convert_cdata_2 (bool is_scaled, bool is_real, double clim_0, double clim_1, const double *cmapv, double x, octave_idx_type lda, octave_idx_type nc, octave_idx_type i, double *av) { if (is_scaled) x = xround ((nc - 1) * (x - clim_0) / (clim_1 - clim_0)); - else + else if (is_real) x = xround (x - 1); if (xisnan (x)) @@ -780,12 +780,13 @@ template void -convert_cdata_1 (bool is_scaled, double clim_0, double clim_1, +convert_cdata_1 (bool is_scaled, bool is_real, double clim_0, double clim_1, const double *cmapv, const T *cv, octave_idx_type lda, octave_idx_type nc, double *av) { for (octave_idx_type i = 0; i < lda; i++) - convert_cdata_2 (is_scaled, clim_0, clim_1, cmapv, cv[i], lda, nc, i, av); + convert_cdata_2 (is_scaled, is_real, + clim_0, clim_1, cmapv, cv[i], lda, nc, i, av); } static octave_value @@ -794,6 +795,7 @@ { dim_vector dv (cdata.dims ()); + // TrueColor data doesn't require conversion if (dv.length () == cdim && dv(cdim-1) == 3) return cdata; @@ -838,22 +840,32 @@ double clim_0 = clim(0); double clim_1 = clim(1); -#define CONVERT_CDATA_1(ARRAY_T, VAL_FN) \ + // FIXME: There is a lot of processing time spent just on data conversion + // both here in graphics.cc and again in gl-render.cc. There must + // be room for improvement! Here a macro expands to a templated + // function which in turn calls another function (covert_cdata_2). + // And in gl-render.cc (opengl_renderer::draw_image), only GLfloat + // is supported anyways so there is another double for loop across + // height and width to convert all of the input data to GLfloat. + +#define CONVERT_CDATA_1(ARRAY_T, VAL_FN, IS_REAL) \ do \ { \ ARRAY_T tmp = cdata. VAL_FN ## array_value (); \ \ - convert_cdata_1 (is_scaled, clim_0, clim_1, cmapv, \ + convert_cdata_1 (is_scaled, IS_REAL, clim_0, clim_1, cmapv, \ tmp.data (), lda, nc, av); \ } \ while (0) if (cdata.is_uint8_type ()) - CONVERT_CDATA_1 (uint8NDArray, uint8_); + CONVERT_CDATA_1 (uint8NDArray, uint8_, false); + else if (cdata.is_uint16_type ()) + CONVERT_CDATA_1 (uint16NDArray, uint16_, false); + else if (cdata.is_double_type ()) + CONVERT_CDATA_1 (NDArray, , true); else if (cdata.is_single_type ()) - CONVERT_CDATA_1 (FloatNDArray, float_); - else if (cdata.is_double_type ()) - CONVERT_CDATA_1 (NDArray, ); + CONVERT_CDATA_1 (FloatNDArray, float_, true); else error ("unsupported type for cdata (= %s)", cdata.type_name ().c_str ()); diff -r 8c537222f1e5 -r 44f0d1a53ead scripts/image/image.m --- a/scripts/image/image.m Sat Apr 26 13:12:35 2014 -0700 +++ b/scripts/image/image.m Sat Apr 26 16:39:20 2014 -0700 @@ -139,13 +139,6 @@ function h = __img__ (hax, do_new, x, y, img, varargin) - ## FIXME: Hack for integer formats which use zero-based indexing - ## Hack favors correctness of display over size of image in memory. - ## True fix must be done in C++ code for renderer. - if (ndims (img) == 2 && (isinteger (img) || islogical (img))) - img = single (img) + 1; - endif - if (! isempty (img)) if (isempty (x))