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