2016-04-25

Displaying hexagonal sampled images

In my earlier posts I added some images enlarged so much that the hexagonal nature of their sampling is visible. You may have wondered how I created these images so that they can be shown in your browser, knowing that there is no image file format that supports hexagonal images. In fact, I had to figure out a way to convert these hexagonal sampled images into square sampled images - but not in a way as you would do it if you want to convert an image from a hexagonal sensor. Because in this case you would want to suppress the visibility of the sampling grid. In my case I wanted to do the exact opposite - I wanted to emphasize the sampling grid.
Well, I guess I could have done it Matlab, as kindof the opposite of the hexagonal resampling operation that I explained in an earlier post. This would have been sufficient for online publishing. But when I first started doing this in 2010 I wanted to have a vector graphic which I could insert into my diploma thesis, so that the images would be rendered in the best possible quality, independent of the actual resolution of the print. Therefor I decided to store the hexagonal images as svg files using some Matlab code. I could then open these svg files in Inkscape, a free vector graphics tool, and save it in any other file format, e.g. pdf for printing (and also viewing on the moditor while still maintaining the nature of a vector graphic) or as png with any desired resolution.
So, to make it short, this is how it works:

  1. export the hexagonal sampled image as svg file (using some matlab code)
  2. open the svg file in Inkscape
  3. export a png file
You can find the Matlab code at the end of the post. Please note that it is not perfect (I didn´t plan to make it public first and I was too lazy to fix all issues later). For example, the area that is used for the hexagonal grid is calculated incorrect, so you may need to fix the page size in your svg editor.
One thing that you should consider is that the svg files are huge as every pixel requires about 100 bytes (compared to three bytes in a bitmap graphics file).
Using Inkscape I found that the export as png works best with 2dpi. This will produce images in which each hexagon is roughly 40 pixels high. You can then scale this image to any smaller size you like. When scaling, make sure not to use bicubic or lanczos interpolation as these will introduce artifacts at the edges of the hexagons. better use bilinear (triangle) interpolation.





function [  ] = HexImWriteSVG( HexImage, Filename )
% writes a hexagonally sampled image to SVG

%check datatype of input image and convert to uint8
if isa(HexImage,'uint8')
    %do nothing
elseif isa(HexImage,'uint16')
    HexImage=uint8(HexImage/2^8);
elseif isa(HexImage,'double')   
    if max(max(max(HexImage)))>1
        fprintf('HexImWriteSVG Error: unsupported data type.\n'); return
    else
        HexImage=uint8(HexImage*2^8);
    end
else
    fprintf('HexImWriteSVG Error: unsupported data type.\n'); return
end
        

HexImageSize=size(HexImage);
HexImageWidth=HexImageSize(2);
HexImageHeight=HexImageSize(1);

%open file for writing
fId = fopen(Filename,'w+');
if (fId < 3)
    fprintf('HexImWriteSVG Error: Failure to open the output file.\n');
    return
end
    
%write SVG
fwrite(fId,['<svg width="' num2str((HexImageWidth+2)*1500) '"  height="' num2str((HexImageHeight+2)*1700) '"><g id="layer1">']);
for y=1:HexImageHeight
    for x=1:HexImageWidth
        fwrite(fId,['<path d="M'...
            num2str((x * 1.5)*980) ','...
            num2str((0.866 + y*1.732 - mod(x,2)*0.866)*980) ' l -500,866 l 500,866 l 1000,0 l 500,-866 l -500,-866 z" style="fill:#'...
            dec2hex(HexImage(y,x,1),2)...
            dec2hex(HexImage(y,x,2),2)...
            dec2hex(HexImage(y,x,3),2) ';" />']);
    end
end

fwrite(fId,'</g></svg>');
fclose(fId);