{"id":482,"date":"2012-02-20T10:47:31","date_gmt":"2012-02-20T15:47:31","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=482"},"modified":"2019-10-31T14:40:30","modified_gmt":"2019-10-31T18:40:30","slug":"writing-image-files","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2012\/02\/20\/writing-image-files\/","title":{"rendered":"Digital image processing using MATLAB: writing image files"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p><i>Today's post is part of an ongoing <a href=\"https:\/\/blogs.mathworks.com\/steve\/category\/dipum-tutorials\/\">tutorial series on digital image processing using MATLAB<\/a>. I'm covering topics in roughly the order used in the book <a href=\"http:\/\/imageprocessingplace.com\/DIPUM-2E\/dipum2e_main_page.htm\">Digital Image Processing Using MATLAB<\/a>.<\/i><\/p>\r\n   <\/introduction>\r\n   <p>The MATLAB function <tt>imwrite<\/tt> writes image data to a variety of different formats including: reads image data from a variety of formats, including JPEG,\r\n      JPEG 2000, TIFF, PNG, and GIF (as well as a few older formats no longer commonly used).\r\n   <\/p>\r\n   <p>Probably most people use form where you just provide the image array and a filename.<\/p>\r\n   <p>I'll read in one of the sample images in Image Processing Toolbox to experiment with.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">rgb = imread(<span style=\"color: #A020F0\">'peppers.png'<\/span>);\r\nimshow(rgb)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/dipum_writing_images_01.png\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imwrite(rgb,<span style=\"color: #A020F0\">'mypeppers.tif'<\/span>)<\/pre><p>In the above call to <tt>imwrite<\/tt>, the function decides which image format to use based on the extension (.tif) in the filename.\r\n   <\/p>\r\n   <p>Sometimes, though, you might want to use a filename extension for a different purpose. In that case, you call pass a third\r\n      argument to <tt>imwrite<\/tt> to let it know which image format to use.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imwrite(rgb, <span style=\"color: #A020F0\">'test_image.study_013'<\/span>, <span style=\"color: #A020F0\">'tif'<\/span>)<\/pre><p>Most image file formats support some form of compression. That means that the image takes up less space on disk than you might\r\n      think based on a simple calculation. For example, the <tt>rgb<\/tt> array above takes up about 576 kilobytes in memory.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bytes_in_memory_peppers = numel(rgb)<\/pre><pre style=\"font-style:oblique\">\r\nbytes_in_memory_peppers =\r\n\r\n      589824\r\n\r\n<\/pre><p>But it takes less space on disk when you save it to an image format that uses compression. Let's try writing to a PNG file:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imwrite(rgb,<span style=\"color: #A020F0\">'mypeppers.png'<\/span>)\r\n\r\ninfo = imfinfo(<span style=\"color: #A020F0\">'mypeppers.png'<\/span>);\r\nbytes_on_disk_peppers_png = info.FileSize<\/pre><pre style=\"font-style:oblique\">\r\nbytes_on_disk_peppers_png =\r\n\r\n      287589\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">compression_ratio = bytes_in_memory_peppers \/ bytes_on_disk_peppers_png<\/pre><pre style=\"font-style:oblique\">\r\ncompression_ratio =\r\n\r\n    2.0509\r\n\r\n<\/pre><p>The PNG format uses <b>lossless compression<\/b>. This means that you can recover the original image data exactly.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">peppers2 = imread(<span style=\"color: #A020F0\">'mypeppers.png'<\/span>);\r\nisequal(rgb, peppers2)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n     1\r\n\r\n<\/pre><p>Lossless compression methods save a lot more space when the image has large constant areas or contains certain kinds of repetitive,\r\n      predictable patterns. For example, this image is a screen shot of a MATLAB plot:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/plot_screen_shot.png\"> <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">url = <span style=\"color: #A020F0\">'https:\/\/blogs.mathworks.com\/images\/steve\/2012\/plot_screen_shot.png'<\/span>;\r\nrgb_plot = imread(url);\r\nbytes_in_memory_plot = numel(rgb_plot)<\/pre><pre style=\"font-style:oblique\">\r\nbytes_in_memory_plot =\r\n\r\n      336000\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">info = imfinfo(url);\r\nbytes_on_disk_plot = info.FileSize<\/pre><pre style=\"font-style:oblique\">\r\nbytes_on_disk_plot =\r\n\r\n        3284\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">compression_ratio = bytes_in_memory_plot \/ bytes_on_disk_plot<\/pre><pre style=\"font-style:oblique\">\r\ncompression_ratio =\r\n\r\n  102.3143\r\n\r\n<\/pre><p>That's a pretty big compression ratio!<\/p>\r\n   <p>Other image file formats, such as JPEG, use <b>lossy compression<\/b>. (There is a lossless form of JPEG, but it is obscure and rarely used.) With lossy compression, properties of the human visual\r\n      system are exploited to reduce the disk size even further, but at a cost --- the original pixels are not exactly recoverable.\r\n      Let's write out the peppers image using JPEG compression.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imwrite(rgb,<span style=\"color: #A020F0\">'peppers.jpg'<\/span>);\r\ninfo = imfinfo(<span style=\"color: #A020F0\">'peppers.jpg'<\/span>);\r\nbytes_on_disk_peppers_jpg = info.FileSize<\/pre><pre style=\"font-style:oblique\">\r\nbytes_on_disk_peppers_jpg =\r\n\r\n       23509\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">compression_ratio_peppers_jpg = bytes_in_memory_peppers \/ <span style=\"color: #0000FF\">...<\/span>\r\n    bytes_on_disk_peppers_jpg<\/pre><pre style=\"font-style:oblique\">\r\ncompression_ratio_peppers_jpg =\r\n\r\n   25.0893\r\n\r\n<\/pre><p>That's a much bigger compression ratio than we got with the PNG format above. The cost is in reduced image quality. JPEG does\r\n      a pretty good job of reducing space without adversely affecting image quality:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imshow(<span style=\"color: #A020F0\">'peppers.jpg'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/dipum_writing_images_02.png\"> <p>But it isn't perfect, as you can see by zooming in.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">subplot(1,2,1)\r\nimshow(<span style=\"color: #A020F0\">'peppers.png'<\/span>)\r\nlimits = [232 276 215 248];\r\naxis(limits)\r\ntitle(<span style=\"color: #A020F0\">'Original'<\/span>)\r\n\r\nsubplot(1,2,2)\r\nimshow(<span style=\"color: #A020F0\">'peppers.jpg'<\/span>)\r\naxis(limits)\r\ntitle(<span style=\"color: #A020F0\">'JPEG compressed'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/dipum_writing_images_03.png\"> <p>You can see the compression artifacts around the stem.<\/p>\r\n   <p>Compression artifacts tend to be more visible on images such as the plot screen shot above.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imwrite(rgb_plot,<span style=\"color: #A020F0\">'plot_screen_shot.jpg'<\/span>)\r\nrgb_plot_compressed = imread(<span style=\"color: #A020F0\">'plot_screen_shot.jpg'<\/span>);\r\n\r\nsubplot(2,2,1)\r\nimshow(rgb_plot)\r\ntitle(<span style=\"color: #A020F0\">'Original image'<\/span>)\r\nlimits = [80 105 210 230];\r\naxis(limits);\r\n\r\nsubplot(2,2,2)\r\nimshow(rgb_plot_compressed)\r\ntitle(<span style=\"color: #A020F0\">'JPEG compressed image'<\/span>)\r\naxis(limits);\r\n\r\nsubplot(2,2,3)\r\nimshow(rgb_plot)\r\nlimits = [345 380 240 265];\r\naxis(limits);\r\n\r\nsubplot(2,2,4)\r\nimshow(rgb_plot_compressed)\r\naxis(limits);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/dipum_writing_images_04.png\"> <p>That's why I usually use PNG for screen shots of many MATLAB graphics. For more complex images, on the other hand, I usually\r\n      use JPEG.\r\n   <\/p>\r\n   <p>For more information, see Section 2.4 of <a href=\"http:\/\/imageprocessingplace.com\/DIPUM-2E\/dipum2e_main_page.htm\"> <i>Digital Image Processing Using MATLAB<\/i><\/a>.\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/dipum-cover.png\"> <\/p>\r\n   <p>See also the reference pages for <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/imwrite.html\"><tt>imwrite<\/tt><\/a>, as well as the section <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/images\/f13-19056.html\">Reading and Writing Image Data<\/a> in the Image Processing Toolbox User's Guide.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_3fd34730ffbe4516b3b41e7a1be0e7dc() {\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='3fd34730ffbe4516b3b41e7a1be0e7dc ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 3fd34730ffbe4516b3b41e7a1be0e7dc';\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        author = 'Steve Eddins';\r\n        copyright = 'Copyright 2012 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 author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\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      \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_3fd34730ffbe4516b3b41e7a1be0e7dc()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.13<br><\/p>\r\n<\/div>\r\n<!--\r\n3fd34730ffbe4516b3b41e7a1be0e7dc ##### SOURCE BEGIN #####\r\n%%\r\n% _Today's post is part of an ongoing\r\n% <https:\/\/blogs.mathworks.com\/steve\/category\/dipum-tutorials\/ tutorial\r\n% series on digital image processing using MATLAB>. I'm covering topics in\r\n% roughly the order used in the book\r\n% <http:\/\/imageprocessingplace.com\/DIPUM-2E\/dipum2e_main_page.htm Digital\r\n% Image Processing Using MATLAB>._\r\n%\r\n%%\r\n% The MATLAB function |imwrite| writes image data to a variety of different \r\n% formats including: reads image data from a variety of formats,\r\n% including JPEG, JPEG 2000, TIFF, PNG, and GIF (as well as a few older\r\n% formats no longer commonly used).\r\n%\r\n% Probably most people use form where you just provide the image array and\r\n% a filename.\r\n%\r\n% I'll read in one of the sample images in Image Processing Toolbox to\r\n% experiment with.\r\n\r\nrgb = imread('peppers.png');\r\nimshow(rgb)\r\n\r\n%%\r\nimwrite(rgb,'mypeppers.tif')\r\n\r\n%%\r\n% In the above call to |imwrite|, the function decides which image format\r\n% to use based on the extension (.tif) in the filename.\r\n%\r\n% Sometimes, though, you might want to use a filename extension for a\r\n% different purpose. In that case, you call pass a third argument to\r\n% |imwrite| to let it know which image format to use.\r\n\r\nimwrite(rgb, 'test_image.study_013', 'tif')\r\n\r\n%%\r\n% Most image file formats support some form of compression. That means that\r\n% the image takes up less space on disk than you might think based on a\r\n% simple calculation. For example, the |rgb| array above takes up\r\n% about 576 kilobytes in memory.\r\n\r\nbytes_in_memory_peppers = numel(rgb)\r\n\r\n%%\r\n% But it takes less space on disk when you save it to an image format that\r\n% uses compression. Let's try writing to a PNG file:\r\n\r\nimwrite(rgb,'mypeppers.png')\r\n\r\ninfo = imfinfo('mypeppers.png');\r\nbytes_on_disk_peppers_png = info.FileSize\r\n\r\n%%\r\ncompression_ratio = bytes_in_memory_peppers \/ bytes_on_disk_peppers_png\r\n\r\n%%\r\n% The PNG format uses *lossless compression*. This means that you can\r\n% recover the original image data exactly.\r\n\r\npeppers2 = imread('mypeppers.png');\r\nisequal(rgb, peppers2)\r\n\r\n%%\r\n% Lossless compression methods save a lot more space when the image has\r\n% large constant areas or contains certain kinds of repetitive, predictable\r\n% patterns. For example, this image is a screen shot of a MATLAB plot:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2012\/plot_screen_shot.png>>\r\n\r\nurl = 'https:\/\/blogs.mathworks.com\/images\/steve\/2012\/plot_screen_shot.png';\r\nrgb_plot = imread(url);\r\nbytes_in_memory_plot = numel(rgb_plot)\r\n\r\n%%\r\ninfo = imfinfo(url);\r\nbytes_on_disk_plot = info.FileSize\r\n\r\n%%\r\ncompression_ratio = bytes_in_memory_plot \/ bytes_on_disk_plot\r\n\r\n%%\r\n% That's a pretty big compression ratio!\r\n%\r\n% Other image file formats, such as JPEG, use *lossy compression*. (There\r\n% is a lossless form of JPEG, but it is obscure and rarely used.) With\r\n% lossy compression, properties of the human visual system are exploited to\r\n% reduce the disk size even further, but at a cost REPLACE_WITH_DASH_DASH- the original pixels\r\n% are not exactly recoverable. Let's write out the peppers image using JPEG\r\n% compression.\r\n\r\nimwrite(rgb,'peppers.jpg');\r\ninfo = imfinfo('peppers.jpg');\r\nbytes_on_disk_peppers_jpg = info.FileSize\r\n\r\n%%\r\ncompression_ratio_peppers_jpg = bytes_in_memory_peppers \/ ...\r\n    bytes_on_disk_peppers_jpg\r\n\r\n%%\r\n% That's a much bigger compression ratio than we got with the PNG format\r\n% above. The cost is in reduced image quality. JPEG does a pretty good job\r\n% of reducing space without adversely affecting image quality:\r\n\r\nimshow('peppers.jpg')\r\n\r\n%%\r\n% But it isn't perfect, as you can see by zooming in.\r\nsubplot(1,2,1)\r\nimshow('peppers.png')\r\nlimits = [232 276 215 248];\r\naxis(limits)\r\ntitle('Original')\r\n\r\nsubplot(1,2,2)\r\nimshow('peppers.jpg')\r\naxis(limits)\r\ntitle('JPEG compressed')\r\n\r\n%%\r\n% You can see the compression artifacts around the stem.\r\n%\r\n% Compression artifacts tend to be more visible on images such as the plot\r\n% screen shot above.\r\n\r\nimwrite(rgb_plot,'plot_screen_shot.jpg')\r\nrgb_plot_compressed = imread('plot_screen_shot.jpg');\r\n\r\nsubplot(2,2,1)\r\nimshow(rgb_plot)\r\ntitle('Original image')\r\nlimits = [80 105 210 230];\r\naxis(limits);\r\n\r\nsubplot(2,2,2)\r\nimshow(rgb_plot_compressed)\r\ntitle('JPEG compressed image')\r\naxis(limits);\r\n\r\nsubplot(2,2,3)\r\nimshow(rgb_plot)\r\nlimits = [345 380 240 265];\r\naxis(limits);\r\n\r\nsubplot(2,2,4)\r\nimshow(rgb_plot_compressed)\r\naxis(limits);\r\n\r\n%%\r\n% That's why I usually use PNG for screen shots of many MATLAB graphics.\r\n% For more complex images, on the other hand, I usually use JPEG.\r\n\r\n%% \r\n% For more information, see Section 2.4 of\r\n% <http:\/\/imageprocessingplace.com\/DIPUM-2E\/dipum2e_main_page.htm\r\n%  _Digital Image Processing Using MATLAB_>. \r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2011\/dipum-cover.png>>\r\n%\r\n% See also the reference pages for\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/imwrite.html |imwrite|>, as\r\n% well as the section\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/images\/f13-19056.html Reading and\r\n% Writing Image Data> in the Image Processing Toolbox User's Guide.\r\n%\r\n% \r\n##### SOURCE END ##### 3fd34730ffbe4516b3b41e7a1be0e7dc\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      Today's post is part of an ongoing tutorial series on digital image processing using MATLAB. I'm covering topics in roughly the order used in the book Digital Image Processing Using... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2012\/02\/20\/writing-image-files\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[21],"tags":[50,332,76,36,164,162,72,52],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/482"}],"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=482"}],"version-history":[{"count":5,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/482\/revisions"}],"predecessor-version":[{"id":3779,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/482\/revisions\/3779"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}