{"id":120,"date":"2007-03-09T07:00:55","date_gmt":"2007-03-09T12:00:55","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/09\/what-happened-to-isgray-isind-isbw-and-isrgb\/"},"modified":"2019-10-23T08:44:41","modified_gmt":"2019-10-23T12:44:41","slug":"what-happened-to-isgray-isind-isbw-and-isrgb","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/09\/what-happened-to-isgray-isind-isbw-and-isrgb\/","title":{"rendered":"What happened to isgray, isind, isbw, and isrgb?"},"content":{"rendered":"<p>In a blog comment recently, <a href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/01\/15\/a-year-of-blogging\/#comment-6503\">Rob asked<\/a> about what happened to <tt>isrgb<\/tt>.  When you run this function, it issues a warning about being obsolete. Rob asked \"What were the toolbox developers thinking?\"\r\n<\/p>\r\n\r\n<p>\r\nThe function <tt>isrgb<\/tt> is closely related to <tt>isgray<\/tt>, <tt>isind<\/tt>, and <tt>isbw<\/tt>, which are also obsolete. I thought I'd try to explain the original purpose of these functions, as well as why they are now obsolete.\r\n<\/p>\r\n\r\n<p>\r\nWhen the Image Processing Toolbox was first being created, in 1992-93, the only MATLAB data type was a two-dimensional, double-precision matrix.  There were no integer arrays, no logical arrays, etc.\r\nMany toolbox functions were intended to operate on more than one type of image: grayscale, indexed, binary, RGB.  Some functions used different algorithms or different defaults, depending upon the input image type.  Such a function might have used <tt>isgray<\/tt>, etc., like this:\r\n<\/p>\r\n\r\n<pre>\r\nfunction B = imfoobar(A)\r\n\r\nif isbw(A)\r\n  B = do_the_binary_thing(A);  \r\n\r\nelseif isind(A)\r\n  B = do_the_indexed_thing(A);\r\n\r\nelseif isgray(A)\r\n  B = do_the_grayscale_thing(A);\r\n\r\nelse\r\n  error('Try, try again'); \r\nend\r\n<\/pre>\r\n\r\n<p>\r\nThere were three problems with this coding pattern:\r\n<ul>\r\n<li> Performance <\/li>\r\n<li> Ambiguity <\/li>\r\n<li> Undesirable limits on input data <\/li>\r\n<\/ul>\r\n\r\n<p>\r\nThe performance problem was that the <tt>is*<\/tt> functions read and performed tests on every matrix value. <tt>isbw(A)<\/tt> tested to see if every element of <tt>A<\/tt> was either 0 or 1.  <tt>isind(A)<\/tt> tested to see if every value was an integer no smaller than 1.  (There were no 0-based uint8 indexed images back then.)  <tt>isgray(A)<\/tt> tested to see if every value was in the range [0.0, 1.0].  As we worked to speed up toolbox functions in the mid-90s, it became apparent that these function calls limited how fast we could get.\r\n<\/p>\r\n\r\n<p>\r\nThe ambiguity problem was simply this:  All of these functions would return true for an all-ones matrix.  Also, <tt>isgray(A)<\/tt> and <tt>isbw(A)<\/tt> would both return true for a matrix containing only zeros and ones.  There was simply no way to reliably distinguish the image types from one another based only on the matrix values.  By this time in the history of MATLAB development, we were beginning to learn hard lessons about ambiguous syntax designs.  Even seemingly benign ambiguities, such as logical indexing, or all those functions that worked down the columns (except when they didn't), were coming back to haunt us.\r\n<\/p>\r\n\r\n<p>\r\nThere's another type of ambiguity associated with these functions.  Consider a 100-by-200-by-3 array, for instance.  Is it an RGB image?  Or a YCbCr image? Maybe it's 3 slices of an MRI, or three frames from a video sequence. The function <tt>isrgb<\/tt> can't really tell.\r\n<\/p>\r\n\r\n<p>\r\nFinally, there was this important principle of Image Processing Toolbox function design:  Except for functions that MUST associate a value with a particular color, toolbox functions should make no particular assumptions about the valid range of input values.  Display functions and colorspace conversions obviously have to assign colors to matrix values.  But most toolbox functions are purely mathematical operations that don't necessarily have anything to do with color, and which can operate on any values.  Convolution (<tt>imfilter<\/tt>) is an example.  Our engineering and scientific customers aren't typically doing picture processing; they are looking at and operating on <em>data<\/em> using image processing operators.  And their <em>data<\/em> could be in any range, and often had meaningful physical units.  Because of this principle, most toolbox functions should not impose any kind of data range restriction, and therefore it generally isn't that useful to be calling <tt>isgray(A)<\/tt> to see if the input was in the range [0.0, 1.0].\r\n<\/p>\r\n\r\n<p>\r\nSo eventually we deprecated these functions, stopped using them within the toolbox, and modified toolbox syntaxes to remove ambiguities associated with testing for image type.\r\n<\/p>\r\n\r\n<p>\r\nIn most cases, the person writing the code knows the context of how the matrix or multidimensional array was created or obtained, and so knows whether the code should treat the input as RGB or YCbCr or whatever. The most common case where it makes sense to detect the image type is when you are processing image files. For example, you have a directory full of TIFF files, and some are indexed, some are RGB, etc.  In this case, I recommend that you determine the image type directly from the output of <tt>imfinfo<\/tt>.\r\n<\/p>\r\n\r\n<p>\r\nThe bottom line is that these functions promise something they can't really deliver.  If the functions weren't deprecated, people would be forever confused about how exactly they are supposed to behave, as well as when they should be used.\r\n<\/p>\r\n","protected":false},"excerpt":{"rendered":"<p>In a blog comment recently, Rob asked about what happened to isrgb.  When you run this function, it issues a warning about being obsolete. Rob asked \"What were the toolbox developers... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/09\/what-happened-to-isgray-isind-isbw-and-isrgb\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[322,326,324,328],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/120"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/comments?post=120"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/120\/revisions"}],"predecessor-version":[{"id":3518,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/120\/revisions\/3518"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}