This fifth Wii programming tutorial will cover how to display JPEG images. As usual, I’m assuming you’ve read all the other tutorials. You can grab the PDF of this tutorial here: codemii-tutorial-5
Firstly download this tutorial5-blank which will contain the required files to get us started. Extract this zip file in C:\devkitPro\examples\gamecube. Open up tutorial5.pnproj and then click on main.c to show the source code.
Included in the download are two files, one called picture.s and a JPEG picture. The picture.s file defines all our variables for the picture and the link to the picture itself. If you open the image file “about.jpg” you’ll see the image with a black background. It’s important to remember that JPEGs aren’t transparent like PNGs are.
The next step needed is to download this libogc_jpeg zip file which contains the required JPEG library. You’ll need to extract it to C:\devkitPro\devkitPPC\powerpc-gekko and let it overwrite any directories.
Now we need to modify our makefile to add in the JPEG library:
[sourcecode language=’c’]LIBS := -logc -lm -ljpeg[/sourcecode]
We can now focus on editing the main.c file. Firstly we’ll need to include the jpeg header file so we can access the jpeg functions.
[sourcecode language=’c’]#include
Two variables need to be defined are piclength and picdata which are both found in the picture.s file. We define these two variables as exern which tells the compiler that we have defined these two variables elsewhere (picture.s) and these variables will be able to be accessed globally.
[sourcecode language=’c’]extern char picdata[];
extern int piclength; [/sourcecode]
The next thing we add is a jpeg function which I have hacked together:
[sourcecode language=’c’]void display_jpeg(JPEGIMG jpeg, int x, int y) {
unsigned int *jpegout = (unsigned int *) jpeg.outbuffer;
int i,j;
int height = jpeg.height;
int width = jpeg.width/2;
for(i=0;i<=width;i++)
for(j=0;j<=height-2;j++)
xfb[(i+x)+320*(j+16+y)]=jpegout[i+width*j];
free(jpeg.outbuffer);
}[/sourcecode]
The above function takes a JPEGIMG structured variable and two integers which will be used to determine where on the screen we want our image to be displayed.
The first line in the function is related to how the jpeg library works. Later on you’ll see that we decompress the jpeg images and when doing so, the jpeg.outbuffer is where the image is stored.
The next few lines define some local variables for the height and width and then copy the jpeg image to out video frame buffer (the screen) to the co-ordinates that we have defined in as x and y. The last line in the function ensures that we clear the space in memory that we made a local copy of the jpeg image (unsigned int *jpegout = (unsigned int *) jpeg.outbuffer; )
We can now start adding jpeg functions the main() function. First things first we define the variable to use that will use the JPEGIMG data structure.
[sourcecode language='c']JPEGIMG about; [/sourcecode]
After that we assign memory to our “about” variable.
[sourcecode language='c']memset(&about, 0, sizeof(JPEGIMG)); [/sourcecode]
According to our picture.s file, it contains two variables; the picture data and the length of the picture. We define our “about” variable inbuffer and inbufferlength with both the global variables.
[sourcecode language='c']about.inbuffer = picdata;
about.inbufferlength = piclength; [/sourcecode]
We then need to decompress the jpeg, by passing the “about” variable.
[sourcecode language='c']JPEG_Decompress(&about); [/sourcecode]
Our last step is to run the display_jpeg function and pass our variable “about” and any x and y co-ordinates we want.
[sourcecode language='c']display_jpeg(about, 60, 100); [/sourcecode]
Our main function now looks like:
[sourcecode language='c']int main() {
JPEGIMG about;
memset(&about, 0, sizeof(JPEGIMG));
about.inbuffer = picdata;
about.inbufferlength = piclength;
JPEG_Decompress(&about);
Initialise();
display_jpeg(about, 60, 100);
return 0;
}[/sourcecode]
tutorial5-jpeg is what our source now looks like. Compile the source and run tutorial5.dol with gcube. You’ll see the image displayed on the screen. I won’t convert this to the Wii as there won’t be any difference between them.
can you explain this line?
int width = jpeg.width-(jpeg.width/2);
isn’t this the same as:
int width = jpeg.width/2;
and whether it is or is not the same, why divide by 2 at all?
Nice find, I’ve always had that in my previous code and didn’t see that 🙂
I’m not entirely sure why, but it has something to do with the way it writes to the video frame buffer (xfb). If you take out the divide by 2 part, then you will see double the image and it will be stretched.
i tried to make the pointer from tutorial4 with a jpeg instead of a small box.
it would always crash soon after starting, but not right away (like a second or so later). first i made a small area that it can only show in there:
if (ir0.x > 100 && ir0.x 100 && ir0.y < 200) {
display_jpeg(about, ir0.x, ir0.y);
}
but it would still crash after showing the jpeg for a bit (while not showing, it could run indefinitely).
someone told me to comment out this line:
free(jpeg.outbuffer);
and now it works.
did i just fix one problem by causing another? what is/was free(jpeg.outbuffer); for?
by any chance could you make a tutorial on how to write the Main.c and makefiles? we seem to be doing all this “add-on” codeing without knowing the very basics.
the box code didn’t post right, but the actual code is simple to figure out and works right
Yes images! I have been waiting for those…Can’t wait for what’s next ^_^
yossi: Making the cursor displayed as a image was going to be a part of the next tutorial.
About free(jpeg.outbuffer) it should just be used for cleaning the memory taken up by the local variable jpeg but to be honest I’ve always had problems with it myself as well. So you should be fine taking it out of your code.
Another thing I’ve found is that sometimes the code in the main() function has to be re-ordered so that the application doesn’t code dump.
Speggy: I wouldn’t know how to make a makefile from scratch. The blank main.c files that I always start off with is the minimal code that will do something on the Gamecube/Wii. You shouldn’t need to re-write the main.c file. Have a look at C:\devkitPro\examples\wii\template\source\template.c if you would like to know more about what each function does.
If you want to learn more about makefiles and general C coding, there should be plenty of online tutorials around.
Ok! I did everything, and find how to run the .dol on the Wii thru my network, but only this one, show me the image for a few seconds and then it return to loader, is that what supouse to do??
BTW thanks for this tutorials it’s been fun and I’m really understanding whats about!!
Yes, that’s what it’s supposed to do, just show one image.
If you add a while(1); then it will keep showing the picture until you turn off the Wii. The next tutorial will show you how to put an image instead of a box for the Wii IR cursor and will cover button pressing.
The call to free() is not correct. free() frees memory allocated with malloc() or calloc() or realloc(). There are other functions which document that they use one of the named functions, and therefore require a free() to their return values.
But you don’t use malloc(). So you mustn’t use free().
You don’t even allocate memory. You also don’t make a local copy of your picture. You copy the _pointer_ to the picture to a local variable, and use that one. But that’s completely unnecessary.
void display_jpeg(JPEGIMG jpeg, int x, int y) {
;
int i,j;
int height = jpeg.height;
int width = jpeg.width/2;
for(i=0;i<=width;i++)
for(j=0;j<=height-2;j++)
xfb[(i+x)+320*j+16+y)]=jpeg.outbuffer[i+width*j];
// free(jpeg.outbuffer); // This must be commented out. Use of free() is WRONG.
}
Sorry this is probably a stupid question but what is the asterisk before variable names for? as in *jpegout.
Thanks.
Great tutorials 🙂
The asterisk before variable names is called a pointer. It’s a way of saying point to the value of the variable instead of assigning additional memory to store the value of the variable. You can take a look at: http://www.cplusplus.com/doc/tutorial/pointers.html for more information.
In this case it’s a little different, but as mokrates has pointed out we are basically assigning a pointer variable to another pointer.
Although I will say that this is the only way I’ve gotten it to work. mokrates, I have tried changing it to jpeg.outbuffer[i+width*j] as you have written but the image isn’t displayed properly and is distorted.
Ahhh, ok, makes sense. Thanks 🙂
One last question, ive seen the libwiisprite library which has some cool features like png transparency, rotating, sizing, and collision detection. Only thing is that its made in C++. How do these languages relate? Is it possible to include this in a normal C application like we’ve been doing with the other libs?
Thanks 🙂
Im getting an interesting error while trying to compile this. I have conflicting unsigned 8bit variable names (u8) between jmorecfg.h and gctypes.h
Without having to go through either of these headers and recasting these variables with different names (or is the gctypes.h supposed to be using the already cast variable?) is there any solution? What am I overlooking and why cant I find it. O.o
[code]
In file included from /opt/devkitpro/libogc/include/jpeglib.h:26,
from /opt/devkitpro/libogc/include/jpeg/jpgogc.h:12,
from /home/user/main.c:14:
/opt/devkitpro/libogc/include/jmorecfg.h:227: error: conflicting types for ‘u8’
/opt/devkitpro/libogc/include/gctypes.h:22: error: previous declaration of ‘u8’ was here
/home/user/src/main.c: In function ‘display_jpeg’:
[/code]
Is your source code exactly as shown in the final zip file? Did you use the included jpeg library zip?
My jmorecfg.h is found in /jpeg and there is no u8 typedef in it. Try removing the file.
Can you provide the source code you are using on http://pastebin.com
This is an interesting article, your a very good writer,keep it up.
How I can load png images using this tecnique?
Thanks
Sorry for my earlier question, Im studing display_png that you posted in the tutorial 6.
You wrote an excelent tutotial ans al the files that are needed are included.
my question now is : how can I use my own jpeg picture or how do I make up the picture.s file ?
The format of picture.s is:
.globl piclength1
.globl picdata1
piclength1: .long picdataend1 – picdata1
picdata1:
.incbin “../include/no.jpg”
picdataend1:
What you need to do is have a different name for piclength, picdata, picdataend1 and the .incbin shows which file to include. So if you wanted to add another picture, you just copy the above code, change the 1’s to 2’s and change the location of the file. After that you need to edit your main.c.
In the main.c file for the above you would need:
extern char picdata1[];
extern int piclength1;
After that you need to look at the JPEGIMG no; part in this tutorial and copy those things until JPEG_Decompress(&no);
Why do you use 320 instead 640 on this line:
xfb[(i+x)+320*(j+16+y)]=jpegout[i+width*j];
?
Ins’t the resolution 640×480?
Yes, the resolution is 640 x 480. If you actually try 640 it stretches the image. I’m not entirely sure about the line.
xfb[(i+x)+320*(j+16+y)]=jpegout[i+width*j];
The +16 is not needed here, it just puts the image 16 pixels lower than specified…
When I copy the void display_jpeg function into my code (after my main), I get a compiler error “invalid use of void expression”. The tutorial went fine. I could add that function and it worked, but not in my program. Any suggestion?
You’ll probably have xfb already defined as follows
static void *xfb = NULL;
you’ll need to change it to:
static u32 *xfb;
JPEG doesn’t like me 🙁
Almost done porting my game from SDL (since SDL was refusing to work).
After this its getting a font to work 😛
Now I am down to my final error:
undefined reference to `JPEG_Decompress(JPEGIMG*)’
The lib includes are:
LIBS := -lwiiuse -lbte -logc -lm -ljpeg
The header and lib file of this tutorial were extracted in the correct dierectory’s
Just in case, lib file is here:
C:\devkitPro\devkitPPC\powerpc-gekko\lib\libjpeg.a
Using programmer’s notepad.
Complete make log:
> “make”
Visuals.cpp
c:/wii/mygames/xmas/source/Visuals.cpp:15: warning: ‘VISUALS_DEFAULT_FLAGS’ defined but not used
linking … chunkmunch.elf
Visuals.o: In function `Visuals’:
c:/wii/mygames/xmas/source/Visuals.cpp:66: undefined reference to `JPEG_Decompress(JPEGIMG*)’
collect2: ld returned 1 exit status
make[1]: *** [/c/wii/mygames/xmas/xmas.elf] Error 1
“make”: *** [build] Error 2
just reinstalled devkitpro (v16) and added the files again
same error still.
undefined reference to `JPEG_Decompress(JPEGIMG*)’
Is there a lib file missing from the http://www.codemii.com/wp-content/uploads/2008/09/libogc_jpeg.zip file?
The libogc_jpeg zip should have everything you need. Could you try compiling http://www.codemii.com/wp-content/uploads/2008/09/tutorial5_jpeg.zip and seeing if that works?
Thanks for the quick reply, I should have tried the tutorial code 😉
The tutorial compiles.
I can use my makefile on the tutorail (compiles).
I can use my project file on the tutorial (compiles).
As soon as I remove: JPEG_Decompress(&about);
Out of my main.cpp, the code compiles…
Might it be because I’m using CPP?
That solved it! 😀
Adjust the header to solve the problem for idiots like me 😉
I should have realised this way earlier
#if defined(__cplusplus)
extern “C”
{
#endif
int JPEG_Decompress(JPEGIMG * jpgimg);
#if defined(__cplusplus)
}
#endif
i did it, and it works, But i am trying hard to understand this one, the other ones were rather easy. But this one is confusing Why do you need the Void display_jpeg?
Is there an Easier way to load pictures? How about PNG pictures,do you also need the same style of code?
If you have GIMP (or some other uber image editing program), you can save the picture as raw RGB, then convert it to Y1CbY2Cr and just copy it, byte for byte, into the framebuffer. This obviously takes up more space (a 640×480 image is 600 kb). Rule of thumb:
If you’re image is built into your program (eg. Background), do it this way. (You don’t have to allocate memory, and it makes life a whole lot easier).
If you’re making some slideshow program (or other program that loads images dynamically), use JPEG.
i extracted the files here. and now my Wiiuse wont work gives me the Error
linking … tutorial5.elf
c:/devkitpro/devkitppc/bin/../lib/gcc/powerpc-gekko/4.2.4/../../../../powerpc-gekko/bin/ld.exe: cannot find -lwiiuse
collect2: ld returned 1 exit status
make[1]: *** [/c/devkitpro/examples/gamecube/tutorial5/tutorial5.elf] Error 1
“make”: *** [build] Error 2
i went on tutorial 3 and got the wiiuse file (from someone elses comment of what i thought was the same problem)
but that didn’t do anything
note, this is only for Tutorial 5 (i havn’t done 6 or any others yet)
asfar as i know…
when i compile tutorial 4 or 3 they work fine.
Are you using the makefile included in the end zip? The makefile included is for the gamecube version and doesn’t have any -lwiiuse in it at all.
but when i loaded it onto my wii it said “not a valid wii file”…
Yes, the zip file is just the gamecube version of it. If tutorial 3 or 4 work which use wiiuse then it has to be your code. Are you including wiiuse/wpad.h ?
Can you copy the tutorial 4 makefile and use it with tutorial 5?
Fail.
C:\devkitPro\devkitPPC\wii_rules:1: error: expected ‘)’ before ‘(‘ token
In file included from c:/projects/wii/go/go1/tutorial5/source/main.c:8:
C:\devkitPro\devkitPPC\wii_rules:2:9: warning: missing terminating ” character
C:\devkitPro\devkitPPC\wii_rules:2: error: missing terminating ” character
C:\devkitPro\devkitPPC\wii_rules:12:2: error: invalid preprocessing directive #–
C:\devkitPro\devkitPPC\wii_rules:14: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:14: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:15: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:15: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:17:2: error: invalid preprocessing directive #–
C:\devkitPro\devkitPPC\wii_rules:19: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:20: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:20: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:22:2: error: invalid preprocessing directive #–
C:\devkitPro\devkitPPC\wii_rules:24: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:24: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:25: error: stray ‘@’ in program
C:\devkitPro\devkitPPC\wii_rules:25: error: stray ‘@’ in program
c:/projects/wii/go/go1/tutorial5/source/main.c: In function ‘main’:
c:/projects/wii/go/go1/tutorial5/source/main.c:58: error: ‘picdata’ undeclared (first use in this function)
c:/projects/wii/go/go1/tutorial5/source/main.c:58: error: (Each undeclared identifier is reported only once
c:/projects/wii/go/go1/tutorial5/source/main.c:58: error: for each function it appears in.)
make[1]: *** [main.o] Error 1
“make”: *** [build] Error 2
WiiRules is broken. But only for this file. How convenient.
How do I break whatever ties it to GCN?
In case anyone is still interested, I did some investigating and found out why the jpeg.width must be divided by 2. Each int in the framebuffer array represents two pixels (in Y1CbY2Cr format), therefore where there is only 320 ints, there are 640 pixels. Height is not affected by this.
Just a small remark:
in C
int a;
…
a – (a/2) != a/2
is sometimes true, hence replacing the code like yossi suggested will not give the same semantics. (Hint: what happens with uneven numbers?)
@ durdadan: I got the same error and I used the tutorial5_jpeg. Whats different is that it cant find ljpeg. Whats up with that?
Did you download http://www.codemii.com/wp-content/uploads/2008/09/libogc_jpeg.zip ?
Yeah, I didnt copy the folders cuz that would have overwritten the other libs and include files, right?
In that zip it only have the JPEG required files. You can just extract them to the C:\devkitPro\devkitPPC\powerpc-gekko and let it overwrite any folders and you should be fine as you wouldn’t previously have this library.
I meant wouldnt it overwrite my other files that are already there? What I did was unzip in the include folder and lib folder that were both there already.
It shouldn’t, but you can just extract the zip elsewhere and copy over the files manually to make sure none are overwritten.
Well, that worked, but now I have a ‘u8’ error. I used the finished example you gave, but when I compiled It said there was a previous declaration of u8.
Could you paste the error here?
In file included from c:\devkitpro\devkitppc\bin\../lib/gcc/powerpc-gekko/4.2.4/../../../../powerpc-gekko/include/jpeglib.h:26,
from c:\devkitpro\devkitppc\bin\../lib/gcc/powerpc-gekko/4.2.4/../../../../powerpc-gekko/include/jpeg/jpgogc.h:12,
from c:/devkitPro/examples/gamecube/tutorial5/tutorial5/source/main.c:7:
c:\devkitpro\devkitppc\bin\../lib/gcc/powerpc-gekko/4.2.4/../../../../powerpc-gekko/include/jmorecfg.h:227: error: conflicting types for ‘u8’
c:/devkitPro/libogc/include/gctypes.h:15: error: previous declaration of ‘u8’ was here
make[1]: *** [main.o] Error 1
“make”: *** [build] Error 2
Here.
If it was my code Id say I made a mistake. But its your example so Im not sure whats wrong.
Can you check your jmorecfg.h for the phrase “u8”?
Very strange as I tried this on DevKitPro r16 and it worked with no issues.
Wait, where would I find that file?
It should be in c:\devkitpro\devkitppc\powerpc-gekko\include\jpeg, but from your above error it seems like it’s in c:\devkitpro\devkitppc\powerpc-gekko\include. Can you try moving it to the jpeg folder?
YES! It finally compiled right! Thanx for your help, I usually dont have this much trouble with stuff like this. Thanx again, and now I can move on! =D
how come all of your tutorials are for gamecube?
Not all of them are, but I did the first few for gamecube (some had the Wii equivalents) because you could actually run them in the gcube emulator that is included in DevKitPro. Another reason being using gcube, it’s easy to experiment and learn quickly on how things work.
im getting all kinds of errors.
c:/devkitpro/devkitppc/bin/../lib/gcc/powerpc-gekko/4.2.4/../../../../powerpc-gekko/bin/ld.exe: cannot find -ljpeg
collect2: ld returned 1 exit status
make[1]: *** [/c/projects/wii/tutorial5/tutorial5.elf] Error 1
“make”: *** [build] Error 2
fail??
Did you download the libogc_jpeg zip file and extract to C:\devkitPro\devkitPPC\powerpc-gekko ?
I’m trying to write a simple display image for the wii…but i’ve this problem:
this is the source:
#include
#include
#include
#include
#include
extern char picdata[];
extern int piclength;
static void *xfb = NULL;
static GXRModeObj *rmode = NULL;
void display_jpeg(JPEGIMG jpeg, int x, int y) {
unsigned int *jpegout = (unsigned int *) jpeg.outbuffer;
int i,j;
int height = jpeg.height;
int width = jpeg.width/2;
for(i=0;i<=width;i++) {
for(j=0;jfbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
// The console understands VT terminal escape codes
// This positions the cursor on row 2, column 0
// we can use variables for this with format codes too
// e.g. printf (“\x1b[%d;%dH”, row, column );
printf(“\x1b[2;0H”);
printf(“Hello World!”);
while(1) {
// Call WPAD_ScanPads each loop, this reads the latest controller states
WPAD_ScanPads();
// WPAD_ButtonsDown tells us which buttons were pressed in this loop
// this is a “one shot” state which will not fire again until the button has been released
u32 pressed = WPAD_ButtonsDown(0);
// We return to the launcher application via exit
if ( pressed & WPAD_BUTTON_HOME ) exit(0);
// Wait for the next frame
VIDEO_WaitVSync();
}
return 0;
}
When doing “make” i get this:
> “make”
wiiworld.c
c:/wiiworld/source/wiiworld.c: In function ‘display_jpeg’:
c:/wiiworld/source/wiiworld.c:21: warning: dereferencing ‘void *’ pointer
c:/wiiworld/source/wiiworld.c:21: error: invalid use of void expression
make[1]: *** [wiiworld.o] Error 1
“make”: *** [build] Error 2
> Process Exit Code: 2
> Time Taken: 00:00
Any suggestion?
don’t know why…these are the first lines of the source: (i hope you can see the include’s now: (anyway jpeg/jpgogc.h is included)
#include
#include
#include
#include
#include
Sorry, this blog software has issues displaying code.
Where is your main function?
You define the display_jpeg function but don’t have the ending bracket or you don’t have the free(jpeg.outbuffer) part either.
Can you paste your complete code to http://www.pastie.org?
So if we were to put multiple images would it go something like this:
extern char picdata1[];
extern int piclength1;
extern char picdata2[];
extern int piclength2;
//display functions, other functions
int main() {
JPEGIMG img1;
JPEGIMG img2;
memset(&img1, 0, sizeof(JPEGIMG));
memset(&img2, 0, sizeof(JPEGIMG));
about.inbuffer = picdata1;
about.inbufferlength = piclength1;
about.inbuffer = picdata2;
about.inbufferlength = piclength2;
JPEG_Decompress(&img1);
JPEG_Decompress(&img2);
//So at this point they would be ready to display anywhere? Are these lines of code essentially the same as Initialize() except for jpegs, so i’m guessing it would be ok to put these into a function.
}
Also, a second question: How would we go about making these in C++? I’ve seen little difference between the two, but i’d still like to know how. The only C i know is from learning C++, and this tutorial, and even at that, i’m an inexperienced programmer. I have never gotten past console applications >_>
Oh sorry, i forgot to ask about the picture.s file:
==========================
.rodata
.balign 32
.globl piclength1
.globl picdata1
piclength1: .long picdataend1 – picdata1
picdata1:
.incbin “../include/about.jpg”
picdataend1:
.rodata
.balign 32
.globl piclength2
.globl picdata2
piclength2: .long picdataend2 – picdata2
picdata2:
.incbin “../include/other.jpg”
picdataend2:
================================
Would that be right?
Yep that’s right.
At that point, yep they are ready to be displayed anywhere. Yes, fine to put these in a function (you might need to put JPEGIMG img1 outside of the function).
About making it into C++, I’m not really sure however I don’t think much needs to be change if anything.
OK, thanks for the swift reply!
You won’t read this
😉
Hi, i am a noob to wii homebrew development. Can you please share how to make the makefile
Hi there, great tutorial. It’s been over 10 years since this was posted, so I’m not expecting a response, but is there anywhere you can direct me for displaying PNGs? Without transparency my program looks really sloppy, since without transparency you can see borders everywhere. I tried using PNGU but I wasn’t able to get it to work, and there’s no documentation on it.