How it works
The procedures below analyze the colors in the day layout and "darken" them to produce the night layout. This is done by analyzing the red, green and blue channels for each color and calculating their brightness and darkness. The brightness (amount of white) is equal to the smallest channel value; the darkness (amount of black) is equal to 255 minus the biggest channel value. Then brightness and darkness are swapped by subtracting brightness from each channel and adding darkness. Thus light colors will become dark and vice versa, while the hue (color) is maintained. For "pure" colors (e.g. pure red, green, blue, or more generally: any color composed of at least one completely black and one full-intensity channel) there is no change; shades of gray will be inverted completely (with black becoming white and vice versa).
All this conversion takes place in the OpenOffice sheet. (Excel might work as well, but was not tested.) You can change the conversion algorithm by playing around with the formulae.
Bugs and Limitations
- Default colors are not handled properly: Items formatted in the default color will not be converted. This may lead to undesirable results such as black text on black background.
- Icons are not modified. The night layout will use the same icons as the day layout. Depending on the layout, this may not be an issue. If you do not want that, you need to convert the icons separately, save them to a different path (or with different names) and adjust the icon paths in the layout accordingly. ImageMagick is a suitable tool for batch-converting multiple bitmap images.
- Just swapping the amounts of black/white causes very "pure" colors to appear extremely bright in the night layout. A conversion strategy which treats brightness in a uniform manner might be a better idea.
- All this can probably be done more nicely in a script and/or with some SAX library to properly extract color information right from navit.xml and add the new layout right there. I went for the more basic approach as I intended to run this just once and see what the result looks like...
- Extract the layout from navit.xml (or whatever your source may be) and save it to a .xml file. In this example we name it android-hdpi.xml.
- Now extract all colors it uses. The command below does that. In addition, it sorts the colors and eliminates duplicates. We are saving the result to a file named colors.txt.
cat android-hdpi.xml | grep color | sed -rn 's/.*(color=\"#[0-9a-fA-F]*\").*/\1/p' | sort -u > colors.txt
- Open the .xml file in a text editor. Replace all occurrences of color="# with color="! and adjust the name, daylayout and active parameters of the layout tag. Save under a different name, in this example we use android-dark-raw.xml.
- Open colors.txt in a text editor, then paste it into an empty OpenOffice spreadsheet. Run "Data > Text to Data". Set " and # as separators. Format the column containing color values as text and choose to hide all others.
- Insert the following formulae into your spreadsheet (the formulae below are for row 1; drag them down in Calc as needed):
|Explanation||Day layout color in web notation||Red channel||Green channel||Blue channel||Amount of black||Amout of white||Red channel of night layout color||Green channel of night layout color||Blue channel of night layout color||Night layout color in web notation|| Replace string such as |
|Formula||(no formula, just the pasted hex color value)||=HEX2DEC(LEFT(A1;2))||=HEX2DEC(MID(A1;3;2))||=HEX2DEC(MID(A1;5;2))||=255-MAX(B1:D1)||=MIN(B1:D1)||=B1-F1+E1||=C1-F1+E1||=D1-F1+E1||=DEC2HEX(G1;2) & DEC2HEX(H1;2) & DEC2HEX(I1;2) & RIGHT(A1;LEN(A1)-6)||="s/!" & A1 & "/#" & J1 & "/g"|
- Copy the column containing the color values from your spreadsheet into the A column of colors.ods. If necessary, copy the formulae down or delete superfluous rows.
- Select the last column, copy it and paste it into an empty text document. Save it as col-replace.sed.
- Now run:
cat android-dark-raw.xml | sed -f col-replace.sed > android-dark.xml
- Copy android-dark.xml into your navit.xml.
- To have Navit automatically switch between day and night layout, give the <layout> tag of the day layout a nightlayout parameter with the name of your night layout. Conversely, give the <layout> tag of the night layout a daylayout parameter with the name of your day layout.
- Now test your layout; you may find that some extra tweaks are needed. For example, while minor roads are drawn in white with a gray border in my day layout, the automatic conversion would give me black roads with a gray border. I decided to manually change that to gray roads with a black border, which is more visible.