This file is indexed.

/usr/share/octave/packages/image-2.4.1/imhist.m is in octave-image 2.4.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
## Copyright (C) 2011, 2012 Carnë Draug <carandraug+dev@gmail.com>
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 3 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, see <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn  {Function File} {} imhist (@var{I})
## @deftypefnx {Function File} {} imhist (@var{I}, @var{n})
## @deftypefnx {Function File} {} imhist (@var{X}, @var{cmap})
## @deftypefnx {Function File} {[@var{counts}, @var{x}] =} imhist (@dots{})
## Produce histogram counts of image @var{I}.
##
## The second argument can either be @var{n}, a scalar that specifies the number
## of bins; or @var{cmap}, a colormap in which case @var{X} is expected to be
## an indexed image. If not specified, @var{n} defaults to 2 for binary images,
## and 256 for grayscale images.
##
## If output is requested, @var{counts} is the number of counts for each bin and
## @var{x} is a range for the bins so that @code{stem (@var{x}, @var{counts})} will
## show the histogram.
##
## @emph{Note:} specially high peaks that may prevent an overview of the histogram
## may not be displayed.  To avoid this, use @code{axis "auto y"} after the call
## to @code{imhist}.
##
## @seealso{hist, histc, histeq}
## @end deftypefn

function [varargout] = imhist (img, b)

  ## "img" can be a normal or indexed image. We need to check "b" to find out
  indexed = false;

  if (nargin < 1 || nargin > 2)
    print_usage;

  elseif (nargin == 1)
    if (islogical (img))
      b = 2;
    else
      b = 256;
    endif

  elseif (nargin == 2)
    if (iscolormap (b))
      if (!isind(img))
        error ("imhist: second argument is a colormap but first argument is not an indexed image.");
      endif
      indexed = true;
      ## an indexed image reads differently wether it's uint8/16 or double
      ## If uint8/16, index+1 is the colormap row number (0 on the image
      ## corresponds to the 1st column on the colormap).
      ## If double, index is the colormap row number (no offset).
      ## isind above already checks for double/uint8/uint16 so we can use isinteger
      ## and isfloat safely
      if ( (isfloat   (img) && max (img(:)) > rows(b)  ) ||
           (isinteger (img) && max (img(:)) > rows(b)-1) )
        warning ("imhist: largest index in image exceeds length of colormap.");
      endif
    elseif (isnumeric (b) && isscalar (b) && fix(b) == b && b > 0)
      if (islogical (img) && b != 2)
        error ("imhist: there can only be 2 bins when input image is binary")
      endif
    else
      error ("imhist: second argument must be a positive integer scalar or a colormap");
    endif
  endif

  ## prepare bins and image
  if (indexed)
    if (isinteger (img))
      bins = 0:rows(b)-1;
    else
      bins = 1:rows(b);
    endif
  else
    if (isinteger (img))
      bins  = linspace (intmin (class (img)), intmax (class (img)), b);
    elseif (islogical (img))
      bins = 0:1;
    else
      ## image must be single or double
      bins = linspace (0, 1, b);
    endif
    ## we will use this bins with histc() where their values will be edges for
    ## each bin. However, what we actually want is for their values to be the
    ## center of each bin. To do this, we decrease their values by half of bin
    ## width and will increase it back at the end of the function. We could do
    ## it on the image and it would be a single step but it would be an heavier
    ## operation since images are likely to be much longer than the bins.
    ## The use of hist() is also not simple for this since values right in the
    ## middle of two bins will go to the bottom bin (4.5 will be placed on the
    ## bin 4 instead of 5 and we must keep matlab compatibility).
    ## Of course, none of this needed for binary images.
    if (!islogical (img))
      bins_adjustment = ((bins(2) - bins(1))/2);
      bins -= bins_adjustment;
    endif
    ## matlab returns bins as one column instead of a row but only for non
    ## indexed images
    bins = bins';

    ## histc does not counts values outside the edges of the bins so we need to
    ## truncate their values.

    ## truncate the minimum... integers could in no way have a value below the
    ## minimum of their class so truncation on this side is only required for
    if (isfloat (img) && min (img(:)) < 0)
      img(img < 0) = 0;
    endif

    ## truncating the maximum... also adjusts floats above 1. We might need
    if (max (img(:)) > bins(end))
      ## bins (end) is probably a decimal number. If an image is an int, we
      ## can't assign the new value since it will be fix(). So we need to change
      ## the image class to double but that will take more memory so let's
      ## avoid it if we can
      if (fix (bins(end)) != bins(end))
        img = double (img);
      endif
      img(img > bins(end)) = bins(end);
    endif
  endif

  [nn] = histc (img(:), bins);
  if (!indexed && !islogical(img))
    bins += bins_adjustment;
  endif

  if (nargout != 0)
    varargout{1} = nn;
    varargout{2} = bins;
  else
    stem (bins, nn, "marker", "none");
    xlim ([bins(1) bins(end)]);
    box off;     # remove the box to see bar for the last bin

    ## If we have a few very high peaks, it prevents the overview of the
    ## histogram since the axis are set automatically. So we consider the
    ## automatic y axis bad if it's 10 times above the median of the
    ## histogram.
    ## The (ylimit != 0) is for cases when most of the bins is zero. In
    ## such cases, the median is zero and we'd get an error trying to set
    ## "ylim ([0 0])". We could adjust it to [0 1] but in such cases, it's
    ## probably important to show how high those few peaks are.
    ylimit = round (median (nn) * 10);
    if (ylim()(2) > ylimit && ylimit != 0)
      ylim ([0 ylimit]);
    endif
    if (indexed)
      colormap (b);
    else
      colormap (gray (b));
    endif
    colorbar ("SouthOutside", "xticklabel", []);
  endif
endfunction

%!shared nn, bb, enn, ebb
%! [nn, bb] = imhist(logical([0 1 0 0 1]));
%!assert({nn, bb}, {[3 2]', [0 1]'})
%! [nn, bb] = imhist([0 0.2 0.4 0.9 1], 5);
%!assert({nn, bb}, {[1 1 1 0 2]', [0 0.25 0.5 0.75 1]'})
%! [nn, bb] = imhist([-2 0 0.2 0.4 0.9 1 5], 5);
%!assert({nn, bb}, {[2 1 1 0 3]', [0 0.25 0.5 0.75 1]'})
%! [nn, bb] = imhist(uint8([0 32 255]), 256);
%! enn = zeros(256, 1); enn([1, 33, 256]) = 1;
%! ebb = 0:255;
%!assert({nn, bb}, {enn, ebb'})
%! [nn, bb] = imhist(int8([-50 0 100]), 31);
%! enn = zeros(31, 1); enn([10, 16, 28]) = 1;
%! ebb = -128:8.5:127;
%!assert({nn, bb}, {enn, ebb'})