|
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 |
}
|