Category : Files from Magazines
Archive   : CUJ0894.ZIP
Filename : FAXSCALE.OLD

 
Output of file : FAXSCALE.OLD contained in archive : CUJ0894.ZIP
/***************************************************************
* file: FAXSCALE.C
* purpose: Minimalist scaler. Scales images over a range of
* 3% to 3200% with a worst case precision of 1/32. This code
* was designed to minimize data, stack and code requirements
* while being reasonably fast and accurate. Since the intended
* use is in fax machine, the scaled lines are clipped or white
* filled to FAX_WIDTH bytes. Refer to the function headers for
* more detailed information. Image lines follow the usual
* monochromatic format of 1 being black, 0 being white and
* bit 7 of each byte being the leftmost pixel. This code is
* an algorithm test bench. The production version is in
* assembly.
* environment: ANSI C tested with Borland 4.0, Zortech 3.1 and
* MSC 5.1
* contains:
* init_fax_scale() - initializes the scaler
* scale_fax_line() - scales a single image line
* copyright: 1992 by David Weber. Unlimited use is granted for
* noncommercial use or for commercial distribution in EXE, OBJ,
* or LIB formats. Do not sell as source without asking first.
* history:
* 06-09-92 - initial code
* 04-04-94 - polished, reformatted, retested, condensed
**************************************************************/

#include
#include
#include


/* data types and defines */

typedef unsigned long ROTATOR; /* rotator type sets scaling
* range and precision */
#define PRECISION (4 * 8) /* ANSI doesn't allow sizeof(ROTATOR)
* in preprocessor */
#define SCALE_MAX (PRECISION * 100) /* upper limit of scaler in % */
#define SCALE_MIN (100 / PRECISION) /* lower limit of scaler in % */
#define FAX_WIDTH 216 /* hardwired byte width of a fax line */

/* rotate instruction, just a kludge until assembly */
#define _ror(val) (val) = ((val) >> 1 | (val) << (PRECISION-1))


/* ROMmable const data */
/* sequential increase in bits per byte: do not change
* without looking closely at init_rotator() */
static const unsigned char pattern[] =
{0x00,0x10,0x44,0x94,0xaa,0xda,0xee,0xfe,0xff,0xff};


/* RAM data */
static ROTATOR x_rotator; /* rotating horizontal pattern */
static ROTATOR y_rotator; /* rotating vertical pattern */
static unsigned int source_width; /* number of bytes in a source line */
static unsigned char x_base; /* n/8 basis for x_rotator */
static unsigned char y_base; /* n/8 basis for y_rotator */


/* local functions */
static int init_rotator(int scale,ROTATOR *rotator,unsigned char *base);


/************************************************
* function: int init_fax_scale(int x_scale,int y_scale,unsigned int source_byte_width)
* Validate the scaling ranges and initialize the scaler. You
* must call this function first before you can use the scaler.
* parameters: horizontal and vertical scaling in percent followed
* by the byte width of a source line.
* returns: 1 if Ok or 0 if either scale is out of range
************************************************/
int init_fax_scale(int x_scale,int y_scale,unsigned int source_byte_width)
{
if (!init_rotator(x_scale,&x_rotator,&x_base))
return 0; /* set up x_rotator */
if (!init_rotator(y_scale,&y_rotator,&y_base))
return 0; /* set up y_rotator */
source_width = source_byte_width; /* save width */
if (((long)source_width * (long)x_scale) / 100L > FAX_WIDTH)
source_width = FAX_WIDTH; /* clip to fax line */
return 1;
}


/************************************************
* function: static int init_rotator(int scale,ROTATOR *rotator,unsigned char *base)
* local function calculates the rotator and basis.
* parameters: scale factor in percent, pointer to rotator,
* pointer to basis.
* returns: 1 if Ok or 0 if scale is out of range
************************************************/
static int init_rotator(int scale,ROTATOR *rotator,unsigned char *base)
{
unsigned int index,mix,i;

/* check scaling range */
if (scale < SCALE_MIN || scale > SCALE_MAX)
return 0;
/* set basis */
*base = scale / 100;
/* get index into pattern */
scale %= 100;
index = (scale * 8) / 100;
/* How we mix 2 consecutive patterns to achieve balance.
* Express it this way to handle round off. */
mix = pattern[((((scale * 8) % 100) + 4) * 8) / 100];
/* for each byte in the rotator, select an appropriate
* pattern byte based on the index and the mix */
*rotator = 0;
for (i = sizeof(ROTATOR) ; i > 0 ; i--)
{
*rotator <<= 8;
*rotator |= pattern[index + (mix & 0x01)];
mix >>= 1;
}
assert((*rotator + *base) != 0);
assert(*base <= PRECISION);
return 1;
}


/************************************************
* function: int scale_fax_line(unsigned char *dest, unsigned char *src)
* Scale the line from src to dest. dest will always be FAX_WIDTH
* wide even if it requires clipping or whiting out the tail. The
* return value indicates the number of times to repeat the line.
* A 0 return means skip it. This was done to keep buffer control in
* the caller. Call scale_fax_line() once for each source line.
* parameters: pointer to destination and source
* returns: number of times to repeat the line (0 to PRECISION)
************************************************/
int scale_fax_line(unsigned char *dest, unsigned char *src)
{
int y_repeat,x_repeat,i,bit;
unsigned int accum,byte;
unsigned char *start;
ROTATOR rotator;

/* get line repeat value and rotate to next */
y_repeat = y_base + (y_rotator & 0x01);
_ror(y_rotator);
/* if anything to do */
if (y_repeat)
{
rotator = x_rotator;
for (i=source_width, accum=1, start=dest ; i > 0 ; i--, src++)
{ /* each byte in the source line */
for (bit=8, byte=*src ; bit > 0 ; bit--)
{ /* for each bit in the byte */
x_repeat = x_base + (rotator & 1);
_ror(rotator); /* get repeat count and rotate */
while (x_repeat--)
{ /* for each repeat */
accum <<= 1; /* copy bit into accumulator */
accum += ((byte & 0x80) != 0);
if (accum & 0x100)
{ /* output a byte and reset sentinel */
*dest++ = accum & 0xff;
accum = 1;
}
}
byte <<= 1;
}
}
if (accum > 1)
{ /* handle fragment */
while ((accum & 0x100) == 0)
accum <<= 1;
*dest++ = accum & 0xff;
}
while (dest < start + FAX_WIDTH)
{ /* white out tail */
*dest++ = 0;
}
}
return y_repeat;
}


  3 Responses to “Category : Files from Magazines
Archive   : CUJ0894.ZIP
Filename : FAXSCALE.OLD

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/