Abstract

This document (and its accompanying attachment) describes the program code used to download and decode image data received from the PicturePerfect adapter. Refer to "An Integrated External Video Monitor, Digitizer, Frame Buffer, and Transmitter" and its associated disclosures for more information.


Image Reception and Decoding Software for Standard Parallel Interface

Problem Solved:

It was necessary to develop IBM PC software to download image data from the PicturePerfect image capture adapter, in order to test the adapter's hardware design and make use of its capabilities.

Known Prior Art:

No products known to the author are capable of receiving 24-bit color image data through the IBM parallel printer port.

Description of Invention:

The attached code (get15.c) downloads a 640 x 400 pixel, 24-bit color image from the PicturePerfect image capture adapter through the standard IBM parallel printer port, converts the image to a 15-bit color format, and stores it to disk in a 512,000-byte MS-DOS file. For each pixel received, it downloads 6 nibbles (4-bit quantities) containing red, green, and blue color values (2 nibbles each). The nibbilizing is necessary because the standard printer port cannot safely be used to receive 8 bits at a time. On a 33 MHz i486-based PC platform, the software requires approximately 15 seconds to download and store the image data.

Applicability:

This software embodies a useful technique for receiving 24-bit color image data through the standard IBM parallel printer port. It could be adapted for use with flatbed scanners, manually operated digitizers, and other external video peripherals.

 


//**********************************************************
//* *
//* GET15.C *
//* *
//* Captures 15-bit PicturePerfect image file *
//* *
//* C>get15 outfile *
//* *
//* C source compatible with Turbo C++ v1.0 or later *
//* *
//**********************************************************
#pragma inline
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <alloc.h>
unsigned char lnib[256],hnib[256];
unsigned char line[640*2];
char outfile[128];
/***************************************************************/
void make_nibtabs(void)
{
int i,j,k;
for (i=0;i<256;i++)
{
j = ((i&0x38) >> 3) | ((i&0x80) >> 4);
k = ((i&0x38) << 1) | (i&0x80);
lnib[i] = j;
hnib[i] = k;
}
}
/***************************************************************/
void init_PPerf(void)
{
int y;
asm{
mov dx,378h;
mov al,80h; xor al,80h; out dx,al; // clear port lines, reset VRAMs
mov al,0h; xor al,80h; out dx,al;
}
for (y=0;y<1000;y++); // wait > 32 CLK14's
}
/***************************************************************/
void download_row(void)
{
int x;
int r,g,b;
for (x=0;x<(640*2);x+=2)
{
asm{
mov dx,378h; mov al,0; xor al,80h; out dx,al; // select RL
jmp $+2; mov dx,379h; in al,dx; and al,0xb8; xor al,80h;
lea bx,lnib; xlat; mov BYTE PTR r,al;
mov dx,378h; mov al,1; xor al,80h; out dx,al; // select RH
jmp $+2; mov dx,379h; in al,dx; and al,0xb8; xor al,80h;
lea bx,hnib; xlat; or BYTE PTR r,al;
mov dx,378h; mov al,2; xor al,80h; out dx,al; // select GL
jmp $+2; mov dx,379h; in al,dx; and al,0xb8; xor al,80h;
lea bx,lnib; xlat; mov BYTE PTR g,al;
mov dx,378h; mov al,3; xor al,80h; out dx,al; // select GH
jmp $+2; mov dx,379h; in al,dx; and al,0xb8; xor al,80h;
lea bx,hnib; xlat; or BYTE PTR g,al;
mov dx,378h; mov al,4; xor al,80h; out dx,al; // select BL
jmp $+2; mov dx,379h; in al,dx; and al,0xb8; xor al,80h;
lea bx,lnib; xlat; mov BYTE PTR b,al;
mov dx,378h; mov al,5; xor al,80h; out dx,al; // select BH
jmp $+2; mov dx,379h; in al,dx; and al,0xb8; xor al,80h;
lea bx,hnib; xlat; or BYTE PTR b,al;
mov dx,378h; // strobe next word
mov al,64; xor al,80h; out dx,al;
mov al,0; xor al,80h; out dx,al;
}
line[x] = ((b & 248) >> 3) | ((g & 56) << 2);
line[x+1] = ((g & 192) >> 6) | ((r & 248) >> 1);
}
}
 
/***************************************************************/
void download_frame(void)
{
int y;
FILE *f1,*f2,*f3;
f1 = fopen("f1temp","w+b");
f2 = fopen("f2temp","w+b");
if ((f1==NULL) || (f2==NULL))
{
fprintf(stderr,"Can't open tempfiles.\n");
exit(3);
}
init_PPerf(); // reset VRAMs
for (y=1;(y<400);y+=2) // read & display field 0 (interlaced video)
{
download_row();
fwrite(line,640*2,1,f1);
}
for (y=0;(y<400);y+=2) // read & display field 1
{
download_row();
fwrite(line,640*2,1,f2);
}
fcloseall();
f1=fopen("f1temp","rb");
f2=fopen("f2temp","rb");
f3=fopen(outfile,"w+b");
for (y=0;y<200;y++)
{
fread(line,640*2,1,f2);
fwrite(line,640*2,1,f3);
fread(line,640*2,1,f1);
fwrite(line,640*2,1,f3);
}
fcloseall();
unlink("f1temp");
unlink("f2temp");
}
/***************************************************************/
void main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr,"Usage: get15 outfile\n");
exit(1);
}
strcpy(outfile,argv[1]);
make_nibtabs();
init_PPerf();
download_frame();
printf("Done\n"); putch(7);
}