home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / vg-2.03 / pcd / pcd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  7.6 KB  |  442 lines

  1. /*
  2.  * Copyright (C) 1993 Michael Davidson.
  3.  * All rights reserved.
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software
  6.  * and its documentation for any purpose and without fee is hereby
  7.  * granted, provided that the above copyright notice appear in all
  8.  * copies and that both that copyright notice and this permission
  9.  * notice appear in supporting documentation.
  10.  *
  11.  * This software is provided "as is" without express or implied warranty.
  12.  */
  13.  
  14. #include    <stdio.h>
  15. #include    <stdlib.h>
  16. #include    <string.h>
  17.  
  18. #include    "vg.h"
  19. #include    "image.h"
  20. #include    "video/video.h"
  21.  
  22. #ifndef    STATIC
  23. #define    STATIC    static
  24. #endif
  25.  
  26. /*
  27.  * Photo CD file definitions
  28.  */
  29. #define    MAX_WIDTH    768
  30. #define    MAX_HEIGHT    512
  31.  
  32. /*
  33.  * Photo CD image orientations
  34.  */
  35.  
  36. #define    ROTATE_0    0
  37. #define    ROTATE_90    1
  38. #define    ROTATE_180    2
  39. #define    ROTATE_270    3
  40.  
  41.  
  42. STATIC image_t    *PCDImage;
  43.  
  44. STATIC int    pcdLoadImage(FILE *fp, int x, int y, int w, int h, int rotate);
  45.  
  46. char    *
  47. pcdInfo(
  48.     FILE    *fp
  49.     )
  50. {
  51.     static char        info[80];
  52.     unsigned char    buf[4096];
  53.  
  54.     if (fread(buf, 4096, 1, fp) != 1)
  55.     return NULL;
  56.  
  57.     if (strcmp(buf+ 0x800, "PCD_IPI") == 0)
  58.     return "Kodak Photo CD image";
  59.  
  60.     if (strcmp(buf, "PCD_OPA") == 0)
  61.     {
  62.     int    n;
  63.  
  64.     n    = (buf[10] << 8) | buf[11];
  65.     sprintf(info, "Kodak Photo CD overview of %d images", n);
  66.     return info;
  67.     }
  68.  
  69.     return NULL;
  70. }
  71.  
  72. int
  73. pcdRead(
  74.     char    *name,
  75.     FILE    *fp
  76.     )
  77. {
  78.     unsigned char    buf[4096];
  79.  
  80.     if (fread(buf, 4096, 1, fp) != 1)
  81.     return imageError("can't read PCD image header");
  82.  
  83.     if (strcmp(buf+ 0x800, "PCD_IPI") == 0)
  84.     return pcdShowImage(name, fp, buf[0xe02] & 0x03);
  85.  
  86.     if (strcmp(buf, "PCD_OPA") == 0)
  87.     {
  88.     int    n;
  89.  
  90.     n    = (buf[10] << 8) | buf[11];
  91.     return pcdShowOverview(name, fp, n);
  92.     }
  93.  
  94.     return imageError("not a PCD image file");
  95. }
  96.  
  97. int
  98. pcdShowImage(
  99.     char    *name,
  100.     FILE    *fp,
  101.     int        rotate
  102.     )
  103. {
  104.     int        r;
  105.     int        w, h;
  106.  
  107.     switch (rotate)
  108.     {
  109.     case 0:        /* no rotation            */
  110.     case 2:        /* rotate 180 degrees        */
  111.         w    = 768;
  112.         h    = 512;
  113.         break;
  114.  
  115.     case 1:        /* rotate  90 degrees left    */
  116.     case 3:        /* rotate  90 degrees right    */
  117.         w    = 512;
  118.         h    = 768;
  119.         break;
  120.     }
  121.  
  122.     if ((PCDImage = imageStart(name, w, h, 24, 0)) == NULL)
  123.     return imageError("can't allocate %dx%d 24 bit Photo-CD image", w, h);
  124.  
  125.     imageShowInfo(1);
  126.  
  127.     /*
  128.      * seek to start of image
  129.      */
  130.     fseek(fp, 96 * 2048L, 0);
  131.     pcdLoadImage(fp, 0, 0, 768, 512, rotate);
  132.   
  133.     return imageEnd();
  134. }
  135.  
  136. int
  137. pcdShowOverview(
  138.     char    *name,
  139.     FILE    *fp,
  140.     int        n
  141.     )
  142. {
  143.     int        i;
  144.     int        r;
  145.     int        rows, cols, page, pages;
  146.     int        h_border, v_border;
  147.     int        images_per_page;
  148.     int        width, height;
  149.     char    buf[80];
  150.     char    sbuf[2048];
  151.     vmode_t    *m;
  152.  
  153.     rewind(fp);
  154.     if (fread(sbuf, 2048, 1, fp) != 1)
  155.     return imageError("can't read PCD image header");
  156.  
  157.     /*
  158.      * calculate overview image layout
  159.      */
  160.     /*
  161.      * calculate rows and columns needed to display
  162.      * overview images in a 4 x 3 format
  163.      */
  164.     rows    = 
  165.     cols    = (n + 11) / 12;
  166.     rows    *= 3;
  167.     cols    *= 4;
  168.  
  169.     /*
  170.      * find the best mode for displaying that number of 192x192 images
  171.      */
  172.     i        = bestDisplayMode(V_GRAPHICS_MODE, cols * 192, rows * 192, 24);
  173.     m        = vidModeInfo(i);
  174.     width    = m->width;
  175.     height    = m->height;
  176.  
  177.     /*
  178.      * given the actual display mode available calculate how many rows and
  179.      * colums will fit on one screen and how many screens we will need
  180.      */
  181.     rows    = height / 192;
  182.     cols    = width  / 192;
  183.     images_per_page    = rows * cols;
  184.     pages    = (n + images_per_page - 1) / images_per_page;
  185.  
  186.     /*
  187.      * calculate the horizontal and vertical border width between images
  188.      */
  189.     h_border    = (width  - (cols * 192)) / cols;
  190.     v_border    = (height - (rows * 192)) / rows;
  191.  
  192.     page    = 0;
  193.  
  194.     for (;;)
  195.     {
  196.     int    first_image;
  197.     int    last_image;
  198.     int    x, y;
  199.     int    row, col;
  200.     int    rotate;
  201.  
  202.     first_image    = page * images_per_page;
  203.     last_image    = first_image + images_per_page - 1;
  204.     if (last_image > n)
  205.         last_image = n;
  206.  
  207.     sprintf(buf, "%s images %d - %d", name, first_image+1, last_image+1);
  208.  
  209.     if ((PCDImage = imageStart(buf, width, height, 24, 0)) == NULL)
  210.         return imageError("can't allocate %dx%d 24 bit image",
  211.         width, height);
  212.  
  213.     imageShowInfo(1);
  214.  
  215. /*
  216.  * load the images here ....
  217.  */
  218.     i    = first_image;
  219.     y    = v_border / 2;
  220.  
  221.     for (row = 0; row < rows && i <= last_image; row++)
  222.     {
  223.         x    = h_border / 2;
  224.         for (col = 0; col < cols && i <= last_image; col++)
  225.         {
  226.         fseek(fp, (5 + 18 * i) * 2048L, 0);
  227.         rotate = sbuf[12 + i] & 0x03;
  228.         if (rotate & 0x01)
  229.             pcdLoadImage(fp, x+32, y, 192, 128, rotate);
  230.         else
  231.             pcdLoadImage(fp, x, y+32, 192, 128, rotate);
  232.  
  233.         x += 192 + h_border;
  234.         i++;
  235.         }
  236.         y    += 192 + v_border;
  237.  
  238.     }
  239.  
  240.     r    = imageEnd();
  241.  
  242.     switch (r)
  243.     {
  244.         case F_NEXT:
  245.         if (++page >= pages)
  246.             return F_NEXT;
  247.         break;
  248.  
  249.         case F_PREV:
  250.         if (--page < 0)
  251.             return F_PREV;
  252.         break;
  253.  
  254.         case F_REDRAW:
  255.         break;
  256.  
  257.         case F_ESC:
  258.         default:
  259.         return r;
  260.     }
  261.     }
  262.     /*NOTREACHED*/
  263. }
  264.  
  265. STATIC int
  266. pcdLoadImage(
  267.     FILE    *fp,
  268.     int        x,
  269.     int        y,
  270.     int        width,
  271.     int        height,
  272.     int        rotate
  273.     )
  274. {
  275.     int        dx;
  276.     int        dy;
  277.     int        i;
  278.     int        r;
  279.     unsigned char    buf[MAX_WIDTH*3];
  280.     unsigned char    Cb[MAX_WIDTH];
  281.     unsigned char    Cr[MAX_WIDTH];
  282.     unsigned char    *Y, *Y0, *Y1, *Cb0, *Cr0;
  283.  
  284.     memset(Cb, 0x80, MAX_WIDTH);
  285.     memset(Cr, 0x80, MAX_WIDTH);
  286.     /*
  287.      * deal with the image orientation
  288.      */
  289.     switch (rotate)
  290.     {
  291.     default:    /* "can't happen" */
  292.         return -1;
  293.  
  294.     case ROTATE_0:
  295.         dx    = 0;
  296.         dy    = 1;
  297.         break;
  298.  
  299.     case ROTATE_90:
  300.         y    += width - 1;
  301.         dx    = 1;
  302.         dy    = 0;
  303.         break;
  304.  
  305.     case ROTATE_180:
  306.         x    += width - 1;
  307.         y    += height - 1;
  308.         dx    = 0;
  309.         dy    = -1;
  310.         break;
  311.  
  312.     case ROTATE_270:
  313.         x    += height - 1;
  314.         dx    = -1;
  315.         dy    = 0;
  316.         break;
  317.     }
  318.  
  319.     Y0    = buf;
  320.     Y1    = buf + width;
  321.     Cb0    = Y1 + width;
  322.     Cr0    = Cb0 + width / 2;
  323.  
  324.     for (i = 0; i < height; i++)
  325.     {
  326.     if ((i & 1) == 0)
  327.     {
  328.         if (fread(buf, width, 3, fp) != 3)
  329.         return -1;
  330.         Y = Y0;
  331.  
  332.         expand(Cb0, Cb, width/2);
  333.         expand(Cr0, Cr, width/2);
  334.  
  335.     }
  336.     else
  337.     {
  338.         Y = Y1;
  339.     }
  340.     if ((r = pcdPutPixels(x, y, Y, Cb, Cr, width, rotate)) != 0)
  341.         return r;
  342.  
  343.     x += dx;
  344.     y += dy;
  345.     }
  346.  
  347.     return 0;
  348. }
  349.  
  350. int
  351. pcdPutPixels(
  352.     int        x,
  353.     int        y,
  354.     void    *Y,
  355.     void    *Cb,
  356.     void    *Cr,
  357.     int        n,
  358.     int        rotate
  359.     )
  360. {
  361.     unsigned char    **pp;
  362.     unsigned char    *p;
  363.     unsigned char    *rgb;
  364.     int            i;
  365.     int            r    = 0;
  366.  
  367.     switch (rotate)
  368.     {
  369.     default:
  370.         r    = -1;
  371.         break;
  372.  
  373.     case ROTATE_0:
  374.         pcd_to_rgb(Y, Cb, Cr, PCDImage->pixels[y] + x * 3, n);
  375.         r    = imageRefresh(x, y, n, 1);
  376.         break;
  377.  
  378.     case ROTATE_90:
  379.         rgb    = alloca(n * 3);
  380.         pcd_to_rgb(Y, Cb, Cr, rgb, n);
  381.         pp    = PCDImage->pixels;
  382.         for (i = 0; i < n; i++)
  383.         {
  384.         p    = &pp[y--][3*x];
  385.         *p++    = *rgb++;
  386.         *p++    = *rgb++;
  387.         *p++    = *rgb++;
  388.         }
  389.         if ((x & 7) == 7)
  390.         r = imageRefresh(x & ~7, y+1, 8, n);
  391.         break;
  392.  
  393.     case ROTATE_180:
  394.         rgb    = alloca(n * 3);
  395.         pcd_to_rgb(Y, Cb, Cr, rgb, n);
  396.         pp    = PCDImage->pixels;
  397.         for (i = 0; i < n; i++)
  398.         {
  399.         p    = &pp[y][3*x--];
  400.         *p++    = *rgb++;
  401.         *p++    = *rgb++;
  402.         *p++    = *rgb++;
  403.         }
  404.         r    = imageRefresh(x+1, y, n, 1);
  405.         break;
  406.  
  407.     case ROTATE_270:
  408.         rgb    = alloca(n * 3);
  409.         pcd_to_rgb(Y, Cb, Cr, rgb, n);
  410.         pp    = PCDImage->pixels;
  411.         for (i = 0; i < n; i++)
  412.         {
  413.         p    = &pp[i][3*x];
  414.         *p++    = *rgb++;
  415.         *p++    = *rgb++;
  416.         *p++    = *rgb++;
  417.         }
  418.         if ((x & 7) == 7)
  419.         r = imageRefresh(x & ~7, y, 8, n);
  420.         break;
  421.  
  422.     }
  423.  
  424.     return    r;
  425. }
  426.  
  427. expand(
  428.     unsigned char    *src,
  429.     unsigned char    *dst,
  430.     int            count
  431.     )
  432. {
  433.     while (--count >= 0)
  434.     {
  435.     unsigned char    c;
  436.  
  437.     c    = *src++;
  438.     *dst++    = c;
  439.     *dst++    = c;
  440.     }
  441. }
  442.