Updated to v1.2: August 23rd, 2014A while back I wanted to make a boot animation for my Nexus 7 2013, that utilized the Google splash screen in the first part of the bootanimation. I started searching Google and XDA, and found that it was embedded in the bootloader somewhere, but nobody had a clue how to retrieve it. I could see the battery charging icons with a hex editor and use FFmpeg to convert them from their encoded rgb24 pixel format into usable images. That was easy, but I couldn't find what I was looking for. I then figured they were in some odd pixel format, maybe even proprietary. I made loops going through every conceivable pixel format at different widths, generating 1000's of images, still nothing. The last thing I tried was making an image where every bit in the bootloader was translated into a pixel, either on or off, still nothing. I pretty much gave up, until I came across this thread. I had heard of run length encoding, but didn't know it was used in Android. I soon found that Google and some manufacturers were using it for the graphics in their bootloaders.
-Embedded a solid jpeg extractor in rlimager1.2.c (java is no longer needed)
-Added a zero byte function to fix the encoding of rgb0, bgr0, 0bgr, & 0rgb pixel formats
Hit the button below to see the splash screen for the Nexus 7 2013, this is a pixel for pixel exact image, with the Google logo and Unlock Icon in their un-encoded form as seen on the devices screen. (unfortunately the splash screen wasn't encoded as a complete image, the text was encoded one place and the lock icon in another, so I did have to use photoshop to make a 1200x1920 black background and place the Google logo and the lock icon in the right position.)
The complete Google splash screen in full 1200x1920 can be downloaded as an attachment at the bottom of this post. It is a PSD with a black background layer and the 518 pixel "Google" and the 72 pixel "unlock" all on separate layers.
This is a Windows batch script I wrote to find images in any type of file. Included in the zip at the bottom of this post is: a modified run length encoder/decoder, rlimager1.2.c, that does the encoding/decoding and the extraction of jpegs from any type of file.
Rlimager1.2.c is based off of the original to565.c put out by the AOSP several years ago. To565 was made to convert an rgb24 image into a rgb565 run length encoded file which could then be named initlogo.rle, and packed into the boot image for a kernel splash screen. Of course having the ability to encode images in this format left users the want to decode them as well (to make sure it worked before they flashed it to their device). XDA user @zebarbu in this thread, made a program to decode rgb565 rle as well. I must credit both of these authors, as rlimager1.2.c is based off of both these programs. I have added additional decoding/encoding of some newer formats; as mentioned below; as well as a jpeg extractor and a function to write 0's where ffmpeg will put 1's in the case of certain pixel formats.
The executable rlimager1.2.exe was compiled with mingw32-gcc 4.8.1 on a 64-bit Intel running Windows 7, and has been tested on Windows 7 Home Premium and Windows 8. The batch script, RUN_length_imager_v1.2.bat, will not work with obsolete versions of Windows. The source file for rlimager1.2.exe and RUN_length_imager_v1.2 batch script are available in the second post, as well as in the `src\` folder of the download. FFmpeg is also in the download, and the source can be found here, while the included pre-compiled version was downloaded at Zeranoe.
Googles ADB is also included in the download, which is located at the bottom of this post.
"Run_length_imager_v1.2.zip", should be unzipped into a new directory.
Click the button below for instructions on how to use rlimager1.2 by itself. Rlimager1.2 is a standalone command line program.
rlimager1.2.exe ([-e] [2-4] | [-d] [2-4] [-m] [max run] [-o] [offset]) < input_file > output_file
Mandatory, one or the other
-d (2-4)Run Length Decode input_file from 2, 3, or 4 byte color pattern
-e (2-4) Run Length Encode input_file to 2, 3, or 4 byte color pattern
-j (output root name) Extract Jpegs from file. Output name can include a full path.
-z (skip) -o (offset) Zero every (skip) bytes, starting with (offset)
Optional for [-d] decoding only:
-m (max run) Maximum pixel run to decode. Default is 0, which defaults to the maximum allowable for each color pattern
-o (offset) Offset (in bytes) to start decoding. Default is 0
rlimager1.2 -d 4 -m 8064 < "C:\example_file.rle" > "C:\output\rle_decoded\example_file.rgb0"
rlimager1.2 -j root_name < "C:\users\downloads\system.img"
Notice with the jpeg extractor example above you have to use: < "inputfile"
rlimager1.2 -z 8 -o 5 -i "C:\output\example_file.rle" -e 4 < "C:\example_file.rgb0" > "C:\output\example_file.rle"
The above example run length encodes the input file, then takes the output file and zeros every eighth byte starting at 5
You can also zero byte any file without doing it all on one line, like:
rlimager1.2 -z 5 -o 8 -i "C:\file_to_be_zeroed_every_5th_byte_strarting_wit h_the_8th.raw"
To load a file into RUN_length_imager_v1.2.bat, you have two options:
-Drag and drop the file you wish to use onto the "RUN_length_imager_v1.2.bat" file.
-Run the program and choose option 4 at the menu. This will pull whichever partition you choose, from your device to your computer.
Note:First and foremost before you get too much into searching for run length encoded images, you should check for jpegs first, especially if you have a Samsung device. It is really fast, and all you have to do is drag the file onto the RUN_length_imager_v1.2.bat file and select option 8 at the main menu. In five seconds or less, if there are jpegs in the file, you will have all of them in their entirety.
The second method requires you to have your ADB drivers for your device installed on your computer. You must also have busybox installed on your device. If for some reason ADB will not start and you end up with a blank partition list, simply close the program and open it back up and it should work. If it still doesn't work your ADB is probably not functioning correctly.
What is run length encoding?
RLE is a method of encoding an image with the intentions of having a smaller filesize. If you have 1000 pixels of the exact same color, you can save memory, by instead of encoding (R,G,B) 1000 times; you can add a count before the pixel description, 1000 (R,G,B). This works real efficiently for images that have lots of pixel runs, but an image where every pixel is different actually will take more memory than your conventional method of storage.
The Run Length Patterns:
I have found three different run length patterns so far. The first is the original one mentioned up above, rgb565, or as I call it 2 byte. This format can be used to encode any pixel format that uses two bytes per pixel. It works like this, the first 2 bytes is the count and the next 2 bytes is the color. The M8 uses this encoding for its bootloader graphics.
Note:The Nexus 5 and 4 use this next one, what I call 3 byte, because it can be used to encode any pixel format that uses...3 bytes per pixel. This encoding uses a 1 byte count and 3 byte color. This is easily the slowest method, for obvious reasons.
When I say "can be used to encode any pixel format that uses two bytes per pixel", I really mean pixel formats with sequential pixels. Some pixel formats use the YUV colorspace. Not all formats stored in the YUV colorspace store the pixels sequentially. For instance some YUV pixel formats will take 6 bytes of data for 4 pixels, but the first 3 bytes are not just for the first 2 pixels.
In the RGB colorspace there are BAYER pixel formats which don't encode sequential pixels either, the colors are split onto different lines in this method. Neither of the previous examples are candidates for this type of run length encoding.
The last one, up to this point, is what I will reference as 4 byte. It works with four byte per pixel pixel formats, and uses 4 bytes for the count and 4 bytes for color. Both Nexus 7's use this format.
There may be more patterns, but it is hard to find partition dumps to download off the internet. I have found several though, and found run length encoded images in almost all of them. If anyone wants to upload a bootloader, I will gratefully add it to my collection and see what is in it.
This program will take any file, and decode it using whatever pixel format you choose, and if you have run length decoding turned on it will automatically associate the proper run length method to make a usable image, if there is one. Another important thing when dealing with raw image files, besides the pixel format, is the line length (width). This width is encoded in regular image files like bmp, jpg, and pngs. But raw images are nothing but pixel data. To get the correct image, if there is one, you have to specify when to go to the next line. I have built loops into the windows script that will let you specify multiple pixel formats to run, with an embedded loop that goes through all of the different widths you choose.
You may want to load a whole bootloader file to see if there are any images in it. To do so just drag and drop the file onto "RUN_length_imager.bat" Since the file contains different types of code and possibly images, you will want to set the maximum pixel count down to around 1000. This will limit the maximum number of a pixel run. This is necessary because not all of the data going through the decoder is meant to be run length decoded obviously, so FF FF FF FF 01 01 0A F0 in a 4 byte rle scheme will decode to over 16 gigabytes if you don't have your maximum pixel run set down to halt this.
Note:Another variable is the byte offset. Since the very first count byte has to go into the decoder as the very first count byte, you may have to offset the whole file up to a certain number of bytes as specified below.
You can stop the program at any time. I designed the program to save your settings before running and after changing anything. So if you accidentally don't set your max run and it seems like it is taking forever, and you are watching the output file size growing and growing, you can simply x out of it, or close it. Restart it and adjust whatever you have to.
For 4 byte rle patterns offsets to be tried are 0,1,2,3,4,5,6,7.The last variable is the width. Hitting 2 in the program will allow you to set a range, or specific widths. Example: My Nexus 7 2013 bootloader has the Google logo as a 518 pixel wide image, the android as 712, the buttons as 1090, and some other things at 600 and 960. I would enter:
For 3 byte rle patterns offsets to be tried are 0,1,2,3
For 2 byte rle patterns offsets to be tried are 0,1,2,3
518 712 1090 600 960
The second method is an exploratory method, where you enter the starting width, skips, ending width. All separated by commas.
712, 1, 1200
Note:Click the button below to see what the entire Nexus 5 bootloader screen looks like when the bootloader "file" is loaded with these settings used: pixel format rgb24, max run 1080, offset 0, line length 1080. The image is really big, because the whole file is run length decoded.
The height is automatically calculated based on the width, filesize, bytes per pixel. This happens at the core of the loops.
After you click the button, scroll down and you will see the bootloader screen towards the bottom of the image.
This is the Nexus 4, whole bootloader, pixel format rgb24, max run 1080, offset 0, line length 720
After you click the button, scroll down and you will see the bootloader screen towards the bottom of the image.
You've Identified there are images, but how do you extract just the images?
You need a good hex editor, don't worry though because you don't have to look at any hex. I prefer 010 Editor by SweetScape Software. You get a free 30 day trial. Download it. Load your bootloader file into it by right clicking on the file and selecting "010 editor". If you don't have your bootloader file you can use option 4 in RUN_length_imager.bat and pull the partition from your device. If you don't know what partition you are looking for or how to do it manually, here is an excellent guide. If you use my script, the partition will be saved in the "__partitions__" folder.
Go up to View:
Set Left Area to Char
Set Right Area to Binary
Change Line Width to Custom Width
Choose a value where the characters on your left pane almost fill up your screen so that when you start scrolling over, your right pane (binary) is right there. The right binary pane is a lot wider, that's why I prefer it on the right. Also choose a width that is evenly divisible by 8, I set mine at 224, using a small 1366x768 laptop.
A real handy shortcut in 010 editor is Ctrl + and Ctrl - to enlarge or shrink the font.The 4 byte run length encoding is the easiest to identify because there is 4 bytes for the count, and the biggest number you can store into a 4 byte address is over 4 billion. The 3rd and 4th bytes are usually nothing but zeros. The only 4 byte pixel format I've seen used so far is, bgr0, which also has the fourth byte as nothing but 8 zeros. Here is what a typical looking 4 byte rle image looks like.
Notice how the count value, mostly, show up as just four periods ....
Sometimes the first byte (period) will be a different character representing a higher value for a run of same colored pixels. Also notice that there is a lot of black and white (gray) shades in the color values. All colors on a grey scale, represented in rgb, are equal values. A value of 255,255,255 is white 200,200,200 is a light shade of grey, and 0,0,0 is black. The rgb values will always be identical to be an exact shade of grey. This image is part of the Google logo which is mostly black and white.
Any area that you highlight in the "char" pane will also be highlighted in the "binary" pane when you scroll over, you'll find this extremely handy. These 8 bytes is one complete encoded run, which represents 15 pixels pure white. You can see exactly how the four count bytes sit beside the bgr0 color bytes. Byte 1 is 00001111, binarys equivalent to decimal 15. Bytes 2, 3, and 4 are 0; then the color bytes 5, 6, 7, 8. Blue is represented with the 5th byte, green the 6th, red the 7th, and the 8th byte is not used in this pixel format. Don't get confused about the pixel format, because this method of encoding will cover all 4 byte per pixel formats, some could use the 4th color byte (or alpha), and the order they're in is not that important right now. Unless you know exactly what you are looking for, like the infamous green android laying on its back, you may be trying to pay more attention to the green column when trying to find where the image starts or stops.
(This is the binary copy of the android image you see if you have a Nexus 7 2013)
(from Nexus 7 2013 bootloader)
This part can be kind of tricky, I actually surprised myself at how good I was at "getting lucky" and finding the correct beginning and ending of an image in the bootloader files. So that probably means that it really isn't that hard, it is just not something you encounter every day. Being aware of how your image should be encoded helps a lot. If you know there are 100's of black pixels at the start and/or end of an image, keep that in your mind when looking at the characters.
An image will never start or end with the count byte(s) as 00000000!!! But, often times they DO start or end after some zeros, or before some zeros at the end. Take for example: This is the beginning of one of the lock images. (notice how it is right after the text ANDROID BOOT, hmm)
(Keep in mind that this is a 4 byte pattern run length encoding, which actually will consume 8 bytes total per run. Four bytes for the count and four bytes for the color. The other two patterns look as you would think: 3 byte .### 2 byte ..##)
Notice how the count bytes before what I have highlighted in blue is all zeros. So you won't start there, move right and see what that is. And that is your image start, it is a run of 28 solid black pixels (0,0,0,0) Once you have identified the start, and hopefully selected it as I have in the screenshot, write down the number after "Start:" Which is 3097596.
This is the end of the lock. Notice the characters all of the sudden changing, this is an indication of a color change. I visually scanned line by line and found this spot that separated all the ÿÿÿ and ÀÀÀ's up above to the newer assortment of characters like ## and 33Ì
Now you need to isolate just that image. With those last 8 bytes selected, go up to Edit - Select Range, and down at the bottom of the screen, enter in the start byte you wrote down earlier. Hit enter and the encoded image will be selected. Copy this by hitting Ctrl-C or going up to Edit - Copy.
Go to File - New - New Hex File
Hit Ctrl-V to paste, or go to Edit - Paste
Now save that file somewhere, and drag and drop it onto "RUN_length_imager.bat"
I already knew the width of the image before writing this, but here is the output with the Line length set at 60,1,80 and pixel format bgr0
You can also encode jpg, bmp, and png files into whatever 2, 3 or 4 byte pixel format you choose. The run length encoding will be automatically adjusted according to which pixel format you choose.
When encoding images into the pixel format rgb0, bgr0, 0rgb ...
Any of those 4 byte formats. FFmpeg will put 11111111 in place of the zero in the zero byte position. I'm not sure why it doesn't put 00000000 like it should, but I know how to fix it, but it involves another option, and I haven't gotten to it yet. If you were to try writing this to your device, I have no idea how Android would treat this 11111111 in the null spot, because as far as I know rgb0 (and cousins) is a made up definition by the writers of FFmpeg to describe rgb24 as rgb32 with 8 bits per color, and 8 padding bits.
Nexus 5 & 4 use the pixel format rgb24. The whole bootloader screen is encoded in one pass, as opposed to drawing several images at different spots on the screen.
The Nexus 7 1 & 2 use the pixel format bgr0. It's kind of ironic that at first when I was looking for the Google logo, I thought it was entirely made up of black and white pixels and stored in an 1 = white 0 = black, binary format (that would account for no one being able to find it, unless you do like I did and use the monow or monob pixel format in FFmpeg), but in actuality the format that it is stored in can potentially contain billions of colors. (4 byte color)
The Nexus 7 2013 Unlock Icon has an extra white pixel at the bottom right that you can clearly see on the device, now that I told you it's there. Does it mean something, or is it just poor editing by the people at Google?
The Nexus 7 2013 has the Google logo encoded in 3 different places in the Bootloader. They are binary copies of each other, so that leads me to believe that the reason for this is to discourage people from trying to edit the images. Maybe you'd brick if you just changed one and not all three? I don't know, but can't think of any other reason why they would do this. There is also two unlock icons, not counting the big one on the bootloader screen that asks you if you're sure you want to unlock it.
The Nexus 7 2013 has the only bootloader, that I've encountered, that not only stores images in a 4 byte run length manner, but there are also non-encoded 3 byte rgb24 images for the battery icon, and charging icons. Even the older Nexus 7 has all of the images run length encoded.
Samsung bootloaders use jpegs, although I did find the Linux penguin, non-encoded in the Note 3. I also found the "font mask" that uses bits to make some different fonts stored as bit masks. You can see it, using the monow or monob pixel format and setting your width at 16 32.
The HTC M8 uses the pixel format rgb565. The only device I own is the second generation Nexus 7, and it is the only one where I have been through the bootloader with a purpose. Since I don't own a M8 I really kind of just glanced at it in the hex editor and found the exclamation triangle, the htc silver logo, and the android laying on its back; all run length encoded. It also has the bit mask font embedded in it for the text, as I mentioned about the Note 3.
I take no responsibility to any damage that is done to your device or computer with this program.Changelog:
The source file and batch script can be found in the following post AND in the download!
Download Run Length Imager v1.2
Current version 1.2
-Embedded a solid jpeg extractor (java is no longer needed)
-Added a zero byte function to fix the encoding of rgb0, bgr0, 0bgr, & 0rgb pixel formats
-Added and Output folder to contain made images
-Several other code modifications
-Added a java jpeg extractor
-Click the button below to view the additional credits related to version 1.1
2013 Nexus 7 where you can see all three logos