Gigi Labs

Please follow Gigi Labs for the latest articles.
Showing posts with label visual studio 2010. Show all posts
Showing posts with label visual studio 2010. Show all posts

Monday, November 25, 2013

SDL2: Loading Images with SDL_image

Welcome!

[Update 2015-11-14: This article is out of date. Check out the latestversion at Gigi Labs.]

In the previous article, "SDL2: Displaying an Image in the Window", we saw how we could load bitmaps using the SDL_LoadBMP() function. Unfortunately, working with bitmaps is very limiting, and the core SDL2 library does not provide the means to work with other image formats. However, such functionality is provided by an extension library called SDL_image. In this article, we will learn how to set up SDL_image and also how to use it to load other image formats.

Setting up SDL_image is not very different from setting up SDL 2.0 itself. You need to go to the SDL_image homepage and download the development libraries and runtime binaries:


Let's concentrate on those development libraries for the moment. Once you extract the contents of the zip file, you'll be able to find an include folder and a lib folder among other stuff. The include folder contains a single header file, SDL_image.h. This needs to go into your C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\SDL2 folder (this is for Visual Studio 2010; you may need to change the v7.0A part depending on the version you're using), or wherever your other SDL2 header files are located, and drop the SDL_image.h file there.

As for the lib folder, whatever is in the x86 subfolder goes into the C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib folder, and whatever is in the x64 subfolder goes into C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\x64.

With that done, let's set up a new project using Visual Studio 2010. Create an Empty Project from the Visual C++ category. Right click on the project and select Properties. In Configuration Properties -> Linker -> System, change the SubSystem to Windows (/SUBSYSTEM:WINDOWS). Then go to Input (also under Linker) and replace the Additional Dependencies with the following:

SDL2.lib;SDL2main.lib;SDL2_image.lib

You'll notice this is a little different from "SDL2: Setting up SDL2 in Visual Studio 2010" in that we've added the SDL2_image.lib. Since this is a new library, we need to link it into our program to use its functionality.

Now let's try some code. Add a file called main.cpp, and let's start off with the following code (it's the same as that used in "SDL2: Displaying an Image in the Window", without the error checking to keep it concise, and also filling the window):
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int main(int argc, char ** argv)
{
    bool quit = false;
    SDL_Event event;

    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window * window = SDL_CreateWindow("SDL2 Displaying Image",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Surface * image = SDL_LoadBMP("image.bmp");
    SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
        image);

    while (!quit)
    {
       SDL_WaitEvent(&event);

       switch(event.type)
       {
       case SDL_QUIT:
           quit = true;
           break;
       }

       SDL_RenderCopy(renderer, texture, NULL, NULL);
       SDL_RenderPresent(renderer);
    }

    SDL_DestroyTexture(texture);
    SDL_FreeSurface(image);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

Now, we're going to load this nice photo (.jpg format) taken in Gardaland in 2006:


Doing this is quite simple. First, we initialise SDL_image by calling IMG_Init() right after the call to SDL_Init():
    IMG_Init(IMG_INIT_JPG);
...and before the call to SDL_Quit(), we shut down SDL_Image using IMG_Quit():

    IMG_Quit();
All we have left to do now is replace the line calling SDL_LoadBMP() with one that uses IMG_Load() instead:
    SDL_Surface * image = IMG_Load("PICT3159.JPG");
You should now be able to build this program (Ctrl+Shift+B). Before you run it, though, make sure that SDL2.dll is in the same folder as your executable. You'll also need to toss in all the DLLs from the runtime binaries package (most likely the x86 one is what you'll be using by default) - that includes SDL2_image.dll along with format-specific files such as libjpeg-9.dll, libpng16-16.dll, etc. If you're going to run from Visual Studio, make sure the image is in the same folder as your main.cpp file; otherwise if you're running straight from the executable, the image should be in the same folder with it.

And voilĂ :


Isn't that sweet? The SDL_image library allows you to load a large variety of image formats, by just replacing SDL_LoadBMP() with IMG_Load(). You'll need to initialise and cleanup the library (although it seems to work even without this) and remember to link the library and include the appropriate header file. But as you can see, it's pretty straightforward.

Sunday, November 17, 2013

SDL2: Displaying an Image in the Window

Hello! :)

[Update 2015-11-14: This article is out of date. Check out the latestversion at Gigi Labs.]

In this article we're going to learn how to load a bitmap image from disk and display it in an SDL2 window. In order to follow along, you'll need to set up a project to work with SDL (see "SDL2: Setting up SDL2 in Visual Studio 2010"), and start off with the basic empty window code from SDL2: Empty Window, which is this:

    #include <SDL2/SDL.h>        
            
    int main(int argc, char ** argv)        
    {        
        bool quit = false;        
        SDL_Event event;        
            
        SDL_Init(SDL_INIT_VIDEO);        
            
        SDL_Window * screen = SDL_CreateWindow("My SDL Empty Window",
            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480,
            0);        
            
        while (!quit)        
        {        
           SDL_WaitEvent(&event);        
            
           switch(event.type)        
           {        
           case SDL_QUIT:        
               quit = true;        
               break;        
           }        
        }        
            
        SDL_Quit();        
            
        return 0;        
    }

Build the application. Remember to place SDL2.dll into your bin\Debug folder. The empty window should appear if you run the application, and you should be able to close it by clicking on the "X" at the top-right corner.

Let's first change the window declaration a little bit (I changed the name of the variable and the window title):

    SDL_Window * window = SDL_CreateWindow("SDL2 Displaying Image",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);

After that, let's create an SDL_Renderer:

    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);

We use SDL_CreateRenderer() to get an instance of SDL_Renderer. This renderer represents the output device (usually your graphics card) to which your code will be drawing. In fact it's the final destination of our image, because we'll be following the steps below:


SDL_CreateRenderer() takes three parameters. The first is the window where we are drawing. The second allows us to select different rendering drivers; in our case we don't care, and we can set it to -1 and get the default one. The last parameter allows us to set SDL_RendererFlags to control how the rendering occurs. We can set it to zero to default to hardware rendering. If any of this sounds confusing, don't worry about it and just use SDL_CreateRender() as it is here.

We can now load the image from disk using the SDL_LoadBMP() function, which takes a path to a bitmap and loads it into an SDL_Surface:

    SDL_Surface * image = SDL_LoadBMP("image.bmp");

I'm using the following photo of the Grand Harbour in Valletta, Malta, which I took back in 2005, and which has a width of 320 pixels and a height of 240 pixels:


Place the image in your bin\Debug folder, where your executable is located.

Next, we need to create a texture.

    SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
        image);

A texture is memory close to the graphics card (see image below), and we use SDL_CreateTextureFromSurface() to directly map our surface (which contains the image we loaded) to a texture.


Now that we have a texture, let's display it in the window. At the end of the while loop, just after the switch statement, add the following:

        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);

We use SDL_RenderCopy() to copy the texture to the output device. There are also a couple of other parameters that we're setting to NULL - more on these in a minute. Finally, SDL_RenderPresent() is what commits the texture to the video memory, displaying the image.

Before we run the program, we must always remember to clean up every resource that we initialise. In our case, that means adding the following just before the call to SDL_Quit():

    SDL_DestroyTexture(texture);  
    SDL_FreeSurface(image);  
    SDL_DestroyRenderer(renderer);  
    SDL_DestroyWindow(window);

If you now run the program from within Visual Studio, surprisingly enough, you get a blank window:


...whereas if you run the program directly from the executable in your solution's bin\Debug folder (where image.bmp is also located), it works:


We'd know more about what's going on if we had proper error handling in place. With every call to the SDL2 API, we should be checking the return values, and displaying an error if any of them fail. SDL_ShowSimpleMessageBox() is great for displaying simple error messages, while SDL_GetError() gives us the actual error text of the last thing that failed. Let's refactor our initialisation code to check for errors and display them:

    SDL_Window * window = SDL_CreateWindow("SDL2 Displaying Image",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
    if (window == NULL)
        SDL_ShowSimpleMessageBox(0, "Window init error", SDL_GetError(),
            window);
    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
    if (renderer == NULL)
        SDL_ShowSimpleMessageBox(0, "Renderer init error",
            SDL_GetError(), window);
    SDL_Surface * image = SDL_LoadBMP("image.bmp");
    if (image == NULL)
        SDL_ShowSimpleMessageBox(0, "Image init error", SDL_GetError(),
            window);
    SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
        image);
    if (texture == NULL)
        SDL_ShowSimpleMessageBox(0, "Texture init error",
            SDL_GetError(), window);

When we run this code, the first error we get is the following:


That's it - the program can't find the image. Remember how it worked when running from the executable, but not from Visual Studio? That's because Visual Studio starts at a different directory. As a quick workaround, just copy image.bmp into your source folder (where main.cpp is located). Hit F5, and it now works:


Fantastic! The image is right there in the window! But... can you see what happened? The image, which has dimensions 320x240, has been stretched to fill the window, which has dimensions 640x480. That's sometimes convenient, because we get scaling for free. However, it makes photos look messy. Let's change our call to SDL_RenderCopy() to fix this:

        SDL_Rect dstrect = { 5, 5, 320, 240 };
        SDL_RenderCopy(renderer, texture, NULL, &dstrect);

Remember those two parameters at the end of SDL_RenderCopy() that we were setting to NULL? If you look at the documentation for SDL_RenderCopy(), you'll see that the last one defines a destination region (which part of the texture will the image be copied to). If it's set to NULL, then the image is stretched to fill the texture - which is what happened above.

By setting dstrect (the last parameter), we can render to only a portion of the window. We set it to an SDL_Rect, with x and y set to 5, and width and height corresponding to the dimensions of the image. When we run the program, we get this:


Excellent! :) In this article we looked at how to create renderers, surfaces and textures. We used these to load bitmaps and display them on the screen. A glimpse into error handling allowed us to troubleshoot issues with loading the image from Visual Studio. Finally, we saw the difference between copying the image to a region of the window, and making it fill the entire window.

I hope you enjoyed this. Come back for more! :)

Monday, October 28, 2013

Unit Tests, The Visual Studio Way

Hi! :)

Last month I wrote a couple of articles on unit testing: "C#: Unit Testing with SharpDevelop and NUnit" and "C#: Mocking and Dependency Injection for Unit Testing a File Sorting Program". These articles gave an introduction to unit testing using SharpDevelop and NUnit. If you're a Visual Studio user, however, you might prefer to use Visual Studio's own unit testing framework, known as MSTest. Visual Studio makes it really easy to run and debug tests directly from within the IDE, however writing the tests is slightly different.

In order to follow along, you'll need a version of Visual Studio from 2010 onwards, and one that includes unit testing (that doesn't include the Express editions, sorry). To demonstrate how to to write unit tests in Visual Studio, we're going to write a little program that tells us whether a year is a leap year or not.

First, let's create a new Console Application in Visual Studio 2010. You can do this by clicking on the "New Project..." link on the Start Page, or through the File Menu.


Above your Main() method, add a public static method called IsLeapYear():

        public static bool IsLeapYear(int year)
        {
            return false; // TODO
        }

We can now implement the logic that will decide whether the year is a leap year or not. We can use the leap year algorithm on Wikipedia. The leap year calculation, although not quite complex, might seem oddly contrived if you're looking at it for the first time. If you're curious about why there are so many conditions, you might want to check out this question on StackOverflow.

So the method ends up looking like this:

        public static bool IsLeapYear(int year)
        {
            if (year % 400 == 0)
                return true;
            else if (year % 100 == 0)
                return false;
            else if (year % 4 == 0)
                return true;
            else
                return false;
        }

The % is called a modulus operator - it performs a division but returns the remainder, not the result. So you know that year is divisible by 4 because the remainder is zero.

Right, now let's create some unit tests for our shiny new method. Before you run off and start belching out code, Visual Studio has this really neat feature where you can just right click somewhere empty and select "Create Unit Tests...":



In the screen that pops up, you can select the methods and properties for which you want to create unit tests. In our case it's just one method, but this is really useful if you have lots of code and want to generate a bunch of skeleton unit tests quickly.


In the "Output project" option at the bottom, you can choose whether to create a new test project or use an existing one. Again, in our case we can just create a new one, but if you already have a test project and want to add to it, you can just select it from the drop-down list. Anyway, hit "OK", name your unit tests project, and hit "Create". By convention, tests projects are usually named as [ProjectName].Tests .


Now, when you're done, you might get this message about InternalsVisibleTo:


See, this is because our Program class is not public, and that makes it internal by default. This means that the test project can't see it. Visual Studio allows projects to access non-public classes anyway by using this thing called InternalsVisibleTo, but in most cases I wouldn't recommend it. Just hit "No".

So now Visual Studio created a new project and some code for us:


In the test project, you'll notice that there's a reference to our LeapYearVs2010 project (because the tests need to use our actual code), and there's also a reference to this Microsoft.VisualStudio.QualityTools.UnitTestFramework thing (try fitting that in a business card) - that's needed for unit tests projects.

You'll also notice a bunch of code was generated. It's mostly full of crap, so let's just take out the bull and leave the beef:

using LeapYearVs2010;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace LeapYearVs2010.Tests
{
    [TestClass()]
    public class ProgramTest
    {
        [TestMethod()]
        [DeploymentItem("LeapYearVs2010.exe")]
        public void IsLeapYearTest()
        {
            int year = 0; // TODO: Initialize to an appropriate value
            bool expected = false; // TODO: Initialize to an appropriate value
            bool actual;
            actual = Program_Accessor.IsLeapYear(year);
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }
    }
}

So, our usings include our LeapYearVs2010 project, and also a namespace for MSTest unit testing. Other than that, it's pretty straightforward: you have a test class (aptly marked with the [TestClass()] attribute, and it contains one or more unit tests (marked with the [TestMethod()] attribute). I know we haven't quite talked about attributes so far, but just stick them in the right places and don't worry about them.

Before we can write any proper unit test code, we'll need to make our Program class (in the LeapYearVs2010 project) public:

    public class Program

We can now write our first unit test. At times you might find the autogenerated skeleton code for unit tests useful, but in our case you can just throw it out and replace it with this:

        [TestMethod()]
        public void IsLeapYearTest()
        {
            int year = 2001;
            bool expected = false;
            bool actual = Program.IsLeapYear(year);
            Assert.AreEqual(expected, actual, "2001 shouldn't be a leap year!");
        }


You can now run the unit tests via the Test menu, -> Run -> All Tests in Solution, or else by right clicking on a TestClass or TestMethod and selecting "Run Tests". This right click option is context sensitive, so if you Run Tests on a TestMethod it will run that unit test; if you Run Tests on a TestClass it will run all unit tests for that class.

Right, now at this point, if you also have Visual Studio 2012 installed, you might run into this bug where the tests will just kinda get stuck, like this:


Apparently this is a known issue and you'll need to install Service Pack 1 for Visual Studio 2010 to get things working. When they do, you'll see a nice green tick mark next to your test:


Let us now add another test:

        [TestMethod()]
        public void IsLeapYearTest2()
        {
            int year = 1900;
            bool expected = true;
            bool actual = Program.IsLeapYear(year);
            Assert.AreEqual(expected, actual);
        }

Run it as before, and...


Whoops! Our second test failed. You can right click the test in the Test Results window and select "View Test Results Details" to obtain additional information including a stack trace (see screenshot above). If you need to, you can put a breakpoint in your test and then from the Test menu go to Debug -> Tests in Current Context while your cursor is in the unit test you want to debug. You can then debug the test as you would with normal code.

In our case, it's pretty clear that 1900 can't be a leap year because it's divisible by 100 but not by 400. So we need only update the expected value as follows:

            bool expected = false;

Finally, let's take a look at how to create unit tests in Visual Studio 2012 and 2013. I'm going to create a new Console Application in this dark-themed VS2013 which looks like it came out of a chimney:


I'm going to set up Program just as I did in VS2010: make the class public, and add the method as before:

        public static bool IsLeapYear(int year)
        {
            if (year % 400 == 0)
                return true;
            else if (year % 100 == 0)
                return false;
            else if (year % 4 == 0)
                return true;
            else
                return false;
        }

Now, let's create the unit tests. Right click in some empty space and...


Uhhhh... crap. Apparently the "Create Unit Tests..." option was removed in Visual Studio 2012, much to people's frustration. Fortunately, there are workarounds that can bring it back. If you don't want to do those, however, you're just going to have to create the test project and unit tests manually. To do this, right click on the solution, then Add -> New Project..., and from the Test category on the left, select "Unit Test Project". Give it a name and hit "OK".


This generates empty test code, and you can take off writing your unit tests from here. With VS2012, it's the same procedure.


Wow, this was long. Well, I hope it helped you learn about some of the unit testing tools that Visual Studio has to offer. It's very convenient because you can run and debug tests directly from within Visual Studio, and in Visual Studio 2010 there is the "Create Unit Tests" option which can be used to quickly generate skeleton code for unit tests of existing code. Sadly, this option is no longer there by default as from Visual Studio 2012, but there are ways of getting it back.

Check back for more programming goodness at Programmer's Ranch! :)