changeset 25980:221c039aa415

Fix rendering of images with permuted x/ydata (bug #49756). * gl-render.cc (opengl_renderer::draw_image): Sort xdata and ydata before computing pixel dimensions and flip dimensions if necessary. * genpropdoc.m: Use "[x/yfirst x/ylast]" instead of "[x/ymin x/ymax]" in documentation for clarity. * imshow.m: Ditto.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Sun, 28 Oct 2018 21:56:40 +0100
parents 69a160d7ab68
children 63b3d5e4e5c3
files doc/interpreter/genpropdoc.m libinterp/corefcn/gl-render.cc scripts/image/imagesc.m scripts/image/imshow.m
diffstat 4 files changed, 80 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/genpropdoc.m	Mon Oct 29 21:56:08 2018 -0700
+++ b/doc/interpreter/genpropdoc.m	Sun Oct 28 21:56:40 2018 +0100
@@ -1150,7 +1150,7 @@
         s.valid = valid_cellstring;
 
       case "xdata"
-        s.doc = "Two-element vector @code{[xmin xmax]} specifying the x \
+        s.doc = "Two-element vector @code{[xfirst xlast]} specifying the x \
 coordinates of the centers of the first and last columns of the image.\n\
 \n\
 Setting @code{xdata} to the empty matrix ([]) will restore the default value \
@@ -1158,7 +1158,7 @@
         s.valid = valid_2elvec;
 
       case "ydata"
-        s.doc = "Two-element vector @code{[ymin ymax]} specifying the y \
+        s.doc = "Two-element vector @code{[yfirst ylast]} specifying the y \
 coordinates of the centers of the first and last rows of the image.\n\
 \n\
 Setting @code{ydata} to the empty matrix ([]) will restore the default value \
--- a/libinterp/corefcn/gl-render.cc	Mon Oct 29 21:56:08 2018 -0700
+++ b/libinterp/corefcn/gl-render.cc	Sun Oct 28 21:56:40 2018 +0100
@@ -3776,10 +3776,23 @@
     if (x.isempty () || y.isempty ())
       return;
 
-    if (w > 1 && x(1) == x(0))
+    // Sort x/ydata and mark flipped dimensions
+    bool xflip = false;
+    if (x(0) > x(1))
+      {
+        std::swap (x(0), x(1));
+        xflip = true;
+      }
+    else if (w > 1 && x(1) == x(0))
       x(1) = x(1) + (w-1);
-
-    if (h > 1 && y(1) == y(0))
+    
+    bool yflip = false;
+    if (y(0) > y(1))
+      {
+        std::swap (y(0), y(1));
+        yflip = true;
+      }
+    else if (h > 1 && y(1) == y(0))
       y(1) = y(1) + (h-1);
 
     const ColumnVector p0 = xform.transform (x(0), y(0), 0);
@@ -3824,7 +3837,7 @@
     // OpenGL won't draw any of the image if its origin is outside the
     // viewport/clipping plane so we must do the clipping ourselves.
 
-    int j0, j1, i0, i1;
+    int j0, j1, jj, i0, i1, ii;
     j0 = 0, j1 = w;
     i0 = 0, i1 = h;
 
@@ -3872,9 +3885,19 @@
               {
                 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);
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+                    
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+                      
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
                   }
               }
 
@@ -3891,9 +3914,19 @@
               {
                 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);
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+                    
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+                      
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
                   }
               }
 
@@ -3910,9 +3943,19 @@
               {
                 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);
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+                    
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+                      
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
                   }
               }
 
@@ -3929,9 +3972,19 @@
               {
                 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);
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+                    
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+                      
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
                   }
               }
 
--- a/scripts/image/imagesc.m	Mon Oct 29 21:56:08 2018 -0700
+++ b/scripts/image/imagesc.m	Sun Oct 28 21:56:40 2018 +0100
@@ -35,8 +35,8 @@
 ## If a range is specified as @w{@code{[max, min]}} then the image will be
 ## reversed along that axis.  For convenience, @var{x} and @var{y} may be
 ## specified as N-element vectors matching the length of the data in @var{img}.
-## However, only the first and last elements will be used to determine the axis
-## limits.
+## However, only the first and last elements will be used to determine
+## the image limits.
 ##
 ## The optional return value @var{h} is a graphics handle to the image.
 ##
--- a/scripts/image/imshow.m	Mon Oct 29 21:56:08 2018 -0700
+++ b/scripts/image/imshow.m	Sun Oct 28 21:56:40 2018 +0100
@@ -49,16 +49,16 @@
 ##
 ## @item @qcode{"xdata"}
 ## If @var{value1} is a 2-element vector, it must contain horizontal image
-## limits in the form [xmin, xmax], where xmin and xmax are the abscissa of
-## the centers of the corner pixels.  Otherwise @var{value1} must be a vector
-## and only the first and last elements will be used for xmin and xmax
-## respectively.
+## limits in the form [xfirst, xlast], where xfirst and xlast are the
+## abscissa of the centers of the corner pixels.  Otherwise @var{value1}
+##  must be a vector and only the first and last elements will be used
+## for xfirst and xlast respectively.
 ##
 ## @item @qcode{"ydata"}
 ## If @var{value1} is a 2-element vector, it must contain vertical image
-## limits in the form [ymin, ymax], where ymin and ymax are the ordinates of
-## the center of the corner pixels.  Otherwise @var{value1} must be a vector
-## and only the first and last elements will be used for ymin and ymax
+## limits in the form [yfirst, ylast], where yfirst and ylast are the ordinates
+## of the center of the corner pixels.  Otherwise @var{value1} must be a vector
+## and only the first and last elements will be used for yfirst and ylast
 ## respectively.
 ##
 ## @end table