?? graphic_loader.c.svn-base
字號:
/* * * Copyright (c) Sigma Designs, Inc. 2004. All rights reserved. * *//** @file graphic_loader.c @brief library to load bitmaps (bmp, png, jpg) @author Raul Chirinos*/#define ALLOW_OS_CODE#include "../include/graphic_loader.h"#include "../include/SigmaOSD1_18x23.h"#include "../include/SigmaOSD1_27x36.h"//#ifdef GUI_REFID_2//#include "../include/Font_Ref2.h"//#endif#include "rmcore/include/rmcore.h"#include "rmlibcw/include/rmlibcw.h"#include <time.h>//#include <sys/queue.h>static RMdrawBuffer g_BaseBuffer;LIST_HEAD(listhead, entry) cache;LIST_HEAD(listheadLRU, entryLRU) lru;typedef struct entry { RMuint32 begin; RMuint32 end; RMuint32 size; RMbool freeBlock; RMbool locked; LIST_ENTRY(entry) entries;}entry;typedef struct entryLRU { entry* item;// time_t ctime; LIST_ENTRY(entryLRU) entries;}entryLRU;#define TILESIZE 16384extern RMbitmapdata g_bitmaps[MAX_BITMAPS];// osd surface size defaultsstatic RMuint32 g_OSDwidth = 720;#ifdef GUI_REFID_2static RMuint32 g_OSDheight = 576;#elsestatic RMuint32 g_OSDheight = 480;#endifextern JSAMPLE * image_buffer; // Points to large array of R,G,B-order dataextern int image_height; // Number of rows in imageextern int image_width; // Number of columns in image#define LOBYTE(w) ((RMuint8)(w))#define HIBYTE(w) ((RMuint8)(((RMuint16)(w) >> 8) & 0xff))RMuint16 rev16(RMuint16 n);static int interlacedOffset[] = { 0, 4, 2, 1 };static int interlacedJumps[] = { 8, 8, 4, 2 };// load infos from coreheader bitmap filesRMbool load_coreheader_data(FILE* fFile, RMbitmapdata *pBmpData, RMBitmapCoreHeader* pInfo);// load infos from infoheader bitmap filesRMstatus load_infoheader_data(struct RUA* pRua, FILE* fFile, RMbitmapdata *pBmpData, RMBitmapInfoHeader* pInfo, RMuint32 *bmpsize);// compute the padding (uiWidthLenInBytes) to BMP_DATA_PADDINGRMstatus compute_padding(struct tagRMBitmap *ptgBitmap);// transform a bitmap data array (beginning at the left bottom corner) into// a regular data array (beginning at the left top corner)RMstatus change_origin(struct tagRMBitmap *ptgBitmap);// calculate scaling factor so image fits in osd surfaceRMuint8 calculate_jpeg_denom(RMuint32 width, RMuint32 height, RMuint32 target_width, RMuint32 target_height);RMFont *PredefinedFonts[PREDEFINED_FONTS] ={ &font_SigmaOSD1_18x23,#ifdef GUI_REFID_2 &font_SigmaOSD1_27x36, &font_Ref2_1#else &font_SigmaOSD1_27x36 //&font_KiSS_Cinea_18#endif};struct my_error_mgr { struct jpeg_error_mgr pub; // "public" fields jmp_buf setjmp_buffer; // for return to caller};typedef struct my_error_mgr * my_error_ptr;// Here's the routine that will replace the standard error_exit method:METHODDEF(void) my_error_exit (j_common_ptr cinfo){ // cinfo->err really points to a my_error_mgr struct, so coerce pointer my_error_ptr myerr = (my_error_ptr) cinfo->err; // Always display the message // We could postpone this until after returning, if we chose (*cinfo->err->output_message) (cinfo); // Return control to the setjmp point longjmp(myerr->setjmp_buffer, 1);}void SetOsdSurfaceSize(RMuint32 width, RMuint32 height){ g_OSDwidth = width; g_OSDheight = height;}RMuint8 calculate_jpeg_denom( RMuint32 width, RMuint32 height, RMuint32 target_width, RMuint32 target_height){ if(width < target_width && height < target_height) return 1; if((width / 2 < target_width) && (height / 2 < target_height)) return 2; if((width / 4 < target_width) && (height / 4 < target_height)) return 4; if((width / 8 < target_width) && (height / 8 < target_height)) return 8; return 0;}RMuint16 rev16(RMuint16 n){ RMuint16 ret = 0; RMuint8 i; for(i = 0; i < 16; i++){ ret = (ret << 1) | (n & 1); n = n >> 1; } return ret;}RMbool isBitmap(RMascii *path){ RMascii buf[BMP_BYTES_TO_CHECK]; FILE *fp; // Open the prospective BITMAP file if ((fp = fopen(path, "rb")) == NULL){ return FALSE; } // Read in some of the signature bytes if (fread(buf, 1, BMP_BYTES_TO_CHECK, fp) != BMP_BYTES_TO_CHECK) return FALSE; // Compare the first PNG_BYTES_TO_CHECK bytes of the signature.entry // Return nonzero (true) if they match fclose(fp); return(buf[0] == 'B' && buf[1] == 'M');}RMstatus load_bitmap( struct RUA* pRua, RMbitmapdata *pBmpData, RMuint32 *bmpsize){ FILE *fFile; RMuint32 ui32Dummy; RMBitmapFileHeader bmpFileHeader; RMBitmapInfoHeader bmpInfoHeader; RMBitmapCoreHeader bmpCoreHeader; enum tagBitmapType eBitmapType; pBmpData->bmp.pData = NULL; RMMemset(pBmpData->bmp.palette, 0, sizeof(pBmpData->bmp.palette)); // open the file if ((fFile = fopen(pBmpData->path,"r")) == NULL){ fprintf(stderr, "GFXLIB: Error opening file %s.\n", pBmpData->path); return RM_ERROR; } // save the bitmap header fread(&bmpFileHeader, 1, RMBITMAPFILEHEADER_REALSIZE, fFile); if((((RMuint8*)&(bmpFileHeader.bfType))[0] != 'B') || (((RMuint8*)&(bmpFileHeader.bfType))[1] != 'M')){ // fprintf(stderr, "%s is not a valid bitmap file.\n", pBmpData->path); fclose(fFile); return RM_ERROR; } // now we reading the next dword to know if we have a RMBitmapInfoHeader // or a RMBitmapCoreHeader if(fread(&ui32Dummy, 1, sizeof(RMuint32), fFile) != sizeof(RMuint32)){ //fprintf(stderr, "End of file %s too soon !.\n", pBmpData->path); fclose(fFile); return RM_ERROR; } switch(((RMuint8*)&ui32Dummy)[0]){ case RMBITMAPCOREHEADER_REALSIZE : // a RMBitmapCoreHeader struct // copy the RMuint32 read just before... RMMemcpy(&bmpCoreHeader, &ui32Dummy, sizeof(RMuint32)); // and the remaining bytes fread((RMuint8*)&bmpCoreHeader + sizeof(RMuint32), 1, RMBITMAPCOREHEADER_REALSIZE - sizeof(RMuint32), fFile); eBitmapType = BMP_TYPE_COREHEADER; pBmpData->bmp.uiWidth = bmpCoreHeader.bcWidth; pBmpData->bmp.uiHeight = bmpCoreHeader.bcHeight; pBmpData->bmp.uiNbBitPerPixel = bmpCoreHeader.bcBitCount; break; case RMBITMAPINFOHEADER_REALSIZE : // a BITMAPINFOHEADER struct // copy the RMuint32 read just before... RMMemcpy(&bmpInfoHeader, &ui32Dummy, sizeof(RMuint32)); // and the remaining bytes fread((RMuint8*)&bmpInfoHeader + sizeof(RMuint32), 1, RMBITMAPINFOHEADER_REALSIZE - sizeof(RMuint32), fFile); eBitmapType = BMP_TYPE_INFOHEADER; pBmpData->bmp.uiWidth = bmpInfoHeader.biWidth; pBmpData->bmp.uiHeight = bmpInfoHeader.biHeight; pBmpData->bmp.uiNbBitPerPixel = bmpInfoHeader.biBitCount; // check the compression format switch(bmpInfoHeader.biCompression) { case BMP_PACK_RGB : // no compression, ok break; case BMP_PACK_RLE4 : // compression, not handled for the moment //fprintf(stderr, "The file %s is RLE4 compressed, aborting bitmap loading.\n", pBmpData->path); fclose(fFile); return RM_ERROR; break; case BMP_PACK_RLE8 : // compression, not handled for the moment //fprintf(stderr, "The file %s is RLE8 compressed, aborting bitmap loading.\n", pBmpData->path); fclose(fFile); return RM_ERROR; break; default : //fprintf(stderr, "The file %s have an unknown compression format.\n", pBmpData->path); fclose(fFile); return RM_ERROR; break; } break; default : //fprintf(stderr, "The file %s have an unknown sub header.\n", pBmpData->path); fclose(fFile); return RM_ERROR; break; } switch(eBitmapType){ case BMP_TYPE_COREHEADER: if(!load_coreheader_data(fFile, pBmpData, &bmpCoreHeader)){ //fprintf(stderr, "Error 1 while loading data in file %s.\n", pBmpData->path); fclose(fFile); return RM_ERROR; } break; case BMP_TYPE_INFOHEADER: if(RMFAILED(load_infoheader_data(pRua, fFile, pBmpData, &bmpInfoHeader, bmpsize))){ //fprintf(stderr, "Error 2 while loading data in file %s.\n", pBmpData->path); fclose(fFile); return RM_ERROR; } break; default: // impossible case but... //fprintf(stderr, "Unknown bitmap type in file %s ?????\n", pBmpData->path); fclose(fFile); return RM_ERROR; break; } fclose(fFile); return RM_OK;}RMbool load_coreheader_data( FILE* fFile, RMbitmapdata *pBmpData, RMBitmapCoreHeader* pInfo){ //fprintf(stderr, "This type of bmp file is not handled for the moment, sorry...\n"); return FALSE;}RMstatus load_infoheader_data( struct RUA* pRua, FILE* fp, RMbitmapdata *pBmpData, RMBitmapInfoHeader* pInfo, RMuint32 *bmpsize){ RMuint32 datasize; RMuint32 ui32AllocSizePalette; RMuint32 to32bpp; RMuint8 *temp; RMuint32 i, j; RMdrawBuffer bmpbuffer; RMstatus status; RMuint32 row, height, width; RMuint32 dataline; RMuint32 databyte; if(pInfo->biClrUsed == 0){ if(pBmpData->bmp.uiNbBitPerPixel != BMP_BPP_24) ui32AllocSizePalette = sizeof(struct tagRMRGBQuad) * (1 << pBmpData->bmp.uiNbBitPerPixel); else ui32AllocSizePalette = pInfo->biClrUsed; } else{ if(pBmpData->bmp.uiNbBitPerPixel != BMP_BPP_24) ui32AllocSizePalette = sizeof(struct tagRMRGBQuad) * pInfo->biClrUsed; else ui32AllocSizePalette = pInfo->biClrUsed; } // read LUT ui32AllocSizePalette = fread(pBmpData->bmp.palette, 1, ui32AllocSizePalette, fp); pBmpData->bmp.uiPaletteSize = ui32AllocSizePalette; to32bpp = (pBmpData->bmp.uiNbBitPerPixel == BMP_BPP_24); if(pInfo->biWidth > g_OSDwidth || pInfo->biHeight > g_OSDheight){ fprintf(stderr, "GFXLIB: BMP MAY EXCEED OSD SURFACE SIZE\n"); //return RM_ERROR; } if(pBmpData->bmp.uiNbBitPerPixel == 1) datasize = (pInfo->biWidth * pInfo->biHeight) / 8; else if(pBmpData->bmp.uiNbBitPerPixel >= 8) datasize = pInfo->biWidth * pInfo->biHeight * (pBmpData->bmp.uiNbBitPerPixel / 8); else{ fprintf(stderr, "GFXLIB: UNSUPPORTED BMP!!!!!!!!\n"); // close the file return RM_ERROR; } if(to32bpp){ datasize += pInfo->biWidth * pInfo->biHeight; } // 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 BMP!!!!!!!!\n"); // close the file return RM_FATALOUTOFMEMORY; } pBmpData->pBmpAddr = bmpbuffer.baseAddr; pBmpData->bmp.pData = bmpbuffer.pMappedAddr; pBmpData->bmp.uiDataSize = datasize; RMMemset(pBmpData->bmp.pData, 0xff, pBmpData->bmp.uiDataSize); compute_padding(&pBmpData->bmp); temp = (RMuint8*) MALLOC(pBmpData->bmp.uiWidthLenInBytes); if(temp == NULL) return RM_ERROR; width = pInfo->biWidth; height = pInfo->biHeight; RMMemset(temp, 0xff, datasize / height); dataline = to32bpp ? width * 3 : pBmpData->bmp.uiWidthLenInBytes; for (row = 0; row < height; row++){ fread(temp, 1, dataline, fp); if(to32bpp){ // 24 to 32 bit // now make it 32 bit, copy and flip it for(i = 0, j = 0; i < 4 * width; i++){ if((i + 1) % 4 != 0) pBmpData->bmp.pData[i + (height - row - 1) * 4 * width] = temp[j++]; } } else{ // copy and flip it for(i = 0, j = 0; i < dataline; i++){ databyte = i + (height - row - 1) * dataline; pBmpData->bmp.pData[databyte] = temp[j++]; } } } RFREE(temp); return RM_OK;}RMstatus compute_padding(struct tagRMBitmap *ptgBitmap){ switch(ptgBitmap->uiNbBitPerPixel){ case 1 : case 2 : case 4 : // padding to the RMuint32 value ptgBitmap->uiWidthLenInBytes = ((ptgBitmap->uiWidth + BMP_DATA_PADDING * (8 / ptgBitmap->uiNbBitPerPixel) - 1) / (BMP_DATA_PADDING * (8 / ptgBitmap->uiNbBitPerPixel))) * BMP_DATA_PADDING; break; case 8 : case 16 : // padding to the RMuint32 value ptgBitmap->uiWidthLenInBytes = (((ptgBitmap->uiWidth * (ptgBitmap->uiNbBitPerPixel / 8)) + BMP_DATA_PADDING - 1) / BMP_DATA_PADDING) * BMP_DATA_PADDING; break; case 24 : // this should be in the case above but is here because it is transformed to 32 bit case 32 : // already padded ptgBitmap->uiWidthLenInBytes = ptgBitmap->uiWidth * 4; break; default : //printf("Unable to pad data for that kind of bpp : %d\n", ptgBitmap->uiNbBitPerPixel); return RM_ERROR; } return RM_OK;}RMstatus change_origin(struct tagRMBitmap *ptgBitmap){ RMuint8* pTmpArray; RMuint32 uiByteJump; RMuint32 uiSrcOffset; RMuint32 uiDestOffset; RMuint32 i; RMstatus bReturnedValue = RM_OK; pTmpArray = (RMuint8*) MALLOC (ptgBitmap->uiDataSize); if(pTmpArray == NULL) return RM_ERROR; switch(ptgBitmap->uiNbBitPerPixel){ case BMP_BPP_1 : case 2 : case BMP_BPP_4 : case BMP_BPP_8 : case BMP_BPP_24 : case 32 : uiByteJump = ptgBitmap->uiWidthLenInBytes; uiSrcOffset = uiByteJump * (ptgBitmap->uiHeight - 1); uiDestOffset = 0; for(i = 0; i < ptgBitmap->uiHeight; i++) { RMMemcpy(&pTmpArray[uiDestOffset], &ptgBitmap->pData[uiSrcOffset], uiByteJump); uiSrcOffset -= uiByteJump; uiDestOffset += uiByteJump; } break; default : // fprintf(stderr, "Unknown bpp.\n"); return RM_ERROR; break; } if(ptgBitmap->pData != NULL){ RFREE(ptgBitmap->pData); ptgBitmap->pData = pTmpArray; } return bReturnedValue;}RMstatus transform_data_to_match_gfxacc(struct tagRMBitmap *ptgBitmap){ RMuint32 i; if(RMFAILED(change_origin(ptgBitmap))) return RM_ERROR; switch(ptgBitmap->uiNbBitPerPixel){ case BMP_BPP_1: // switch the MSB's and the LSB's of each bytes in a BITMAP's structure data array, // cause the graphic accelerator of mambo counts the bits in a byte like this : // 7 6 5 4 3 2 1 0 // and the bits in a bitmap are like this : // 0 1 2 3 4 5 6 7 for(i=0 ; i<ptgBitmap->uiDataSize ; i++) { ptgBitmap->pData[i] = ((ptgBitmap->pData[i] & (1 << 0)) << 7) | ((ptgBitmap->pData[i] & (1 << 1)) << 5) | ((ptgBitmap->pData[i] & (1 << 2)) << 3) | ((ptgBitmap->pData[i] & (1 << 3)) << 1) | ((ptgBitmap->pData[i] & (1 << 4)) >> 1) | ((ptgBitmap->pData[i] & (1 << 5)) >> 3) | ((ptgBitmap->pData[i] & (1 << 6)) >> 5) | ((ptgBitmap->pData[i] & (1 << 7)) >> 7); } return RM_OK; break; case 2 : // switch the MSB's and the LSB's of each bytes in a BITMAP's structure data array, // cause the graphic accelerator of mambo counts the bits in a byte like this : // 3 3 2 2 1 1 0 0 // and the bits in a bitmap are like this : // 0 0 1 1 2 2 3 3
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -