PGM and PBM to QL

Authors

Publication

Pub Details

Date

Pages

See all articles from QL Hacker's Journal 10

Editor’s Note – There is a Freeware Unix package called PBMPLUS that converts to/from a number of graphics formats. It does this by using three intermediate formats, PBM, PGM, and PPM. Herb Schaaf has written a C program that will convert a PGM and PBM file to the QL. Since the conversion is going from a large number of colors to only 8, don’t expect the results to be astonishing.

I find it interesting to see Herb take the time to figure out the PGM and PBM file formats and how to convert them to the QL. Both of us hope that some of you will find it useful.

/*   pgmtoql8_c Sample C Program to read a
* file such as al125.pgm (pixel gray scale)
* and display on QL in 8 color mode
* May 22, 1992 9am
*/

#include <stdio_h>
#include <qlib_h>
#include <qdos_h>
#include <string.h>

#define MAX_I 130 /* maximum image dimension */
/* based on 2x2 block size */
#define LEFT_EDGE 126 /* for image out screen */

char _PROG_NAME[] = "pgmtoql8";

struct QLRECT grawin, *grwin;
FILE *fp_grwn; /* file pointer for graphic window */
FILE *fp_in; /* file pointer for input images */
unsigned char in_image[MAX_I*MAX_I];
/* input image array */
unsigned char out_image[MAX_I*MAX_I];
/* output image array */
unsigned char rid_one[1];
/* get 'rid' of one byte */
char img_type[6]; /* image file type (P5 = gray) */
char filein[36]; /* input file name */
char grayvals[4]; /* keyboard input values */
long width, height; /* input image width, height */
int max_color, max_count; /* maximum color value */
int present; /* number of color values found */
int pixels; /* number of pels read in from file */
long colors[256]; /* histogram of density ? */
long maxcount; /* highest count in colors[] */
int color; /* for colors[] */
int levels; /* number of grey levels */
int row, col, block; /* loop control values */
int x, y, w, h; /* QLRECT values */
long to_grwn, to_in;
int count;

main()
{
/* get name of image file */
printf("name of image file ?\nsuch as flp2_AL125_PGM
or\nflp2_MNDRL125_PGM\n");
gets(filein);
printf("%s\n",filein);
/* open image file to read */
fp_in = fopen(filein,"rb"); /* read binary file */
if (fp_in == NULL)
{
printf("Error Opening image file %s\n",filein);
printf("Touch ENTER");
getch();
exit(1);
}
to_in = getchid(fileno(fp_in));
printf("opened input file #%u located at %u\n",fileno
(fp_in), fp_in);
/* set mode, etc. */
grwin = &grawin;
mt_dmode("8","0");
fp_grwn = freopen("scr_512x256a0x0","w",stdout);
to_grwn = getchid(fileno(stdout));
sd_bordr(to_grwn,-1,2,2);
sd_setst(to_grwn,-1,6);
sd_setpa(to_grwn,-1,6);
sd_setsz(to_grwn,-1,1,0);
sd_setin(to_grwn,-1,1);
grwin->q_width = 256; w = grawin.q_width;
grwin->q_height = 256; h = grawin.q_height;
grwin->q_x = LEFT_EDGE; x = grawin.q_x;
grwin->q_y = 0; y = grawin.q_y;
sd_clear(to_grwn,-1);
sd_clear(stderr,-1);

/* read header information */
printf("Reading Header information\n - - - \n\n");
read_pgm_header(fp_in);
printf("\nplease wait - - reading pixels\n");

if((width >= MAX_I) || (height >= MAX_I)){
printf("%d wide by %d high is oversize\n",width,
height);
printf("limit is %d x %d\n",MAX_I-1,MAX_I-1);
printf("\n touch [space-bar] to exit");
getch(); exit(1);
}
/* read image into 1 dimensional array */
pixels = fread(in_image, sizeof(unsigned char),width*
height,fp_in);
fclose(fp_in);
printf(" %d pixels\n\n",pixels);

/* 'grey' shades */

printf("gray shades ? 2 to 255 ");
gets(grayvals);
printf(" %s\n",grayvals);
levels = 256 / (atoi(grayvals));
/* Histogram ? */
sd_setin(to_grwn,-1,0);
for (row = 0; row <= (pixels/width); row++)
{
for (col = 0; col <= width; col++)
{
color = in_image[col + (row*width)];
colors[color] = colors[color] + 1;
}
}
printf("touch ENTER\n");
getch();

/* find maximum and missing values */
maxcount = 0;
present = 256;
printf("values missing for:\n");
for (count = 0; count <= 255; count++)
{

if(maxcount < colors[count])
{
maxcount = colors[count];
max_count = count;
}
if(colors[count] == 0)
{
printf("%4d",count);
present--;
}
}
printf("\n%d values found \n%d has the maximum
count of %d\n", present, max_count, maxcount);

printf("\ntouch ENTER\n");
getch();
sd_bordr(to_grwn,-1,0,0);
sd_clear(to_grwn,-1);
/* draw lines */
sd_iscale(to_grwn,-1,256,0,0);
for (count = 0; count <= 255; count++)
{
sd_iline(to_grwn,-1, 0,count, colors[count], count);
}
sd_pos(to_grwn,-1,20,22);
printf("touch ENTER\n");
getch();


/* change by some function for new output file */
/* let's try dividing into grey levels */
/* or the inversion idea 255 - value */

/* set size of block for pixelating */
block = 2;
grwin->q_width = block; w = grawin.q_width;
grwin->q_height = block; h = grawin.q_height;
for (row = 0; row <= (pixels/width); row++)
{
grwin->q_y = 0+(block*row); y = grawin.q_y;
for (col = 0; col <= width; col++)
{
grwin->q_x=LEFT_EDGE+(block*col); x = grawin.q_x;
out_image[col + (row*width)] = in_image[col +
(row*width)] / levels;

/* now we need a little plotting going on */
sd_fill(to_grwn,-1,out_image[col + (row*width)]
,grwin);
}

}
/* hang on until we see it */
grwin->q_width = 512; w = grawin.q_width;
grwin->q_height = 256; h = grawin.q_height;
grwin->q_x = 0; x = grawin.q_x;
grwin->q_y = 0; y = grawin.q_y;
sd_setin(to_grwn,-1,0);
getch();
printf("ENTER to leave");
getch();
fclose(fp_grwn);
exit(0);
}

int getint(fp) /* from John Bradley's */
FILE *fp; /* XV version 2.00 */
{ /* as of 02/01/92 */
int c, i;
int garbage, numgot=0;
/* skip ahead */
c = getc(fp);
while(1) {
/* comments ? */
if (c == '#'){ /* found a comment */
while(c != '\n' && c != EOF) {
c = getc(fp);
printf("%c",c);
}
}
if (c == EOF){
return 0;
}
if ( c >='0' && c <= '9') break; /* found a number */
if ( c != ' ' && c != '\t' && c != '\r' && c != '\n'
&& c != ',') garbage = 1;
c = getc(fp);
}

/* go until non-number */
i = 0;
while(1){
i = (i*10) + (c - '0');
c = getc(fp);
if ( c == EOF) return i;
if ( c < '0' || c > '9') break;
}
numgot++;
return i;
}

read_pgm_header(fp)
FILE *fp;

{
int c, c1, file_type;
c = getc(fp);
c1 = getc(fp);
if(c!='P' || c1<'5' || c1>'6') {
printf("PGM error: unsupported format.\n");
printf("Must be raw grayscale or color.\n");
getch(); exit(1);
}
img_type[0]=c; img_type[1]=c1; img_type[3]='\0';
printf("Image type: %s\n",img_type);
width = getint(fp);
printf("%d wide\n",width);
height= getint(fp);
printf("%d high\n",height);
max_color = getint(fp);
printf("%d colors\n",max_color);
if ( max_color <= 0){
printf("PGM error: Garbage in Header\n");
getch(); exit(1);
}
return (c1-'0');
}

/* end of pgmtoql8_c May 22, 1992 noon */
/* pbmtoql2C_c
* H. L. Schaaf
* Program to read a bit mapped black/white file
* such as ram2_out_pbm from RDSphere programs
* and display on QL in 2 color mode, block size == 1
* compensates for density by discounting guide boxes etc.
* compile with %300000 -bufp150K
* returns 96% and 20% memory usage
* June 3, 1992 11:15
*/

#include <stdio_h>
#include <qlib_h>
#include <qdos_h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#define MAX_W 512 /* maximum image dimension */
#define MAX_H 256 /* based on 1x1 block size */
#define LEFT_EDGE 0 /* for image out screen */
#define IMAGE_DOTS 86400 /* assumes 360 x 240 */

char _PROG_NAME[] = "pbmtoql2C";

struct QLRECT grawin, *grwin;
FILE *fp_grwn; /* file pointer for graphic window */
FILE *fp_in; /* file pointer for input images */
unsigned char in_image[MAX_H*MAX_W];/* input image array */
char img_type[6]; /* image file type (P4 = b&w) */
char filein[36]; /* input file name */
int width, height; /* input image width, height */
int img_bytes; /* number of bytes in image */
int row, col, block; /* loop control values */
int x, y, w, h; /* QLRECT values */
long to_grwn, to_in; /* QL channel id */
int bp, img_byte, count, ort;
unsigned char bit_string[9];
int byte_count, wite_count, hite_count;


main()
{
/* get name of image file */
sd_clear(fgetchid(stdout),-1);
printf("name of image file ?\nsuch as flp1_SP1_PBM \n");
gets(filein);
printf("\n%s\n",filein);
/* open image file to read */
fp_in = fopen(filein,"rb"); /* read binary file */
if (fp_in == NULL)
{
printf("Error Opening image file %s\n",filein);
printf("Touch [space-bar]");
getch(); exit(1);
}
to_in = getchid(fileno(fp_in));
printf("opened input file #%u located at %u\n",fileno
(fp_in), fp_in);
printf("\n touch [space-bar]\n");
getch();
/* set mode, etc. */
grwin = &grawin;
mt_dmode("4","0");
fp_grwn = freopen("scr_512x256a0x0","w",stdout);
to_grwn = getchid(fileno(stdout));
sd_bordr(to_grwn,-1,0,0);
sd_setst(to_grwn,-1,6);
sd_setpa(to_grwn,-1,7);
sd_setsz(to_grwn,-1,1,0);
sd_setin(to_grwn,-1,0);
grwin->q_width = 512; w = grawin.q_width;
grwin->q_height = 256; h = grawin.q_height;
grwin->q_x = LEFT_EDGE; x = grawin.q_x;
grwin->q_y = 0; y = grawin.q_y;
sd_clear(to_grwn,-1);
sd_clear(stderr,-1);

/* read header information */
printf("\nReading Header information\n - - - \n\n");
read_pbm_header(fp_in);
printf("\nplease wait - - reading bytes\n");

/* read image into 1 dimensional array */
img_bytes = fread(in_image, sizeof(unsigned char),(width
*height)/8,fp_in);
fclose(fp_in);
printf(" %d img_bytes\n\n",img_bytes);
printf("touch [space-bar]\n");
getch();
sd_clear(to_grwn,-1);
/* density == bits set per image */
count = hite_count = wite_count= 0;
/* set size of block for pixelating */

block = 1;
grwin->q_width = block; w = grawin.q_width;
grwin->q_height = block; h = grawin.q_height;


for (byte_count=0; byte_count<img_bytes; byte_count++) {
img_byte = in_image[byte_count];
for ( bp = 0; bp < 8; bp++) {
if(img_byte > 127) {
img_byte -= 128;
grwin->q_x = LEFT_EDGE + wite_count;
grwin->q_y = hite_count;
x = grawin.q_x; y = grawin.q_y;
sd_fill(to_grwn,-1,0,grwin);
count++;
}
img_byte <<= 1;
wite_count++;
if(wite_count == width) {
wite_count = 0;
hite_count++;
}
}
}

getch();

/* hang on until we see it */
grwin->q_width = 512; w = grawin.q_width;
grwin->q_height = 256; h = grawin.q_height;
grwin->q_x = 0; x = grawin.q_x;
grwin->q_y = 0; y = grawin.q_y;
sd_setin(to_grwn,-1,0);
sd_tab(to_grwn,-1,48);
count -= 96; /* take out guide boxes */
printf("count = %d\n",count);
sd_tab(to_grwn,-1,48);
printf("last x = %d\n",wite_count);
sd_tab(to_grwn,-1,48);
printf("last y = %d\n",hite_count);
sd_tab(to_grwn,-1,48);
printf("width = %d\n",width);
sd_tab(to_grwn,-1,48);
printf("%d/%d = \n",(100*count),IMAGE_DOTS);
sd_tab(to_grwn,-1,48);
printf("%d with\n",(100*count)/IMAGE_DOTS);
ort = (100*count) % IMAGE_DOTS;
sd_tab(to_grwn,-1,48);
printf("%d left over\n",ort);
ort = ort*100;
ort = ort/IMAGE_DOTS;
getch();
sd_tab(to_grwn,-1,48);
sd_tab(to_grwn,-1,48);
printf("density:\n");
sd_tab(to_grwn,-1,48);
sd_tab(to_grwn,-1,48);
printf("%3d.%2d %%\n",((100*count)/(IMAGE_DOTS)),ort);
printf("\n\n");
sd_tab(to_grwn,-1,48);
printf(" [space-bar]\n");
sd_tab(to_grwn,-1,48);
printf(" to leave\n");
getch();
fclose(fp_grwn);
exit(0);
}


read_pbm_header(fp)
FILE *fp;
{
int c, c1, file_type;
c = getc(fp);
c1 = getc(fp);
if(c != 'P' || c1 != '4') {
printf("PBM error: unsupported format.\n");
printf("must be bitmapped black/white.\n");
getch(); exit(1);
}
img_type[0]=c; img_type[1]=c1; img_type[3]='\0';
printf("image type: %s\n",img_type);
width = getint(fp);
printf("%d wide\n",width);
height= getint(fp);
printf("%d high\n",height);
return( c1 - '0');
}


int getint(fp) /* from John Bradley's */
FILE *fp; /* xv version 2.00 */
{ /* as of 02/01/92 */
int c, i;
int garbage, numgot=0;
/* skip ahead */
c = getc(fp);
while(1) {
/* comments ? */
if (c == '#'){ /* found a comment */
printf("#");
while(c != '\n' && c != EOF) {
c = getc(fp);
printf("%c",c);
}
}
if (c == EOF){
return 0;
}
if ( c >='0' && c <= '9') break; /* found a number */
if ( c != ' ' && c != '\t' && c != '\r' && c != '\n'
&& c != ',') garbage = 1;
c = getc(fp);
}

/* go until non-number */
i = 0;
while(1){
i = (i*10) + (c - '0');
c = getc(fp);
if ( c == EOF) return i;
if ( c < '0' || c > '9') break;
}
numgot++;
return i;
}

itoab(n, s, b) /* convert integer to string in base b */
int n; char *s; int b;
{
char *ptr;
int lowbit;
ptr = s;
b >>= 1;
do {
lowbit = n & 1;
n = ( n >> 1 ) & INT_MAX;
*ptr = ((n%b) << 1) + lowbit;
if( *ptr <10)
*ptr += '0';
else *ptr += 55;
++ptr;
}
while (n /= b);
*ptr = 0;
reverse (s);
}


reverse(s) /* reverse string in place */
char *s;
{
char *j;
int c;
j=s+strlen(s) -1;
while(s < j) {
c = *s;
*s++ = *j;
*j-- = c;
}
}


itoa(n,s) /* convert int n to string s */
char *s; int n;
{
int sign;
char *ptr;
ptr = s;
if((sign=n)<0) n= -n;
do{
*ptr++ = n % 10 + '0';
} while (( n = n / 10) > 0);
if ( sign <0) *ptr++ = '-';
*ptr = '\0';
reverse(s);
}

/* end of pbmtoql2C_c June 3, 1992 11:45 */

Products

 

Downloadable Media

 
Scroll to Top