/* gil_resize.cpp
*  @author Rafał Oracz (R.Oracz@stud.elka.pw.edu.pl)
*
* Program demonstruje sposób zmiany rozmiarów obrazka,przy pomocy biblioteki GIL, i jej rozszerzeń: numeric, opencv.
* Zapis plików wspiera rozszerzenie io. 
* W przykładzie posługuję się plikami typu jpg, do obsługi których wymagana jest biblioteka libjpeg.lib (http://www.ijg.org)
  Do poprawnego działania musimy zmienic nazwe odpowieniego pliku jconfig.* na jconfig.h (dla VS: jconfig.vs -> jconfig.h)
*
* Zmiane rozmiarów możemy zrealizować albo za pomocą rozszerzenia numeric, albo zapomocą rozszerzenia opencv.
* numeric: http://opensource.adobe.com/wiki/display/gil/Downloads
* opencv: http://sourceforge.net/projects/opencvlibrary/ + help: http://opencv.willowgarage.com/wiki/
*
*
* Dla poprawnej kompilacji musimy linkerowi wskazać odpowiednie katalogi: 
	/sciezka_do/OpenCV/lib  (jeśli korzystamy z opencv)
	/sciezka_do/jpeg-6b/lib (obowiązkowo)
  Oraz dodać dodatkowe zależnosci:	
	Libjpeg: libjpeg.lib 
	OpenCV: cv.lib cxcore.lib (jeśli korzystamy z opencv)
  Dodajemy ścieżki do niezbędnych nagłówków:
    /sciezka_do/OpenCV/cxcore/include	
    /sciezka_do/OpenCV/CV/include
    /sciezka_do/jpeg-6b
    /sciezka_do/boost_1_*  ;)
  Zignorować biblioteke (Ignore Specific Library w 'Project properties->Linker->Input' dla VS)
	LIBC.lib
	
* Do testowania należy umieścic plik *.jpg w katalogu z progamem. Wywołanie opisane jest przy funkcji main. 	
* W wyniku działania programu, powstanie 6 nowych plików obrazujących działanie poszczególnych sposobów zmiany rozmiaru.
*/

#include <iostream>
#include <boost/gil/image.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/gil/extension/io/jpeg_io.hpp>
#include <boost/gil/extension/numeric/sampler.hpp>
#include <boost/gil/extension/numeric/resample.hpp>
#include <boost/gil/extension/opencv/resize.hpp>

using namespace boost::gil;

int main(int argc, char* argv[]) // Wywołanie: gil_resize nazwa_pliku szerokość wysokość.
{
    if(argc != 4) { std::cout << "Usage: resize filename width height.\n"; return 1; };

    
	char* inputFileName = argv[1];				// nazwa pliku wejściowego w formacie jpg.
    int width = atoi(argv[2]);					// szerokość obrazu wyjściowego
    int height = atoi(argv[3]);					// wysokość obraz wyjściowego
    
    rgb8_image_t imgOriginal;					// 8-bitowy wejsciowy obraz RGB
    rgb8_image_t imgResized(width,height);		// 8-bitowy wyjsciowy obraz RGB
    
    
    /* Funkcje view(), const_view() zwracają swojego rodzaju wskaźnik na obraz znajdujący się w pamięci.
		Jak można się domyślić funkcja const_view() zabezpiecza nas przed zmianą obrazu, 
		dlatego dla obrazu wyjściowego będziemy uzywać view(), dla oryginalnego const_view(). */
    
    
    
   	// ZACZYNAMY
   	// Na początek 2 przykłady wykorzystujące rozszerzenie numeric dostarczające 2 samplerów.	 
    
    
    /* Alokujemy pamięć zależną od wymiarów pliku wejściowego, następnie wgrana zostanie zawartość obrazka.
       Nstępuje tu również sprawdzanie czy plik jest poprawnym formatem jpg, 
       i czy jego parametry są zgodne z parametrami imgOriginal. W razie błędu rzucany jest wyjątek std::ios_base::failure */
    jpeg_read_image(inputFileName, imgOriginal);  
    
		/* Funkcja resize_view odpowiedzialna jest za skopiowanie zawartości obrazka, 
		   skalując go do nowych rozmiarów, za pomocą samplera podanego jako 3ci argument */
		resize_view(const_view(imgOriginal), view(imgResized), bilinear_sampler()); 
		/* Zapisujemy otrzymany obraz pod wskazaną nazwą. 
		   Może zostać rzucony wyjątek std::ios_base::failure
		   jeśli format nie jest wspierany przez rozszerzenie I/O
		   lub zapisanie pliku się nie powidedzie.	 */
		jpeg_write_view("out.numeric.bilinear.jpg", const_view(imgResized));


	// powtarzamy dla nearest_neighbor_sampler:
		resize_view(const_view(imgOriginal), view(imgResized), nearest_neighbor_sampler());
		jpeg_write_view("out.numeric.nearest_neighbor.jpg", const_view(imgResized)); 
    
    
    
    
    // Teraz czas na rozszerzenie opencv, które dostarcza nam 4 różne algorytmy resamplingu.

		// Funkcja resize analogiczna do resize_view z numeric extension.
		opencv::resize(view(imgOriginal), view(imgResized), opencv::bilinear());
		jpeg_write_view("out.opencv.bilinear.jpg", const_view(imgResized));
		
		opencv::resize(view(imgOriginal), view(imgResized), opencv::nearest_neigbor()); // UWAGA! nazwa to nearest_neigbor, a nie nearest_neighbor. Błąd językowy ??
		jpeg_write_view("out.opencv.nearest_neighbor.jpg", const_view(imgResized));
    
		opencv::resize(view(imgOriginal), view(imgResized), opencv::area());
		jpeg_write_view("out.opencv.area.jpg", const_view(imgResized));
	
		opencv::resize(view(imgOriginal), view(imgResized), opencv::bicubic());
		jpeg_write_view("out.opencv.bicubic.jpg", const_view(imgResized));

    return 0;
}
