Patch by David Powell:
* Implement color palette generation for the boot splash images in the generate_boot_screen build tool. Only 4-bit screen support is missing now. * Adopted images.h with the new results from generate_boot_screen. This should fix black boot screens for graphics cards that don't support true color modes for the native resolution. I've tried to find the ticket, #2177 almost looks like the one, but it looks more like the mode is out of range if I understand the ticket right. Thanks a lot, David, and sorry it took so very long to apply your patch! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27223 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
e2bc27448f
commit
ec56835f51
File diff suppressed because it is too large
Load Diff
@ -781,16 +781,15 @@ blit4(const uint8 *data, uint16 width, uint16 height, uint16 imageWidth,
|
||||
|
||||
|
||||
static void
|
||||
blit_image(const uint8 *data, const uint8* indexedData, uint16 width,
|
||||
uint16 height, uint16 imageWidth, const uint8 *palette, uint16 left,
|
||||
uint16 top)
|
||||
blit_image(const uint8 *data, uint16 width, uint16 height, uint16 imageWidth,
|
||||
const uint8 *palette, uint16 left, uint16 top)
|
||||
{
|
||||
switch (gKernelArgs.frame_buffer.depth) {
|
||||
case 4:
|
||||
return blit4(indexedData, width, height, imageWidth, palette,
|
||||
return blit4(data, width, height, imageWidth, palette,
|
||||
left, top);
|
||||
case 8:
|
||||
return blit8(indexedData, width, height, imageWidth, palette,
|
||||
return blit8(data, width, height, imageWidth, palette,
|
||||
left, top);
|
||||
case 15:
|
||||
return blit15(data, width, height, imageWidth, left, top);
|
||||
@ -805,7 +804,7 @@ blit_image(const uint8 *data, const uint8* indexedData, uint16 width,
|
||||
|
||||
|
||||
static void
|
||||
uncompress_RLE(const uint8 compressed[], uint8 *uncompressed)
|
||||
uncompress_24bit_RLE(const uint8 compressed[], uint8 *uncompressed)
|
||||
{
|
||||
uint32 cursorUncompressed = 0;
|
||||
uint32 cursorCompressed = 0;
|
||||
@ -842,6 +841,39 @@ uncompress_RLE(const uint8 compressed[], uint8 *uncompressed)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uncompress_8Bit_RLE(const uint8 compressed[], uint8 *uncompressed)
|
||||
{
|
||||
uint32 cursorUncompressed = 0;
|
||||
uint32 cursorCompressed = 0;
|
||||
uint8 count = 0;
|
||||
uint8 item = 0;
|
||||
int i = 0;
|
||||
|
||||
while (compressed[cursorCompressed]) {
|
||||
// at the end of the channel there is a terminating 0,
|
||||
// so the loop will end... (ref: generate_boot_screen.cpp)
|
||||
count = compressed[cursorCompressed++];
|
||||
if (count < 128) {
|
||||
// regular run, repeat "item" "count" times...
|
||||
item = compressed[cursorCompressed++];
|
||||
for (i = count - 1; i >= 0; --i) {
|
||||
uncompressed[cursorUncompressed] = item;
|
||||
cursorUncompressed++;
|
||||
}
|
||||
} else {
|
||||
// enumeration, just write the next "count" items as is...
|
||||
count = count - 128;
|
||||
for (i = count - 1; i >= 0; --i) {
|
||||
uncompressed[cursorUncompressed]
|
||||
= compressed[cursorCompressed++];
|
||||
cursorUncompressed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
extern "C" void
|
||||
@ -916,13 +948,27 @@ fallback:
|
||||
memset((void *)sFrameBuffer, 0,
|
||||
gKernelArgs.frame_buffer.physical_buffer.size);
|
||||
|
||||
uint8 *uncompressedLogo = (uint8 *)kernel_args_malloc(kSplashLogoWidth
|
||||
* kSplashLogoHeight * 3);
|
||||
if (uncompressedLogo == NULL)
|
||||
return;
|
||||
uncompress_RLE(kSplashLogoCompressedImage, uncompressedLogo);
|
||||
uint8 *uncompressedLogo = NULL;
|
||||
switch (gKernelArgs.frame_buffer.depth) {
|
||||
case 8:
|
||||
uncompressedLogo = (uint8 *)kernel_args_malloc(kSplashLogoWidth
|
||||
* kSplashLogoHeight);
|
||||
if (uncompressedLogo == NULL)
|
||||
return;
|
||||
uncompress_8Bit_RLE(kSplashLogo8BitCompressedImage,
|
||||
uncompressedLogo);
|
||||
break;
|
||||
default:
|
||||
uncompressedLogo = (uint8 *)kernel_args_malloc(kSplashLogoWidth
|
||||
* kSplashLogoHeight * 3);
|
||||
if (uncompressedLogo == NULL)
|
||||
return;
|
||||
uncompress_24bit_RLE(kSplashLogo24BitCompressedImage,
|
||||
uncompressedLogo);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: support indexed versions of the images!
|
||||
// TODO: support 4-bit indexed version of the images!
|
||||
|
||||
// render splash logo
|
||||
uint16 iconsHalfHeight = kSplashIconsHeight / 2;
|
||||
@ -937,16 +983,39 @@ fallback:
|
||||
int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100;
|
||||
|
||||
height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height);
|
||||
blit_image(uncompressedLogo, NULL, width, height, kSplashLogoWidth,
|
||||
NULL, x, y);
|
||||
blit_image(uncompressedLogo, width, height, kSplashLogoWidth,
|
||||
k8BitPalette, x, y);
|
||||
|
||||
kernel_args_free(uncompressedLogo);
|
||||
|
||||
gKernelArgs.boot_splash = (uint8 *)kernel_args_malloc(kSplashIconsWidth
|
||||
* kSplashIconsHeight * 3);
|
||||
if (gKernelArgs.boot_splash == NULL)
|
||||
return;
|
||||
uncompress_RLE(kSplashIconsCompressedImage, gKernelArgs.boot_splash );
|
||||
const uint8* lowerHalfIconImage;
|
||||
|
||||
switch (gKernelArgs.frame_buffer.depth) {
|
||||
case 8:
|
||||
// pointer into the lower half of the icons image data
|
||||
gKernelArgs.boot_splash
|
||||
= (uint8 *)kernel_args_malloc(kSplashIconsWidth
|
||||
* kSplashIconsHeight);
|
||||
if (gKernelArgs.boot_splash == NULL)
|
||||
return;
|
||||
uncompress_8Bit_RLE(kSplashIcons8BitCompressedImage,
|
||||
gKernelArgs.boot_splash );
|
||||
lowerHalfIconImage = gKernelArgs.boot_splash
|
||||
+ (kSplashIconsWidth * iconsHalfHeight);
|
||||
break;
|
||||
default:
|
||||
// pointer into the lower half of the icons image data
|
||||
gKernelArgs.boot_splash
|
||||
= (uint8 *)kernel_args_malloc(kSplashIconsWidth
|
||||
* kSplashIconsHeight * 3);
|
||||
if (gKernelArgs.boot_splash == NULL)
|
||||
return;
|
||||
uncompress_24bit_RLE(kSplashIcons24BitCompressedImage,
|
||||
gKernelArgs.boot_splash );
|
||||
lowerHalfIconImage = gKernelArgs.boot_splash
|
||||
+ (kSplashIconsWidth * iconsHalfHeight) * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// render initial (grayed out) icons
|
||||
// the grayed out version is the lower half of the icons image
|
||||
@ -961,12 +1030,9 @@ fallback:
|
||||
y = kSplashLogoHeight + (gKernelArgs.frame_buffer.height - height)
|
||||
* placementY / 100;
|
||||
|
||||
// pointer into the lower half of the icons image data
|
||||
const uint8* lowerHalfIconImage = gKernelArgs.boot_splash
|
||||
+ (kSplashIconsWidth * iconsHalfHeight) * 3;
|
||||
height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height);
|
||||
blit_image(lowerHalfIconImage, NULL, width, height,
|
||||
kSplashIconsWidth, NULL, x, y);
|
||||
blit_image(lowerHalfIconImage, width, height, kSplashIconsWidth,
|
||||
k8BitPalette, x, y);
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,10 +36,34 @@
|
||||
static struct frame_buffer_boot_info *sInfo;
|
||||
static uint8 *sUncompressedIcons;
|
||||
|
||||
static void
|
||||
blit8_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
|
||||
uint16 left, uint16 top)
|
||||
{
|
||||
data += (imageWidth * imageTop + imageLeft);
|
||||
uint8* start = (uint8*)(sInfo->frame_buffer
|
||||
+ sInfo->bytes_per_row * (top + imageTop) + 1 * (left + imageLeft));
|
||||
|
||||
for (int32 y = imageTop; y < imageBottom; y++) {
|
||||
const uint8* src = data;
|
||||
uint8* dst = start;
|
||||
for (int32 x = imageLeft; x < imageRight; x++) {
|
||||
dst[0] = src[0];
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
|
||||
data += imageWidth;
|
||||
start = (uint8*)((addr_t)start + sInfo->bytes_per_row);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
blit15_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
|
||||
const uint8 *palette, uint16 left, uint16 top)
|
||||
uint16 left, uint16 top)
|
||||
{
|
||||
data += (imageWidth * imageTop + imageLeft) * 3;
|
||||
uint16* start = (uint16*)(sInfo->frame_buffer
|
||||
@ -67,7 +91,7 @@ blit15_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
static void
|
||||
blit16_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
|
||||
const uint8 *palette, uint16 left, uint16 top)
|
||||
uint16 left, uint16 top)
|
||||
{
|
||||
data += (imageWidth * imageTop + imageLeft) * 3;
|
||||
uint16* start = (uint16*)(sInfo->frame_buffer
|
||||
@ -94,7 +118,7 @@ blit16_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
static void
|
||||
blit24_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
|
||||
const uint8 *palette, uint16 left, uint16 top)
|
||||
uint16 left, uint16 top)
|
||||
{
|
||||
data += (imageWidth * imageTop + imageLeft) * 3;
|
||||
uint8* start = (uint8*)(sInfo->frame_buffer
|
||||
@ -120,7 +144,7 @@ blit24_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
static void
|
||||
blit32_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
|
||||
const uint8 *palette, uint16 left, uint16 top)
|
||||
uint16 left, uint16 top)
|
||||
{
|
||||
data += (imageWidth * imageTop + imageLeft) * 3;
|
||||
uint32* start = (uint32*)(sInfo->frame_buffer
|
||||
@ -142,26 +166,30 @@ blit32_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||
|
||||
|
||||
static void
|
||||
blit_cropped(const uint8* data, const uint8* indexedData,
|
||||
uint16 imageLeft, uint16 imageTop, uint16 imageRight, uint16 imageBottom,
|
||||
uint16 imageWidth, const uint8 *palette, uint16 left, uint16 top)
|
||||
blit_cropped(const uint8* data, uint16 imageLeft, uint16 imageTop,
|
||||
uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
|
||||
uint16 left, uint16 top)
|
||||
{
|
||||
switch (sInfo->depth) {
|
||||
case 8:
|
||||
blit8_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
|
||||
imageWidth, left, top);
|
||||
return;
|
||||
case 15:
|
||||
blit15_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
|
||||
imageWidth, palette, left, top);
|
||||
imageWidth, left, top);
|
||||
return;
|
||||
case 16:
|
||||
blit16_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
|
||||
imageWidth, palette, left, top);
|
||||
imageWidth, left, top);
|
||||
return;
|
||||
case 24:
|
||||
blit24_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
|
||||
imageWidth, palette, left, top);
|
||||
imageWidth, left, top);
|
||||
return;
|
||||
case 32:
|
||||
blit32_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
|
||||
imageWidth, palette, left, top);
|
||||
imageWidth, left, top);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -213,7 +241,7 @@ boot_splash_set_stage(int stage)
|
||||
int stageRightEdge = width * (stage + 1) / BOOT_SPLASH_STAGE_MAX;
|
||||
|
||||
height = min_c(iconsHalfHeight, sInfo->height);
|
||||
blit_cropped(sUncompressedIcons, NULL, stageLeftEdge, 0, stageRightEdge,
|
||||
height, kSplashIconsWidth, NULL, x, y);
|
||||
blit_cropped(sUncompressedIcons, stageLeftEdge, 0, stageRightEdge,
|
||||
height, kSplashIconsWidth, x, y);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,11 @@ BuildPlatformMain <build>copyattr : copyattr.cpp
|
||||
BuildPlatformMain <build>data_to_source : data_to_source.cpp
|
||||
: $(HOST_LIBSUPC++) ;
|
||||
|
||||
BuildPlatformMain <build>generate_boot_screen : generate_boot_screen.cpp
|
||||
UsePrivateObjectHeaders generate_boot_screen.cpp : shared : : true ;
|
||||
UsePrivateObjectHeaders ColorQuantizer.cpp : shared : : true ;
|
||||
BuildPlatformMain <build>generate_boot_screen :
|
||||
generate_boot_screen.cpp
|
||||
ColorQuantizer.cpp
|
||||
: $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) png z ;
|
||||
|
||||
BuildPlatformMain <build>listattr : listattr.cpp : $(HOST_LIBBE) ;
|
||||
@ -88,6 +92,10 @@ SEARCH on [ FGristFiles
|
||||
UpdateMimeInfoThread.cpp MimeUpdateThread.cpp database_support.cpp
|
||||
] = [ FDirName $(HAIKU_TOP) src build libbe storage mime ] ;
|
||||
|
||||
SEARCH on [ FGristFiles
|
||||
ColorQuantizer.cpp
|
||||
] = [ FDirName $(HAIKU_TOP) src kits shared ] ;
|
||||
|
||||
SubInclude HAIKU_TOP src tools addattr ;
|
||||
SubInclude HAIKU_TOP src tools bfs_shell ;
|
||||
SubInclude HAIKU_TOP src tools copy_to_bfs_image ;
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Artur Wyszynski <harakash@gmail.com>
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Philippe Saint-Pierre <stpere@gmail.com>
|
||||
* David Powell <david@mad.scientist.com>
|
||||
*/
|
||||
|
||||
//! Haiku boot splash image generator/converter
|
||||
@ -16,10 +17,12 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// TODO: Generate the single optimal palette for all three images,
|
||||
// store palette versions of these images as well, so that they are
|
||||
// ready to be used during boot in case we need to run in palette
|
||||
// VGA mode.
|
||||
#include <ColorQuantizer.h>
|
||||
|
||||
// TODO: Create 4 bit palette version of these
|
||||
// images as well, so that they are ready to be
|
||||
// used during boot in case we need to run in
|
||||
// palette 4 bit VGA mode.
|
||||
|
||||
|
||||
FILE* sOutput = NULL;
|
||||
@ -131,7 +134,7 @@ new_line_if_required()
|
||||
|
||||
|
||||
static void
|
||||
write_image(const char* baseName, int width, int height, png_bytep* rowPtrs)
|
||||
write_24bit_image(const char* baseName, int width, int height, png_bytep* rowPtrs)
|
||||
{
|
||||
fprintf(sOutput, "static const uint16 %sWidth = %d;\n", baseName, width);
|
||||
fprintf(sOutput, "static const uint16 %sHeight = %d;\n", baseName, height);
|
||||
@ -140,7 +143,7 @@ write_image(const char* baseName, int width, int height, png_bytep* rowPtrs)
|
||||
int buffer[128];
|
||||
// buffer[0] stores count, buffer[1..127] holds the actual values
|
||||
|
||||
fprintf(sOutput, "static uint8 %sCompressedImage[] = {\n\t",
|
||||
fprintf(sOutput, "static uint8 %s24BitCompressedImage[] = {\n\t",
|
||||
baseName);
|
||||
|
||||
for (int c = 0; c < 3; c++) {
|
||||
@ -164,12 +167,12 @@ write_image(const char* baseName, int width, int height, png_bytep* rowPtrs)
|
||||
bufferActive = false;
|
||||
count = 2;
|
||||
if (buffer[0] > 1) {
|
||||
fprintf (sOutput, "%d, ",
|
||||
fprintf(sOutput, "%d, ",
|
||||
128 + buffer[0] - 1);
|
||||
new_line_if_required();
|
||||
for (int i = 1; i < buffer[0] ; i++) {
|
||||
fprintf( sOutput, "%d, ",
|
||||
buffer[i] );
|
||||
fprintf(sOutput, "%d, ",
|
||||
buffer[i]);
|
||||
new_line_if_required();
|
||||
}
|
||||
}
|
||||
@ -241,21 +244,222 @@ write_image(const char* baseName, int width, int height, png_bytep* rowPtrs)
|
||||
|
||||
|
||||
static void
|
||||
parse_image(const char* filename, const char* baseName)
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
png_bytep* rowPtrs = NULL;
|
||||
png_structp pngPtr;
|
||||
png_infop infoPtr;
|
||||
read_png(filename, width, height, rowPtrs, pngPtr, infoPtr);
|
||||
write_image(baseName, width, height, rowPtrs);
|
||||
write_8bit_image(const char* baseName, int width, int height, unsigned char** rowPtrs)
|
||||
{
|
||||
int buffer[128];
|
||||
// buffer[0] stores count, buffer[1..127] holds the actual values
|
||||
|
||||
fprintf(sOutput, "static uint8 %s8BitCompressedImage[] = {\n\t",
|
||||
baseName);
|
||||
|
||||
// NOTE: I don't care much about performance at this step,
|
||||
// decoding however...
|
||||
unsigned char currentValue = rowPtrs[0][0];
|
||||
int count = 0;
|
||||
|
||||
// When bufferActive == true, we store the number rather than writing
|
||||
// them directly; we use this to store numbers until we find a pair..
|
||||
bool bufferActive = false;
|
||||
|
||||
sOffset = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
unsigned char* row = rowPtrs[y];
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (row[x] == currentValue) {
|
||||
if (bufferActive) {
|
||||
bufferActive = false;
|
||||
count = 2;
|
||||
if (buffer[0] > 1) {
|
||||
fprintf(sOutput, "%d, ",
|
||||
128 + buffer[0] - 1);
|
||||
new_line_if_required();
|
||||
for (int i = 1; i < buffer[0] ; i++) {
|
||||
fprintf(sOutput, "%d, ",
|
||||
buffer[i]);
|
||||
new_line_if_required();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
count++;
|
||||
if (count == 127) {
|
||||
fprintf(sOutput, "127, ");
|
||||
new_line_if_required();
|
||||
fprintf(sOutput, "%d, ", currentValue);
|
||||
new_line_if_required();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bufferActive) {
|
||||
if (buffer[0] == 127) {
|
||||
// we don't have enough room,
|
||||
// flush the buffer
|
||||
fprintf(sOutput, "%d, ",
|
||||
128 + buffer[0] - 1);
|
||||
new_line_if_required();
|
||||
for (int i = 1; i < buffer[0]; i++) {
|
||||
fprintf(sOutput, "%d, ", buffer[i]);
|
||||
new_line_if_required();
|
||||
}
|
||||
buffer[0] = 0;
|
||||
}
|
||||
buffer[0]++;
|
||||
buffer[buffer[0]] = row[x];
|
||||
} else if (count > 0) {
|
||||
buffer[0] = 1;
|
||||
buffer[1] = row[x];
|
||||
bufferActive = true;
|
||||
if (count > 1) {
|
||||
fprintf(sOutput, "%d, ", count);
|
||||
new_line_if_required();
|
||||
fprintf(sOutput, "%d, ", currentValue);
|
||||
new_line_if_required();
|
||||
}
|
||||
}
|
||||
currentValue = row[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bufferActive) {
|
||||
// I could have written 127 + buffer[0],
|
||||
// but I think this is more readable...
|
||||
fprintf(sOutput, "%d, ", 128 + buffer[0] - 1);
|
||||
new_line_if_required();
|
||||
for (int i = 1; i < buffer[0] ; i++) {
|
||||
fprintf(sOutput, "%d, ", buffer[i]);
|
||||
new_line_if_required();
|
||||
}
|
||||
} else {
|
||||
fprintf(sOutput, "%d, %d, ", count, currentValue);
|
||||
new_line_if_required();
|
||||
}
|
||||
// we put a terminating zero for the next byte that indicates
|
||||
// a "count", to indicate the end
|
||||
fprintf(sOutput, "0");
|
||||
|
||||
fprintf(sOutput, "\n\t");
|
||||
fprintf(sOutput, "};\n\n");
|
||||
}
|
||||
|
||||
|
||||
unsigned char
|
||||
nearest_color(unsigned char* color, RGBA palette[256])
|
||||
{
|
||||
int i, dist, minDist, index = 0;
|
||||
minDist = 255 * 255 + 255 * 255 + 255 * 255 + 1;
|
||||
for (i = 0; i < 256; i++) {
|
||||
int dr = ((int)color[2]) - palette[i].r;
|
||||
int dg = ((int)color[1]) - palette[i].g;
|
||||
int db = ((int)color[0]) - palette[i].b;
|
||||
dist = dr * dr + dg * dg + db * db;
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
create_8bit_images(const char* logoBaseName, int logoWidth, int logoHeight,
|
||||
png_bytep* logoRowPtrs, const char* iconsBaseName, int iconsWidth,
|
||||
int iconsHeight, png_bytep* iconsRowPtrs)
|
||||
{
|
||||
// Generate 8-bit palette
|
||||
BColorQuantizer quantizer(256, 8);
|
||||
quantizer.ProcessImage(logoRowPtrs, logoWidth, logoHeight);
|
||||
quantizer.ProcessImage(iconsRowPtrs, iconsWidth, iconsHeight);
|
||||
|
||||
RGBA palette[256];
|
||||
quantizer.GetColorTable(palette);
|
||||
|
||||
// convert 24-bit logo image to 8-bit indexed color
|
||||
uint8* logoIndexedImageRows[logoHeight];
|
||||
for (int y = 0; y < logoHeight; y++) {
|
||||
logoIndexedImageRows[y] = new uint8[logoWidth];
|
||||
for (int x = 0; x < logoWidth; x++) {
|
||||
logoIndexedImageRows[y][x] = nearest_color(&logoRowPtrs[y][x*3],
|
||||
palette);
|
||||
}
|
||||
}
|
||||
|
||||
// convert 24-bit icons image to 8-bit indexed color
|
||||
uint8* iconsIndexedImageRows[iconsHeight];
|
||||
for (int y = 0; y < iconsHeight; y++) {
|
||||
iconsIndexedImageRows[y] = new uint8[iconsWidth];
|
||||
for (int x = 0; x < iconsWidth; x++) {
|
||||
iconsIndexedImageRows[y][x] = nearest_color(&iconsRowPtrs[y][x*3],
|
||||
palette);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf(sOutput, "#ifndef __BOOTSPLASH_KERNEL__\n");
|
||||
|
||||
// write the 8-bit color palette
|
||||
fprintf(sOutput, "static const uint8 k8BitPalette[] = {\n");
|
||||
for (int c = 0; c < 256; c++) {
|
||||
fprintf(sOutput, "\t0x%x, 0x%x, 0x%x,\n",
|
||||
palette[c].r, palette[c].g, palette[c].b);
|
||||
}
|
||||
fprintf(sOutput, "\t};\n\n");
|
||||
|
||||
// write the 8-bit images
|
||||
write_8bit_image(logoBaseName, logoWidth, logoHeight, logoIndexedImageRows);
|
||||
write_8bit_image(iconsBaseName, iconsWidth, iconsHeight,
|
||||
iconsIndexedImageRows);
|
||||
|
||||
fprintf(sOutput, "#endif\n\n");
|
||||
|
||||
// free memory
|
||||
for (int y = 0; y < logoHeight; y++)
|
||||
delete[] logoIndexedImageRows[y];
|
||||
|
||||
for (int y = 0; y < iconsHeight; y++)
|
||||
delete[] iconsIndexedImageRows[y];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_images(const char* logoFilename, const char* logoBaseName,
|
||||
const char* iconsFilename, const char* iconsBaseName)
|
||||
{
|
||||
int logoWidth;
|
||||
int logoHeight;
|
||||
png_bytep* logoRowPtrs = NULL;
|
||||
png_structp logoPngPtr;
|
||||
png_infop logoInfoPtr;
|
||||
|
||||
int iconsWidth;
|
||||
int iconsHeight;
|
||||
png_bytep* iconsRowPtrs = NULL;
|
||||
png_structp iconsPngPtr;
|
||||
png_infop iconsInfoPtr;
|
||||
|
||||
read_png(logoFilename, logoWidth, logoHeight, logoRowPtrs, logoPngPtr,
|
||||
logoInfoPtr);
|
||||
read_png(iconsFilename, iconsWidth, iconsHeight, iconsRowPtrs, iconsPngPtr,
|
||||
iconsInfoPtr);
|
||||
|
||||
// write 24-bit images
|
||||
write_24bit_image(logoBaseName, logoWidth, logoHeight, logoRowPtrs);
|
||||
write_24bit_image(iconsBaseName, iconsWidth, iconsHeight, iconsRowPtrs);
|
||||
|
||||
// write 8-bit index color images
|
||||
create_8bit_images(logoBaseName, logoWidth, logoHeight, logoRowPtrs,
|
||||
iconsBaseName, iconsWidth, iconsHeight, iconsRowPtrs);
|
||||
|
||||
// free resources
|
||||
png_destroy_read_struct(&pngPtr, &infoPtr, NULL);
|
||||
for (int y = 0; y < height; y++)
|
||||
free(rowPtrs[y]);
|
||||
free(rowPtrs);
|
||||
png_destroy_read_struct(&logoPngPtr, &logoInfoPtr, NULL);
|
||||
for (int y = 0; y < logoHeight; y++)
|
||||
free(logoRowPtrs[y]);
|
||||
free(logoRowPtrs);
|
||||
|
||||
png_destroy_read_struct(&iconsPngPtr, &iconsInfoPtr, NULL);
|
||||
for (int y = 0; y < iconsHeight; y++)
|
||||
free(iconsRowPtrs[y]);
|
||||
free(iconsRowPtrs);
|
||||
}
|
||||
|
||||
|
||||
@ -308,10 +512,8 @@ main(int argc, char* argv[])
|
||||
fprintf(sOutput, "static const int32 kSplashIconsPlacementY = %d;\n\n",
|
||||
iconPlacementY);
|
||||
|
||||
parse_image(argv[1], "kSplashLogo");
|
||||
parse_image(argv[4], "kSplashIcons");
|
||||
parse_images(argv[1], "kSplashLogo", argv[4], "kSplashIcons");
|
||||
|
||||
fclose(sOutput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user