📄 graphic_loader.c.svn-base
字号:
int bit_depth, color_type, interlace_type; FILE *fp; png_bytep *row_pointers; png_uint_32 row; int num_palette; png_colorp pal; RMuint32 datasize; RMstatus status; RMdrawBuffer bmpbuffer; RMuint8 channels; RMbool to32bpp = FALSE; // used if 24bpp to convert to 32bpp RMuint32 bufbyte, databyte; if ((fp = fopen(pBmpData->path, "rb")) == NULL) return RM_ERROR; // Create and initialize the png_struct with the desired error handler // functions. If you want to use the default stderr and longjump method, // you can supply NULL for the last three parameters. We also supply the // the compiler header file version, so that we know if the application // was compiled with a compatible version of the library. png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL){ fclose(fp); return RM_ERROR; } // Allocate/initialize the memory for image information. info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL){ fclose(fp); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return RM_ERROR; } // Set error handling if you are using the setjmp/longjmp method (this is // the normal method of doing things with libpng). REQUIRED unless you // set up your own error handlers in the png_create_read_struct() earlier. if (setjmp(png_jmpbuf(png_ptr))){ // Free all of the memory associated with the png_ptr and info_ptr png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); // If we get here, we had a problem reading the file return RM_ERROR; } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); // this call prevent us from switching the bit ourselves as before (build 41) png_set_bgr(png_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); // this may be a 3 state button for which only a third of the horizontal size may be displayed if(height > g_OSDheight){ fprintf(stderr, "GFXLIB: PNG EXCEEDS OSD SURFACE SIZE [%s]\n", pBmpData->path); // clean up after the read, and free any memory allocated png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); // close the file fclose(fp); return RM_ERROR; }// printf("width = %ld, height = %ld, bpp = %d, color type = %d, interlaced = %d\n",// width, height, bit_depth, color_type, interlace_type); if(color_type == PNG_COLOR_TYPE_RGB) channels = 3; else if(color_type == PNG_COLOR_TYPE_RGB_ALPHA) channels = 4; else if(color_type == PNG_COLOR_TYPE_PALETTE) channels = 1; else{ fprintf(stderr, "GFXLIB: UNSUPPORTED PNG [%s]\n", pBmpData->path); // clean up after the read, and free any memory allocated png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); // close the file fclose(fp); return RM_ERROR; } pBmpData->bmp.uiWidth = width; pBmpData->bmp.uiHeight = height; pBmpData->bmp.uiNbBitPerPixel = bit_depth * channels; pBmpData->bmp.uiWidthLenInBytes = width; datasize = width * height; // 24 bit not yet supported and has to be converted to 32 bit to32bpp = (pBmpData->bmp.uiNbBitPerPixel >= 24); if(to32bpp){ datasize = 4 * width * height; pBmpData->bmp.uiWidthLenInBytes = 4 * width; } else{ datasize = width * height; // adjust to 32bit datasize = datasize + datasize % 4; pBmpData->bmp.uiWidthLenInBytes = width; } *bmpsize = datasize; status = AllocateBuffer(&bmpbuffer, datasize, FALSE); if(RMFAILED(status)){ fprintf(stderr, "GFXLIB: NOT ENOUGH DRAM TO ALLOCATE PNG [%s]\n", pBmpData->path); // clean up after the read, and free any memory allocated png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); // close the file fclose(fp); return RM_FATALOUTOFMEMORY; } pBmpData->pBmpAddr = bmpbuffer.baseAddr; pBmpData->bmp.pData = bmpbuffer.pMappedAddr; pBmpData->bmp.uiDataSize = datasize; RMMemset(pBmpData->bmp.pData, 0xff, pBmpData->bmp.uiDataSize); png_read_update_info(png_ptr, info_ptr); row_pointers = png_malloc(png_ptr, sizeof(png_bytep)); RMMemset(row_pointers, 0, sizeof(png_bytep)); row_pointers[0] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); for (row = 0; row < height; row++){ png_read_row(png_ptr, row_pointers[0], NULL); if(to32bpp){ if(pBmpData->bmp.uiNbBitPerPixel == 32){ RMMemcpy(pBmpData->bmp.pData + row * width * 4, row_pointers[0], width * 4); // set alpha to 0xff if background if(pBmpData->isBackground){ for(databyte = 0, bufbyte = 0; databyte < 4 * width; databyte++){ if((databyte + 1) % 4 == 0) pBmpData->bmp.pData[databyte] = 0xff; } } } else{ // 24 to 32 bit for(databyte = 0, bufbyte = 0; databyte < 4 * width; databyte++){ if((databyte + 1) % 4 != 0) pBmpData->bmp.pData[databyte + row * 4 * width] = (row_pointers[0])[bufbyte++]; } } } else RMMemcpy(pBmpData->bmp.pData + row * width, row_pointers[0], width); } png_read_end(png_ptr, info_ptr); // read LUT if(pBmpData->bmp.uiNbBitPerPixel == 8){ num_palette = 256; pBmpData->bmp.uiPaletteSize = 1024; png_get_PLTE(png_ptr, info_ptr, &pal, &num_palette); for(row = 0; row < (png_uint_32)num_palette; row++){ pBmpData->bmp.palette[row].rgbRed = pal[row].red; pBmpData->bmp.palette[row].rgbGreen = pal[row].green; pBmpData->bmp.palette[row].rgbBlue = pal[row].blue; } } png_free(png_ptr, row_pointers[0]); png_free(png_ptr, row_pointers); // clean up after the read, and free any memory allocated png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); // close the file fclose(fp); return RM_OK;}RMbool isJpeg(RMascii *path){ RMuint8 buf[JPG_BYTES_TO_CHECK]; FILE *fp; // Open the prospective JPG file if ((fp = fopen(path, "rb")) == NULL){ return FALSE; } // Read in some of the signature bytes if (fread(buf, 1, JPG_BYTES_TO_CHECK, fp) != JPG_BYTES_TO_CHECK) return FALSE; fclose(fp); return (buf[0] == 0xff && buf[1] == 0xd8);}RMstatus load_jpeg( struct RUA* pRua, RMbitmapdata *pBmpData, RMuint32 *bmpsize){ struct jpeg_decompress_struct cinfo; // decompression params RMfile fp; // source file JSAMPARRAY buffer; // Output buffer RMuint32 row_stride; // physical row width in output buffer struct my_error_mgr jerr; RMuint32 row; RMuint8 bpp; RMbool to32bpp = FALSE; // used if 24bpp to convert to 32bpp RMuint32 databyte, bufbyte; RMuint8 temp; RMuint32 datasize; RMstatus status = RM_OK; RMdrawBuffer bmpbuffer; if((fp = RMOpenFile(pBmpData->path, RM_FILE_OPEN_READ)) == NULL){ fprintf(stderr, "GFXLIB: Cannot open %s\n", pBmpData->path); return RM_ERROR; } // allocate and initialize JPEG decompression object // set up the normal JPEG error routines, then override error_exit. cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; // Establish the setjmp return context for my_error_exit to use. if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); RMCloseFile(fp); return RM_ERROR; } // initialize the JPEG decompression object. jpeg_create_decompress(&cinfo); // specify data source jpeg_stdio_src_rm_file(&cinfo, fp); // read file parameters with jpeg_read_header() jpeg_read_header(&cinfo, TRUE); // scale to 1/2, 1/4 or 1/8 if image does not fit in osd surface. we'll rescale it to fit later on if(cinfo.image_width > g_OSDwidth || cinfo.image_height > g_OSDheight){ cinfo.scale_num = 1; cinfo.scale_denom = calculate_jpeg_denom(cinfo.image_width, cinfo.image_height, g_OSDwidth, g_OSDheight); if(cinfo.scale_denom == 0){ fprintf(stderr, "GFXLIB: NOT ENOUGH DRAM (%lu, %lu bytes) TO ALLOCATE JPEG [%s]\n", (RMuint32)cinfo.image_width, (RMuint32)cinfo.image_height, pBmpData->path); // Release JPEG decompression object jpeg_destroy_decompress(&cinfo); RMCloseFile(fp); return RM_FATALOUTOFMEMORY; } } cinfo.dct_method = JDCT_FASTEST; cinfo.do_fancy_upsampling = FALSE; // Start decompressor jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; bpp = cinfo.num_components * 8; pBmpData->bmp.uiWidth = cinfo.output_width; pBmpData->bmp.uiHeight = cinfo.output_height; pBmpData->bmp.uiNbBitPerPixel = bpp; // convert to 32 bit data if 24 bit to32bpp = (bpp == 24); if(to32bpp){ datasize = 4 * cinfo.output_width * cinfo.output_height; pBmpData->bmp.uiWidthLenInBytes = 4 * cinfo.output_width; } else{ datasize = row_stride * cinfo.output_height; // adjust to 32bit datasize = datasize + datasize % 4; pBmpData->bmp.uiWidthLenInBytes = row_stride; } if(pBmpData->pBmpAddr == 0){ *bmpsize = datasize; status = AllocateBuffer(&bmpbuffer, datasize, FALSE); if(RMFAILED(status)){ fprintf(stderr, "GFXLIB: NOT ENOUGH DRAM (%lu bytes)TO ALLOCATE JPEG [%s]\n", datasize, pBmpData->path); // Release JPEG decompression object jpeg_destroy_decompress(&cinfo); RMCloseFile(fp); return RM_FATALOUTOFMEMORY; } pBmpData->pBmpAddr = bmpbuffer.baseAddr; pBmpData->bmp.pData = bmpbuffer.pMappedAddr; } pBmpData->bmp.uiDataSize = datasize; RMMemset(pBmpData->bmp.pData, 0xff, pBmpData->bmp.uiDataSize); // Make a one-row-high sample array that will go away when done with image -- handled by libjpeg buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); // copy rows for (row = 0; row < cinfo.output_height; row++){ jpeg_read_scanlines(&cinfo, buffer, 1); if(cinfo.jpeg_color_space != JCS_GRAYSCALE){ // reverse row (gbr -> rgb) for(bufbyte = 0; bufbyte < row_stride; ){ temp = (*buffer)[bufbyte]; (*buffer)[bufbyte] = (*buffer)[bufbyte + 2]; (*buffer)[bufbyte + 2] = temp; bufbyte += 3; } } temp = 0; if(to32bpp){ for(databyte = 0, bufbyte = 0; databyte < 4 * cinfo.output_width; databyte++){ if((databyte + 1) % 4 != 0) pBmpData->bmp.pData[databyte + row * 4 * cinfo.output_width] = (*buffer)[bufbyte++]; } } else{ RMMemcpy(pBmpData->bmp.pData + row * row_stride, *buffer, row_stride); // set alpha to 0xff if background if(pBmpData->isBackground){ for(databyte = 0, bufbyte = 0; databyte < 4 * cinfo.output_width; databyte++){ if((databyte + 1) % 4 == 0) pBmpData->bmp.pData[databyte] = 0xff; } } } } // set LUT if(cinfo.jpeg_color_space == JCS_GRAYSCALE && bpp == 8){ pBmpData->bmp.uiPaletteSize = 1024; for(row = 0; row < 256; row++){ pBmpData->bmp.palette[row].rgbRed = row; pBmpData->bmp.palette[row].rgbGreen = row; pBmpData->bmp.palette[row].rgbBlue = row; } } // Finish decompression jpeg_finish_decompress(&cinfo); // Release JPEG decompression object jpeg_destroy_decompress(&cinfo); RMCloseFile(fp); return RM_OK;}RMstatus load_gif( struct RUA* pRua, RMbitmapdata *pBmpData, RMuint32 *bmpsize){ RMuint32 datasize; RMstatus status; RMuint16 width, height; GifFileType *gif_hdr; RMdrawBuffer bmpbuffer; RMuint16 row, column, i, j; GifRecordType rtype; gif_hdr = DGifOpenFileName(pBmpData->path); if(gif_hdr == NULL) return RM_ERROR; width = gif_hdr->SWidth; height = gif_hdr->SHeight; if(width > g_OSDwidth || height > g_OSDheight){ fprintf(stderr, "GFXLIB: GIF EXCEEDS OSD SURFACE SIZE [%s]\n", pBmpData->path); // clean up after the read, and free any memory allocated DGifCloseFile(gif_hdr); return RM_ERROR; }// printf("width = %ld, height = %ld, bpp = %d, color type = %d, interlaced = %d\n",// width, height, bit_depth, color_type, interlace_type); pBmpData->bmp.uiWidth = width; pBmpData->bmp.uiHeight = height; pBmpData->bmp.uiNbBitPerPixel = (RMuint8) gif_hdr->SColorResolution; pBmpData->bmp.uiWidthLenInBytes = width; datasize = width * height; // adjust to 32bit datasize = datasize + datasize % 4; *bmpsize = datasize; status = AllocateBuffer(&bmpbuffer, datasize, FALSE); if(RMFAILED(status)){ fprintf(stderr, "GFXLIB: NOT ENOUGH DRAM TO ALLOCATE GIF [%s]\n", pBmpData->path); // clean up after the read, and free any memory allocated DGifCloseFile(gif_hdr); return RM_FATALOUTOFMEMORY; } pBmpData->pBmpAddr = bmpbuffer.baseAddr; pBmpData->bmp.pData = bmpbuffer.pMappedAddr; pBmpData->bmp.uiDataSize = datasize; RMMemset(pBmpData->bmp.pData, 0xff, pBmpData->bmp.uiDataSize); // read image record type rtype = UNDEFINED_RECORD_TYPE; DGifGetRecordType(gif_hdr, &rtype); while(rtype != IMAGE_DESC_RECORD_TYPE){ DGifGetRecordType(gif_hdr, &rtype); } // read image data if(DGifGetImageDesc(gif_hdr) == GIF_ERROR){ DGifCloseFile(gif_hdr); return RM_ERROR; } row = gif_hdr->Image.Top; column = gif_hdr->Image.Left; if(gif_hdr->Image.Interlace){ for(i = 0; i < 4; ++i) { for (j = row + interlacedOffset[i]; j < row + height; j+= interlacedJumps[i]){ if(DGifGetLine(gif_hdr, pBmpData->bmp.pData + (j * width), width ) == GIF_ERROR){ DGifCloseFile(gif_hdr); return RM_ERROR; } } } } else{ for(j = 0; j < height; j++) { if(DGifGetLine(gif_hdr, pBmpData->bmp.pData + (j * width), width ) == GIF_ERROR){ DGifCloseFile(gif_hdr); return RM_ERROR; } } } // read LUT if(pBmpData->bmp.uiNbBitPerPixel == 8 && gif_hdr->SColorMap != NULL){ pBmpData->bmp.uiPaletteSize = 1024; for(row = 0; row < 256; row++){ pBmpData->bmp.palette[row].rgbRed = gif_hdr->SColorMap->Colors[row].Red; pBmpData->bmp.palette[row].rgbGreen = gif_hdr->SColorMap->Colors[row].Green; pBmpData->bmp.palette[row].rgbBlue = gif_hdr->SColorMap->Colors[row].Blue; } } DGifCloseFile(gif_hdr); return RM_OK;}static void PrintCacheStatys(RMascii* where){// entry* np;//// entryLRU* lp;// RMuint32 blocks_till_now = g_OSDwidth + ((g_OSDwidth & 0x3F) ? (64 - (g_OSDwidth & 0x3F)) : 0);// blocks_till_now *= g_OSDheight + ((g_OSDheight & 0x3F) ? (64 - (g_OSDheight & 0x3F)) : 0);// blocks_till_now *= 10;// blocks_till_now /= TILESIZE;//// printf("================ %s =================\n",where);// printf("================ Cache Begin =================\n\n");// for(np = cache.lh_first; np != NULL; np = np->entries.le_next)// {// RMuint16 blocks = np->size / TILESIZE;// RMuint16 i;// for(i = 0; i < blocks; i++)// {// if(np->freeBlock)// {// printf(".");// blocks_till_now --;// } else {// if(i == 0)// {// printf("[");// blocks_till_now --;// } else if(i == blocks - 1)// {// printf("]");// blocks_till_now --;// }// else// {// printf("=");// blocks_till_now --;// }// }//// if(!(blocks_till_now % 48))// printf("\n");// }//// printf("block: %p next: %p prev: %p\n", np, np->entries.le_next, np->entries.le_prev);//// printf("begin: %lu end: %lu: size: %lu free: %d locked %d\n", np->begin, np->end, np->size, np->freeBlock, np->locked);// }// printf("\n================ Cache End ===================\n");// printf("================ LRU Begin ===================\n");// for(lp = lru.lh_first; lp != NULL; lp = lp->entries.le_next)// {// printf("block: %p next: %p prev: %p item: %p\n", lp, lp->entries.le_next, lp->entries.le_prev, lp->item);//// printf("begin: %d end: %d: size: %d free: %d\n", (RMuint16)np->begin, (RMuint16)np->end, (RMuint16)np->size, np->freeBlock);// }// printf("================ LRU End =====================\n");}RMstatus AllocateBuffer( RMdrawBuffer *pBuffer, RMuint32 size, RMbool locked){ RMstatus status = RM_ERROR;// RMuint32 limit; RMuint32 innersize; entry* np = NULL; for(np = cache.lh_first; np != NULL; np = np->entries.le_next) { if(np->size >= size && np->freeBlock) { innersize = ((size / TILESIZE) + 1) * TILESIZE; if(np->size > innersize) { entry* n = (entry*) MALLOC (sizeof(entry)); entryLRU* nlru = (entryLRU*) MALLOC (sizeof(entryLRU)); n->begin = np->begin; // printf("%lu %lu %d\n", size, innersize, (RMuint16)((size / TILESIZE) + 1)); n->end = n->begin + innersize; n->size = innersize; n->freeBlock = FALSE; n->locked = locked; pBuffer->baseAddr = n->begin; pBuffer->size = size; pBuffer->limit = n->end; pBuffer->offset = 0; pBuffer->pMappedAddr = g_BaseBuffer.pMappedAddr + n->begin - g_BaseBuffer.baseAddr; np->begin = n->end; np->size = np->size - innersize; nlru->item = n; LIST_INSERT_HEAD(&lru, nlru, entries); if(np == cache.lh_first) { LIST_INSERT_HEAD(&cache, n, entries); } else { entry* t = np->entries.le_prev; // printf("%p %p %p %p\n", np->entries.le_prev, t, t->entries.le_next, np); LIST_INSERT_AFTER(t, n, entries); if(np->size == 0) { LIST_REMOVE(&cache, np, entries); RFREE(np); } } PrintCacheStatys("Allocate Buffer greater"); return RM_OK;//break; } else { entryLRU* nlru = (entryLRU*) MALLOC (sizeof(entryLRU)); np->freeBlock = FALSE; np->locked = locked; pBuffer->baseAddr = np->begin; pBuffer->size = size; pBuffer->limit = np->end; pBuffer->offset = 0; pBuffer->pMappedAddr = g_BaseBuffer.pMappedAddr + np->begin - g_BaseBuffer.baseAddr; nlru->item = np; LIST_INSERT_HEAD(&lru, nlru, entries); PrintCacheStatys("Allocate Buffer equel"); return RM_OK;//break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -