{"id":30,"date":"2017-06-23T13:26:55","date_gmt":"2017-06-23T13:26:55","guid":{"rendered":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/?p=30"},"modified":"2022-05-21T14:09:22","modified_gmt":"2022-05-21T14:09:22","slug":"image-rendering-and-animation","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/2017\/06\/23\/image-rendering-and-animation\/","title":{"rendered":"Image Rendering and Animation"},"content":{"rendered":"<figure id=\"attachment_32\" aria-describedby=\"caption-attachment-32\" style=\"width: 639px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2022\/05\/axacutian_cropped.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-32\" src=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2022\/05\/axacutian_cropped.png\" alt=\"\" width=\"639\" height=\"331\" srcset=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2022\/05\/axacutian_cropped.png 639w, https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2022\/05\/axacutian_cropped-300x155.png 300w\" sizes=\"auto, (max-width: 639px) 100vw, 639px\" \/><\/a><figcaption id=\"caption-attachment-32\" class=\"wp-caption-text\">Let&#8217;s hope not all humans are that ugly &#8212; probably some Axacutian<\/figcaption><\/figure>\n<p>This post will be about the compression algorithm used for the graphics and how it plays into the animation system of Supernova.<\/p>\n<p>The images consist of a custom palette of 239 colors and divided up into sections that define its size and a pointer to the image data. An exception to this are the newspaper articles, seen in the intro of the game.<\/p>\n<p><a href=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/scummvm00000.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-34\" src=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/scummvm00000-1024x768.png\" alt=\"\" width=\"580\" height=\"435\" srcset=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/scummvm00000-1024x768.png 1024w, https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/scummvm00000-300x225.png 300w, https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/scummvm00000-768x576.png 768w, https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/scummvm00000-1200x900.png 1200w, https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/scummvm00000.png 1280w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a>Those bitmap images have dimensions of 640&#215;480 and only monochrome colors, instead of 256-colors palettized 320&#215;200. The difference in their encoding can be seen <a href=\"https:\/\/github.com\/Joefish\/scummvm\/blob\/supernova\/engines\/supernova\/graphics.cpp#L137\">here in the code<\/a>. So, for the mode 0x11 images I mask the bits of a byte and depending if the bit is set 0 (Black) or 11 (63% White) is written. It is safe to use palette colors as the first 16 colors of the default palette, defined <a href=\"https:\/\/github.com\/Joefish\/scummvm\/blob\/supernova\/engines\/supernova\/msn_def.h#L263\">here<\/a>, won&#8217;t be overwritten by an image&#8217;s custom palette.<\/p>\n<p>Mode 0x13 images that make up the rest of the game&#8217;s graphics are compressed in a run-length encoding (RLE) and are 320&#215;200 256-color palettized. The following describes the structure of the file format:<\/p>\n<p><a href=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/image-encoding.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-35\" src=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/image-encoding.png\" alt=\"\" width=\"642\" height=\"470\" srcset=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/image-encoding.png 642w, https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/image-encoding-300x220.png 300w\" sizes=\"auto, (max-width: 642px) 100vw, 642px\" \/><\/a>The image decoding part can be found <a href=\"https:\/\/github.com\/Joefish\/scummvm\/blob\/supernova\/engines\/supernova\/graphics.cpp#L105\">here<\/a>. It works more or less like this:<\/p>\n<p>The encoded image is read into a variable &#8216;input&#8217; byte by byte<\/p>\n<ul>\n<li>If input &lt; numRepeat, write the next value read input-times<\/li>\n<li>If input &lt; numZw, write the (input &#8211; numRepeat)th value of &#8216;twin-value array&#8217; twice<\/li>\n<li>Otherwise, write input value directly<\/li>\n<\/ul>\n<p>The success of this simple way of compression depends on how monotonous the image is. The less color changes happen in a scanline the better the compression.<\/p>\n<div style=\"width: 580px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-30-1\" width=\"580\" height=\"326\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/Images-and-Sections-f1V0fki_zjo.mp4?_=1\" \/><a href=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/Images-and-Sections-f1V0fki_zjo.mp4\">https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/Images-and-Sections-f1V0fki_zjo.mp4<\/a><\/video><\/div>\n<p style=\"text-align: center;\"><em>(Source: https:\/\/www.youtube.com\/watch?v=f1V0fki_zjo)<\/em><\/p>\n<p>Sections, as already mentioned, describe an image section that most of the time shows objects in different states of interaction, like an opened or closed door, by redrawing only part of the base image (section 0).<\/p>\n<p>As you can see in the video, sections 7, 8 and 9 are the frames for the animation of the &#8216;slide door&#8217; to the airlock. And that&#8217;s the whole trick. Well, a door sliding open in 3 frames is not that impressive, so I composed a video with 3 scenes from the game that meet your expectations a bit more when you hear the word &#8216;animation&#8217;<\/p>\n<div style=\"width: 580px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-30-2\" width=\"580\" height=\"326\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/mission-supernova-animations-ezjaOoF80Jo.mp4?_=2\" \/><a href=\"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/mission-supernova-animations-ezjaOoF80Jo.mp4\">https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-content\/uploads\/sites\/22\/2017\/06\/mission-supernova-animations-ezjaOoF80Jo.mp4<\/a><\/video><\/div>\n<p style=\"text-align: center;\"><em>(Source: https:\/\/www.youtube.com\/watch?v=ezjaOoF80Jo)<\/em><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post will be about the compression algorithm used for the graphics and how it plays into the animation system of Supernova. The images consist of a custom palette of 239 colors and divided up into sections that define its size and a pointer to the image data. An exception to this are the newspaper [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-30","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/posts\/30","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/comments?post=30"}],"version-history":[{"count":3,"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/posts\/30\/revisions"}],"predecessor-version":[{"id":39,"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/posts\/30\/revisions\/39"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/media?parent=30"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/categories?post=30"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/joefish-gsoc\/wp-json\/wp\/v2\/tags?post=30"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}