Source file: /~heha/hs/dos/hp2xx_hs.zip/to_img.c

/* 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: ASCII (7 bit)2