Ticket #1999: patch_bootsplash_20080406.diff

File patch_bootsplash_20080406.diff, 7.5 KB (added by stpere, 16 years ago)

Enhanced RLE, see comment

  • src/tools/generate_boot_screen.cpp

     
    55 *  Authors:
    66 *      Artur Wyszynski <harakash@gmail.com>
    77 *      Stephan Aßmus <superstippi@gmx.de>
     8 *      Philippe Saint-Pierre <stpere@gmail.com>
    89 */
    910
    1011//! Haiku boot splash image generator/converter
     
    1314#include <png.h>
    1415#include <string>
    1516#include <stdarg.h>
     17#include <stdint.h>
    1618
    1719// TODO: Generate the single optimal palette for all three images,
    1820// store palette versions of these images as well, so that they are
     
    2123
    2224
    2325FILE* sOutput = NULL;
     26int   sOffset = 0;
    2427
    25 
    2628static void
    2729error(const char *s, ...)
    2830{
     
    120122
    121123
    122124static void
     125newLineIfRequired()
     126{
     127    sOffset++;
     128    if (sOffset%12 == 0)
     129    {
     130        fprintf(sOutput, "\n\t");
     131    }
     132}
     133
     134
     135static void
    123136writeHeader(const char* baseName, int width, int height, png_bytep* rowPtrs)
    124137{
    125138    fprintf(sOutput, "static const uint16 %sWidth = %d;\n", baseName, width);
    126139    fprintf(sOutput, "static const uint16 %sHeight = %d;\n", baseName, height);
    127140    fprintf(sOutput, "#ifndef __BOOTSPLASH_KERNEL__\n");
    128     fprintf(sOutput, "static const RLE_element %sCompressedImage[] = {\n\t",
     141   
     142    int buffer[128];
     143    // buffer[0] stores count, buffer[1..127] holds the actual values
     144
     145    fprintf(sOutput, "static uint8 %sCompressedImage[] = {\n\t",
    129146        baseName);
    130147
    131     int offset = 0;
    132     int lastColor = -1;
    133     int counter = 0;
    134     for (int y = 0; y < height; y++) {
    135         png_byte* row = rowPtrs[y];
    136         for (int x = 0; x < width * 3; x++) {
    137             if (lastColor == row[x]) {
    138                 // if the currentColor is already being counted...
    139                 counter++;
    140             } else {
    141                 // otherwise display what we had in memory, record that color
    142                 // and reset the counter...
    143                 if (lastColor != -1) {
    144                     offset++;
    145                     fprintf(sOutput, "{%d, 0x%02x}, ", counter, lastColor);
    146                     if (offset % 6 == 0) {
    147                         fprintf(sOutput, "\n\t");
     148    for (int c = 0; c < 3; c++)
     149    {
     150        // for each component i.e. R, G, B ...
     151        // NOTE : I don't care much about performance at this step, decoding however...
     152        int currentValue = rowPtrs[0][c];
     153        int count = 0;
     154
     155        // When bufferActive == true, we store the number rather than writing
     156        // them directly; we use this to store numbers until we find a pair..
     157        bool bufferActive = false;
     158
     159        sOffset = 0;
     160
     161        for (int y = 0; y < height; y++) {
     162            png_byte* row = rowPtrs[y];
     163            for (int x = c; x < width * 3; x += 3) {
     164                if (row[x] == currentValue) {
     165                    if (bufferActive) {
     166                        bufferActive = false;
     167                        count = 2;
     168                        if (buffer[0] > 1) {
     169                            fprintf (sOutput, "%d, ",
     170                                128 + buffer[0] - 1);
     171                            newLineIfRequired();
     172                            for (int i = 1; i < buffer[0] ; i++) {
     173                                fprintf( sOutput, "0x%02x, ",
     174                                    buffer[i] );
     175                                newLineIfRequired();
     176                            }
     177                        }
     178                    } else {
     179                        count++;
     180                        if (count == 127) {
     181                            fprintf (sOutput, "127, ");
     182                            newLineIfRequired();
     183                            fprintf (sOutput, "0x%02x, ", currentValue);
     184                            newLineIfRequired();
     185                            count = 0;
     186                        }
    148187                    }
     188                } else {
     189                    if (bufferActive) {
     190                        if (buffer[0] == 127) {
     191                            // we don't have enough room,
     192                            // flush the buffer
     193                            fprintf (sOutput, "%d, ",
     194                                128 + buffer[0] - 1);
     195                            newLineIfRequired();
     196                            for (int i = 1; i < buffer[0] ; i++) {
     197                                fprintf( sOutput, "0x%02x, ",
     198                                    buffer[i] );
     199                                newLineIfRequired();
     200                            }
     201                            buffer[0] = 0;
     202                        }
     203                        buffer[0]++;
     204                        buffer[ buffer[0] ] = row[x];
     205                    } else if (count > 0) {
     206                        buffer[0] = 1;
     207                        buffer[1] = row[x];
     208                        bufferActive = true;
     209                        if (count > 1) {
     210                            fprintf (sOutput, "%d, ", count);
     211                            newLineIfRequired();
     212                            fprintf (sOutput, "0x%02x, ",
     213                                currentValue);
     214                            newLineIfRequired();
     215                        }
     216                    }
     217                    currentValue = row[x];
    149218                }
    150                 lastColor = row[x];
    151                 counter = 1;
    152219            }
    153 
    154             if (x == width * 3 - 1 && y == height - 1) {
    155                 // we have reach the end
    156                 fprintf(sOutput, "{%d, 0x%02x}\n};\n\n", counter, row[x]);
    157                 offset++;
    158                 break;
     220        }
     221        if (bufferActive) {
     222            // I could have written 127 + buffer[0], but I think this is more readable...
     223            fprintf (sOutput, "%d, ", 128 + buffer[0] - 1);
     224            newLineIfRequired();
     225            for (int i = 1; i < buffer[0] ; i++) {
     226                fprintf( sOutput, "0x%02x, ", buffer[i] );
     227                newLineIfRequired();
    159228            }
     229        } else {
     230            fprintf(sOutput, "%d, 0x%02x, ", count, currentValue);
     231            newLineIfRequired();
     232        }       
     233        // we put a ending zero, just to indicate end of channel
     234        fprintf(sOutput, "0");
     235        if (c != 2) {
     236            fprintf(sOutput, ",");
    160237        }
     238        fprintf(sOutput, "\n\t");
    161239    }
    162     fprintf(sOutput, "static const uint32 %sSize = %d;\n", baseName, offset);
     240    fprintf(sOutput, "};\n");
    163241    fprintf(sOutput, "#endif\n\n");
    164242}
    165243
     
    232310    fprintf(sOutput, "static const int32 kSplashIconsPlacementY = %d;\n\n",
    233311        iconPlacementY);
    234312
    235     fprintf(sOutput, "struct RLE_element \n{\n\tuint16 count; \n\tuint8 "
    236         "colorComponent;\n};\n\n");
    237 
    238313    parseImage(argv[1], "kSplashLogo");
    239314    parseImage(argv[4], "kSplashIcons");
    240315
  • src/system/boot/platform/bios_ia32/video.cpp

     
    796796
    797797
    798798static void
    799 uncompress_RLE(const RLE_element *compressed, uint8 *uncompressed, uint32 size)
     799uncompress_RLE(const uint8 compressed[], uint8 *uncompressed)
    800800{
    801     uint32 cursor = 0;
    802     for (uint32 i = 0; i < size; i++) {
    803         memset(uncompressed + cursor, compressed[i].colorComponent,
    804             compressed[i].count);
    805         cursor += compressed[i].count;
    806     }
     801    uint32 cursorUncompressed = 0;
     802    uint32 cursorCompressed = 0;
     803    uint8 count = 0;
     804    uint8 item = 0;
     805    int i = 0;
     806    for (uint8 c = 0; c < 3; c++) {
     807        // for Red channel, then Green, then finally Blue...
     808        cursorUncompressed = c;
     809        while (compressed[ cursorCompressed ]) {
     810            // at the end of the channel there is a stopper 0, so the loop will end...
     811            // (ref: generate_boot_screen.cpp)
     812            count = compressed[ cursorCompressed++ ];
     813            if (count < 128) {
     814                // regular run, repeat "item" "count" times...
     815                item = compressed[ cursorCompressed++ ];
     816                for (i = count - 1; i >= 0; --i) {
     817                    uncompressed[ cursorUncompressed ] = item;
     818                    cursorUncompressed += 3;
     819                }
     820            } else {
     821                // enumeration, just write the next "count" items as is...
     822                count = count - 128;
     823                for (i = count - 1; i >= 0; --i) {
     824                    uncompressed[ cursorUncompressed ] = compressed[ cursorCompressed++ ];
     825                    cursorUncompressed += 3;
     826                }
     827            }
     828        }
     829        // the current position of compressed[cursor] is the end of channel, we skip it...
     830        cursorCompressed++;
     831    }
    807832}
    808833
    809834//  #pragma mark -
     
    884909        * kSplashLogoHeight * 3);
    885910    if (uncompressedLogo == NULL)
    886911        return;
    887     uncompress_RLE(kSplashLogoCompressedImage, uncompressedLogo,
    888         kSplashLogoSize);
     912    uncompress_RLE(kSplashLogoCompressedImage, uncompressedLogo);
    889913
    890914    // TODO: support indexed versions of the images!
    891915
     
    911935        * kSplashIconsHeight * 3);
    912936    if (gKernelArgs.boot_splash == NULL)
    913937        return;
    914     uncompress_RLE(kSplashIconsCompressedImage, gKernelArgs.boot_splash,
    915         kSplashIconsSize);
     938    uncompress_RLE(kSplashIconsCompressedImage, gKernelArgs.boot_splash );
    916939
    917940    // render initial (grayed out) icons
    918941    // the grayed out version is the lower half of the icons image