home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / ximtoppm.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  11KB  |  359 lines

  1. /* ximtoppm.c - read an Xim file and produce a portable pixmap
  2. **
  3. ** Copyright (C) 1991 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "ppm.h"
  14. #include "xim.h"
  15.  
  16. static int ReadXim ARGS(( FILE *in_fp, XimImage *xim ));
  17. static int ReadXimHeader ARGS(( FILE *in_fp, XimImage *header ));
  18. static int ReadXimImage ARGS(( FILE *in_fp, XimImage *xim ));
  19. static int ReadImageChannel ARGS(( FILE *infp, byte *buf, unsigned int *bufsize, int encoded ));
  20.  
  21. int
  22. main( argc, argv )
  23.     int argc;
  24.     char *argv[];
  25.     {
  26.     FILE *ifp;
  27.     XimImage xim;
  28.     pixel *pixelrow, colormap[256];
  29.     register pixel *pP;
  30.     int argn, rows, cols, row, mapped;
  31.     register int col;
  32.     pixval maxval;
  33.  
  34.  
  35.     ppm_init( &argc, argv );
  36.  
  37.     argn = 1;
  38.  
  39.     if ( argn < argc )
  40.     {
  41.     ifp = pm_openr( argv[argn] );
  42.     ++argn;
  43.     }
  44.     else
  45.     ifp = stdin;
  46.  
  47.     if ( argn != argc )
  48.     pm_usage( "[ximfile]" );
  49.  
  50.     if ( ! ReadXim( ifp, &xim ) )
  51.     pm_error( "can't read Xim file" );
  52.     rows = xim.height;
  53.     cols = xim.width;
  54.     if ( xim.nchannels == 1 && xim.bits_channel == 8 )
  55.     {
  56.     int i;
  57.  
  58.     mapped = 1;
  59.     maxval = 255;
  60.     for ( i = 0; i < xim.ncolors; ++i )
  61.         {
  62.         PPM_ASSIGN(
  63.         colormap[i], xim.colors[i].red,
  64.         xim.colors[i].grn, xim.colors[i].blu );
  65.         /* Should be colormap[xim.colors[i].pixel], but Xim is broken. */
  66.         }
  67.     }
  68.     else if ( xim.nchannels == 3 )
  69.     {
  70.     mapped = 0;
  71.     maxval = pm_bitstomaxval( xim.bits_channel );
  72.     }
  73.     else
  74.     pm_error(
  75.         "unknown Xim file type, nchannels == %d, bits_channel == %d",
  76.         xim.nchannels, xim.bits_channel );
  77.  
  78.     ppm_writeppminit( stdout, cols, rows, maxval, 0 );
  79.     pixelrow = ppm_allocrow( cols );
  80.  
  81.     for ( row = 0; row < rows; ++row )
  82.     {
  83.     if ( mapped )
  84.         {
  85.         register byte *xbp;
  86.  
  87.         for ( col = 0, pP = pixelrow,
  88.               xbp = xim.data + row * xim.bytes_per_line;
  89.           col < cols;
  90.           ++col, ++pP, ++xbp )
  91.         *pP = colormap[*xbp];
  92.         }
  93.     else
  94.         {
  95.         register byte *xrbp, *xgbp, *xbbp;
  96.  
  97.         for ( col = 0, pP = pixelrow,
  98.               xrbp = xim.data + row * xim.bytes_per_line,
  99.               xgbp = xim.grn_data + row * xim.bytes_per_line,
  100.               xbbp = xim.blu_data + row * xim.bytes_per_line;
  101.           col < cols;
  102.           ++col, ++pP, ++xrbp, ++xgbp, ++xbbp )
  103.         PPM_ASSIGN( *pP, *xrbp, *xgbp, *xbbp );
  104.         }
  105.     ppm_writeppmrow( stdout, pixelrow, cols, maxval, 0 );
  106.     }
  107.     pm_close( ifp );
  108.     pm_close( stdout );
  109.     exit( 0 );
  110.     }
  111.  
  112. /* The rest is excerpted and slightly modified from the X.V11R4 version
  113. ** of xim_io.c.
  114. */
  115.  
  116. /***********************************************************************
  117. *  File:   xlib.c
  118. *  Author: Philip Thompson
  119. *  $Date: 89/11/01 10:14:23 $
  120. *  $Revision: 1.14 $
  121. *  Purpose: General xim libray of utililities
  122. *  Copyright (c) 1988  Philip R. Thompson
  123. *                Computer Resource Laboratory (CRL)
  124. *                Dept. of Architecture and Planning
  125. *                M.I.T., Rm 9-526
  126. *                Cambridge, MA  02139
  127. *   This  software and its documentation may be used, copied, modified,
  128. *   and distributed for any purpose without fee, provided:
  129. *       --  The above copyright notice appears in all copies.
  130. *       --  This disclaimer appears in all source code copies.
  131. *       --  The names of M.I.T. and the CRL are not used in advertising
  132. *           or publicity pertaining to distribution of the software
  133. *           without prior specific written permission from me or CRL.
  134. *   I provide this software freely as a public service.  It is NOT a
  135. *   commercial product, and therefore is not subject to an an implied
  136. *   warranty of merchantability or fitness for a particular purpose.  I
  137. *   provide it as is, without warranty.
  138. *   This software is furnished  only on the basis that any party who
  139. *   receives it indemnifies and holds harmless the parties who furnish
  140. *   it against any claims, demands, or liabilities connected with using
  141. *   it, furnishing it to others, or providing it to a third party.
  142. *
  143. *   Philip R. Thompson (phils@athena.mit.edu)
  144. ***********************************************************************/
  145.  
  146. static int
  147. ReadXim(in_fp, xim)
  148.     FILE *in_fp;
  149.     XimImage *xim;
  150. {
  151.     if (!ReadXimHeader(in_fp, xim)) {
  152.         pm_message("can't read xim header" );
  153.     return(0);
  154.     }
  155.     if (!ReadXimImage(in_fp, xim)) {
  156.         pm_message("can't read xim data" );
  157.     return(0);
  158.     }
  159.     return(1);
  160. }
  161.  
  162. static int
  163. ReadXimHeader(in_fp, header)
  164.     FILE *in_fp;
  165.     XimImage  *header;
  166. {
  167.     int  i;
  168.     char *cp;
  169.     XimAsciiHeader  a_head;
  170.  
  171.     cp = (char *) header;
  172.     for (i = 0; i < sizeof(XimImage); ++i )
  173.     *cp++ = 0;
  174.     /* Read header and verify image file formats */
  175.     if (fread((char *)&a_head, sizeof(ImageHeader), 1, in_fp) != 1) {
  176.         pm_message("ReadXimHeader: unable to read file header" );
  177.         return(0);
  178.     }
  179.     if (atoi(a_head.header_size) != sizeof(ImageHeader)) {
  180.         pm_message("ReadXimHeader: header size mismatch" );
  181.         return(0);
  182.     }
  183.     if (atoi(a_head.file_version) != IMAGE_VERSION) {
  184.         pm_message("ReadXimHeader: incorrect Image_file version" );
  185.         return(0);
  186.     }
  187.     header->width = atoi(a_head.image_width);
  188.     header->height = atoi(a_head.image_height);
  189.     header->ncolors = atoi(a_head.num_colors);
  190.     header->nchannels = atoi(a_head.num_channels);
  191.     header->bytes_per_line = atoi(a_head.bytes_per_line);
  192. /*    header->npics = atoi(a_head.num_pictures);
  193. */
  194.     header->bits_channel = atoi(a_head.bits_per_channel);
  195.     header->alpha_flag = atoi(a_head.alpha_channel);
  196.     if (strlen(a_head.author)) {
  197.         if (!(header->author = calloc((unsigned int)strlen(a_head.author)+1,
  198.                 1))) {
  199.             pm_message("ReadXimHeader: can't calloc author string" );
  200.             return(0);
  201.         }
  202.     header->width = atoi(a_head.image_width);
  203.         strncpy(header->author, a_head.author, strlen(a_head.author));
  204.     }
  205.     if (strlen(a_head.date)) {
  206.         if (!(header->date =calloc((unsigned int)strlen(a_head.date)+1,1))){
  207.             pm_message("ReadXimHeader: can't calloc date string" );
  208.             return(0);
  209.         }
  210.     header->width = atoi(a_head.image_width);
  211.         strncpy(header->date, a_head.date, strlen(a_head.date));
  212.     }
  213.     if (strlen(a_head.program)) {
  214.         if (!(header->program = calloc(
  215.                     (unsigned int)strlen(a_head.program) + 1, 1))) {
  216.             pm_message("ReadXimHeader: can't calloc program string" );
  217.             return(0);
  218.         }
  219.     header->width = atoi(a_head.image_width);
  220.         strncpy(header->program, a_head.program,strlen(a_head.program));
  221.     }
  222.     /* Do double checking for bakwards compatibility */
  223.     if (header->npics == 0)
  224.         header->npics = 1;
  225.     if (header->bits_channel == 0)
  226.         header->bits_channel = 8;
  227.     else if (header->bits_channel == 24) {
  228.         header->nchannels = 3;
  229.         header->bits_channel = 8;
  230.     }
  231.     if ((int)header->bytes_per_line == 0)
  232.         if (header->bits_channel == 1 && header->nchannels == 1)
  233.             header->bytes_per_line = (header->width + 7) / 8;
  234.         else
  235.             header->bytes_per_line = header->width;
  236.     header->datasize =(unsigned int)header->bytes_per_line * header->height;
  237.     if (header->nchannels == 3 && header->bits_channel == 8)
  238.         header->ncolors = 0;
  239.     else if (header->nchannels == 1 && header->bits_channel == 8) {
  240.         header->colors = (Color *)calloc((unsigned int)header->ncolors,
  241.                 sizeof(Color));
  242.         if (header->colors == NULL) {
  243.             pm_message("ReadXimHeader: can't calloc colors" );
  244.             return(0);
  245.         }
  246.         for (i=0; i < header->ncolors; i++) {
  247.             header->colors[i].red = a_head.c_map[i][0];
  248.             header->colors[i].grn = a_head.c_map[i][1];
  249.             header->colors[i].blu = a_head.c_map[i][2];
  250.         }
  251.     }
  252.     return(1);
  253. }
  254.  
  255. static int
  256. ReadXimImage(in_fp, xim)
  257.     FILE *in_fp;
  258.     XimImage *xim;
  259. {
  260.     if (xim->data) {
  261.         free((char *)xim->data);
  262.         xim->data = (byte *)0;
  263.     }
  264.     if (xim->grn_data) {
  265.         free((char *)xim->grn_data);
  266.         xim->grn_data = (byte *)0;
  267.     }
  268.     if (xim->blu_data) {
  269.         free((char *)xim->blu_data);
  270.         xim->blu_data = (byte *)0;
  271.     }
  272.     if (xim->other) {
  273.         free((char *)xim->other);
  274.         xim->other = (byte *)0;
  275.     }
  276.     xim->npics = 0;
  277.     if (!(xim->data = (byte *)calloc(xim->datasize, 1))) {
  278.         pm_message("ReadXimImage: can't malloc pixmap data" );
  279.         return(0);
  280.     }
  281.     if (!ReadImageChannel(in_fp, xim->data, &xim->datasize, 0)) {
  282.         pm_message("ReadXimImage: end of the images" );
  283.         return(0);
  284.     }
  285.     if (xim->nchannels == 3) {
  286.         xim->grn_data = (byte *)malloc(xim->datasize);
  287.         xim->blu_data = (byte *)malloc(xim->datasize);
  288.         if (xim->grn_data == NULL || xim->blu_data == NULL) {
  289.             pm_message("ReadXimImage: can't malloc rgb channel data" );
  290.             free((char *)xim->data);
  291.             if (xim->grn_data)  free((char *)xim->grn_data);
  292.             if (xim->blu_data)  free((char *)xim->blu_data);
  293.             xim->data = xim->grn_data = xim->blu_data = (byte*)0;
  294.             return(0);
  295.         }
  296.         if (!ReadImageChannel(in_fp, xim->grn_data, &xim->datasize, 0))
  297.             return(0);
  298.         if (!ReadImageChannel(in_fp, xim->blu_data, &xim->datasize, 0))
  299.             return(0);
  300.     }
  301.     if (xim->alpha_flag) {
  302.         if ((xim->other = (byte *)malloc(xim->datasize)) == NULL) {
  303.             pm_message("ReadXimImage: can't malloc alpha data" );
  304.             return(0);
  305.         }
  306.         if (!ReadImageChannel(in_fp, xim->other, &xim->datasize, 0))
  307.             return(0);
  308.     }
  309.     xim->npics = 1;
  310.     return(1);
  311. }
  312.  
  313. static int
  314. ReadImageChannel(infp, buf, bufsize, encoded)
  315. FILE *infp;
  316.     byte  *buf;
  317.     unsigned int  *bufsize;
  318.     int  encoded;
  319. {
  320.     register int  i, runlen, nbytes;
  321.     register unsigned int  j;
  322.     register byte *line;
  323.     long  marker;
  324.  
  325.     if (!encoded)
  326.         j = fread((char *)buf, 1, (int)*bufsize, infp);
  327.     else {
  328.         if ((line=(byte *)malloc((unsigned int)BUFSIZ)) == NULL) {
  329.             pm_message("ReadImageChannel: can't malloc() fread string" );
  330.             return(0);
  331.         }
  332.         /* Unrunlength encode data */
  333.         marker = ftell(infp);
  334.         j = 0;
  335.         while (((nbytes=fread((char *)line, 1, BUFSIZ, infp)) > 0) &&
  336.             (j < *bufsize)) {
  337.             for (i=0; (i < nbytes) && (j < *bufsize); i++) {
  338.                 runlen = (int)line[i]+1;
  339.                 i++;
  340.                 while (runlen--)
  341.                     buf[j++] = line[i];
  342.             }
  343.             marker += i;
  344.         }
  345.         /* return to the begining of the next image's bufffer */
  346.         if (fseek(infp, marker, 0) == -1) {
  347.             pm_message("ReadImageChannel: can't fseek to location in image buffer" );
  348.             return(0);
  349.         }
  350.         free((char *)line);
  351.     }
  352.     if (j != *bufsize) {
  353.         pm_message("unable to complete channel: %u / %u (%d%%)",
  354.             j, *bufsize, (int)(j*100.0 / *bufsize) );
  355.         *bufsize = j;
  356.     }
  357.     return(1);
  358. }
  359.