# [MAKE] Boot Logo for a Laptop

Posted 1 year ago
3165 Views
|
|
17 Total Likes
|
 Open in Cloud | Attachments for Desktop at the EndWARNING: Customizing boot logo of the laptop might require flash the BIOS firmware, which has a small chance to fail and permanently "brick" the laptop!Just as many people, I do a lot of work on my laptop. And naturally, just like many people, I want to customize it to feel like "mine". One thing I always wanted was to change the boot logo, since that's the first thing you see when you wake up your electric friend. Image my excitement when I found out that there's an official BIOS Update Utility just for that for my ThinkPad T440s! The only catch, according to the vaguely written documentation in the utility, and a bunch of internet articles I found, it seems that the logo designs are subject to certain constraints: the most suitable format is GIF image dimensions must be less than 768 x 432 image must be below 30KiB. Having got that out of the way, it's time to make my awesome logo!As a start, I generated a vector drawing using the Constantia font and the lovely \[LightBulb] icon. vectorgraph = ExportString[ Style["i\[LightBulb]ea", 100, Bold, FontFamily -> "Constantia"] // Echo , "PDF"] // ImportString[#, "PDF"][[1]] & I wanted my logo to look low-poly styled. Firstly, I made the edges jagged by chossing a large value for MaxCellMeasure. bregionInit = vectorgraph // BoundaryDiscretizeGraphics[ #, MaxCellMeasure -> 10 ] & Next, I trianglized the region with TriangulateMesh. For the same reason, a large MaxCellMeasure really helps to give the low-poly effect. In addition, a high MeshQualityGoal is necessary to create somewhat regular triangle pieces.At this point, the 30KiB limitation I talked about earlier comes into play. Many triangles means more details means larger file size, even for GIF. Through some good old eye-balling, I settled on a value of 0.7, which manages to look great while still staying under the limit. mesh = TriangulateMesh[ bregionInit , MeshQualityGoal -> .7 , MaxCellMeasure -> 200 ] The shape looks good to me. For afterward manipulation, let's collect all the triangles with their positions. polys = MeshPrimitives[mesh, 2]; centers = PropertyValue[{mesh, 2}, MeshCellCentroid]; polys // Short centers // Short (* {Polygon[{{2.115,19.2363},{4.8094,19.2363},{1.94625,20.9013}}],<<367>>,Polygon[<<1>>]} {{2.95688,19.7913},<<367>>,{58.7516,38.3716}} *) Pretty good, but better with some colors!One possible way to paint my triangles is to shade them according to their heights.To do that I extracted the heights and rescaled them to get a percentage $\lambda$ so those near the central horizontal line have values near 0, and those furthest have values near 1. It will serve as a "gradient mask" for later use. ?s = centers[[;; , 2]] // RightComposition[ Through@*{Identity, Mean} , Apply[Subtract] , Abs /* Rescale ]; Time to choose a color scheme. I find "StarryNightColors" very delightful. polysNew = MapThread[Function[{p, c, ?}, { FaceForm[ColorData["StarryNightColors"][2 ?]] , p} ] , {polys, centers, ?s} , 1]; polysNew // Shallow /* Short (* {{FaceForm[<<1>>],Polygon[<<1>>]},{FaceForm[<<1>>],Polygon[<<1>>]},<<7>>,{FaceForm[<<1>>],Polygon[<<1>>]},<<359>>} *) logo = Graphics[{polysNew}, Background -> Black, PlotRangePadding -> 0] Looks much better now, isn't it?However, I am still not satisfied. Bearing in mind the file size restriction, maybe I can experiment with some geometric transformations? logo = Block[{ polysNew, ?TransFunc = Function[x, (1 - Cos[?/2 x]^3)/2] }, polysNew = MapThread[Function[{p, c, ?}, { FaceForm[ColorData["StarryNightColors"][2 ?]] , MapAt[(1 - ?) # + ? c &, {1, ;;}]@p} ] , {polys, centers, ?s // ?TransFunc} , 1]; Graphics[{polysNew}, Background -> Black, PlotRangePadding -> 0] ] Not bad, except that the central pieces are now waaay too dark. Let's add some bright edges for them. logo = Block[{ polysNew, ?TransFunc = Function[x, (1 - Cos[?/2 x]^3)/2] }, polysNew = MapThread[Function[{p, c, ?}, { If[? > .3, {}, EdgeForm@{GrayLevel[1 - ?^.5], AbsoluteThickness[0]} ] , FaceForm[ColorData["StarryNightColors"][2 ?]] , MapAt[(1 - ?) # + ? c &, {1, ;;}]@p} ] , {polys, centers, ?s // ?TransFunc} , 1]; Graphics[{polysNew}, Background -> Black, PlotRangePadding -> 0] ] The warming yellow has been restricted to the light bulb, leaving me pure deep blue glossy letters. I think I'm good to go :DTo fit the constraint of the utility tool, the final work is to rasterize the image and export it to GIF. logoImg = logo // RightComposition[ Image[#, ImageSize -> 1000] & , ImagePad[#, 50, Black] & , ImageResize[#, 768 + 45] & , ImageCrop ]; logoFile = Export[ FileNameJoin[{NotebookDirectory[], "logoImg.gif"}] , logoImg , "GIF" ]; Unfortunately, despite my very carefully tuning, the resulting GIF still exceeded the file size limitation of 30KiB. FileSize[logoFile] // UnitConvert[#, "Kibibytes"] & 48.8789KiBI searched around and came to a commandline tool called Gifsicle. The following command (run in OS' console) finally did the trick. Hurray! gifsicle -k 50 -O3 --no-extensions --no-comments < logoImg.gif > LOGO2.gif Now check the perfect file size, FileSize[FileNameJoin[{NotebookDirectory[], "LOGO2.gif"}]] // UnitConvert[#, "Kibibytes"] & 29.7598KiBThe rest is refreshingly straight forward. I dropped my LOGO2.GIF in the utility's own directory and executed the firmware update utility. It automatically picked up the logo image and proceeded to modify my firmware. One reboot later, I was rewarded by my very own boot logo!Easter eggs:Can you guess what happened when I remembered my another old ThinkPad the next day?(The color scheme used here was "CoffeeTones".)At last, the family photo of my electric friends :) Thanks for watching and ... ...Stay tuned! Next post we will share our experiment on making cool booting animation with Mathematica for Android phones! :) Attachments: