#include #include #include #include #include #include // Filename #define JPG_FILE_NAME "jpegdemo/sample.jpg" // Maximum texture size #define MAX_TEXSIZE_X 1024 #define MAX_TEXSIZE_Y 1024 // Maximum value of texture reduction rate #define MAX_SMALL_RATE 8 // Image / Thumbnail image #define DEC_JPEG 0 #define DEC_THUMB 1 #define NO_ERROR 0 // Round up to the common multiple of base static u32 round_up(u32 value, u32 base) { if(value % base != 0) return value + (base - (value % base)); else return value; } void main() { void *arenaMem2Lo; void *arenaMem2Hi; // Handle for heap memory MEMHeapHandle hExpHeap; // File information DVDFileInfo fileInfo; // Work area for the library void* jpeg_workarea; // JPG data to load from u8 *jpeg_stream_data = NULL; // JPG load size u32 jpg_stream_size; // JPG file size s32 readsize; // Are thumbnails included? BOOL thumb_Enable = FALSE; // Temporary variables used for calculating the texture reduction s32 tmp_small_rate,tmpx,tmpy; // PAD status PADStatus pads[PAD_MAX_CONTROLLERS]; //====================================== // Actual image //====================================== // Plain data for loading the texture (16-bit RGB 565) u16 *texturebuffer = NULL; //Texture for display GXTexObj m_tobj; // Size data after decoding TMCCJPEGJpegSize jpeg_data_size; //====================================== // Thumbnail //====================================== // Plain data for loading the texture (16-bit RGB 565) u16 *thumbbuffer = NULL; //Texture for thumbnail GXTexObj m_tobj_thumb; // Size data after decoding TMCCJPEGJpegSize thumb_data_size; //======================================================================================= // Start decoding //======================================================================================= DEMOInit(NULL); // Create a heap region in MEM2 arenaMem2Lo = OSGetMEM2ArenaLo(); arenaMem2Hi = OSGetMEM2ArenaHi(); hExpHeap = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo); // Create the JPEG work area jpeg_workarea = (void *)MEMAllocFromExpHeapEx(hExpHeap, TMCC_JPEG_WORKAREA_SIZE, 32); // Open the JPG file if(!DVDOpen(JPG_FILE_NAME, &fileInfo)) { OSReport("JPG Open Error.\n"); return; } // Size of the buffer that should be created jpg_stream_size = DVDGetLength(&fileInfo); // For optical discs, make this a multiple of 32 readsize = (s32)round_up(jpg_stream_size, 32); // Create buffer jpeg_stream_data = (u8 *)MEMAllocFromExpHeapEx(hExpHeap, (u32)readsize, 32); // Load the file's contents into the buffer if(readsize != DVDRead( &fileInfo, jpeg_stream_data, readsize, 0)) { OSReport("counldn't read data.\n"); return; } // Stop reading from the optical disc DVDClose( &fileInfo ); OSReport("completed reading data.\n"); // Create the image texture { // Get the image size and the memory size during expansion if(TMCCJPEGDecGetSize( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size, GX_TF_RGB565, 1, DEC_JPEG, &jpeg_data_size) != NO_ERROR) // Failed to get the size { OSReport("failed to get texbuffersize.\n"); } else { OSReport("real jpeg graphic size (width,height) = (%d,%d)\n",jpeg_data_size.width,jpeg_data_size.height); OSReport("required texture buffer size = %d\n",jpeg_data_size.texBufferSize); // If the texture's sides are longer than 1024 pixels, reduce them tmpx = jpeg_data_size.width; tmpy = jpeg_data_size.height; tmp_small_rate = 1; while( (tmpx > MAX_TEXSIZE_X || tmpy > MAX_TEXSIZE_Y) && tmp_small_rate < MAX_SMALL_RATE ) { tmp_small_rate *= 2; tmpx = jpeg_data_size.width / tmp_small_rate; tmpy = jpeg_data_size.height / tmp_small_rate; } // Display the reduction rate OSReport("small scale rate = %d\n",tmp_small_rate); // Recalculate using the reduced texture size TMCCJPEGDecGetSize( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size, GX_TF_RGB565, tmp_small_rate, DEC_JPEG, &jpeg_data_size); OSReport("texture size (width,height) = (%d,%d)\n",jpeg_data_size.width,jpeg_data_size.height); OSReport("new required texture buffer size = %d\n",jpeg_data_size.texBufferSize); // Create the texture buffer texturebuffer = (u16*)MEMAllocFromExpHeapEx(hExpHeap, (u32)jpeg_data_size.texBufferSize, 32); // Decode if(TMCCJPEGDecDecode( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size, (void *)texturebuffer, (u32)jpeg_data_size.texBufferSize, GX_TF_RGB565, tmp_small_rate, DEC_JPEG) != NO_ERROR) // Failed to decode { OSReport("failed to decode.\n"); } // Create the image texture else { OSReport("texture making.\n"); DCFlushRange(texturebuffer, (u32)jpeg_data_size.texBufferSize); GXInitTexObj(&m_tobj, (void *)texturebuffer, (u16)jpeg_data_size.width, (u16)jpeg_data_size.height, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&m_tobj, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1); } } } // Create the thumbnail texture { // Get the image size and the memory size during expansion if(TMCCJPEGDecGetSize( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size, GX_TF_RGB565, 1, DEC_THUMB, &thumb_data_size) != NO_ERROR) // When there are no thumbnails { OSReport("failed to get thumb texbuffersize.\n"); } else // When there are thumbnails { OSReport("thumbnail graphic size (width,height) = (%d,%d)\n",thumb_data_size.width,thumb_data_size.height); OSReport("required texture buffer size = %d\n",thumb_data_size.texBufferSize); if( thumb_data_size.width > MAX_TEXSIZE_X || thumb_data_size.height > MAX_TEXSIZE_Y ) // When the length of the sides is greater than 1024 pixels { OSReport("thumbnail graphic size is too large.\n"); } else // When the length of the sides is 1024 pixels or less { // Create the texture buffer thumbbuffer = (u16*)MEMAllocFromExpHeapEx(hExpHeap, (u32)thumb_data_size.texBufferSize, 32); // Decode if(TMCCJPEGDecDecode( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size, (void *)thumbbuffer, (u32)thumb_data_size.texBufferSize, GX_TF_RGB565, 1 , DEC_THUMB) != NO_ERROR) // Failed to decode { OSReport("failed to decode.\n"); } // Create the image texture else { OSReport("texture making.\n"); DCFlushRange(thumbbuffer, (u32)thumb_data_size.texBufferSize); GXInitTexObj(&m_tobj_thumb, (void *)thumbbuffer, (u16)thumb_data_size.width, (u16)thumb_data_size.height, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&m_tobj_thumb, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1); // With thumbnail thumb_Enable = TRUE; } } } } // Set the projection matrix for an orthogonal projection. { Mtx44 p; MTXOrtho(p, 0.0f, 480.0f, 0.0f, 640.0f, 0.0f, 500.0f); GXSetProjection( p, GX_ORTHOGRAPHIC ); } // Set the model view matrix as an identity matrix. { Mtx mv; MTXIdentity( mv ); GXLoadPosMtxImm( mv, GX_PNMTX0 ); GXSetCurrentMtx( GX_PNMTX0 ); } // Debug display { OSReport("\n"); OSReport("\n"); OSReport("JPG decode simple demo\n"); } while(1) { PADRead(pads); if (pads[0].button & PAD_BUTTON_A) { break; } DEMOBeforeRender(); //Render settings GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GXSetNumChans(1); GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); GXSetNumTexGens(1); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); GXSetNumTevStages(1); GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, 255}); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO); GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE); GXSetCullMode(GX_CULL_NONE); // Draw the normal image { f32 x1,x2,y1,y2; x1 = 0; y1 = 0; x2 = x1 + (f32)jpeg_data_size.width; y2 = y1 + (f32)jpeg_data_size.height; GXLoadTexObj(&m_tobj, GX_TEXMAP0); GXBegin(GX_QUADS, GX_VTXFMT0, 4); GXPosition3f32(x1, y1, 0); GXTexCoord2f32(0.f, 0.f); GXPosition3f32(x2, y1, 0); GXTexCoord2f32(1.f, 0.f); GXPosition3f32(x2, y2, 0); GXTexCoord2f32(1.f, 1.f); GXPosition3f32(x1, y2, 0); GXTexCoord2f32(0.f, 1.f); GXEnd(); } // Draw the thumbnail image if(thumb_Enable) { f32 x1,x2,y1,y2; x1 = 320; y1 = 0; x2 = x1 + (f32)thumb_data_size.width; y2 = y1 + (f32)thumb_data_size.height; GXLoadTexObj(&m_tobj_thumb, GX_TEXMAP0); GXBegin(GX_QUADS, GX_VTXFMT0, 4); GXPosition3f32(x1, y1, 0); GXTexCoord2f32(0.f, 0.f); GXPosition3f32(x2, y1, 0); GXTexCoord2f32(1.f, 0.f); GXPosition3f32(x2, y2, 0); GXTexCoord2f32(1.f, 1.f); GXPosition3f32(x1, y2, 0); GXTexCoord2f32(0.f, 1.f); GXEnd(); } DEMODoneRender(); } MEMFreeToExpHeap( hExpHeap, jpeg_workarea ); MEMFreeToExpHeap( hExpHeap, jpeg_stream_data ); OSHalt("finish.\n"); }