// Read data from the bitmap file static int readbmp(char *buf, char *pal, int maxwidth, int maxheight){ char *linebuffer; s_bitmap * bitmap; int x,y,s,d,filepos; if(buf){ y = 0; while(y<maxheight && y<bmp_header.ysize){ linebuffer = buf + y*maxwidth; seekpackfile(handle,bmp_header.picstart+((bmp_header.ysize-y-1)*bmp_header.xsize),SEEK_SET); readpackfile(handle,linebuffer,bmp_header.xsize); ++y; } } if(pal && (linebuffer=(char*)malloc(1024))){ seekpackfile(handle,bmp_header.picstart-1024, SEEK_SET); readpackfile(handle,linebuffer,1024); for(s=0,d=0;s<1024;s+=4,d+=3){ pal[d] = linebuffer[s+2]; pal[d+1] = linebuffer[s+1]; pal[d+2] = linebuffer[s]; } free(linebuffer); } return 1; }
static void passgifblock(int handle) { int len; // Skip all contained blocks while((len = readbyte(handle)) != 0) seekpackfile(handle, len, SEEK_CUR); }
static void handle_gfx_control(anigif_info *info, int n) { int len; int skip; unsigned char buf[4]; // Handle all contained blocks while((len = readbyte(info->info[n].handle)) != 0) { skip = len - 4; if(len > 4) { len = 4; } readpackfile(info->info[n].handle, buf, len); if(skip > 0) { seekpackfile(info->info[n].handle, skip, SEEK_CUR); } if(buf[0] & 1) { info->info[n].transparent = buf[3]; } info->info[n].lastdelay = (buf[2] << 8) | buf[1]; // disposal = (buf[0]>>2) & 7; // inputflag = (buf[0]>>1) & 1; } }
static void passgifblock(anigif_info *info, int n) { int len; // Skip all contained blocks while((len = readbyte(info->info[n].handle)) != 0) { seekpackfile(info->info[n].handle, len, SEEK_CUR); } }
static void handle_gfx_control(int handle) { int len; int skip; unsigned char buf[4]; // Handle all contained blocks while((len = readbyte(handle)) != 0) { skip = len - 4; if(len > 4) len = 4; readpackfile(handle, buf, len); if(skip > 0) seekpackfile(handle, skip, SEEK_CUR); if(buf[0] & 1) transparent = buf[3]; lastdelay = (buf[2] << 8) | buf[1]; // disposal = (buf[0]>>2) & 7; // inputflag = (buf[0]>>1) & 1; } }
// Open a BMP stream static int openbmp(char *filename, char *packfilename) { #if DC || GP2X || SYMBIAN unsigned char mybmpheader[0x36]; #endif if((handle = openpackfile(filename, packfilename)) == -1) { return 0; } #if DC || GP2X || SYMBIAN if(readpackfile(handle, &mybmpheader, 0x36) != 0x36) { #else if(readpackfile(handle, &bmp_header, sizeof(s_bmpheader)) != sizeof(s_bmpheader)) { #endif closepackfile(handle); return 0; } #if DC || GP2X || SYMBIAN build_bmp_header(&bmp_header, mybmpheader); #else bmp_header.bm = SwapLSB16(bmp_header.bm); bmp_header.numplanes = SwapLSB16(bmp_header.numplanes); bmp_header.bpp = SwapLSB16(bmp_header.bpp); bmp_header.filesize = SwapLSB32(bmp_header.filesize); bmp_header.reserved = SwapLSB32(bmp_header.reserved); bmp_header.picstart = SwapLSB32(bmp_header.picstart); bmp_header.headersize = SwapLSB32(bmp_header.headersize); bmp_header.xsize = SwapLSB32(bmp_header.xsize); bmp_header.ysize = SwapLSB32(bmp_header.ysize); bmp_header.filesize = SwapLSB32(bmp_header.filesize); bmp_header.compression = SwapLSB32(bmp_header.compression); bmp_header.picsize = SwapLSB32(bmp_header.picsize); bmp_header.hres = SwapLSB32(bmp_header.hres); bmp_header.vres = SwapLSB32(bmp_header.vres); bmp_header.numcolors_used = SwapLSB32(bmp_header.numcolors_used); bmp_header.numcolors_important = SwapLSB32(bmp_header.numcolors_important); #endif if(bmp_header.bm != 0x4D42 || bmp_header.bpp != 8 || bmp_header.compression) { closepackfile(handle); return 0; } res[0] = bmp_header.xsize; res[1] = bmp_header.ysize; return 1; } // Read data from the bitmap file static int readbmp(unsigned char *buf, unsigned char *pal, int maxwidth, int maxheight) { unsigned char *linebuffer; int y, s, d; int pb = PAL_BYTES; if(buf) { y = 0; while(y < maxheight && y < bmp_header.ysize) { linebuffer = buf + y * maxwidth; seekpackfile(handle, bmp_header.picstart + ((bmp_header.ysize - y - 1)*bmp_header.xsize), SEEK_SET); readpackfile(handle, linebuffer, bmp_header.xsize); ++y; } } if(pal && (linebuffer = (unsigned char *)malloc(1024))) { seekpackfile(handle, bmp_header.picstart - 1024, SEEK_SET); readpackfile(handle, linebuffer, 1024); if(pb == 512) // 16bit 565 { for(s = 0, d = 0; s < 1024; s += 4, d += 2) { *(unsigned short *)(pal + d) = colour16(linebuffer[s + 2], linebuffer[s + 1], linebuffer[s]); } } else if(pb == 768) // 24bit palette, RGBA-BGR { for(s = 0, d = 0; s < 1024; s += 4, d += 3) { pal[d] = linebuffer[s + 2]; pal[d + 1] = linebuffer[s + 1]; pal[d + 2] = linebuffer[s]; } } else if(pb == 1024) { for(s = 0, d = 0; s < 1024; s += 4, d += 4) { *(unsigned *)(pal + d) = colour32(linebuffer[s + 2], linebuffer[s + 1], linebuffer[s]); } } free(linebuffer); linebuffer = NULL; } return 1; }
static int readpng(unsigned char *buf, unsigned char *pal, int width, int height) { unsigned char *png_data = NULL, *png_data_ptr; unsigned char *inflated_data = NULL; z_stream zlib_stream = {.zalloc = Z_NULL, .zfree = Z_NULL, .opaque = Z_NULL, .avail_in = 0, .next_in = Z_NULL, .avail_out = 0, .next_out = Z_NULL}; if (inflateInit(&zlib_stream) != Z_OK) { goto readpng_abort; } // Read the rest of the file into a single chunk of memory to save on expensive I/O operations. int data_start_pos = seekpackfile(handle, 0, SEEK_CUR) + 4; // +4 bytes to skip the CRC at the end of IHDR chunk int data_size = seekpackfile(handle, 0, SEEK_END) - data_start_pos; seekpackfile(handle, data_start_pos, SEEK_SET); png_data = malloc(data_size); if (!png_data) { goto readpng_abort; } else if (readpackfile(handle, png_data, data_size) != data_size) { goto readpng_abort; } png_data_ptr = png_data; if (buf) { // the "+1"s are because each scanline has an extra byte denoting the filter type size_t inflated_size; if (png_is_interlaced) { inflated_size = (width/8 + 1) * (height/8) * 2 + (width/4 + 1) * (height/8) + (width/4 + 1) * (height/4) + (width/2 + 1) * (height/4) + (width/2 + 1) * (height/2) + (width + 1) * (height/2); } else { inflated_size = (width + 1) * height; } inflated_data = malloc(inflated_size); zlib_stream.avail_out = inflated_size; zlib_stream.next_out = inflated_data; } // Now read the remaining chunks of the file while (png_data_ptr < (png_data + data_size)) { struct png_chunk_header *p_chunk_header = (struct png_chunk_header *) png_data_ptr; uint32_t chunk_size = SwapMSB32(p_chunk_header->chunk_size); png_data_ptr += sizeof(*p_chunk_header); // PLTE chunk: contains the palette if (pal && p_chunk_header->chunk_name == SwapMSB32(PNG_CHUNK_PLTE)) { unsigned int ncolors = chunk_size / 3, i; int *pal32 = (int*) pal; if (chunk_size % 3 != 0) { goto readpng_abort; } for (i = 0; i < ncolors; i++) { pal32[i] = colour32(png_data_ptr[0], png_data_ptr[1], png_data_ptr[2]); png_data_ptr += 3; } png_data_ptr += 4; } /* IDAT chunks contain the actual image data, compressed with DEFLATE in the zlib format. There can be multiple IDAT chunks, but their data together forms a single compressed stream. */ else if (buf && p_chunk_header->chunk_name == SwapMSB32(PNG_CHUNK_IDAT)) { zlib_stream.avail_in = chunk_size; zlib_stream.next_in = png_data_ptr; int zret; zret = inflate(&zlib_stream, Z_SYNC_FLUSH); if (zret == Z_STREAM_END) { break; } else if (zret != Z_OK) { printf("inflate failed: %i\n", zret); goto readpng_abort; } png_data_ptr += chunk_size + 4; } else { png_data_ptr += chunk_size + 4; } } if (buf) { if (zlib_stream.avail_out != 0) { printf("error: incomplete compressed stream\n"); goto readpng_abort; } if (png_is_interlaced) { png_decode_interlaced(buf, inflated_data, width, height); } else { png_decode_regular(buf, inflated_data, width, height); } } inflateEnd(&zlib_stream); free(inflated_data); free(png_data); return 1; readpng_abort: inflateEnd(&zlib_stream); free(inflated_data); free(png_data); return 0; } // ============================== GIF loading =============================== typedef struct { char magic[6]; unsigned short screenwidth, screenheight; unsigned char flags; unsigned char background; unsigned char aspect; } gifheaderstruct; #if DC || GP2X || SYMBIAN #define sizeof_gifheaderstruct 13 #endif typedef struct { unsigned short left, top, width, height; unsigned char flags; } gifblockstruct; #if DC || GP2X || SYMBIAN #define sizeof_iblock 9 #endif static gifheaderstruct gif_header; static unsigned char readbyte(int handle) { unsigned char c = 0; readpackfile(handle, &c, 1); return c; }
/** * Reads a script file into an allocated buffer. Be sure to call free() on the * returned buffer when you are done with it! * * Returns the buffer on success, NULL on failure. */ static char *readScript(const char *path) { #if 1 // stdio version char *scriptText = NULL; int fileSize; FILE *fp = fopen(path, "rb"); if(!fp) goto error; if (fseek(fp, 0, SEEK_END) < 0) goto error; fileSize = ftell(fp); scriptText = (char*) malloc(fileSize + 1); if (fseek(fp, 0, SEEK_SET) < 0) goto error; if ((int)fread(scriptText, 1, fileSize, fp) != fileSize) goto error; scriptText[fileSize] = 0; fclose(fp); return scriptText; error: // ideally, this error message would include the name of the file that tried to import this file printf("Script error: unable to open file '%s' for importing\n", path); if (scriptText) { free(scriptText); } if (fp) { fclose(fp); } return NULL; #else // packfile I/O version int handle = openpackfile(path, packfile); int size; char *buffer = NULL; if(handle < 0) { goto error; } size = seekpackfile(handle, 0, SEEK_END); if(size < 0) { goto error; } buffer = malloc(size + 1); if(buffer == NULL) { goto error; } if(seekpackfile(handle, 0, SEEK_SET) < 0) { goto error; } if(readpackfile(handle, buffer, size) < 0) { goto error; } closepackfile(handle); buffer[size] = '\0'; return buffer; error: // ideally, this error message would include the name of the file that tried to import this file printf("Script error: unable to open file '%s' for importing\n", path); if(buffer) { free(buffer); } if(handle >= 0) { closepackfile(handle); } return NULL; #endif }
int64_t webm_tell(void *userdata) { return seekpackfile((int)userdata, 0, SEEK_CUR); }
int webm_seek(int64_t offset, int whence, void *userdata) { return seekpackfile((int)userdata, (int)offset, whence); }