At the start of this year a tiny e-reader called the xt4 took the internet by storm. I want to say its in part to jvschoolz and his gentle influence of showing off niche tech that fits into his workflow. I will admit I was one of these people that were first put onto the device by him. After watching that initial video I ordered one myself as I figured it would be an easier way to have a distraction free reading device on me.
Page Discrepancy
After getting the device I quickly realized that it only supported specific formats, and the only format that was able to display the math symbols and pictures in my computer science books was the custom format designed for the device. Thankfully someone with the use of AI was able to craft a website to take more common formats and convert them the the custom format that the device used. This brought me to my issue, Now although I sometimes read with the device I will also read the physical book or the digital version on a larger device. This brings up the issue that when im reading the book on another platform I need to know what page I need to switch to on the xt4 as its page numbers are independent from the actual page numbers.
Building a Raylib program in Golang
Again im not one to shy away from admitting when I enjoy something, and Raylib is one of thoes libaries that just make doing things enjoyable. Golang has also been a language that I have been enjoying learning at the start of this year, so naturally it felt only natural to combine the two. Choosing Raylib affords me to not worry about a lot of the implementation like “will it work on X system?”, because Raylib has taken care of this and a lot of other problems. This allows me to just focus on building the program that I want. Which the main bulk of the program was figuring out how to convert from one data format to uncompressed grayscale.
Deconstructing and Expanding bits
The first format is XTG and XTC. XTG is the basic monochrome image file type and XTC is a container to house multiple monochrome XTG image file types. My initial point of attack was to use ImHex, which is a fantastic program to see the internal makeup of a file, with the addition of having a scriptable language that lets you specify how this data should be laid out and then visually color codes that section of data. The data structure for XTG and XTH are both similar and laid out as follows
- a 4 byte string for the identifier mark, either XTG or XTH
- the devices width
- the devices height
- the devices color mode
- if compression was used
- the size of data, as the product of width and height
- the data itself
The tale of two bit planes
A bit plane is a data structure of lining up binary data as a plane and sequencing the data as the planes rather then sequentially. XTG takes the sequential approach, each bit represents a pixel that is either black or white. XTH stores its data onto two bit planes. The data represents four possible values from 00 being a white pixel to 11 being a black pixel, 10 and 01 being light and dark gray. Since the data is two bits each bit is seperated onto its own bit plane. So to get the first pixel we need the first bit from both bit planes.
Putting it all togther with Raylib
Being able to oranize the data we can now display our custom file type. Using Raylib it’s relatively simple to take this data and load it as an image texture in the grayscale format. With a few extra lines of code we can make it so the arrow keys iterate through the pages and display the current page number.