/* Copyright (c) 1992 - 1994 Norbert Meyer & Heinz W. Werntges. */
/** to_img.c: converts the HP2xx-intern bitmap into a GEM bit-
** image file, normally labelled with the extension
** IMG --- part of project "hp2xx" (from Heinz Werntges).
**
** The IMG-format was originally proposed as standard
** bit-image format for the graphical enviroment GEM
** by Digital Research which is used by the Atari ST
** and TT computers (GEM and the IMG-format are also
** available for IBM PC-compatible computers). But
** during the first years other pixel graphic formats
** became popular. Now, the Atari ST, TT-series begins
** to diversify and the IMG-format has a Renaissance,
** since it is independent from the used screen type.
** In future the IMG-format will be one of the most
** important pixel graphic-formats for Atari ST, TT-
** computers.
**
** A second reason why the IMG-format is important is
** the fact, that the Public Domain Atari-TeX supports
** it - and HP2xx has the intent to be a tool for TeX.
**
**
** 91/12/13 V 1.00 NM Originating (Friday, 13th!)
** 92/01/26 V 1.01 NM Bottom-up order, ANSI style calls
** 92/02/28 V 1.02 NM Percent information instead of activity-points
** 92/05/17 V 1.02b HWW Output to stdout if outfile == '-'
** 92/05/19 V 1.02c HWW Abort if color mode
** 92/11/08 V 1.02d HWW File opening changed to standard
** 94/02/14 V 1.10a HWW Adapted to changes in hp2xx.h
**
** NOTE by HWW: This file is maintained by NM (due to lack of time,
** only occasionally). Recent changes done by myself
** only resulted out of necessity. Volunteer maintainers for
** this file should contact NM (for his address, see file
** hp2xx.c). I guess he'll be willing to hand this job over.
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bresnham.h"
#include "hp2xx.h"
int vert_rep_IMG(PicBuf *pb, int y) {
/* counts number of vertical repetitions of a row below y */
int vert_rep=0; /* vertical repetition factor */
DevPt p; /* position in row */
int cmp_y; /* row number of compared row */
int linelen; /* number of bytes of tile line */
Byte *line,*l0;
line=(Byte*)malloc(pb->ksix); /* buffer for one tile line */
if (!line) {
Eprintf("vert_rep_IMG: cannot allocate %d buffer bytes.\n",
pb->ksix);
return 0;
}
for (cmp_y=y+1; y<pb->pext.y; y++) {
for (p.x = 0; p.x<pb->pext.x; p.x+=pb->ksi) {
p.y=y;
l0=GetTileLine(pb,&p,&linelen);
memcpy(line,l0,linelen);
/* must be buffered, L0 may be void after next GetTileLine() */
p.y=cmp_y;
if (memcmp(line,GetTileLine(pb,&p,NULL),linelen)) goto exi;
/* found first difference! */
}
vert_rep++; /* All line pieces are equal */
if (vert_rep>=254) break;
}
exi:
free(line);
return vert_rep;
}
/* ---------------------------------------------------------------- */
Byte get_byte_IMG(PicBuf *pb, int x_byte, int y) {
DevPt p;
Byte *line;
p.x=(x_byte<<pb->dsh)&~(pb->ksi-1);
p.y=y;
line=GetTileLine(pb,&p,NULL);
if (!line) return 0;
return line[x_byte&(pb->ksix-1)];
}
int SR_IMG (PicBuf *pb, int x, int y, Byte cmp) {
/* determines number of empty or full solid runs
starting at actual byte position */
int SR_c = 0; /* counts solid runs */
int cmp_pos; /* it's position */
int Img_w = pb->nb; /* number of bytes/row */
for (cmp_pos = x; cmp_pos < Img_w; cmp_pos++) {
if(get_byte_IMG(pb,cmp_pos, y)!=cmp) break;
SR_c++;
if (SR_c >= 127) break;
}
return SR_c;
}
/* ---------------------------------------------------------------- */
int PR_IMG(PicBuf *pb, int pos, int row_c) {
/* determines number of pattern runs starting at actual position */
int PR_c = 0; /* counts full solid runs */
Byte first_byte; /* first byte of pattern (2 bytes) */
Byte second_byte; /* second byte of pattern */
Byte cmp_1st_byte; /* 1st byte for comparision */
Byte cmp_2nd_byte; /* 2nd byte for comparision */
int cmp_pos; /* actual position */
int Img_w = pb->nb; /* number of bytes/row */
if (pos + 3 < Img_w)
{
/* actual position is not end of the row */
first_byte = get_byte_IMG(pb,pos,row_c);
second_byte = get_byte_IMG(pb,pos+1,row_c);
for(cmp_pos = pos + 2; cmp_pos + 1 < Img_w; cmp_pos += 2)
{
cmp_1st_byte = get_byte_IMG(pb,cmp_pos,row_c);
cmp_2nd_byte = get_byte_IMG(pb,cmp_pos+1,row_c);
if (cmp_1st_byte != first_byte || cmp_2nd_byte != second_byte)
break;
PR_c++;
if (PR_c >= 254)
break;
}
return PR_c;
} else
/* actual position to close to the end of the row */
return 0;
}
/* ---------------------------------------------------------------- */
static int
write_byte_IMG (Byte write_byte, FILE *fd)
/* Writes one Byte to the opened IMG-file */
{
if (fputc((int)write_byte, fd) == EOF)
{
PError("\nhp2xx --- writing IMG file:");
return ERROR;
}
return 0;
}
/* ---------------------------------------------------------------- */
int write_VR_IMG (Byte number, FILE *fd) {
/* Writes vertical repetition label to the opened IMG-file */
int err;
err = write_byte_IMG((Byte)0, fd);
if (err) return err;
err = write_byte_IMG((Byte)0, fd);
if (err) return err;
err = write_byte_IMG((Byte)255, fd);
if (err) return err;
return write_byte_IMG(number, fd);
}
/* ---------------------------------------------------------------- */
static int
write_PR_IMG ( Byte number, Byte first_byte, Byte second_byte, FILE *fd)
/* Writes pattern run label to the opened IMG-file */
{
int err;
err = write_byte_IMG((Byte)0, fd);
if (err) return err;
err = write_byte_IMG(number, fd);
if (err) return err;
err = write_byte_IMG(first_byte, fd);
if (err) return err;
return write_byte_IMG(second_byte, fd);
}
/* ---------------------------------------------------------------- */
static int
write_empty_SR_IMG (Byte number, FILE *fd)
/* Writes empty solid run to the opened IMG-file */
{
return write_byte_IMG(number, fd);
}
/* ---------------------------------------------------------------- */
static int
write_full_SR_IMG (Byte number, FILE *fd)
/* Writes empty solid run to the opened IMG-file */
{
Byte write_byte = (Byte)128;
write_byte = write_byte | number;
return write_byte_IMG(write_byte, fd);
}
/* ---------------------------------------------------------------- */
static int
write_BS_IMG (Byte number, FILE *fd)
/* Writes bit string label to the opened IMG-file */
{
int err;
err = write_byte_IMG((Byte)128, fd);
if (err) return err;
return write_byte_IMG(number, fd);
}
/* ---------------------------------------------------------------- */
typedef struct { /* All MOTOROLA (Big Endian) notation */
short version; /* version number */
short hlength; /* header length (in WORDs) */
short bpp; /* bit per pixel */
short prun; /* length of pattern run */
short pwidth; /* width of pixel in um */
short pheight; /* height of pixel in um */
short width; /* X extent */
short height; /* Y extent */
} IMGHEADER;
int PicBuf_to_IMG (const GEN_PAR *pg, const OUT_PAR *po) {
IMGHEADER h;
FILE *fd; /* file descriptor */
int row_c; /* row counter */
int Img_w = po->picbuf->nb; /* bytes per row */
int Img_h = po->picbuf->pext.y; /* number of lines */
int Dpi_x = po->dpi_x; /* dots per inch */
int Dpi_y = po->dpi_y;
int vert_rep; /* vertical repetitions */
Byte act_byte; /* actual byte */
int act_pos; /* actual byte-position in the row */
int first_pos = 0; /* first pos. of bit string */
int last_pos = 0; /* last pos. of bit string */
int i_pos; /* loop index */
int open_BS; /* was a bit string opened? */
int empty_SR_len; /* length of empty solid run */
int full_SR_len; /* length of full solid run */
int PR_len; /* length of pattern run */
int BS_len; /* length of bit string */
int err;
PicBuf *pb;
pb=po->picbuf;
if (pb->depth>1) {
Eprintf ( "\nIMG mode does not support colors yet -- sorry\n");
return ERROR;
}
/* */
/* action message */
/* */
if (!pg->quiet) {
Eprintf("\n\nWriting IMG output: %d rows of %d bytes\n",
pb->pext.y, pb->nb);
Eprintf ("\n%s:\no open",
*po->outfile == '-' ? "<stdout>" : po->outfile);
}
if (*po->outfile != '-') {
fd=FOPEN(po->outfile, WRITE_BIN);
if (!fd) {
PError ("hp2xx -- opening output file");
return ERROR;
}
}else fd=stdout;
/**
** write header (8 words)
**/
if (!pg->quiet) Eprintf ("\no write\n - header");
h.version =MOTORS(1);
h.hlength =MOTORS(8);
h.bpp =MOTORS(1);
h.prun =MOTORS(2);
h.pwidth =MOTORS(25400/Dpi_x);
h.pheight =MOTORS(25400/Dpi_y);
h.width =MOTORS(Img_w*8);
h.height =MOTORS(Img_h);
if (fwrite(&h,sizeof(h),1,fd)!=1) {
err=ERROR;
goto IMG_exit;
}
if (!pg->quiet) Eprintf ("\n - data: ");
/**
** Loop over all lines
**/
for (row_c = 0; row_c < Img_h; row_c++) {
if (!pg->quiet) ShowPercent(row_c,Img_h);
/* */
/* Determine vertical repetition */
/* */
if ((vert_rep = vert_rep_IMG(pb, row_c)) > 0) {
row_c += vert_rep;
if (!pg->quiet) ShowPercent(row_c,Img_h);
if ((err = write_VR_IMG((Byte)(vert_rep + 1), fd)) != 0) goto IMG_exit;
}
/**
** Analyse actual row in detail
**/
/* prepare bit string switch */
open_BS = FALSE;
/* prepare byte position */
act_pos = 0;
/**
** Loop over all bytes in actual row
**/
do {
if(open_BS == TRUE ) {
/* bit string was opened before */
if ( (empty_SR_len = SR_IMG(pb,act_pos,row_c,0)) > 3
|| (full_SR_len = SR_IMG(pb,act_pos,row_c,0xFF)) > 3
|| (PR_len = PR_IMG(pb,act_pos,row_c)) > 2
|| act_pos >= Img_w - 1
|| last_pos - first_pos + 1 >= 254) {
/* it's worth to stop the bit string */
open_BS = FALSE;
if (act_pos >= Img_w -1) { /* special case: */
last_pos = act_pos; /* last byte in row */
act_pos++;
}
BS_len = last_pos - first_pos + 1;
if ((err = write_BS_IMG((Byte)BS_len, fd)) != 0) goto IMG_exit;
for (i_pos = first_pos; i_pos <= last_pos; i_pos++) {
act_byte = get_byte_IMG(pb,i_pos,row_c);
if ((err = write_byte_IMG(act_byte, fd)) != 0) goto IMG_exit;
}
}else{ /* the bit string should continue */
last_pos = act_pos;
act_pos++;
}
}else{ /* no bit string open */
if ((empty_SR_len = SR_IMG(pb,act_pos,row_c,0)) > 0) {
act_pos += empty_SR_len;
if ((err = write_empty_SR_IMG((Byte)empty_SR_len, fd)) != 0)
goto IMG_exit;
}else if ((full_SR_len = SR_IMG(pb,act_pos,row_c,0xFF)) > 0) {
act_pos += full_SR_len;
if ((err = write_full_SR_IMG((Byte)full_SR_len, fd)) != 0)
goto IMG_exit;
}else if ((PR_len = PR_IMG(pb,act_pos,row_c)) > 0) {
if ((err = write_PR_IMG((Byte)(PR_len + 1),
get_byte_IMG(pb,act_pos,row_c),
get_byte_IMG(pb,act_pos+1,row_c),
fd)) != 0) goto IMG_exit;
act_pos += (PR_len + 1) * 2;
}else{ /* remaining: bit string, open it */
open_BS = TRUE;
first_pos = act_pos;
last_pos = act_pos;
if (act_pos < Img_w - 1)
act_pos++;
}
}
}while (act_pos < Img_w);
}
if(!pg->quiet) Eprintf("\no close\n");
IMG_exit:
if (fd && fd!=stdout && fclose(fd)) {
PError("\nhp2xx -- closing IMG:");
return ERROR;
}
if(!pg->quiet) Eprintf("\n(End of IMG)\n");
return err;
}
Detected encoding: UTF-8 | 0
|