Menampilkan dan Menyimpan Gambar Bitmap dengan SDL

Untuk membuat game, kita perlu menampilkan gambar. Dalam SDL, kita bisa menampilkan gambar dengan menggunakan SDL_LoadBMP untuk memuat gambar yang akan kita gunakan dan menyimpannya dalam variabel dengan tipe data SDL_Surface*. Function SDL_LoadBMP hanya bisa menggunakan file bitmap, dan bukan digunakan untuk memuat format gambar lainnya. Kalian akan perlu library tambahan kalau ingin menampilkan format gambar lain. Tapi, sementara ini, itu sudah cukup karena tujuan kita hanya belajar menampilkan gambar dengan SDL.

Sebelum menjalankan program, gambar yang akan dimuat harus diletakkan di folder project atau programnya, sesuai dengan folder atau directory yang aktif.
SDL_LoadBMP hanya perlu digunakan sebanyak sekali. Setelah gambar berhasil dimuat, kita bisa menampilkan gambar tersebut berkali-kali dengan SDL_BlitSurface. Function SDL_BlitSurface, menggunakan nilai kembalian dari SDL_LoadBMP yang sudah disimpan dalam variabel. Di akhir program, kita perlu menggunakan SDL_FreeSurface untuk mengosongkan memori dari variabel yang berisi gambar
Untuk program yang akan kita buat kali ini, saya menggunakan file dengan nama "Codelogi.bmp" dengan gambar seperti di atas. Kalian bisa mengganti gambarnya asalkan nama filenya sesuai dengan parameter function yang ada dalam kode program. Contoh kode program yang bisa kita gunakan untuk menampilkan file bitmap bisa kalian lihat di bawah ini.
#include <SDL2/SDL.h>

int main( int argc, char* args[] ){
    SDL_Window* window = NULL;
    SDL_Surface* screenSurface = NULL;

    if( SDL_Init( SDL_INIT_VIDEO ) < 0 ){
        printf( "Error: %s\n", SDL_GetError() );
    }else{
        window = SDL_CreateWindow( "SDLku", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN );
        if( window == NULL ){
            printf( "Error : %s", SDL_GetError() );
        }else{
            screenSurface = SDL_GetWindowSurface( window );

            SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0x00) );
            SDL_Surface *bmp=SDL_LoadBMP("Codelogi.bmp");
                        
            SDL_BlitSurface(bmp, 0, screenSurface, 0);
            SDL_UpdateWindowSurface( window );
            SDL_FreeSurface(bmp);
            SDL_Delay( 2000 );
     }
 }

 SDL_DestroyWindow( window );
 SDL_Quit();

 return 0;
}

Kode program di atas menampilkan gambar di sisi kiri atas, karena parameter ke-2 dan ke-4 function SDL_BlitSurface menggunakan 0 / NULL. 

Mengatur Posisi Gambar

Contoh kode program sebelumnya tidak menyertakan penempatan posisi gambar di window. Jika kalian ingin menentukan posisi gambarnya, parameter ke-4 dari function SDL_BlitSurface perlu menggunakan variabel dengan tipe data SDL_Rect seperti kode program di bawah ini.

#include <SDL2/SDL.h>

int main( int argc, char* args[] ){
    SDL_Window* window = NULL;
    SDL_Surface* screenSurface = NULL;
    SDL_Rect rct={0, 0, 0, 0};

    if( SDL_Init( SDL_INIT_VIDEO ) < 0 ){
        printf( "Error: %s\n", SDL_GetError() );
    }else{
        window = SDL_CreateWindow( "SDLku", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN );
        if( window == NULL ){
            printf( "Error : %s", SDL_GetError() );
        }else{
            screenSurface = SDL_GetWindowSurface( window );

            SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0x00) );
            SDL_Surface *bmp=SDL_LoadBMP("Codelogi.bmp");
        
            //Atur posisinya
            rct.x=40;
            rct.y=40;
                        
            SDL_BlitSurface(bmp, 0, screenSurface, &rct);
            SDL_UpdateWindowSurface( window );
            SDL_FreeSurface(bmp);
            SDL_Delay( 2000 );
         }
     }

     SDL_DestroyWindow( window );
     SDL_Quit();

     return 0;
} 

Contoh di atas meletakkan gambar di posisi x dan y dengan nilai 40. Ukuran gambar bisa kalian dapatkan dari variabel bertipe SDL_Surface* yang menyimpan gambar setelah SDL_LoadBMP digunakan. Walaupun begitu, lebar dan tinggi gambar tidak bisa kita ubah saat kita menggunakan SDL_Blit Surface. Ada function lain yang sejenis dan bisa digunakan untuk mengubah ukuran gambar yang mungkin akan saya bahas lain kali.

Btw, mungkin ada yang bertanya, "Apa fungsi parameter ke-2 dari function SDL_BlitSurface?". Untuk sementara ini saya tidak akan menjelaskannya supaya tulisan ini tidak terlalu panjang. Saya akan membahasnya lain kali.

Menyimpan Gambar Bitmap

Selain menampilkan langsung gambar ke permukaan window, kita juga bisa menyimpan gambar ke variabel Bertipe SDL_Surface. Untuk lebih sederhananya, variabel dengan tipe data tersebut bisa kita sebut surface. Surface pada SDL seperti layer pada program pengolah foto. Kita bisa mengubah isi dari surface sebelum menampilkannya ke permukaan window. Kalau kita tidak mau menampilkannya dan hanya mengubahnya, kita bisa juga melakukannya.

Selain bisa diubah isinya, SDL_Surface ke file Bitmap juga bisa disimpan dengan function SDL_SaveBMP. Parameter dari function tersebut cuma dua. Parameter pertamanya adalah surface yang mau disimpan, dan yang kedua adalah nama filenya. Setelah disimpan ke dalam file, kita bisa menemukan filenya di tempat yang sama dengan program atau direktori yang sedang aktif jika kita tidak menentukan nama foldernya.

Sekarang kita akan mencoba membuat program yang menyimpan surface dari permukaan window setelah window diberi gambar. Kode programnya bisa kalian lihat di bawah ini.
#include <SDL2/SDL.h>

int main( int argc, char* args[] ){
 SDL_Window* window = NULL;
 SDL_Rect rct, rcd; 
 SDL_Surface* layar = NULL;
 int x, y, tinggi, lebar;
 
 if( SDL_Init( SDL_INIT_VIDEO ) < 0 ){
     printf( "Error: %s\n", SDL_GetError() );
 }else{
     window = SDL_CreateWindow( "SDLku", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN );
     if( window == NULL ){
         printf( "Error : %s", SDL_GetError() );
     }else{
         layar = SDL_GetWindowSurface( window );

         SDL_FillRect( layar, NULL, SDL_MapRGB( layar->format, 0xFF, 0xFF, 0xFF) );
         SDL_Surface *tmp=SDL_LoadBMP("Codelogi.bmp");
         if(tmp){
             SDL_Surface *bmp=SDL_ConvertSurface(tmp, layar->format, 0);
             SDL_FreeSurface(tmp);
             rct.x=0;
             rct.y=0;
             rct.w=bmp->w;
             rct.h=bmp->h;
   
             lebar=bmp->w/4;
             tinggi=bmp->h/4;
             rcd.x=0;
             rcd.y=0;
             rcd.w=lebar;
             rcd.h=tinggi;
      
             for(y=0;y<4;y++){
                rcd.x=0;
                for(x=0;x<4;x++){
                    SDL_BlitScaled( bmp, &rct, layar, &rcd);
                    rcd.x+=lebar;
                }
                rcd.y+=tinggi;
             }
         }
  
         SDL_UpdateWindowSurface( window );
         SDL_Delay(2000);
         SDL_SaveBMP(layar, "foto.bmp");
     }
 }

 SDL_DestroyWindow( window );
 SDL_Quit();

 return 0;
}

Pada contoh kode program di atas saya tidak menggunakan loop, tapi saya menggunakan SDL_Delay. Jadi programnya akan menutup setelah 2000 milidetik atau dua detik. Kalau kalian melihat folder project atau program kalian, kalian seharusnya melihat ada file dengan nama "foto.bmp" atau nama lain sesuai dengan isi parameter kedua SDL_SaveBMP.

Oh ya, jangan lupa untuk meletakkan file dengan nama "Codelogi.bmp" sebelum menjalankan programnya. Program yang dihasilkan kode di atas butuh file dengan nama tersebut.

Untuk yang malas mengetik, kalian bisa mendownload kode programnya di sini.