1 #include <string.h>
2 #include <demo.h>
3 #include <revolution.h>
4 #include <revolution/mix.h>
5 #include <revolution/mem.h>
6 #include <revolution/tmcc_jpeg.h>
7 
8 // Filename
9 #define JPG_FILE_NAME  "jpegdemo/sample.jpg"
10 
11 // Maximum texture size
12 #define MAX_TEXSIZE_X 1024
13 #define MAX_TEXSIZE_Y 1024
14 // Maximum value of texture reduction rate
15 #define MAX_SMALL_RATE 8
16 
17 // Image / Thumbnail image
18 #define DEC_JPEG    0
19 #define DEC_THUMB   1
20 
21 #define NO_ERROR 0
22 
23 // Round up to the common multiple of base
round_up(u32 value,u32 base)24 static u32 round_up(u32 value, u32 base)
25 {
26     if(value % base != 0)
27         return value + (base - (value % base));
28     else
29         return value;
30 }
31 
main()32 void main()
33 {
34     void          *arenaMem2Lo;
35     void          *arenaMem2Hi;
36     // Handle for heap memory
37     MEMHeapHandle  hExpHeap;
38     // File information
39     DVDFileInfo   fileInfo;
40     // Work area for the library
41     void* jpeg_workarea;
42     // JPG data to load from
43     u8 *jpeg_stream_data = NULL;
44     // JPG load size
45     u32 jpg_stream_size;
46     // JPG file size
47     s32 readsize;
48     // Are thumbnails included?
49     BOOL thumb_Enable = FALSE;
50     // Temporary variables used for calculating the texture reduction
51     s32 tmp_small_rate,tmpx,tmpy;
52     // PAD status
53     PADStatus      pads[PAD_MAX_CONTROLLERS];
54 
55     //======================================
56     // Actual image
57     //======================================
58     // Plain data for loading the texture (16-bit RGB 565)
59     u16 *texturebuffer = NULL;
60     //Texture for display
61     GXTexObj    m_tobj;
62     // Size data after decoding
63     TMCCJPEGJpegSize jpeg_data_size;
64     //======================================
65     // Thumbnail
66     //======================================
67     // Plain data for loading the texture (16-bit RGB 565)
68     u16 *thumbbuffer = NULL;
69     //Texture for thumbnail
70     GXTexObj    m_tobj_thumb;
71     // Size data after decoding
72     TMCCJPEGJpegSize thumb_data_size;
73 
74 
75     //=======================================================================================
76     // Start decoding
77     //=======================================================================================
78     DEMOInit(NULL);
79 
80     // Create a heap region in MEM2
81     arenaMem2Lo = OSGetMEM2ArenaLo();
82     arenaMem2Hi = OSGetMEM2ArenaHi();
83     hExpHeap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
84 
85     // Create the JPEG work area
86     jpeg_workarea = (void *)MEMAllocFromExpHeapEx(hExpHeap, TMCC_JPEG_WORKAREA_SIZE, 32);
87 
88     // Open the JPG file
89     if(!DVDOpen(JPG_FILE_NAME, &fileInfo))
90     {
91         OSReport("JPG Open Error.\n");
92         return;
93     }
94 
95     // Size of the buffer that should be created
96     jpg_stream_size = DVDGetLength(&fileInfo);
97     // For optical discs, make this a multiple of 32
98     readsize = (s32)round_up(jpg_stream_size, 32);
99 
100     // Create buffer
101     jpeg_stream_data = (u8 *)MEMAllocFromExpHeapEx(hExpHeap, (u32)readsize, 32);
102 
103     // Load the file's contents into the buffer
104     if(readsize != DVDRead( &fileInfo, jpeg_stream_data, readsize, 0))
105     {
106         OSReport("counldn't read data.\n");
107         return;
108     }
109     // Stop reading from the optical disc
110     DVDClose( &fileInfo );
111     OSReport("completed reading data.\n");
112 
113     // Create the image texture
114     {
115         // Get the image size and the memory size during expansion
116         if(TMCCJPEGDecGetSize( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size,
117                                GX_TF_RGB565, 1, DEC_JPEG, &jpeg_data_size)
118                                != NO_ERROR)
119         // Failed to get the size
120         {
121             OSReport("failed to get texbuffersize.\n");
122         }
123         else
124         {
125             OSReport("real jpeg graphic size (width,height) = (%d,%d)\n",jpeg_data_size.width,jpeg_data_size.height);
126             OSReport("required texture buffer size = %d\n",jpeg_data_size.texBufferSize);
127 
128             // If the texture's sides are longer than 1024 pixels, reduce them
129             tmpx = jpeg_data_size.width;
130             tmpy = jpeg_data_size.height;
131             tmp_small_rate = 1;
132             while( (tmpx > MAX_TEXSIZE_X || tmpy > MAX_TEXSIZE_Y)  && tmp_small_rate < MAX_SMALL_RATE )
133             {
134                 tmp_small_rate *= 2;
135                 tmpx = jpeg_data_size.width / tmp_small_rate;
136                 tmpy = jpeg_data_size.height / tmp_small_rate;
137             }
138 
139             // Display the reduction rate
140             OSReport("small scale rate = %d\n",tmp_small_rate);
141 
142             // Recalculate using the reduced texture size
143             TMCCJPEGDecGetSize( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size,
144                                GX_TF_RGB565, tmp_small_rate, DEC_JPEG, &jpeg_data_size);
145 
146             OSReport("texture size (width,height) = (%d,%d)\n",jpeg_data_size.width,jpeg_data_size.height);
147             OSReport("new required texture buffer size = %d\n",jpeg_data_size.texBufferSize);
148 
149 
150             // Create the texture buffer
151             texturebuffer = (u16*)MEMAllocFromExpHeapEx(hExpHeap, (u32)jpeg_data_size.texBufferSize, 32);
152             // Decode
153             if(TMCCJPEGDecDecode( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size,
154                                   (void *)texturebuffer, (u32)jpeg_data_size.texBufferSize, GX_TF_RGB565, tmp_small_rate, DEC_JPEG)
155                                   != NO_ERROR)
156             // Failed to decode
157             {
158                 OSReport("failed to decode.\n");
159             }
160             // Create the image texture
161             else
162             {
163                 OSReport("texture making.\n");
164                 DCFlushRange(texturebuffer, (u32)jpeg_data_size.texBufferSize);
165 
166                 GXInitTexObj(&m_tobj, (void *)texturebuffer,
167                                       (u16)jpeg_data_size.width, (u16)jpeg_data_size.height,
168                                       GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
169                 GXInitTexObjLOD(&m_tobj, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
170             }
171         }
172     }
173 
174     // Create the thumbnail texture
175     {
176         // Get the image size and the memory size during expansion
177         if(TMCCJPEGDecGetSize( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size,
178                                GX_TF_RGB565, 1, DEC_THUMB, &thumb_data_size)
179                                != NO_ERROR)
180         // When there are no thumbnails
181         {
182             OSReport("failed to get thumb texbuffersize.\n");
183         }
184         else
185         // When there are thumbnails
186         {
187             OSReport("thumbnail graphic size (width,height) = (%d,%d)\n",thumb_data_size.width,thumb_data_size.height);
188             OSReport("required texture buffer size = %d\n",thumb_data_size.texBufferSize);
189 
190             if( thumb_data_size.width > MAX_TEXSIZE_X || thumb_data_size.height > MAX_TEXSIZE_Y )
191             // When the length of the sides is greater than 1024 pixels
192             {
193                 OSReport("thumbnail graphic size is too large.\n");
194             }
195             else
196             // When the length of the sides is 1024 pixels or less
197             {
198 
199                 // Create the texture buffer
200                 thumbbuffer = (u16*)MEMAllocFromExpHeapEx(hExpHeap, (u32)thumb_data_size.texBufferSize, 32);
201                 // Decode
202                 if(TMCCJPEGDecDecode( (void *)jpeg_workarea, (void *)jpeg_stream_data, jpg_stream_size,
203                                   (void *)thumbbuffer, (u32)thumb_data_size.texBufferSize, GX_TF_RGB565, 1 , DEC_THUMB)
204                                   != NO_ERROR)
205                 // Failed to decode
206                 {
207                     OSReport("failed to decode.\n");
208                 }
209                 // Create the image texture
210                 else
211                 {
212                     OSReport("texture making.\n");
213                     DCFlushRange(thumbbuffer, (u32)thumb_data_size.texBufferSize);
214 
215                     GXInitTexObj(&m_tobj_thumb, (void *)thumbbuffer,
216                          (u16)thumb_data_size.width, (u16)thumb_data_size.height,
217                          GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
218                     GXInitTexObjLOD(&m_tobj_thumb, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
219 
220                     // With thumbnail
221                     thumb_Enable = TRUE;
222                 }
223             }
224         }
225     }
226 
227 
228     // Set the projection matrix for an orthogonal projection.
229     {
230         Mtx44 p;
231         MTXOrtho(p, 0.0f, 480.0f, 0.0f, 640.0f, 0.0f, 500.0f);
232         GXSetProjection( p, GX_ORTHOGRAPHIC );
233     }
234     // Set the model view matrix as an identity matrix.
235     {
236         Mtx mv;
237         MTXIdentity( mv );
238         GXLoadPosMtxImm( mv, GX_PNMTX0 );
239         GXSetCurrentMtx( GX_PNMTX0 );
240     }
241 
242     // Debug display
243     {
244         OSReport("\n");
245         OSReport("\n");
246         OSReport("JPG decode simple demo\n");
247     }
248 
249     while(1)
250     {
251         PADRead(pads);
252 
253         if (pads[0].button & PAD_BUTTON_A)
254         {
255             break;
256         }
257 
258         DEMOBeforeRender();
259 
260         //Render settings
261         GXClearVtxDesc();
262         GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
263         GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
264         GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
265         GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
266 
267         GXSetNumChans(1);
268         GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
269 
270         GXSetNumTexGens(1);
271         GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
272 
273         GXSetNumTevStages(1);
274         GXSetTevColor(GX_TEVREG0, (GXColor){255, 255, 255, 255});
275         GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
276         GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
277         GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
278         GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
279         GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
280 
281         GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
282         GXSetZMode(GX_FALSE, GX_LEQUAL, GX_FALSE);
283 
284         GXSetCullMode(GX_CULL_NONE);
285 
286         // Draw the normal image
287         {
288             f32 x1,x2,y1,y2;
289 
290             x1 = 0;
291             y1 = 0;
292 
293             x2 = x1 + (f32)jpeg_data_size.width;
294             y2 = y1 + (f32)jpeg_data_size.height;
295 
296             GXLoadTexObj(&m_tobj, GX_TEXMAP0);
297 
298             GXBegin(GX_QUADS, GX_VTXFMT0, 4);
299             GXPosition3f32(x1, y1, 0);
300             GXTexCoord2f32(0.f, 0.f);
301             GXPosition3f32(x2, y1, 0);
302             GXTexCoord2f32(1.f, 0.f);
303             GXPosition3f32(x2, y2, 0);
304             GXTexCoord2f32(1.f, 1.f);
305             GXPosition3f32(x1, y2, 0);
306             GXTexCoord2f32(0.f, 1.f);
307             GXEnd();
308         }
309 
310         // Draw the thumbnail image
311         if(thumb_Enable)
312         {
313             f32 x1,x2,y1,y2;
314 
315             x1 = 320;
316             y1 = 0;
317 
318             x2 = x1 + (f32)thumb_data_size.width;
319             y2 = y1 + (f32)thumb_data_size.height;
320 
321             GXLoadTexObj(&m_tobj_thumb, GX_TEXMAP0);
322 
323             GXBegin(GX_QUADS, GX_VTXFMT0, 4);
324             GXPosition3f32(x1, y1, 0);
325             GXTexCoord2f32(0.f, 0.f);
326             GXPosition3f32(x2, y1, 0);
327             GXTexCoord2f32(1.f, 0.f);
328             GXPosition3f32(x2, y2, 0);
329             GXTexCoord2f32(1.f, 1.f);
330             GXPosition3f32(x1, y2, 0);
331             GXTexCoord2f32(0.f, 1.f);
332             GXEnd();
333         }
334 
335         DEMODoneRender();
336     }
337 
338     MEMFreeToExpHeap( hExpHeap, jpeg_workarea );
339     MEMFreeToExpHeap( hExpHeap, jpeg_stream_data );
340 
341     OSHalt("finish.\n");
342 }
343 
344