From 4478f2a06a10b2d0c1d74fcfc17d7f2ecdcc3fb0 Mon Sep 17 00:00:00 2001 From: James Shaw Date: Fri, 23 Nov 2007 14:48:45 +0000 Subject: Add prototype image readers in reader.c. Refactor libsprite.c to split up structs and functions. svn path=/import/jshaw/libsprite/; revision=9983 --- trunk/build.sh | 1 + trunk/libsprite.c | 207 ++++++++++++++++++++++++++++-------------------------- trunk/reader.c | 55 +++++++++++++++ 3 files changed, 162 insertions(+), 101 deletions(-) create mode 100644 trunk/reader.c diff --git a/trunk/build.sh b/trunk/build.sh index c40783b..324603f 100755 --- a/trunk/build.sh +++ b/trunk/build.sh @@ -1,2 +1,3 @@ #!/bin/bash gcc -W -Wall -pedantic -Werror -std=c99 -o libsprite libsprite.c +gcc -W -Wall -pedantic -Werror -std=c99 -o reader reader.c diff --git a/trunk/libsprite.c b/trunk/libsprite.c index 3154fff..fe61a45 100644 --- a/trunk/libsprite.c +++ b/trunk/libsprite.c @@ -22,7 +22,7 @@ struct sprite_mode { uint32_t ydpi; }; -struct sprite_header { +struct sprite { unsigned char name[13]; /* last byte for 0 terminator */ struct sprite_mode* mode; bool hasmask; @@ -33,6 +33,13 @@ struct sprite_header { uint32_t height; }; +struct sprite_header { + uint32_t width_words; /* width and height in words */ + uint32_t height_words; + uint32_t first_used_bit; /* old format only (spriteType = 0) */ + uint32_t last_used_bit; +}; + uint32_t sprite_read_word(FILE* stream) { unsigned char b[4]; @@ -46,7 +53,7 @@ uint32_t sprite_read_word(FILE* stream) return BTUINT(b); } -void sprite_read_bytes(FILE* stream, unsigned char* buf, size_t count) +void sprite_read_bytes(FILE* stream, uint8_t* buf, size_t count) { size_t bytesRead = fread(buf, 1, count, stream); @@ -155,9 +162,92 @@ struct sprite_mode* sprite_get_mode(uint32_t spriteMode) return mode; } -/*sprite_get_image(struct sprite_header* header) +void sprite_load_image(uint8_t* image, uint8_t* mask, struct sprite* sprite, struct sprite_header* header) +{ + image = image; mask = mask; sprite = sprite; header = header; +} + +struct sprite* sprite_load_sprite(FILE* spritefile) { -}*/ + uint32_t nextSpriteOffset = sprite_read_word(spritefile); + + struct sprite* sprite = malloc(sizeof(struct sprite)); + struct sprite_header* header = malloc(sizeof(struct sprite_header)); + + sprite_read_bytes(spritefile, sprite->name, 12); + sprite->name[12] = '\0'; + + header->width_words = sprite_read_word(spritefile) + 1; /* file has width - 1 and height - 1 */ + header->height_words = sprite_read_word(spritefile) + 1; + header->first_used_bit = sprite_read_word(spritefile); /* old format only (spriteType = 0) */ + header->last_used_bit = sprite_read_word(spritefile); + + uint32_t imageOffset = sprite_read_word(spritefile); + assert(imageOffset >= 44); /* should never be smaller than the size of the header) */ + + uint32_t maskOffset = sprite_read_word(spritefile); + uint32_t spriteModeWord = sprite_read_word(spritefile); + + sprite->mode = sprite_get_mode(spriteModeWord); + assert(sprite->mode->colorbpp > 0); + assert(sprite->mode->xdpi > 0); + assert(sprite->mode->ydpi > 0); + + sprite->palettesize = imageOffset - 44; + sprite->haspalette = (sprite->palettesize > 0); + + uint32_t imageSize; + uint32_t maskSize; + + if (imageOffset == maskOffset) { + sprite->hasmask = false; + imageSize = nextSpriteOffset - 44 - sprite->palettesize; + maskSize = 0; + } else { + sprite->hasmask = true; + imageSize = maskOffset - imageOffset; + maskSize = nextSpriteOffset - 44 - sprite->palettesize - imageSize; + } + + if (sprite->hasmask) LOGDBG("maskSize %u\n", maskSize); + + uint32_t* palette = NULL; + if (sprite->haspalette) { + assert(sprite->palettesize % 8 == 0); + palette = malloc(sizeof(uint32_t) * sprite->palettesize); + uint32_t paletteEntries = sprite->palettesize / 8; + + /* Each palette entry is two words big + * The second word is a duplicate of the first + * I think this is in case you ever wanted flashing colours + * PRM1-730 + */ + for (uint32_t j = 0; j < paletteEntries; j++) { + uint32_t word1 = sprite_read_word(spritefile); + uint32_t word2 = sprite_read_word(spritefile); + assert(word1 == word2); /* TODO: if they aren't, START FLASHING */ + + palette[j] = word1; + } + } + + uint8_t* image = malloc(imageSize); + sprite_read_bytes(spritefile, image, imageSize); + + uint8_t* mask = malloc(maskSize); + sprite_read_bytes(spritefile, mask, maskSize); + + /* sanity check imageSize */ + assert((header->width_words) * 4 * (header->height_words) == imageSize); + /* TODO: sanity check maskSize */ + sprite_load_image(image, mask, sprite, header); + + free(image); + free(mask); + free(header); + + return sprite; +} int main(int argc, char *argv[]) { @@ -193,102 +283,21 @@ int main(int argc, char *argv[]) } for (uint32_t i = 0; i < spriteCount; i++) { - uint32_t nextSpriteOffset = sprite_read_word(spritefile); - - struct sprite_header* header = malloc(sizeof(struct sprite_header)); - - sprite_read_bytes(spritefile, header->name, 12); - header->name[12] = '\0'; - - uint32_t width = sprite_read_word(spritefile); - uint32_t height = sprite_read_word(spritefile); - uint32_t firstUsedBit = sprite_read_word(spritefile); /* old format only (spriteType = 0) */ - uint32_t lastUsedBit = sprite_read_word(spritefile); - uint32_t imageOffset = sprite_read_word(spritefile); - assert(imageOffset >= 44); /* should never be smaller than the size of the header) */ - - uint32_t maskOffset = sprite_read_word(spritefile); - uint32_t spriteModeWord = sprite_read_word(spritefile); - - header->mode = sprite_get_mode(spriteModeWord); - assert(header->mode->colorbpp > 0); - assert(header->mode->xdpi > 0); - assert(header->mode->ydpi > 0); - - header->palettesize = imageOffset - 44; - header->haspalette = (header->palettesize > 0); - - uint32_t imageSize; - uint32_t maskSize; - - if (imageOffset == maskOffset) { - header->hasmask = false; - imageSize = nextSpriteOffset - 44 - header->palettesize; - maskSize = 0; - } else { - header->hasmask = true; - imageSize = maskOffset - imageOffset; - maskSize = nextSpriteOffset - 44 - header->palettesize - imageSize; - } - - LOGDBG("\nLoading sprite %u\n", i); - LOGDBG("nextSpriteOffset %u\n", nextSpriteOffset); - LOGDBG("name %s\n", header->name); - LOGDBG("width %u\n", width); - LOGDBG("height %u\n", height); - LOGDBG("firstUsedBit %u\n", firstUsedBit); - LOGDBG("lastUsedBit %u\n", lastUsedBit); - LOGDBG("imageOffset %u\n", imageOffset); - LOGDBG("maskOffset %u\n", maskOffset); - if (spriteModeWord > 255) { - LOGDBG("spriteModeWord 0x%x\n", spriteModeWord); - } else { - LOGDBG("spriteModeWord %u\n", spriteModeWord); - } - LOGDBG("\tcolorbpp %u\n", header->mode->colorbpp); - LOGDBG("\txdpi %u\n", header->mode->xdpi); - LOGDBG("\tydpi %u\n", header->mode->ydpi); - - LOGDBG("hasPalette %s\n", header->haspalette ? "YES" : "NO"); - if (header->haspalette) LOGDBG("paletteSize %u\n", header->palettesize); - LOGDBG("imageSize %u\n", imageSize); - LOGDBG("hasMask %s\n", header->hasmask ? "YES" : "NO"); - if (header->hasmask) LOGDBG("maskbpp %u\n", header->mode->maskbpp); - if (header->hasmask) LOGDBG("maskSize %u\n", maskSize); - - uint32_t* palette = NULL; - if (header->haspalette) { - assert(header->palettesize % 8 == 0); - palette = malloc(sizeof(uint32_t) * header->palettesize); - uint32_t paletteEntries = header->palettesize / 8; - - /* Each palette entry is two words big - * The second word is a duplicate of the first - * I think this is in case you ever wanted flashing colours - */ - for (uint32_t j = 0; j < paletteEntries; j++) { - uint32_t word1 = sprite_read_word(spritefile); - uint32_t word2 = sprite_read_word(spritefile); - assert(word1 == word2); /* TODO: if they aren't, START FLASHING */ - - palette[j] = word1; - } - } - - unsigned char* image = malloc(imageSize); - sprite_read_bytes(spritefile, image, imageSize); - - unsigned char* mask = malloc(maskSize); - sprite_read_bytes(spritefile, mask, maskSize); + struct sprite* sprite = sprite_load_sprite(spritefile); + LOGDBG("\nname %s\n", sprite->name); + LOGDBG("\tcolorbpp %u\n", sprite->mode->colorbpp); + LOGDBG("\txdpi %u\n", sprite->mode->xdpi); + LOGDBG("\tydpi %u\n", sprite->mode->ydpi); + + LOGDBG("hasPalette %s\n", sprite->haspalette ? "YES" : "NO"); + if (sprite->haspalette) LOGDBG("paletteSize %u\n", sprite->palettesize); - LOGDBG("calculated width in bytes %u\n", ((width + 1) * (height + 1) * 4)); - uint32_t widthInBits = (width + 1) * 4 /* bytes per word */ * 8 /* bits per byte */; - uint32_t widthInPixelsWithoutCrop = widthInBits / header->mode->colorbpp; - uint32_t heightInPixels = height + 1; - LOGDBG("width in pixels (without crop) %u\n", widthInPixelsWithoutCrop); - LOGDBG("height in pixels %u\n", heightInPixels); + LOGDBG("hasMask %s\n", sprite->hasmask ? "YES" : "NO"); + if (sprite->hasmask) LOGDBG("maskbpp %u\n", sprite->mode->maskbpp); } + fclose(spritefile); + return EXIT_SUCCESS; } @@ -299,7 +308,3 @@ int main(int argc, char *argv[]) 24bpp: bbggrrbb | ggrr.... 16bpp: bgr0bgr0 | bgr0bgr0 */ - -/* - -*/ diff --git a/trunk/reader.c b/trunk/reader.c new file mode 100644 index 0000000..3ac5260 --- /dev/null +++ b/trunk/reader.c @@ -0,0 +1,55 @@ +#include "stdio.h" +#include "stdlib.h" +#include "stdint.h" + +/* method for 16bpp and above (>1 byte per pixel) */ +void sprite_high_colour() +{ + /*uint32_t imgSize = 8;*/ /* in bytes */ + /* 0xddccbbaa 0xeeeeffff */ + uint8_t img[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xff, 0xff, 0xee, 0xee}; + uint32_t widthPixels = 2; + uint32_t currentByteIndex = 0; /* only for standalone test -- fread() will maintain this */ + + uint32_t bpp = 24; + uint32_t bytesPerPixel = bpp >> 3; /* divide by 8 */ + + + for (uint32_t x = 0; x < widthPixels; x++) { + uint32_t pixel = 0; + for (uint32_t j = 0; j < bytesPerPixel; j++) { + uint8_t b = img[currentByteIndex++]; + pixel = pixel | (b << (j * 8)); + } + printf("%x\n", pixel); + } +} + +void sprite_low_colour() +{ + uint8_t img[] = {0xab, 0xcd, 0x12, 0x34 }; + uint32_t widthInBits = 32; + uint32_t currentByteIndex = 0; /* only for standalone test -- fread() will maintain this */ + + uint32_t bpp = 8; + + uint32_t bitmask = (1 << bpp) - 1; /* creates a mask of 1s that is bpp bits wide */ + uint8_t currentbyte = img[currentByteIndex++]; + + for (uint32_t x = 0; x < widthInBits; x+=bpp) { + uint32_t offset_into_byte = x % 8; + uint32_t pixel = (currentbyte & (bitmask << offset_into_byte)) >> offset_into_byte; + printf("%x\n", pixel); + + if (offset_into_byte + bpp == 8) { + currentbyte = img[currentByteIndex++]; + } + } +} + +int main() +{ + sprite_low_colour(); + + return EXIT_SUCCESS; +} -- cgit v1.2.1