{"id":305,"date":"2013-07-29T09:46:27","date_gmt":"2013-07-29T07:46:27","guid":{"rendered":"http:\/\/www.ancor.ch\/schoebey\/?p=305"},"modified":"2013-08-01T22:17:09","modified_gmt":"2013-08-01T20:17:09","slug":"fragmented-images","status":"publish","type":"post","link":"https:\/\/www.ancor.ch\/schoebey\/?p=305","title":{"rendered":"Fragmented Images"},"content":{"rendered":"<h2>Proposal for a new image format (container)<\/h2>\n<p>In addition to several MIP-levels, the image file contains a matrix of fixed-size sub-images for each MIP-level (e.g. 1024x1024px).<\/p>\n<p>Each sub-image has a set of coordinates\/indexes attached to it so that the original image can easily be reconstructed by stitching the sub-images together.<a href=\"http:\/\/www.ancor.ch\/schoebey\/wp-content\/uploads\/2013\/07\/grid.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-medium wp-image-318\" alt=\"grid\" src=\"http:\/\/www.ancor.ch\/schoebey\/wp-content\/uploads\/2013\/07\/grid-122x300.png\" width=\"122\" height=\"300\" \/><\/a><\/p>\n<p>The MIP-based file format will have to be altered slightly: Instead of a simple JPG-compressed MIP-level, a tiled image would have to be stored.<\/p>\n<p>Since every MIP-level is only half the size of its previous level, the number of tiles will be reduced by a factor of 4 in each step.<\/p>\n<p>The file header now consisting of a simple offset map would have to be extended to store the intra-MIP offsets for each tile in addition to the MIP-level offset.<\/p>\n<h2><\/h2>\n<h2><\/h2>\n<h2><\/h2>\n<h2>Why all the effort?<\/h2>\n<p>if the user zooms in on a large image (several megapixels), decoding of the next higher res MIP-level takes a lot of time.<\/p>\n<p>Current screens only have resolutions of 2-3 megapixels, meaning the full image is never visible, so decoding the whole image is a waste of memory and time. A simple grid-based visibility test would quickly yield which tiles are actually visible and which are hidden from view. Only the (partially) visible ones would have to send a load request to the image loader thread, greatly reducing decoding time and memory consumption.<\/p>\n<h2>The overhead<\/h2>\n<p>instead of reading just one offset and jumping directly to the data, the image loader thread will have to read two offsets.<\/p>\n<p>The first offset value is necessary to jump to the MIP-level internal offset table describing the offset for each image tile.<\/p>\n<p>The second offset value is necessary to jump from the MIP-level offset table directly to the tile data.<\/p>\n<p>Each data request now consists of two offset lookups instead of just one, but considering the significant reduction in the amount of data actually read from the file, the overhead is neglectable.<\/p>\n<h2><!--more--> Example Code<\/h2>\n<pre lang=\"cpp\">void convertToLFI(const QString&amp; sImagePath)\r\n{\r\n  \/\/ LFI: Lightbox fragmented image\r\n  \/\/ open the file and pass it on to the decoding chain to get a QImage\r\n  QImage img;\r\n  if (imageLoader::eOk == CApi::loadImage(sImagePath, img))\r\n  {\r\n    \/\/ write static header information\r\n    stream &lt;&lt; QString(\"LightBox fragmented image\");\r\n    stream &lt;&lt; (int)0x6c696768; \/\/ light\r\n    stream &lt;&lt; (int)0x74626f78; \/\/ box\r\n\r\n    int iNofReductionsX = log(img.width())\/log(2) - 7;\r\n    int iNofReductionsY = log(img.height())\/log(2) - 7;\r\n    int iNofMipLevels = min(iNofReductionsX, iNofReductionsY);\r\n\r\n    \/\/ reserve space for the MIP offset table\r\n    QDataStream mipOffsetsStream = stream;\r\n    stream += iNofMipLevels * sizeof(int) + 32; \/\/ advance stream by number of mip levels and add some padding\r\n\r\n    while (128 &gt;= img.width() &amp;&amp; 128 &gt;= img.height())\r\n    {\r\n      \/\/ determine the offset\r\n      mipOffsetsStream &lt;&lt; stream.pos();\r\n\r\n      \/\/ store the MIP level\r\n \u00c2\u00a0   \u00c2\u00a0int iNofTilesX = img.width() \/ 128;\r\n \u00c2\u00a0   \u00c2\u00a0int iNofTilesY = img.height() \/ 128;\r\n      QDataStream subImgOffsetStream = stream;\r\n      stream += iNofTilesX * iNofTilesY * sizeof(int);\r\n      for (int iY = 0; iY &lt; iNofTilesY; ++iY)\r\n      {\r\n        for (int iX = 0; iX &lt; iNofTilesX; ++iX)\r\n        {\r\n          subImgOffsetStream &lt;&lt; stream.pos();\r\n          stream &lt;&lt; getSubImage(img, iX, iY, 128, 128, \"jpg\"); \/\/ write the sub-image to the stream\r\n        }\r\n      }\r\n    }\r\n  }\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Proposal for a new image format (container) In addition to several MIP-levels, the image file contains a matrix of fixed-size sub-images for each MIP-level (e.g. 1024x1024px). Each sub-image has a set of coordinates\/indexes attached to it so that the original image can easily be reconstructed by stitching the sub-images together. The MIP-based file format will [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,3,13],"tags":[],"class_list":["post-305","post","type-post","status-publish","format-standard","hentry","category-brainstorming","category-code","category-lightbox"],"_links":{"self":[{"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=\/wp\/v2\/posts\/305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=305"}],"version-history":[{"count":18,"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=\/wp\/v2\/posts\/305\/revisions"}],"predecessor-version":[{"id":327,"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=\/wp\/v2\/posts\/305\/revisions\/327"}],"wp:attachment":[{"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ancor.ch\/schoebey\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}