Advertisement
Guest User

sdl-imageviewer.c

a guest
Mar 20th, 2013
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 18.18 KB | None | 0 0
  1. //  imgv, a simple SDL-based image viewer for the Ben Nanonote
  2. //  Version 0.3.0
  3. //  Last edited by Fernando Carello <fcarello@libero.it> 2010-05-24
  4. //  Last edited by Niels Kummerfeldt <niels.kummerfeldt@tuhh.de> 2010-10-19
  5. //
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <SDL/SDL.h>
  9. #include <SDL/SDL_image.h>
  10. #include <SDL/SDL_rotozoom.h>
  11. #include <SDL/SDL_ttf.h>
  12.  
  13. #define TRUE 1
  14. #define FALSE 0
  15. #define SCREENWIDTH 320
  16. #define SCREENHEIGHT 240
  17. #define SCREENBPP 32
  18. #define SMOOTHING_OFF   0
  19. #define SMOOTHING_ON    1
  20. #define PANSTEP 40
  21. #define ZOOMSTEP 1.2
  22. #define SLIDESHOWTIMEOUT (1000 * timeoutsecs)
  23. #define VERSION "0.3.1"
  24.  
  25. void quit()
  26. {
  27.     TTF_Quit();
  28.     SDL_Quit();
  29.  
  30.     exit(1);
  31. }
  32.  
  33. SDL_Surface *initScreen()
  34. {
  35.     // Initialize the SDL library
  36.     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
  37.     {
  38.         fprintf(stderr, "\n Couldn't initialize SDL: %s\n\n", SDL_GetError());
  39.         quit();
  40.     }
  41.  
  42.     // Set video mode
  43.     SDL_Surface *screen = SDL_SetVideoMode(SCREENWIDTH, SCREENHEIGHT, SCREENBPP,
  44.                                            SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWACCEL);
  45.     if (screen == (SDL_Surface *) (NULL))
  46.     {
  47.         fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n\n", SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SDL_GetError());
  48.         quit();
  49.     }
  50.  
  51.     // Can't stand the useless arrow... Ben has no pointing device
  52.     SDL_ShowCursor(SDL_DISABLE);   
  53.  
  54.     TTF_Init();
  55.  
  56.     return screen;
  57. }
  58.  
  59. SDL_Surface *loadImage(char *filename)
  60. {
  61.     // Load Picture
  62.     SDL_Surface *tmp = IMG_Load(filename);
  63.     if (tmp == (SDL_Surface *) (NULL))
  64.     {
  65. #if 0 /* ZIPIT_Z2 */
  66.         fprintf(stderr, "\n Couldn't load image file %s: %s\n\n", filename, SDL_GetError());
  67.         quit();
  68. #else
  69.     return NULL;
  70. #endif
  71.     }
  72.  
  73.     // Auto rotate image to fit screen
  74.     //if (tmp->w > SCREENWIDTH || tmp->h > SCREENHEIGHT) {
  75.     //    if (tmp->h > tmp->w * 1.1) {
  76.     //        SDL_Surface *t = rotateSurface90Degrees(tmp, 3);
  77.     //        SDL_FreeSurface(tmp);
  78.     //        tmp = t;
  79.     //    }
  80.     //}
  81.  
  82.     // Convert picture in same format as video framebuffer, to optimize blit performances
  83.     SDL_Surface *picture = SDL_DisplayFormat(tmp);
  84. #if 0 /* ZIPIT_Z2 */
  85.     if (picture == (SDL_Surface *) (NULL))
  86.     {
  87.         fprintf(stderr, "\n Internal error from DisplayFormat\n\n");
  88.         quit();
  89.     }
  90. #endif
  91.     SDL_FreeSurface(tmp);
  92.  
  93.     return picture;
  94. }
  95.  
  96. void pan(SDL_Surface *image, SDL_Rect *pos, int dx, int dy)
  97. {
  98.     if (image->w > SCREENWIDTH) {
  99.         pos->x += dx;
  100.         if (pos->x < 0) {
  101.             pos->x = 0;
  102.         }
  103.         if (pos->x >= image->w - SCREENWIDTH) {
  104.             pos->x = (Sint16) (image->w - SCREENWIDTH);
  105.         }
  106.     } else {
  107.         pos->x = 0;
  108.     }
  109.     if (image->h > SCREENHEIGHT) {
  110.         pos->y += dy;
  111.         if (pos->y < 0) {
  112.             pos->y = 0;
  113.         }
  114.         if (pos->y >= image->h - SCREENHEIGHT) {
  115.             pos->y = (Sint16) (image->h - SCREENHEIGHT);
  116.         }
  117.     } else {
  118.         pos->y = 0;
  119.     }
  120. }
  121.  
  122. SDL_Surface *zoomIn(SDL_Surface *image, SDL_Rect *pos, double *scale)
  123. {
  124.     *scale *= ZOOMSTEP;
  125.  
  126.     SDL_Surface *result = zoomSurface(image, *scale, *scale, SMOOTHING_ON);
  127.     if (result == (SDL_Surface *) (NULL))
  128.     {
  129.         fprintf(stderr, "\n Error from zoomSurface()\n\n");
  130.         quit();
  131.     }
  132.  
  133.     pos->x *= ZOOMSTEP;
  134.     int dx = SCREENWIDTH * (ZOOMSTEP-1) * 0.5;
  135.     pos->y *= ZOOMSTEP;
  136.     int dy = SCREENHEIGHT * (ZOOMSTEP-1) * 0.5;
  137.     pan(result, pos, dx, dy);
  138.  
  139.     return result;
  140. }
  141.  
  142. SDL_Surface *zoomOut(SDL_Surface *image, SDL_Rect *pos, double *scale)
  143. {
  144.     *scale /= ZOOMSTEP;
  145.  
  146.     SDL_Surface *result = zoomSurface(image, *scale, *scale, SMOOTHING_ON);
  147.     if (result == (SDL_Surface *) (NULL))
  148.     {
  149.         fprintf(stderr, "\n Error from zoomSurface()\n\n");
  150.         quit();
  151.     }
  152.  
  153.     pos->x += SCREENWIDTH * (1-ZOOMSTEP) * 0.5;
  154.     pos->x /= ZOOMSTEP;
  155.     pos->y += SCREENHEIGHT * (1-ZOOMSTEP) * 0.5;
  156.     pos->y /= ZOOMSTEP;
  157.     pan(result, pos, 0, 0);
  158.  
  159.     return result;
  160. }
  161.  
  162. SDL_Surface *zoomFit(SDL_Surface *image, SDL_Rect *pos, double *scale)
  163. {
  164.     pos->x = 0;
  165.     pos->y = 0;
  166.     double scale_x = (double) (SCREENWIDTH) / (double) (image->w);
  167.     double scale_y = (double) (SCREENHEIGHT) / (double) (image->h);
  168.     if (scale_y < scale_x) {
  169.         *scale = scale_y;
  170.     } else {
  171.         *scale = scale_x;
  172.     }
  173.  
  174.     SDL_Surface *result = zoomSurface(image, *scale, *scale, SMOOTHING_ON);
  175.     if (result == (SDL_Surface *) (NULL))
  176.     {
  177.         fprintf(stderr, "\n Error from zoomSurface()\n\n");
  178.         quit();
  179.     }
  180.  
  181.     return result;
  182. }
  183.  
  184. SDL_Surface *zoom100(SDL_Surface *image, SDL_Rect *pos, double *scale)
  185. {
  186.     SDL_Surface *result = SDL_ConvertSurface(image, image->format, image->flags);
  187.     if (result == (SDL_Surface *) (NULL))
  188.     {
  189.         fprintf(stderr, "\n Error from ConvertSurface()\n\n");
  190.         quit();
  191.     }
  192.  
  193.     if (*scale < 1.0) {
  194.         pos->x /= *scale;
  195.         pos->y /= *scale;
  196.         pos->x -= SCREENWIDTH * (1-(1 / *scale)) * 0.5;
  197.         pos->y -= SCREENHEIGHT * (1-(1 / *scale)) * 0.5;
  198.     } else {
  199.         pos->x += SCREENWIDTH * (1-*scale) * 0.5;
  200.         pos->y += SCREENHEIGHT * (1-*scale) * 0.5;
  201.         pos->x /= *scale;
  202.         pos->y /= *scale;
  203.     }
  204.     pan(result, pos, 0, 0);
  205.     *scale = 1.0;
  206.  
  207.     return result;
  208. }
  209.  
  210. SDL_Surface *drawFileName(char *filename, TTF_Font *font, int slideShow)
  211. {
  212.     if(font) {
  213.         SDL_Color foregroundColor = { 0, 0, 0, 0 };
  214.         SDL_Color backgroundColor = { 200, 200, 200, 0 };
  215.  
  216.         char text[strlen(filename)+4];
  217.         strcpy(text, filename);
  218.         if (slideShow) {
  219.             strcat(text, " >>");
  220.         }
  221.         return TTF_RenderText_Shaded(font, text, foregroundColor, backgroundColor);
  222.     }
  223.     return NULL;
  224. }
  225.  
  226. void drawImage(SDL_Surface *image, SDL_Rect *pos, SDL_Surface *screen, SDL_Surface *filename)
  227. {
  228.     SDL_FillRect(screen, (SDL_Rect *) NULL, 0); // draw background color (black)
  229.  
  230.     SDL_Rect screenPos;
  231.     if (image->w < SCREENWIDTH) {
  232.         screenPos.x = (SCREENWIDTH - image->w) / 2;
  233.     } else {
  234.         screenPos.x = 0;
  235.     }
  236.     if (image->h < SCREENHEIGHT) {
  237.         screenPos.y = (SCREENHEIGHT - image->h) / 2;
  238.     } else {
  239.         screenPos.y = 0;
  240.     }
  241.     SDL_BlitSurface(image, pos, screen, &screenPos);
  242.  
  243.     if(filename) {
  244.         SDL_Rect textLocation = { 0, 0, 0, 0 };
  245.         if (filename->w > SCREENWIDTH) {
  246.             textLocation.x = SCREENWIDTH - filename->w;
  247.         }
  248.         SDL_BlitSurface(filename, NULL, screen, &textLocation);
  249.     }
  250.  
  251.     SDL_Flip(screen);
  252. }
  253.  
  254. Uint32 timerCallback(Uint32 interval, void *param)
  255. {
  256.     param = NULL;
  257.     SDL_Event event;
  258.     SDL_KeyboardEvent keyEvent;
  259.  
  260.     keyEvent.type = SDL_KEYDOWN;
  261.     keyEvent.keysym.unicode = 0;
  262.     keyEvent.keysym.scancode = 0;
  263.     keyEvent.keysym.mod = 0;
  264.     keyEvent.keysym.sym = SDLK_n;
  265.  
  266.     event.type = SDL_KEYDOWN;
  267.     event.key = keyEvent;
  268.  
  269.     SDL_PushEvent(&event);
  270.  
  271.     return interval;
  272. }
  273.  
  274. void print_help(char *name)
  275. {
  276.         fprintf(stderr,  "\n Image Viewer -- imgv v%s.  Usage: \n"
  277.             " imgv -d -f -l -r -s[+|-][secs] <image files>\n\n"
  278.             " Command line options are like the hotkeys\n"
  279.             "  except -s has additional modifiers to\n"
  280.             "  control display time and the finish.\n"
  281.             "  (+ = loop, - = halt, otherwise exit)\n"
  282.             "  Also, -l with -r rotates 180 degrees.\n"
  283.             " Hotkeys:\n"
  284.             " 'f' fit to screen\n"
  285.             " 'z' zoom at pixel level\n"
  286.             " 'i' zoom in  'o' zoom out\n"
  287.             " 'l' rotate left  'r' rotate right\n"
  288.             " 'n' next image  'p' previous image\n"
  289.             " 'd' show / hide file name\n"
  290.             " 's' start / stop slide show\n"
  291.             " 'arrows' pan  'ESC' quit\n\n", VERSION);
  292. }
  293.  
  294. int main(int argc, char *argv[])
  295. {
  296.     SDL_Surface *screen      = NULL,
  297.                 *newimage       = NULL,
  298.                 *image       = NULL,
  299.                 *scaledImage = NULL,
  300.                 *name        = NULL;
  301.     SDL_Rect     picturePortion;
  302.     TTF_Font    *font = NULL;
  303.     double       scale = 1.0;
  304.     int          currentImageNumber = 0,
  305.                  oldImageNumber = 0,
  306.                  showFileName = TRUE,
  307.                  runSlideShow = FALSE,
  308.                  isRunning = TRUE;
  309.     SDL_TimerID  slideShowTimer = 0;
  310.  
  311.     int          timeoutsecs = 5;
  312.     int          loopShow=0;
  313.     int          fullscreen=0;
  314.     int          angle = 0;
  315.    
  316.     // Process command line
  317.     if (argc < 2) {
  318.         print_help(argv[0]);
  319.         exit(0);
  320.     }
  321.  
  322.     /* loop along the possible list of arguments */
  323.     while((--argc>0) && (**++argv=='-'))
  324.     {
  325.       char c;
  326.       int n;
  327.       while(c=*++*argv)
  328.       {
  329.     switch(c)
  330.     {
  331.     case 'f': /* -f display images in fullscreen */
  332.       fullscreen=1;
  333.       break;
  334.  
  335.     case 'd': /* -d do not show file name */
  336.       showFileName = 1 - showFileName;
  337.       break;
  338.  
  339.     case 'h': /* -h display help text and exit */
  340.       print_help(*(argv-1));
  341.       return;
  342.  
  343.     case 'l': /* -r=l rotate image */
  344.     /* if option -r already has been used then angle=180 */
  345.       if(angle==1) //270)
  346.         angle=2;   //180;
  347.       else /* only option -r has been given */
  348.         angle=3;    //90;
  349.       break;
  350.  
  351.     case 'r': /* -r rotate image */
  352.     /* if option -l already has been used then angle=180 */
  353.       if(angle==3) //90)
  354.         angle=2;   //180;
  355.       else /* only option -R has been given */
  356.         angle=1;   //270;
  357.       break;
  358.      
  359.     case 's': /* -s display images in a slideshow */
  360.       if (*(*argv+1) == '-')
  361.       {
  362.           loopShow = 0; // stop after slideshow but do not exit.
  363.           ++*argv; // Eat the s (get the minus below).
  364.       }
  365.       else if (*(*argv+1) == '+')
  366.       {
  367.           loopShow = 1; // Loop slideshow forever.
  368.           ++*argv; // Eat the s (get the minus below).
  369.       }
  370.       else loopShow =-1;
  371.       n = sscanf(*argv+1, "%d", &timeoutsecs);
  372.       if(n <= 0)
  373.         timeoutsecs = 5;
  374.       else
  375.         while(isdigit(*(++*argv+1))); // Eat the s and all but last digit.
  376.       runSlideShow = 1 - runSlideShow;
  377.       if (timeoutsecs < 0)
  378.         timeoutsecs *=1;
  379.       break;
  380.  
  381.     default:
  382.       printf("illegal option %c\n",c);
  383.       return;
  384.     }
  385.       }
  386.     }
  387.  
  388.     screen = initScreen();
  389.  
  390.     font = TTF_OpenFont("font.ttf", 11);
  391.     if (font == (TTF_Font *) (NULL)) {
  392.         font = TTF_OpenFont("/usr/share/imgv/font.ttf", 11);
  393.     }
  394.     if (font == (TTF_Font *) (NULL)) {
  395.         font = TTF_OpenFont("/usr/share/fonts/ttf-dejavu/DejaVuSans.ttf", 11);
  396.     }
  397.  
  398.     picturePortion.w = SCREENWIDTH;
  399.     picturePortion.h = SCREENHEIGHT;
  400.  
  401. #if 0 /* ZIPIT_Z2 */
  402.     image = loadImage(argv[0]);
  403. #else
  404.     /* Find the first real image file. */
  405.     while ((image = loadImage(argv[0])) == NULL)
  406.     {
  407.       if (--argc<=0)
  408.       {
  409.     fprintf(stderr, "\n Couldn't load image file %s: %s\n\n", argv[0], SDL_GetError());
  410.         quit();
  411.       }
  412.       fprintf(stderr, "\n Skipping non-image file %s: %s\n\n", argv[0], SDL_GetError());
  413.       //SDL_ClearError();
  414.       argv++;
  415.     }
  416. #endif
  417.  
  418.     if (runSlideShow)
  419.       slideShowTimer = SDL_AddTimer(SLIDESHOWTIMEOUT, timerCallback, NULL);
  420.     if (angle)
  421.     {
  422.       SDL_FreeSurface(scaledImage);
  423.       SDL_Surface *tmp = rotateSurface90Degrees(image, angle);
  424.       SDL_FreeSurface(image);
  425.       image = tmp;
  426.     }
  427.     if (fullscreen)
  428.       scaledImage = zoomFit(image, &picturePortion, &scale);
  429.     else
  430.  
  431.     if (image->w < SCREENWIDTH && image->h < SCREENHEIGHT) {
  432.         scaledImage = zoom100(image, &picturePortion, &scale);
  433.     } else {
  434.         scaledImage = zoomFit(image, &picturePortion, &scale);
  435.     }
  436.     name = drawFileName(argv[currentImageNumber], font, runSlideShow);
  437.     drawImage(scaledImage, &picturePortion, screen, name);
  438.  
  439.     do {
  440.         SDL_Event event;
  441.         if (SDL_WaitEvent(&event) && event.type == SDL_KEYDOWN) {
  442.             switch (event.key.keysym.sym) {
  443.                 case SDLK_LEFT: // PAN LEFT
  444.                     pan(scaledImage, &picturePortion, -PANSTEP, 0);
  445.                     break;
  446.                 case SDLK_RIGHT: // PAN RIGHT
  447.                     pan(scaledImage, &picturePortion, PANSTEP, 0);
  448.                     break;
  449.                 case SDLK_UP: // PAN UP
  450.                     pan(scaledImage, &picturePortion, 0, -PANSTEP);
  451.                     break;
  452.                 case SDLK_DOWN: // PAN DOWN
  453.                     pan(scaledImage, &picturePortion, 0, PANSTEP);
  454.                     break;
  455.                 case SDLK_i: // ZOOM IN
  456.                     SDL_FreeSurface(scaledImage);
  457.                     scaledImage = zoomIn(image, &picturePortion, &scale);
  458.                     break;
  459.                 case SDLK_o: // ZOOM OUT
  460.                     SDL_FreeSurface(scaledImage);
  461.                     scaledImage = zoomOut(image, &picturePortion, &scale);
  462.                     break;
  463.                 case SDLK_f: // ZOOM TO FIT SCREEN
  464.                     SDL_FreeSurface(scaledImage);
  465.                     scaledImage = zoomFit(image, &picturePortion, &scale);
  466.                     break;
  467.                 case SDLK_z: // ZOOM TO ORIGINAL SIZE
  468.                     SDL_FreeSurface(scaledImage);
  469.                     scaledImage = zoom100(image, &picturePortion, &scale);
  470.                     break;
  471.                 case SDLK_l: // ROTATE LEFT
  472.                     {
  473.                         SDL_FreeSurface(scaledImage);
  474.                         SDL_Surface *tmp = rotateSurface90Degrees(image, 3);
  475.                         SDL_FreeSurface(image);
  476.                         image = tmp;
  477.                         scaledImage = zoomSurface(image, scale, scale, SMOOTHING_ON);
  478.                         int x = picturePortion.x;
  479.                         picturePortion.x = picturePortion.y + SCREENHEIGHT/2 - SCREENWIDTH/2;
  480.                         picturePortion.y = scaledImage->h - x - SCREENHEIGHT/2 - SCREENWIDTH/2;
  481.                         pan(scaledImage, &picturePortion, 0, 0);
  482.                     }
  483.                     break;
  484.                 case SDLK_r: // ROTATE RIGHT
  485.                     {
  486.                         SDL_FreeSurface(scaledImage);
  487.                         SDL_Surface *tmp = rotateSurface90Degrees(image, 1);
  488.                         SDL_FreeSurface(image);
  489.                         image = tmp;
  490.                         scaledImage = zoomSurface(image, scale, scale, SMOOTHING_ON);
  491.                         int x = picturePortion.x;
  492.                         picturePortion.x = scaledImage->w - picturePortion.y - SCREENWIDTH/2
  493.                                            - SCREENHEIGHT/2;
  494.                         picturePortion.y = x + SCREENWIDTH/2 - SCREENHEIGHT/2;
  495.                         pan(scaledImage, &picturePortion, 0, 0);
  496.                     }
  497.                     break;
  498.                 case SDLK_n: // NEXT IMAGE
  499.             oldImageNumber = currentImageNumber;
  500.         nextim:
  501.                     if ((loopShow == 1) && (argc >1) && (currentImageNumber >= argc-1))
  502.                         currentImageNumber=-1;
  503.                     if (currentImageNumber < argc-1) {
  504.                         ++currentImageNumber;
  505.  
  506.                         newimage = loadImage(argv[currentImageNumber]);
  507.             if (newimage == NULL)
  508.               goto nextim;
  509.             SDL_FreeSurface(image);
  510.             SDL_FreeSurface(scaledImage);
  511.             SDL_FreeSurface(name);
  512.             image=newimage;
  513.  
  514.                         if (image->w < SCREENWIDTH && image->h < SCREENHEIGHT) {
  515.                             scaledImage = zoom100(image, &picturePortion, &scale);
  516.                         } else {
  517.                             scaledImage = zoomFit(image, &picturePortion, &scale);
  518.                         }
  519.                         name = drawFileName(argv[currentImageNumber], font, runSlideShow);
  520.                     } else {
  521.                 currentImageNumber = oldImageNumber; /* Last known good image */
  522.                         if (runSlideShow) {
  523.                             SDL_RemoveTimer(slideShowTimer);
  524.                             runSlideShow = FALSE;
  525.                             name = drawFileName(argv[currentImageNumber], font, runSlideShow);
  526.                 if (loopShow == -1)
  527.                 {
  528.                   isRunning = FALSE;
  529.                 }
  530.                         }
  531.                     }
  532.                     break;
  533.                 case SDLK_p: // PREVIOUS IMAGE
  534.         previm:
  535.                     if (currentImageNumber > 0) {
  536.                         --currentImageNumber;
  537.             if (image){
  538.               SDL_FreeSurface(image);
  539.               SDL_FreeSurface(scaledImage);
  540.               SDL_FreeSurface(name);
  541.             }
  542.                         image = loadImage(argv[currentImageNumber]);
  543.             if (image == NULL)
  544.               goto previm;
  545.                         if (image->w < SCREENWIDTH && image->h < SCREENHEIGHT) {
  546.                             scaledImage = zoom100(image, &picturePortion, &scale);
  547.                         } else {
  548.                             scaledImage = zoomFit(image, &picturePortion, &scale);
  549.                         }
  550.                         name = drawFileName(argv[currentImageNumber], font, runSlideShow);
  551.                     }
  552.                     break;
  553.                 case SDLK_s: // START / STOP SLIDESHOW
  554.                     runSlideShow = 1 - runSlideShow;
  555.                     name = drawFileName(argv[currentImageNumber], font, runSlideShow);
  556.                     if (runSlideShow) {
  557.                         slideShowTimer = SDL_AddTimer(SLIDESHOWTIMEOUT, timerCallback, NULL);
  558.                     } else {
  559.                         SDL_RemoveTimer(slideShowTimer);
  560.                     }
  561.                     break;
  562.                 case SDLK_d: // SHOW / HIDE FILENAME
  563.                     showFileName = 1 - showFileName;
  564.                     break;
  565.                 case SDLK_ESCAPE: // QUIT
  566.                 case SDLK_q:
  567.                     isRunning = FALSE;
  568.                     break;
  569.                 default:
  570.                     break;
  571.              } // end of switch (event.key.keysym.sym)
  572.         } // end of if(SDL_WaitEvent())
  573.         drawImage(scaledImage, &picturePortion, screen, showFileName ? name : 0);
  574.     } while(isRunning); // end of do
  575.  
  576.     SDL_FreeSurface(image);
  577.     SDL_FreeSurface(scaledImage);
  578.     SDL_FreeSurface(screen);
  579.  
  580.     TTF_CloseFont(font);
  581.     TTF_Quit();
  582.  
  583.     SDL_Quit();
  584.  
  585.     return 0;
  586. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement