Skip to content

eppisai/GSoC-Task---T1191

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 

Repository files navigation

AXIOM Remote UI Challenge: 2 bit image drawing

Subtask Completed in 2 Bit Image Drawing

  • A Python Script to Convert Image to Array
  • DrawIcon2bit method in Painter to draw 2 Bit icons in firmware
  • Extended Icon.h, to better fit 2 bit icon data, and its colors
  • Added Transparency feature in Drawing 2 bit Icon
  • Unit Test to verify Proper Implementation
  • How Image to array conversion in Python Script is happening?

  • Repository for Image to Array Conversion Python Script
  • def image_to_array(im):
       im = rgba_to_2bit(im)
       array = []
       im = np.array(im)
       im = im.reshape(im.size//4,4)
       setbits = np.array([0, 2, 4, 6])
       for i in im:
           bits = i<<setbits
           array.append(bits.sum())
       return array
    

    Above image_to_array Function,

    1. converts the image, to its quantized version with 4 colors,
    2. then converts image to a numpy array, which is then reshaped to a 2d numpy array of width 4 and height (im.size/4)
    3. We reshaped the array into size of 4 since, each byte in final output would have 4 pixel, (2 bit per pixel)
    4. For each pixel row (size is 4) in image array, we convert it to byte, shifting each bit in muliples of 2(4 values), and then adding them
    5. We set the 1st bit of each row of image as Least significant bit, because we need to start drawing from 1st bit. (last bit is MSB - most significant bit)
    6. made a new array with bytes of pixel bits.

    def rgba_to_2bit(image):
      white_image = Image.new('RGBA', image.size, (255, 255, 255))
      image = Image.alpha_composite(white_image, image)
      image = image.convert('L')
      image = image.quantize(4)
      return image
    
    

    Above rgba_to_2bit Function,

    1. Mixes background color (white to get correct rgb conversion) with pixel color in the ratio of their alpha value(transparency), called alpha compositing.
    2. converts the image to greyscale and then in quantizes its colors to 4.
    3. We are converting image to grey scale to have a gradual decreasing shades of black to white, we can extract colors manually also.

  • Repository of AXIOM Remote, with 2 bit image Task
  • DrawIcon2bit Method

    void Painter::DrawIcon2Bit(const Icon2bit* image, uint16_t x, uint16_t y, float transparency = 0)
    {
            int b = 0;
            for (uint16_t yIndex = 0; yIndex < image->Height; yIndex++)
            {
                uint16_t yPos = y + yIndex;
    
                for (uint16_t xIndex = 0; xIndex < image->Width;)
                {
                    uint8_t data = image->Data[b];
                    for (int i = 0; i < 8; i+=2)
                    {
                        uint8_t pixel = ((1 << 2) - 1) & (data >> i);
    
                        if(pixel)
                        {
                            uint16_t pixelcolor = image->IndexedColors[pixel];
                            uint16_t backcolor = _framebuffer[y * _framebufferWidth + x];
                            uint16_t finalcolor = ApplyTransparency(transparency, pixelcolor, backcolor);
                            DrawPixel(x + xIndex, yPos, finalcolor);
                        }
    
                        xIndex++;
                    }
                    b++;
                }
            }  
    }
    
    

    Above is a farily straight forward function, which processes each byte and extracts bits from bytes in pairs of two and matches each pair to its corresponding color, and then apply Transparency to it.


    Transparency function for 2 bit icon

    uint16_t Painter::ApplyTransparency(float transparency, uint16_t color, uint16_t background)
    {   
        uint16_t pixelColor = 0;
    
        //Red color channel with transparency amount of Background color
        pixelColor +=  uint16_t( (color & 0xF800)*(1 - transparency) + (background & 0xF800)*transparency ) & 0xF800;
    
        //Green color channel with transparency amount of Background color
        pixelColor += uint16_t( (color & 0x07E0)*(1 - transparency) + (background & 0x07E0)*transparency ) & 0x07E0;
    
        //blue color channel with transparency amount of Background color
        pixelColor += uint16_t( (color & 0x001F)*(1 - transparency) + (background & 0x001F)*transparency ) & 0x001F;
    
        return pixelColor;
    } 
    
    

    Above function,applies transparency by taking background color in Transparency amount, and Pixel color in (1 - transparency) amount in the new color.
    Note : Value of Transparency is between 0 and 1 (float, not double).I am using RGB565 color chanel masks, complete article is in references.


    Extended Icon2bit.h

    #ifndef ICON2BIT_H
    #define ICON2BIT_H
    
    #include <inttypes.h>
    
    #include "../../Utils.h"
    enum class ImageDataFormat : uint8_t
    {
    	Monochrome = 0,
    	Indexed2Bit = 1
    };
    
    struct Icon2bit
    {
        const uint16_t Width;
        const uint16_t Height;
        ImageDataFormat Format;
        uint16_t IndexedColors[4];
        const uint8_t* Data;
    };
    
    #endif // ICON2BIT_H
    
    

    Above structure, extends Icon.h with color storage of 2 bit icon and, and enum for user readability

    References Used

  • For color extraction for 16 bit RGB565 pixel, I am using RGB565 color masks, as descrided here
  • For RGB to RGBA conversion and for transparency in remote (alpha compositing), I am using this simple formula, described in 1st answer

  • Output

    • 1st image is 2 bit icon with 0 percent transparency and 2nd image is 2 bit icon with 60 percent transparency



    About

    AXIOM Remote UI Challenge: 2 bit image drawing

    Resources

    Stars

    Watchers

    Forks

    Releases

    No releases published

    Packages

    No packages published