Blame converter/other/pnmtoddif.c

Packit 78deda
/*
Packit 78deda
 * Author:      Burkhard Neidecker-Lutz
Packit 78deda
 *              Digital CEC Karlsruhe
Packit 78deda
 *      neideck@nestvx.enet.dec.com 
Packit 78deda
Packit 78deda
 Copyright (c) Digital Equipment Corporation, 1992
Packit 78deda
Packit 78deda
 Permission to use, copy, modify, and distribute this software and its
Packit 78deda
 documentation for any purpose and without fee is hereby granted,
Packit 78deda
 provided that the above copyright notice appear in all copies and that
Packit 78deda
 both that copyright notice and this permission notice appear in
Packit 78deda
 supporting documentation, and that the name of Digital Equipment
Packit 78deda
 Corporation not be used in advertising or publicity pertaining to
Packit 78deda
 distribution of the software without specific, written prior
Packit 78deda
 permission. Digital Equipment Corporation makes no representations
Packit 78deda
 about the suitability of this software for any purpose. It is provided
Packit 78deda
 "as is" without express or implied warranty.
Packit 78deda
Packit 78deda
 Version: 1.0           30.07.92
Packit 78deda
Packit 78deda
*/
Packit 78deda
Packit 78deda
#include <string.h>
Packit 78deda
Packit 78deda
#include "mallocvar.h"
Packit 78deda
#include "pnm.h"
Packit 78deda
Packit 78deda
/* The structure we use to convey all sorts of "magic" data to the DDIF */
Packit 78deda
/* header write procedure.                      */
Packit 78deda
Packit 78deda
typedef struct {
Packit 78deda
    int width;
Packit 78deda
    int height;
Packit 78deda
    int h_res;            /* Resolutions in dpi for bounding box */
Packit 78deda
    int v_res;
Packit 78deda
    int bits_per_pixel;
Packit 78deda
    int bytes_per_line;
Packit 78deda
    int spectral;         /* 2 == monochrome, 5 == rgb        */
Packit 78deda
    int components;
Packit 78deda
    int bits_per_component;
Packit 78deda
    int polarity;         /* zeromin == 2 , zeromax == 1      */
Packit 78deda
} imageparams;
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* ASN.1 basic encoding rules magic number */
Packit 78deda
#define UNIVERSAL 0
Packit 78deda
#define APPLICATION 1
Packit 78deda
#define CONTEXT 2
Packit 78deda
#define PRIVATE 3
Packit 78deda
Packit 78deda
#define PRIM 0
Packit 78deda
#define CONS 1
Packit 78deda
Packit 78deda
/* "tag": Emit an ASN tag of the specified class and tag number.    */
Packit 78deda
/* This is used in conjuntion with the                  */
Packit 78deda
/* wr_xxx routines that follow to construct the various ASN.1 entities. */
Packit 78deda
/* Writing each entity is a two-step process, where first the tag is    */
Packit 78deda
/* written and then the length and value.               */
Packit 78deda
/* All of these routines take a pointer to a pointer into an output */
Packit 78deda
/* buffer in the first argument and update it accordingly.      */
Packit 78deda
Packit 78deda
static void tag(unsigned char ** buffer, int cl, int constructed,
Packit 78deda
                unsigned int t)
Packit 78deda
{
Packit 78deda
    int tag_first;
Packit 78deda
    unsigned int stack[10];
Packit 78deda
    int sp;
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    tag_first = (cl << 6) | constructed << 5;
Packit 78deda
    if (t < 31) {         /* Short tag form   */
Packit 78deda
        *p++ = tag_first | t;
Packit 78deda
    } else {          /* Long tag form */
Packit 78deda
        *p++ = tag_first | 31;
Packit 78deda
        sp = 0;
Packit 78deda
        while (t > 0) {
Packit 78deda
            stack[sp++] = t & 0x7f; 
Packit 78deda
            t >>= 7;
Packit 78deda
        }
Packit 78deda
        while (--sp > 0) {  /* Tag values with continuation bits */
Packit 78deda
            *p++ = stack[sp] | 0x80;
Packit 78deda
        }
Packit 78deda
        *p++ = stack[0];    /* Last tag portion without continuation bit */
Packit 78deda
    }
Packit 78deda
    *buffer = p;      /* Update buffer pointer */
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Emit indefinite length encoding */
Packit 78deda
static void 
Packit 78deda
ind(unsigned char **buffer)
Packit 78deda
{
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    *p++ = 0x80;
Packit 78deda
    *buffer = p;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Emit ASN.1 NULL */
Packit 78deda
static void 
Packit 78deda
wr_null(unsigned char **buffer)
Packit 78deda
{
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    *p++ = 0;
Packit 78deda
    *buffer = p;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Emit ASN.1 length only into buffer, no data */
Packit 78deda
static void 
Packit 78deda
wr_length(unsigned char ** buffer, int amount)
Packit 78deda
{
Packit 78deda
    int length;
Packit 78deda
    unsigned int mask;
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    length = 4;
Packit 78deda
    mask = 0xff000000;
Packit 78deda
Packit 78deda
    if (amount < 128) {
Packit 78deda
        *p++ = amount;
Packit 78deda
    } else {          /* > 127 */
Packit 78deda
        while (!(amount & mask)) {  /* Search for first non-zero byte */
Packit 78deda
            mask >>= 8;
Packit 78deda
            --length;
Packit 78deda
        }
Packit 78deda
Packit 78deda
        *p++ = length | 0x80;       /* Number of length bytes */
Packit 78deda
Packit 78deda
        while (--length >= 0) {     /* Put length bytes   */
Packit 78deda
            *p++ =(amount >> (8*length)) & 0xff;
Packit 78deda
        }
Packit 78deda
Packit 78deda
    }
Packit 78deda
    *buffer = p;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* BER encode an integer and write it's length and value */
Packit 78deda
static void 
Packit 78deda
wr_int(unsigned char ** buffer, int val)
Packit 78deda
{
Packit 78deda
    int length;
Packit 78deda
    int sign;
Packit 78deda
    unsigned int mask;
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    if (val == 0) {
Packit 78deda
        *p++ = 1;               /* length */
Packit 78deda
        *p++ = 0;               /* value  */
Packit 78deda
    } else {
Packit 78deda
        sign = val < 0 ? 0xff : 0x00;   /* Sign bits */
Packit 78deda
        length = 4;
Packit 78deda
        mask  = 0xffu << 24;
Packit 78deda
        while ((val & mask) == sign) {  /* Find the smallest representation */
Packit 78deda
            length--;
Packit 78deda
            mask >>= 8;
Packit 78deda
        }
Packit 78deda
        sign = (0x80 << ((length-1)*8)) & val; /* New sign bit */
Packit 78deda
        if (((val < 0) && !sign) || ((val > 0) && sign)) { /* Sign error */
Packit 78deda
            length++;
Packit 78deda
        }
Packit 78deda
        *p++ = length;          /* length */
Packit 78deda
        while (--length >= 0) {
Packit 78deda
            *p++ = (val >> (8*length)) & 0xff;
Packit 78deda
        }
Packit 78deda
    }
Packit 78deda
    *buffer = p;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Emit and End Of Coding sequence  */
Packit 78deda
static void 
Packit 78deda
eoc(unsigned char ** buffer)
Packit 78deda
{
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    *p++ = 0;
Packit 78deda
    *p++ = 0;
Packit 78deda
    *buffer = p;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Emit a simple string */
Packit 78deda
static 
Packit 78deda
void wr_string(unsigned char ** const buffer, const char * const val)
Packit 78deda
{
Packit 78deda
    int length;
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    length  = strlen(val);        
Packit 78deda
    if (length > 127) {
Packit 78deda
        fprintf(stderr,"Can't encode length > 127 yet (%d)\n",length);
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
    *p++ = length;
Packit 78deda
    {
Packit 78deda
        const char * valCursor;
Packit 78deda
        for (valCursor = val; *valCursor; ++valCursor)
Packit 78deda
            *p++ = *valCursor;
Packit 78deda
    }
Packit 78deda
    *buffer = p;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Emit a ISOLATIN-1 string */
Packit 78deda
static void 
Packit 78deda
emit_isolatin1(unsigned char ** const buffer, const char * const val)
Packit 78deda
{
Packit 78deda
    int length;
Packit 78deda
    unsigned char *p = *buffer;
Packit 78deda
Packit 78deda
    length  = strlen(val) + 1;        /* One NULL byte and charset leader */
Packit 78deda
    if (length > 127) {
Packit 78deda
        fprintf(stderr,"Can't encode length > 127 yet (%d)\n",length);
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
    *p++ = length;
Packit 78deda
    *p++ = 1;             /* ISO LATIN-1 */
Packit 78deda
    {
Packit 78deda
        const char * valCursor;
Packit 78deda
        for (valCursor = val; *valCursor; ++valCursor)
Packit 78deda
            *p++ = *valCursor;
Packit 78deda
    }
Packit 78deda
    *buffer = p;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Write the DDIF grammar onto "file" up to the actual starting location */
Packit 78deda
/* of the image data. The "ip" structure needs to be set to the right    */
Packit 78deda
/* values. A lot of the values here are hardcoded to be just right for   */
Packit 78deda
/* the bit grammars that the PBMPLUS formats want.           */
Packit 78deda
Packit 78deda
static int 
Packit 78deda
write_header(FILE *file, imageparams *ip)
Packit 78deda
{
Packit 78deda
    unsigned char buffer[300];            /* Be careful with the size ! */
Packit 78deda
    unsigned char *p = buffer;
Packit 78deda
    int headersize;
Packit 78deda
    int bounding_x;
Packit 78deda
    int bounding_y;
Packit 78deda
    int i;
Packit 78deda
Packit 78deda
    /* Calculate the bounding box from the resolutions    */
Packit 78deda
    bounding_x = ((int) (1200 * ((double) (ip->width) / ip->h_res)));
Packit 78deda
    bounding_y = ((int) (1200 * ((double) (ip->height) / ip->v_res)));
Packit 78deda
Packit 78deda
    /* This is gross. The entire DDIF grammar is constructed by   */
Packit 78deda
    /* hand. The indentation is meant to indicate DDIF document structure */
Packit 78deda
Packit 78deda
    tag(&p,PRIVATE,CONS,16383); ind(&p);      /* DDIF Document */
Packit 78deda
    tag(&p,CONTEXT,CONS, 0); ind(&p);        /* Document Descriptor */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,1);  /* Major Version */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_int(&p,3);  /* Minor Version */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 2); wr_string(&p,"PBM+"); /* Product Indentifier */
Packit 78deda
    tag(&p,CONTEXT,CONS, 3); ind(&p);       /* Product Name */
Packit 78deda
    tag(&p,PRIVATE,PRIM, 9); emit_isolatin1(&p,"PBMPLUS Writer V1.0");
Packit 78deda
    eoc(&p);
Packit 78deda
    eoc(&p);                 /* Document Descriptor */
Packit 78deda
    tag(&p,CONTEXT,CONS, 1); ind(&p);        /* Document Header     */
Packit 78deda
    tag(&p,CONTEXT,CONS, 3); ind(&p);       /* Version */
Packit 78deda
    tag(&p,PRIVATE,PRIM, 9); emit_isolatin1(&p,"1.0");
Packit 78deda
    eoc(&p);
Packit 78deda
    eoc(&p);                 /* Document Header */
Packit 78deda
    tag(&p,CONTEXT,CONS, 2); ind(&p);        /* Document Content    */
Packit 78deda
    tag(&p,APPLICATION,CONS,2); ind(&p);    /* Segment Primitive    */
Packit 78deda
    eoc(&p);
Packit 78deda
    tag(&p,APPLICATION,CONS,2); ind(&p);    /* Segment  */
Packit 78deda
    tag(&p,CONTEXT,CONS, 3); ind(&p);      /* Segment Specific Attributes */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 2); wr_string(&p,"$I");  /* Category */
Packit 78deda
    tag(&p,CONTEXT,CONS,22); ind(&p);     /* Image Attributes */
Packit 78deda
    tag(&p,CONTEXT,CONS, 0); ind(&p);    /* Image Presentation Attributes */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_int(&p,0);  /* Pixel Path */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 2); wr_int(&p,270); /* Line Progression */
Packit 78deda
    tag(&p,CONTEXT,CONS, 3); ind(&p);   /* Pixel Aspect Ratio */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,1); /* PP Pixel Dist */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_int(&p,1); /* LP Pixel Dist */
Packit 78deda
    eoc(&p);                /* Pixel Aspect Ratio */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 4); wr_int(&p,ip->polarity);  
Packit 78deda
        /* Brightness Polarity */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 5); wr_int(&p,1);  /* Grid Type    */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 7); wr_int(&p,ip->spectral);  /* Spectral Mapping */
Packit 78deda
    tag(&p,CONTEXT,CONS,10); ind(&p);   /* Pixel Group Info */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,1); /* Pixel Group Size */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_int(&p,1); /* Pixel Group Order */
Packit 78deda
    eoc(&p);                /* Pixel Group Info */
Packit 78deda
    eoc(&p);                     /* Image Presentation Attributes */
Packit 78deda
    tag(&p,CONTEXT,CONS, 1); ind(&p);    /* Component Space Attributes */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,1);  /* Component Space Organization */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_int(&p,1);  /* Planes per Pixel */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 2); wr_int(&p,1);  /* Plane Significance   */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 3); wr_int(&p,ip->components);  
Packit 78deda
        /* Number of Components    */
Packit 78deda
    tag(&p,CONTEXT,CONS, 4); ind(&p);   /* Bits per Component   */
Packit 78deda
    for (i = 0; i < ip->components; i++) {
Packit 78deda
        tag(&p,UNIVERSAL,PRIM,2); wr_int(&p,ip->bits_per_component);
Packit 78deda
    }
Packit 78deda
    eoc(&p);                /* Bits per Component   */
Packit 78deda
    tag(&p,CONTEXT,CONS, 5); ind(&p);   /* Component Quantization Levels */
Packit 78deda
    for (i = 0; i < ip->components; i++) {
Packit 78deda
        tag(&p,UNIVERSAL,PRIM,2); wr_int(&p,1 << ip->bits_per_component);
Packit 78deda
    }
Packit 78deda
    eoc(&p);                /* Component Quantization Levels */
Packit 78deda
    eoc(&p);                 /* Component Space Attributes */
Packit 78deda
    eoc(&p);                  /* Image Attributes */
Packit 78deda
    tag(&p,CONTEXT,CONS,23); ind(&p);     /* Frame Parameters */
Packit 78deda
    tag(&p,CONTEXT,CONS, 1); ind(&p);    /* Bounding Box */
Packit 78deda
    tag(&p,CONTEXT,CONS, 0); ind(&p);   /* lower-left   */
Packit 78deda
    tag(&p,CONTEXT,CONS, 0); ind(&p);  /* XCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,0);
Packit 78deda
    eoc(&p);                           /* XCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,CONS, 1); ind(&p);  /* YCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,0);
Packit 78deda
    eoc(&p);                               /* YCoordinate  */
Packit 78deda
    eoc(&p);                /* lower left */
Packit 78deda
    tag(&p,CONTEXT,CONS, 1); ind(&p);       /* upper right */
Packit 78deda
    tag(&p,CONTEXT,CONS, 0); ind(&p);      /* XCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,bounding_x);
Packit 78deda
    eoc(&p);               /* XCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,CONS, 1); ind(&p);      /* YCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,bounding_y);
Packit 78deda
    eoc(&p);                   /* YCoordinate  */
Packit 78deda
    eoc(&p);                            /* upper right */
Packit 78deda
    eoc(&p);                 /* Bounding Box */
Packit 78deda
    tag(&p,CONTEXT,CONS, 4); ind(&p);    /* Frame Position */
Packit 78deda
    tag(&p,CONTEXT,CONS, 0); ind(&p);   /* XCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,0);
Packit 78deda
    eoc(&p);                /* XCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,CONS, 1); ind(&p);   /* YCoordinate  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,0);
Packit 78deda
    eoc(&p);                    /* YCoordinate  */
Packit 78deda
    eoc(&p);                 /* Frame Position */
Packit 78deda
    eoc(&p);                  /* Frame Parameters */
Packit 78deda
    eoc(&p);                        /* Segment Specific Attributes */
Packit 78deda
    eoc(&p);                    /* Segment */
Packit 78deda
    tag(&p,APPLICATION,CONS,17); ind(&p);   /* Image Data Descriptor */
Packit 78deda
    tag(&p,UNIVERSAL,CONS,16); ind(&p);    /* Sequence */
Packit 78deda
    tag(&p,CONTEXT,CONS, 0); ind(&p);     /* Image Coding Attributes */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_int(&p,ip->width); /* Pixels per Line    */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 2); wr_int(&p,ip->height);  /* Number of Lines  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 3); wr_int(&p,2);   /* Compression Type */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 5); wr_int(&p,0);   /* Data Offset  */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 6); wr_int(&p,ip->bits_per_pixel);  /* Pixel Stride */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 7); wr_int(&p,ip->bytes_per_line * 8);
Packit 78deda
        /* Scanline Stride    */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 8); wr_int(&p,1);   /* Bit Order        */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 9); wr_int(&p,ip->bits_per_pixel);  
Packit 78deda
        /* Planebits per Pixel */
Packit 78deda
    tag(&p,CONTEXT,CONS,10); ind(&p);    /* Byteorder Info   */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 0); wr_int(&p,1);  /* Byte Unit        */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_int(&p,1);  /* Byte Order   */
Packit 78deda
    eoc(&p);                 /* Byteorder Info   */
Packit 78deda
    tag(&p,CONTEXT,PRIM,11); wr_int(&p,3);   /* Data Type        */
Packit 78deda
    eoc(&p);                              /* Image Coding Attributes */
Packit 78deda
    tag(&p,CONTEXT,PRIM, 1); wr_length(&p,ip->bytes_per_line*ip->height);  
Packit 78deda
        /* Component Plane Data */
Packit 78deda
    /* End of DDIF document Indentation */
Packit 78deda
    headersize = p - buffer;
Packit 78deda
    if (headersize >= 300)  {
Packit 78deda
        fprintf(stderr,"Overran buffer area %d >= 300\n",headersize);
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
Packit 78deda
    return (fwrite(buffer, 1, headersize, file) == headersize);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
/* Write all the closing brackets of the DDIF grammar that are missing */
Packit 78deda
/* The strange indentation reflects exactly the same indentation that  */
Packit 78deda
/* we left off in the write_header procedure.                  */
Packit 78deda
static int 
Packit 78deda
write_trailer(FILE * file)
Packit 78deda
{
Packit 78deda
    unsigned char buffer[30];
Packit 78deda
    unsigned char *p = buffer;
Packit 78deda
    int trailersize;
Packit 78deda
Packit 78deda
    /* Indentation below gives DDIF document structure */
Packit 78deda
    eoc(&p);                        /* Sequence */
Packit 78deda
    eoc(&p);                     /* Image Data Descriptor */
Packit 78deda
    tag(&p,APPLICATION,PRIM,1); wr_null(&p);     /* End Segment */
Packit 78deda
    tag(&p,APPLICATION,PRIM,1); wr_null(&p);     /* End Segment */
Packit 78deda
    eoc(&p);                  /* Document Content */
Packit 78deda
    eoc(&p);                   /* DDIF Document */
Packit 78deda
    /* End of DDIF document Indentation */
Packit 78deda
    trailersize = p - buffer;
Packit 78deda
    if (trailersize >= 30)  {
Packit 78deda
        fprintf(stderr,"Overran buffer area %d >= 30\n",trailersize);
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
Packit 78deda
    return(fwrite(buffer, 1, trailersize, file) == trailersize);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
static void
Packit 78deda
convertPbmRaster(FILE *          const ifP,
Packit 78deda
                 int             const format,
Packit 78deda
                 unsigned int    const cols,
Packit 78deda
                 unsigned int    const rows,
Packit 78deda
                 FILE *          const ofP,
Packit 78deda
                 unsigned int    const bytesPerLine,
Packit 78deda
                 unsigned char * const data) {
Packit 78deda
                 
Packit 78deda
    bit * const pixels = pbm_allocrow(cols);
Packit 78deda
Packit 78deda
    unsigned int row;
Packit 78deda
Packit 78deda
    for (row = 0; row < rows; ++row) {
Packit 78deda
        unsigned int col;
Packit 78deda
        unsigned int k;
Packit 78deda
        unsigned int mask;
Packit 78deda
        unsigned char * p;
Packit 78deda
        size_t bytesWritten;
Packit 78deda
Packit 78deda
        pbm_readpbmrow(ifP, pixels, cols, format);
Packit 78deda
Packit 78deda
        mask = 0x00;
Packit 78deda
        p = &data[0];
Packit 78deda
        for (col = 0, k = 0; col < cols; ++col) {
Packit 78deda
            if (pixels[col] == PBM_BLACK)
Packit 78deda
                mask |= 1 << k;
Packit 78deda
            if (k == 7) {
Packit 78deda
                *p++ = mask;
Packit 78deda
                mask = 0x00;
Packit 78deda
                k = 0;
Packit 78deda
            } else
Packit 78deda
                ++k;
Packit 78deda
        }
Packit 78deda
        if (k != 7)
Packit 78deda
            /* Flush the rest of the column */
Packit 78deda
            *p = mask;
Packit 78deda
Packit 78deda
        bytesWritten =  fwrite(data, 1, bytesPerLine, ofP);
Packit 78deda
        if (bytesWritten != bytesPerLine)
Packit 78deda
            pm_error("File write error on Row %u", row);
Packit 78deda
    }
Packit 78deda
Packit 78deda
    pbm_freerow(pixels);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
static void
Packit 78deda
convertPgmRaster(FILE *          const ifP,
Packit 78deda
                 int             const format,
Packit 78deda
                 xelval          const maxval,
Packit 78deda
                 unsigned int    const cols,
Packit 78deda
                 unsigned int    const rows,
Packit 78deda
                 FILE *          const ofP,
Packit 78deda
                 unsigned int    const bytesPerLine,
Packit 78deda
                 unsigned char * const data) {
Packit 78deda
Packit 78deda
    gray * const pixels = pgm_allocrow(cols);
Packit 78deda
Packit 78deda
    unsigned int row;
Packit 78deda
Packit 78deda
    for (row = 0; row < rows; ++row) {
Packit 78deda
        unsigned char * p;
Packit 78deda
        unsigned int col;
Packit 78deda
        size_t bytesWritten;
Packit 78deda
Packit 78deda
        p = &data[0];
Packit 78deda
Packit 78deda
        pgm_readpgmrow(ifP, pixels, cols, maxval, format);
Packit 78deda
Packit 78deda
        for (col = 0; col < cols; ++col)
Packit 78deda
            *p++ = (unsigned char) pixels[col];
Packit 78deda
Packit 78deda
        bytesWritten = fwrite(data, 1, bytesPerLine, ofP);
Packit 78deda
        if (bytesWritten != bytesPerLine)
Packit 78deda
            pm_error("File write error on Row %u", row);
Packit 78deda
    }
Packit 78deda
    pgm_freerow(pixels);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
static void
Packit 78deda
convertPpmRaster(FILE *          const ifP,
Packit 78deda
                 int             const format,
Packit 78deda
                 xelval          const maxval,
Packit 78deda
                 unsigned int    const cols,
Packit 78deda
                 unsigned int    const rows,
Packit 78deda
                 FILE *          const ofP,
Packit 78deda
                 unsigned int    const bytesPerLine,
Packit 78deda
                 unsigned char * const data) {
Packit 78deda
Packit 78deda
    pixel * const pixels = ppm_allocrow(cols);
Packit 78deda
Packit 78deda
    unsigned int row;
Packit 78deda
Packit 78deda
    for (row = 0; row < rows; ++row) {
Packit 78deda
        unsigned char * p;
Packit 78deda
        unsigned int col;
Packit 78deda
        size_t bytesWritten;
Packit 78deda
Packit 78deda
        p = &data[0];
Packit 78deda
Packit 78deda
        ppm_readppmrow(ifP, pixels, cols, maxval, format);
Packit 78deda
Packit 78deda
        for (col = 0; col < cols; ++col) {
Packit 78deda
            *p++ = PPM_GETR(pixels[col]);
Packit 78deda
            *p++ = PPM_GETG(pixels[col]);
Packit 78deda
            *p++ = PPM_GETB(pixels[col]);
Packit 78deda
        }
Packit 78deda
        bytesWritten =  fwrite(data, 1, bytesPerLine, ofP);
Packit 78deda
        if (bytesWritten != bytesPerLine)
Packit 78deda
            pm_error("File write error on Row %u", row);
Packit 78deda
    }
Packit 78deda
    ppm_freerow(pixels);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
static void
Packit 78deda
convertRaster(FILE *       const ifP,
Packit 78deda
              int          const format,
Packit 78deda
              xelval       const maxval,
Packit 78deda
              unsigned int const cols,
Packit 78deda
              unsigned int const rows,
Packit 78deda
              FILE *       const ofP,
Packit 78deda
              unsigned int const bytesPerLine) {
Packit 78deda
Packit 78deda
    unsigned char * data;
Packit 78deda
Packit 78deda
    MALLOCARRAY(data, bytesPerLine);
Packit 78deda
Packit 78deda
    if (data == NULL)
Packit 78deda
        pm_error("Couldn't allocate %u-byte line buffer", bytesPerLine);
Packit 78deda
Packit 78deda
    switch (PNM_FORMAT_TYPE(format)) {
Packit 78deda
    case PBM_TYPE:
Packit 78deda
        convertPbmRaster(ifP, format, cols, rows, ofP, bytesPerLine, data);
Packit 78deda
        break;
Packit 78deda
    case PGM_TYPE:
Packit 78deda
        convertPgmRaster(ifP, format, maxval, cols, rows, ofP, bytesPerLine,
Packit 78deda
                         data);
Packit 78deda
        break;
Packit 78deda
    case PPM_TYPE:
Packit 78deda
        convertPpmRaster(ifP, format, maxval, cols, rows, ofP, bytesPerLine,
Packit 78deda
                         data);
Packit 78deda
        break;
Packit 78deda
    default:
Packit 78deda
        pm_error("INTERNAL ERROR: impossible format value");
Packit 78deda
    }
Packit 78deda
Packit 78deda
    free(data);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
int
Packit 78deda
main(int argc, char *argv[]) {
Packit 78deda
    FILE           *ifd;
Packit 78deda
    FILE           *ofd;
Packit 78deda
    int             rows, cols;
Packit 78deda
    xelval          maxval;
Packit 78deda
    int             format;
Packit 78deda
    const char     * const usage = "[-resolution x y] [pnmfile [ddiffile]]";
Packit 78deda
    char           *outfile;
Packit 78deda
    int       argn;
Packit 78deda
    int hor_resolution = 75;
Packit 78deda
    int ver_resolution = 75;
Packit 78deda
    imageparams ip;
Packit 78deda
Packit 78deda
    pnm_init(&argc, argv);
Packit 78deda
Packit 78deda
    for (argn = 1;argn < argc && argv[argn][0] == '-';argn++) {
Packit 78deda
        int arglen = strlen(argv[argn]);
Packit 78deda
Packit 78deda
        if (!strncmp (argv[argn],"-resolution", arglen)) {
Packit 78deda
            if (argn + 2 < argc) {
Packit 78deda
                hor_resolution = atoi(argv[argn+1]);
Packit 78deda
                ver_resolution = atoi(argv[argn+2]);
Packit 78deda
                argn += 2;
Packit 78deda
                continue;
Packit 78deda
            } else {
Packit 78deda
                pm_usage(usage);
Packit 78deda
            }
Packit 78deda
        } else {
Packit 78deda
            pm_usage(usage);
Packit 78deda
        }
Packit 78deda
    }
Packit 78deda
Packit 78deda
    if (hor_resolution <= 0 || ver_resolution <= 0) {
Packit 78deda
        fprintf(stderr,"Unreasonable resolution values: %d x %d\n",
Packit 78deda
                hor_resolution,ver_resolution);
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
Packit 78deda
    if (argn == argc - 2) {
Packit 78deda
        ifd = pm_openr(argv[argn]);
Packit 78deda
        outfile = argv[argn+1];
Packit 78deda
        if (!(ofd = fopen(outfile,"wb"))) {
Packit 78deda
            perror(outfile);
Packit 78deda
            exit(1);
Packit 78deda
        }
Packit 78deda
    } else if (argn == argc - 1) {
Packit 78deda
        ifd = pm_openr(argv[argn]);
Packit 78deda
        ofd = stdout;
Packit 78deda
    } else {
Packit 78deda
        ifd = stdin;
Packit 78deda
        ofd = stdout;
Packit 78deda
    }
Packit 78deda
Packit 78deda
    pnm_readpnminit(ifd, &cols, &rows, &maxval, &format);
Packit 78deda
Packit 78deda
    ip.width = cols;
Packit 78deda
    ip.height = rows;
Packit 78deda
    ip.h_res = hor_resolution;
Packit 78deda
    ip.v_res = ver_resolution;
Packit 78deda
Packit 78deda
    switch (PNM_FORMAT_TYPE(format)) {
Packit 78deda
    case PBM_TYPE:
Packit 78deda
        ip.bits_per_pixel = 1;
Packit Service ad4525
        overflow_add(cols, 7);
Packit 78deda
        ip.bytes_per_line = (cols + 7) / 8;
Packit 78deda
        ip.spectral = 2;
Packit 78deda
        ip.components = 1;
Packit 78deda
        ip.bits_per_component = 1;
Packit 78deda
        ip.polarity = 1;
Packit 78deda
        break;
Packit 78deda
    case PGM_TYPE:
Packit 78deda
        ip.bytes_per_line = cols;
Packit 78deda
        ip.bits_per_pixel = 8;
Packit 78deda
        ip.spectral = 2;
Packit 78deda
        ip.components = 1;
Packit 78deda
        ip.bits_per_component = 8;
Packit 78deda
        ip.polarity = 2;
Packit 78deda
        break;
Packit 78deda
    case PPM_TYPE:
Packit Service ad4525
        overflow2(cols, 3);
Packit 78deda
        ip.bytes_per_line = 3 * cols;
Packit 78deda
        ip.bits_per_pixel = 24;
Packit 78deda
        ip.spectral = 5;
Packit 78deda
        ip.components = 3;
Packit 78deda
        ip.bits_per_component = 8;
Packit 78deda
        ip.polarity = 2;
Packit 78deda
        break;
Packit 78deda
    default:
Packit 78deda
        fprintf(stderr, "Unrecognized PBMPLUS format %d\n", format);
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
Packit 78deda
    if (!write_header(ofd,&ip)) {
Packit 78deda
        perror("Writing header");
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
Packit 78deda
    convertRaster(ifd, format, maxval, cols, rows, ofd, ip.bytes_per_line);
Packit 78deda
Packit 78deda
    pm_close(ifd);
Packit 78deda
Packit 78deda
    if (!write_trailer(ofd)) {
Packit 78deda
        perror("Writing trailer");
Packit 78deda
        exit(1);
Packit 78deda
    }
Packit 78deda
Packit 78deda
    if (fclose(ofd) == EOF) {
Packit 78deda
        perror("Closing output file");
Packit 78deda
        exit(1);
Packit 78deda
    };
Packit 78deda
Packit 78deda
    return(0);
Packit 78deda
}