{"id":1094,"date":"2014-07-11T13:50:40","date_gmt":"2014-07-11T17:50:40","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=1094"},"modified":"2019-11-01T11:09:26","modified_gmt":"2019-11-01T15:09:26","slug":"under-the-hood-of-imread","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2014\/07\/11\/under-the-hood-of-imread\/","title":{"rendered":"Under the hood of imread"},"content":{"rendered":"\r\n<div class=\"content\"><p>I'm going to play a small trick on you today. Try reading in this JPEG file using <tt>imread<\/tt>:<\/p><pre class=\"codeinput\">url = <span class=\"string\">'https:\/\/blogs.mathworks.com\/images\/steve\/2014\/peppers.jpg'<\/span>;\r\nrgb = imread(url);\r\nimshow(rgb)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2014\/imread_under_the_hood_01.png\" alt=\"\"> <p>So what's the trick? Well, look more closely at this file using <tt>imfinfo<\/tt>:<\/p><pre class=\"codeinput\">info = imfinfo(url)\r\n<\/pre><pre class=\"codeoutput\">\r\ninfo = \r\n\r\n                  Filename: 'https:\/\/blogs.mathworks.com\/images\/steve\/2014\/...'\r\n               FileModDate: '11-Jul-2014 14:46:33'\r\n                  FileSize: 287677\r\n                    Format: 'png'\r\n             FormatVersion: []\r\n                     Width: 512\r\n                    Height: 384\r\n                  BitDepth: 24\r\n                 ColorType: 'truecolor'\r\n           FormatSignature: [137 80 78 71 13 10 26 10]\r\n                  Colormap: []\r\n                 Histogram: []\r\n             InterlaceType: 'none'\r\n              Transparency: 'none'\r\n    SimpleTransparencyData: []\r\n           BackgroundColor: []\r\n           RenderingIntent: []\r\n            Chromaticities: []\r\n                     Gamma: []\r\n               XResolution: []\r\n               YResolution: []\r\n            ResolutionUnit: []\r\n                   XOffset: []\r\n                   YOffset: []\r\n                OffsetUnit: []\r\n           SignificantBits: []\r\n              ImageModTime: '16 Jul 2002 16:46:41 +0000'\r\n                     Title: []\r\n                    Author: []\r\n               Description: 'Zesty peppers'\r\n                 Copyright: 'Copyright The MathWorks, Inc.'\r\n              CreationTime: []\r\n                  Software: []\r\n                Disclaimer: []\r\n                   Warning: []\r\n                    Source: []\r\n                   Comment: []\r\n                 OtherText: []\r\n\r\n<\/pre><p>See it yet? No?<\/p><p>Look at the Format field:<\/p><pre class=\"codeinput\">info.Format\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\npng\r\n\r\n<\/pre><p>The function <tt>imfinfo<\/tt> is claiming this this JPEG file is really a PNG file, which is a completely different image file format!<\/p><p>So what's going on here? Is this a JPEG file or not?<\/p><p>This trick question is really just an excuse to peek under the hood of <tt>imread<\/tt> to see how an interesting piece of it works. (Well, it's interesting to me, at least.)<\/p><p>Before opening the hood, though, let's try reading one more file. And notice that this filename has an extension that has nothing to do with any particular image format.<\/p><pre class=\"codeinput\">url2 = <span class=\"string\">'https:\/\/blogs.mathworks.com\/images\/steve\/2014\/peppers.fruit_study_2014_Jul_11'<\/span>;\r\n\r\nrgb2 = imread(url2);\r\nimshow(rgb2)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2014\/imread_under_the_hood_02.png\" alt=\"\"> <p>OK, so <tt>imread<\/tt> can successfully read this image file even without an extension indicating its format.<\/p><p>If you're curious, a lot of the <tt>imread<\/tt> code that makes all this work is available for you to look at in your installation of MATLAB. (If, on the other hand, you're not curious, then this would be a good time to go over and read <a href=\"https:\/\/blogs.mathworks.com\/cleve\">Cleve's blog<\/a> instead.) For example, you can view the source code for <tt>imread<\/tt> in the MATLAB Editor by typing <tt>edit imread<\/tt>. (Please don't modify the code, though!)<\/p><p>Here's a partial fragment of code near the top:<\/p><pre>if (isempty(fmt_s))\r\n    % The format was not specified explicitly.<\/pre><pre>    ... snip ...<\/pre><pre>    % Try to determine the file type.\r\n    [format, fmt_s] = imftype(filename);<\/pre><p>Hmm, what's that function <tt>imftype<\/tt>?<\/p><pre class=\"codeinput\">which <span class=\"string\">imftype<\/span>\r\n<\/pre><pre class=\"codeoutput\">'imftype' not found.\r\n<\/pre><p>It doesn't appear to exist!<\/p><p>It does exist, but it happens to be a private function. The function <tt>which<\/tt> will find it if you tell <tt>which<\/tt> to look at little harder.<\/p><pre class=\"codeinput\">which <span class=\"string\">-all<\/span> <span class=\"string\">imftype<\/span>\r\n<\/pre><pre class=\"codeoutput\">\/Applications\/MATLAB_R2014a.app\/toolbox\/matlab\/imagesci\/private\/imftype.m  % Private to imagesci\r\n<\/pre><p>Even though you can't directly call this function (that's what <i>private<\/i> means here), you can still look at it in the MATLAB Editor by typing <tt>edit private\/imftype<\/tt>.<\/p><p>Here's some code from near the beginning of <tt>imftype<\/tt>.<\/p><pre>idx = find(filename == '.');\r\nif (~isempty(idx))\r\n    extension = lower(filename(idx(end)+1:end));\r\nelse\r\n    extension = '';\r\nend<\/pre><pre>% Try to get useful imformation from the extension.<\/pre><pre>if (~isempty(extension))<\/pre><pre>    % Look up the extension in the file format registry.\r\n    fmt_s = imformats(extension);<\/pre><pre>    if (~isempty(fmt_s))<\/pre><pre>        if (~isempty(fmt_s.isa))<\/pre><pre>            % Call the ISA function for this format.\r\n            tf = feval(fmt_s.isa, filename);<\/pre><pre>            if (tf)<\/pre><pre>                % The file is of that format.  Return the ext field.\r\n                format = fmt_s.ext{1};\r\n                return;<\/pre><pre>            end\r\n        end\r\n    end\r\nend<\/pre><p>In English: If the filename has an extension on it, use the <tt>imformats<\/tt> function to get a function that can test to see whether the file really has that format.<\/p><p>So what's that new function <tt>imformats<\/tt> in the middle there? Well, you can call this one directly. Try it.<\/p><pre class=\"codeinput\">s = imformats\r\n<\/pre><pre class=\"codeoutput\">\r\ns = \r\n\r\n1x19 struct array with fields:\r\n\r\n    ext\r\n    isa\r\n    info\r\n    read\r\n    write\r\n    alpha\r\n    description\r\n\r\n<\/pre><p>That output is not very readable. If we were designing this today, we'd probably make <tt>imformats<\/tt> return a table. Fortunately we've got an easy way to convert a struct array into table!<\/p><pre class=\"codeinput\">t = struct2table(s)\r\n<\/pre><pre class=\"codeoutput\">\r\nt = \r\n\r\n       ext          isa         info          read         write      alpha\r\n    __________    _______    ___________    _________    _________    _____\r\n\r\n    {1x1 cell}    @isbmp     @imbmpinfo     @readbmp     @writebmp    0    \r\n    {1x1 cell}    @iscur     @imcurinfo     @readcur     ''           1    \r\n    {1x2 cell}    @isfits    @imfitsinfo    @readfits    ''           0    \r\n    {1x1 cell}    @isgif     @imgifinfo     @readgif     @writegif    0    \r\n    {1x1 cell}    @ishdf     @imhdfinfo     @readhdf     @writehdf    0    \r\n    {1x1 cell}    @isico     @imicoinfo     @readico     ''           1    \r\n    {1x2 cell}    @isjp2     @imjp2info     @readjp2     @writej2c    0    \r\n    {1x1 cell}    @isjp2     @imjp2info     @readjp2     @writejp2    0    \r\n    {1x2 cell}    @isjp2     @imjp2info     @readjp2     ''           0    \r\n    {1x2 cell}    @isjpg     @imjpginfo     @readjpg     @writejpg    0    \r\n    {1x1 cell}    @ispbm     @impnminfo     @readpnm     @writepnm    0    \r\n    {1x1 cell}    @ispcx     @impcxinfo     @readpcx     @writepcx    0    \r\n    {1x1 cell}    @ispgm     @impnminfo     @readpnm     @writepnm    0    \r\n    {1x1 cell}    @ispng     @impnginfo     @readpng     @writepng    1    \r\n    {1x1 cell}    @ispnm     @impnminfo     @readpnm     @writepnm    0    \r\n    {1x1 cell}    @isppm     @impnminfo     @readpnm     @writepnm    0    \r\n    {1x1 cell}    @isras     @imrasinfo     @readras     @writeras    1    \r\n    {1x2 cell}    @istif     @imtifinfo     @readtif     @writetif    0    \r\n    {1x1 cell}    @isxwd     @imxwdinfo     @readxwd     @writexwd    0    \r\n\r\n\r\n               description            \r\n    __________________________________\r\n\r\n    'Windows Bitmap'                  \r\n    'Windows Cursor resources'        \r\n    'Flexible Image Transport System' \r\n    'Graphics Interchange Format'     \r\n    'Hierarchical Data Format'        \r\n    'Windows Icon resources'          \r\n    'JPEG 2000 (raw codestream)'      \r\n    'JPEG 2000 (Part 1)'              \r\n    'JPEG 2000 (Part 2)'              \r\n    'Joint Photographic Experts Group'\r\n    'Portable Bitmap'                 \r\n    'Windows Paintbrush'              \r\n    'Portable Graymap'                \r\n    'Portable Network Graphics'       \r\n    'Portable Any Map'                \r\n    'Portable Pixmap'                 \r\n    'Sun Raster'                      \r\n    'Tagged Image File Format'        \r\n    'X Window Dump'                   \r\n\r\n<\/pre><p>Now we've gotten to some interesting stuff! This table represents the guts of how <tt>imread<\/tt>, <tt>imfinfo<\/tt>, and <tt>imwrite<\/tt> knows how to deal with the many different image file formats supported.<\/p><p>If you pass an extension to <tt>imformats<\/tt>, it looks through file formats it knows about to see if it matches a standard one.<\/p><pre class=\"codeinput\">imformats(<span class=\"string\">'jpg'<\/span>)\r\n<\/pre><pre class=\"codeoutput\">\r\nans = \r\n\r\n            ext: {'jpg'  'jpeg'}\r\n            isa: @isjpg\r\n           info: @imjpginfo\r\n           read: @readjpg\r\n          write: @writejpg\r\n          alpha: 0\r\n    description: 'Joint Photographic Experts Group'\r\n\r\n<\/pre><p>Let's go back to the original file peppers.jpg and consider what happens in the code we've seen so far.<\/p><p>1. We did not specify the format explicitly (with a 2nd argument) when we called <tt>imread<\/tt>, so <tt>imread<\/tt> called <tt>imftype<\/tt> to determine the format type.<\/p><p>2. The function <tt>imftype<\/tt> found an extension ('.jpg') at the end of the filename, so it asked the <tt>imformats<\/tt> function about the extension, and <tt>imformats<\/tt> returned a set of function handles useful for doing things with JPEG files. One of the function handles, <tt>@isjpg<\/tt>, tests to see whether a file is a JPEG file or not.<\/p><p>To be completely truthful, <tt>@isjpg<\/tt> just does a quick check based only on the first few bytes of the file. Look at the code by typing <tt>edit private\/isjpg<\/tt>. Here are the key lines.<\/p><pre>fid = fopen(filename, 'r', 'ieee-le');\r\nassert(fid ~= -1, message('MATLAB:imagesci:validate:fileOpen', filename));\r\nsig = fread(fid, 2, 'uint8');\r\nfclose(fid);\r\ntf = isequal(sig, [255; 216]);<\/pre><p><i>OK, I have now taught you enough so that you can thoroughly confuse <tt>imread<\/tt> if you really want to. But don't you already have enough hobbies?<\/i><\/p><p>3. In this case, the file wasn't actually a JPEG file, so the function handle <tt>@isjpg<\/tt> returned 0 (false).<\/p><p>That brings us to the rest of the excitement in <tt>imftype<\/tt>.<\/p><pre>% Get all formats from the registry.\r\nfmt_s = imformats;<\/pre><pre>% Look through each of the possible formats.\r\nfor p = 1:length(fmt_s)\r\n    % Call each ISA function until the format is found.\r\n    if (~isempty(fmt_s(p).isa))\r\n        tf = feval(fmt_s(p).isa, filename);\r\n        if (tf)\r\n            % The file is of that format.  Return the ext field.\r\n            format = fmt_s(p).ext{1};\r\n            fmt_s = fmt_s(p);\r\n            return\r\n        end\r\n    else\r\n        warning(message('MATLAB:imagesci:imftype:missingIsaFunction'));\r\n    end\r\nend<\/pre><p>In English: For every image file format we know about, run the corresponding <tt>isa<\/tt> function handle on the file. If one of the <tt>isa<\/tt> functions returns true, then return the corresponding set of information from <tt>imformats<\/tt>.<\/p><p>Back to the story for our misnamed image file peppers.jpg. The <tt>@isjpg<\/tt> function handle returned false for it. So <tt>imftype<\/tt> then tried the <tt>isa<\/tt> function handles for every image file format. One of them, <tt>@ispng<\/tt>, returned 1 (true). That information was passed back up to <tt>imread<\/tt>, which then read the file successfully as a PNG, which was the file's true format type.<\/p><p>Finally, here's what happened for the image file peppers.2014_Jul_11. When <tt>imftype<\/tt> passed the extension <tt>'2014_Jul_11'<\/tt> to <tt>imformats<\/tt>, no such image format extension was found, so <tt>imformats<\/tt> returned empty. That caused <tt>imftype<\/tt> to go into the code that simply tried every image format it knew about, which again worked when it got to PNG.<\/p><p>Phew! That's the story of the effort <tt>imread<\/tt> makes to read your images in correctly.<\/p><p>For the three of you that are still reading along, I'll send a t-shirt to the first one to post a convincingly complete explanation of this line of code from above:<\/p><pre>extension = lower(filename(idx(end)+1:end));<\/pre><script language=\"JavaScript\"> <!-- \r\n    function grabCode_f9c07ef9c5a74f2999e73645476ca32d() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='f9c07ef9c5a74f2999e73645476ca32d ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' f9c07ef9c5a74f2999e73645476ca32d';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2014 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_f9c07ef9c5a74f2999e73645476ca32d()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2014a<br><\/p><\/div><!--\r\nf9c07ef9c5a74f2999e73645476ca32d ##### SOURCE BEGIN #####\r\n%%\r\n% I'm going to play a small trick on you today. Try reading in this JPEG\r\n% file using |imread|:\r\n\r\nurl = 'https:\/\/blogs.mathworks.com\/images\/steve\/2014\/peppers.jpg';\r\nrgb = imread(url);\r\nimshow(rgb)\r\n\r\n%%\r\n% So what's the trick? Well, look more closely at this file using\r\n% |imfinfo|:\r\n\r\ninfo = imfinfo(url)\r\n\r\n%%\r\n% See it yet? No?\r\n%\r\n% Look at the Format field:\r\n\r\ninfo.Format\r\n\r\n%%\r\n% The function |imfinfo| is claiming this this JPEG file is really a PNG\r\n% file, which is a completely different image file format!\r\n%\r\n% So what's going on here? Is this a JPEG file or not?\r\n%\r\n% This trick question is really just an excuse to peek under the hood of\r\n% |imread| to see how an interesting piece of it works. (Well, it's\r\n% interesting to me, at least.)\r\n%\r\n% Before opening the hood, though, let's try reading one more file. And\r\n% notice that this filename has an extension that has nothing to do with\r\n% any particular image format.\r\n\r\nurl2 = 'https:\/\/blogs.mathworks.com\/images\/steve\/2014\/peppers.fruit_study_2014_Jul_11';\r\n\r\nrgb2 = imread(url2);\r\nimshow(rgb2)\r\n\r\n%%\r\n% OK, so |imread| can successfully read this image file even without an\r\n% extension indicating its format.\r\n%\r\n% If you're curious, a lot of the |imread| code that makes all this work is\r\n% available for you to look at in your installation of MATLAB. (If, on the\r\n% other hand, you're not curious, then this would be a good time to go over\r\n% and read <https:\/\/blogs.mathworks.com\/cleve Cleve's blog> instead.) For\r\n% example, you can view the source code for |imread| in the MATLAB Editor\r\n% by typing |edit imread|. (Please don't modify the code, though!)\r\n%\r\n% Here's a partial fragment of code near the top:\r\n%\r\n%  if (isempty(fmt_s))\r\n%      % The format was not specified explicitly.\r\n%      \r\n%      ... snip ...\r\n%      \r\n%      % Try to determine the file type.\r\n%      [format, fmt_s] = imftype(filename);\r\n%\r\n% Hmm, what's that function |imftype|?\r\n\r\nwhich imftype\r\n\r\n%%\r\n% It doesn't appear to exist!\r\n%\r\n% It does exist, but it happens to be a private function. The function\r\n% |which| will find it if you tell |which| to look at little harder.\r\n\r\nwhich -all imftype\r\n\r\n%%\r\n% Even though you can't directly call this function (that's what _private_\r\n% means here), you can still look at it in the MATLAB Editor by typing\r\n% |edit private\/imftype|.\r\n%\r\n% Here's some code from near the beginning of |imftype|.\r\n%\r\n%  idx = find(filename == '.');\r\n%  if (~isempty(idx))\r\n%      extension = lower(filename(idx(end)+1:end));\r\n%  else\r\n%      extension = '';\r\n%  end\r\n%  \r\n%  % Try to get useful imformation from the extension.\r\n%  \r\n%  if (~isempty(extension))\r\n%      \r\n%      % Look up the extension in the file format registry.\r\n%      fmt_s = imformats(extension);\r\n%      \r\n%      if (~isempty(fmt_s))\r\n%      \r\n%          if (~isempty(fmt_s.isa))\r\n%  \r\n%              % Call the ISA function for this format.\r\n%              tf = feval(fmt_s.isa, filename);\r\n%              \r\n%              if (tf)\r\n%                \r\n%                  % The file is of that format.  Return the ext field.\r\n%                  format = fmt_s.ext{1};\r\n%                  return;\r\n%                  \r\n%              end\r\n%          end\r\n%      end\r\n%  end\r\n%\r\n% In English: If the filename has an extension on it, use the |imformats|\r\n% function to get a function that can test to see whether the file really\r\n% has that format.\r\n%\r\n% So what's that new function |imformats| in the middle there? Well, you\r\n% can call this one directly. Try it.\r\n\r\ns = imformats\r\n\r\n%%\r\n% That output is not very readable. If we were designing this today, we'd\r\n% probably make |imformats| return a table. Fortunately we've got an easy\r\n% way to convert a struct array into table!\r\n\r\nt = struct2table(s)\r\n\r\n%%\r\n% Now we've gotten to some interesting stuff! This table represents the\r\n% guts of how |imread|, |imfinfo|, and |imwrite| knows how to deal with the\r\n% many different image file formats supported.\r\n%\r\n% If you pass an extension to |imformats|, it looks through file formats it\r\n% knows about to see if it matches a standard one.\r\n\r\nimformats('jpg')\r\n\r\n%%\r\n% Let's go back to the original file peppers.jpg and consider what happens\r\n% in the code we've seen so far.\r\n%\r\n% 1. We did not specify the format explicitly (with a 2nd argument) when we\r\n% called |imread|, so |imread| called |imftype| to determine the format\r\n% type.\r\n%\r\n% 2. The function |imftype| found an extension ('.jpg') at the end of the\r\n% filename, so it asked the |imformats| function about the extension, and\r\n% |imformats| returned a set of function handles useful for doing things\r\n% with JPEG files. One of the function handles, |@isjpg|, tests to see\r\n% whether a file is a JPEG file or not.\r\n%\r\n% To be completely truthful, |@isjpg| just does a quick check based only on\r\n% the first few bytes of the file. Look at the code by typing |edit\r\n% private\/isjpg|. Here are the key lines.\r\n%\r\n%  fid = fopen(filename, 'r', 'ieee-le');\r\n%  assert(fid ~= -1, message('MATLAB:imagesci:validate:fileOpen', filename));\r\n%  sig = fread(fid, 2, 'uint8');\r\n%  fclose(fid);\r\n%  tf = isequal(sig, [255; 216]);\r\n%\r\n% _OK, I have now taught you enough so that you can thoroughly confuse\r\n% |imread| if you really want to. But don't you already have enough\r\n% hobbies?_\r\n%\r\n% 3. In this case, the file wasn't actually a JPEG file, so the function\r\n% handle |@isjpg| returned 0 (false).\r\n%\r\n% That brings us to the rest of the excitement in |imftype|.\r\n%\r\n%  % Get all formats from the registry.\r\n%  fmt_s = imformats;\r\n%  \r\n%  % Look through each of the possible formats.\r\n%  for p = 1:length(fmt_s)\r\n%      % Call each ISA function until the format is found.\r\n%      if (~isempty(fmt_s(p).isa))\r\n%          tf = feval(fmt_s(p).isa, filename);\r\n%          if (tf)\r\n%              % The file is of that format.  Return the ext field.\r\n%              format = fmt_s(p).ext{1};\r\n%              fmt_s = fmt_s(p);\r\n%              return\r\n%          end\r\n%      else\r\n%          warning(message('MATLAB:imagesci:imftype:missingIsaFunction')); \r\n%      end\r\n%  end\r\n%\r\n% In English: For every image file format we know about, run the\r\n% corresponding |isa| function handle on the file. If one of the |isa|\r\n% functions returns true, then return the corresponding set of information\r\n% from |imformats|.\r\n%\r\n% Back to the story for our misnamed image file peppers.jpg. The |@isjpg|\r\n% function handle returned false for it. So |imftype| then tried the |isa|\r\n% function handles for every image file format. One of them, |@ispng|,\r\n% returned 1 (true). That information was passed back up to |imread|, which\r\n% then read the file successfully as a PNG, which was the file's true\r\n% format type.\r\n%\r\n% Finally, here's what happened for the image file peppers.2014_Jul_11.\r\n% When |imftype| passed the extension |'2014_Jul_11'| to |imformats|, no\r\n% such image format extension was found, so |imformats| returned empty.\r\n% That caused |imftype| to go into the code that simply tried every image\r\n% format it knew about, which again worked when it got to PNG.\r\n%\r\n% Phew! That's the story of the effort |imread| makes to read your images\r\n% in correctly.\r\n%\r\n% For the three of you that are still reading along, I'll send a t-shirt to\r\n% the first one to post a convincingly complete explanation of this line of\r\n% code from above:\r\n%\r\n%  extension = lower(filename(idx(end)+1:end));\r\n##### SOURCE END ##### f9c07ef9c5a74f2999e73645476ca32d\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2014\/imread_under_the_hood_02.png\" onError=\"this.style.display ='none';\" \/><\/div><p>\r\nI'm going to play a small trick on you today. Try reading in this JPEG file using imread:url = 'https:\/\/blogs.mathworks.com\/images\/steve\/2014\/peppers.jpg';\r\nrgb = imread(url);\r\nimshow(rgb)\r\n So... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2014\/07\/11\/under-the-hood-of-imread\/\">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":[615,681,1083,348,677,679,332,500,76,36,472,346,705,849,1085,1071,749],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1094"}],"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=1094"}],"version-history":[{"count":3,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1094\/revisions"}],"predecessor-version":[{"id":1097,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1094\/revisions\/1097"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=1094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=1094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=1094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}