home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************
- * file: DISPLAY.C
- * purpose: display a PCX file
- * contains:
- * display_file() - displays a file.
- * display_sample() - gets a pointer to a sample of the displayed file.
- * copyright: 1993 by David Weber. All rights reserved.
- * This software can be used for any purpose as object, library or executable.
- * It cannot be sold for profit as source code.
- * history:
- * 02-26-93 - initial code, cobbled from various stuff
- **************************************************************/
-
- #include <stdio.h>
- #include <io.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include "gui.h"
- #include "display.h"
- #include "zone.h"
-
- /* local prototypes */
- static int get_pcx_header(int fh);
- static unsigned int read_pcx(unsigned char *buffer,unsigned int number_of_bytes);
- static unsigned int read_source_buffer(void);
- static int open_scaler(int xscale,int yscale,DISPLAY_BOX *screen,DISPLAY_BOX *file);
- static int scaler(unsigned char *buffer);
- static void close_scaler(void);
- static int open_sampler(DISPLAY_BOX *file);
- static void get_sample(unsigned char *scaler_buffer,int ylines);
-
- /* local data */
- /* PCX */
- static int src_fh; /* file handle of source */
- static unsigned int bytes_per_line; /* byte width of image */
- static unsigned int lines_per_page; /* pixel length of image */
- static unsigned int src_bytes; /* byte count in buffer */
- static unsigned int src_size; /* size of buffer */
- static unsigned char *src_buffer; /* buffer pointer */
- /* SCALER */
- static unsigned char *scaler_buffer; /* buffer for scaler operations */
- static int scaler_in_bytes_per_line; /* input bytes per line */
- static int scaler_out_bytes_per_line; /* output bytes per line */
- static int scaler_error; /* scaler y error */
- static int scaler_delta; /* scale ratio delat error */
- static unsigned int scaler_buffer_size; /* minimum buffer size */
- static int scaler_lines; /* minimum lines in buffer */
- static short *scaler_offset; /* offset from line start for scaler_mask */
- static unsigned short *scaler_mask; /* bit mask of input line */
- static int scaler_xscale; /* x scale value in fixed point .00 */
- static int scaler_yscale; /* y scale value in fixed point .00 */
- /* DISPLAY */
- static unsigned char *display_buffers[MAX_DISPLAY_BUFFERS]; /* array of buffers for display */
- static int display_buffer_count = 0; /* number of allocated buffers */
- static int display_lines_per_buffer; /* number of lines in a buffer */
- static int display_bytes_per_line; /* number of bytes in a display_buffer line */
- static DISPLAY_BOX display_screen_box; /* screen info */
- static NUMBERED_BOX *numbered_boxes = NULL; /* numbered boxes outside of image */
- /* IMAGE SAMPLING */
- static int xsample,ysample,xdelta,ydelta; /* scaled image dimensions */
- static int sample_line; /* current sample line */
- static unsigned char *display_sample_ptr = NULL; /* pointer to sampled image */
-
- /************************************************
- * function: int display_file(char *filename)
- * Opens PCX file and displays same, displays error box
- * if it fails
- * parameters: pointer to file name
- * returns: 1 if done or 0 if failed
- ************************************************/
- int display_file(char *filename)
- {
- fg_box_t box;
- DISPLAY_BOX screen;
- int screen_aspect_ratio;
- DISPLAY_BOX file;
- int file_aspect_ratio;
- int xscale,yscale,i,skip_it;
- unsigned char *p;
-
- if (display_buffer_count > 0)
- { /* clear out previous buffers */
- for (i = 0 ; i < display_buffer_count ; i++)
- free(display_buffers[i]);
- display_buffer_count = 0;
- }
- if (display_sample_ptr != NULL)
- free(display_sample_ptr);
- screen.x = 0; /* size the display area on screen */
- screen.y = 0;
- screen.width = gui_screen_width;
- screen.height = gui_screen_height - 2 * gui_char_height;
- fg_make_box(box,0,0,screen.width-1,screen.height-1); /* clear screen */
- fg_msm_hidecursor();
- fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
- fg_msm_showcursor();
- if ((src_buffer = (unsigned char *) malloc(PCX_READ_BUFFER)) == NULL)
- { /* file read buffer */
- message_box("Out of memory.");
- return 0;
- }
- if ((src_fh = open(filename,O_RDONLY | O_BINARY)) == -1) /* open file */
- {
- message_box("Cannot open file.");
- free(src_buffer);
- return 0;
- }
- if (!get_pcx_header(src_fh)) /* decode header */
- {
- message_box("Not a valid monochrome PCX file.");
- free(src_buffer);
- close(src_fh);
- return 0;
- } /* the following calculations are fixed point .00 */
- screen_aspect_ratio = (int) (((long)gui_screen_width * 100L) / (long)gui_screen_height);
- file.x = file.y = 0; /* display area of file */
- file.width = bytes_per_line * 8;
- file.height = lines_per_page;
- file_aspect_ratio = (int) (((long)file.width * 100L) / (long)file.height);
- if (file.width < screen.width || file.height < screen.height)
- { /* if it has to be scaled up, it has too little info for region finding */
- message_box("PCX file too small for region finding.");
- free(src_buffer);
- close(src_fh);
- return 0;
- }
- if (IDEAL_SCREEN_ASPECT > file_aspect_ratio)
- { /* y major scaling */
- yscale = (int) (((long)file.height * 100L) / (long)screen.height);
- xscale = (int) (((long)yscale * (long)IDEAL_SCREEN_ASPECT) / (long)screen_aspect_ratio);
- screen.width = (int) (((long)file.width * 100L) / (long)xscale);
- screen.x = (gui_screen_width - screen.width) / 2;
- }
- else
- { /* x major scaling */
- xscale = (int) (((long)file.width * 100L) / (long)screen.width);
- yscale = (int) (((long)xscale * (long)screen_aspect_ratio) / (long)IDEAL_SCREEN_ASPECT);
- screen.height = (int) (((long)file.height * 100L) / (long)yscale);
- screen.y = (gui_screen_height - 2 * gui_char_height - screen.height) / 2;
- }
- src_bytes = src_size = 0;
- if (!open_scaler(xscale,yscale,&screen,&file)) /* set up scaler */
- {
- free(src_buffer);
- close(src_fh);
- message_box("Out of memory.");
- return 0;
- }
- display_screen_box = screen; /* set up display parameters */
- display_bytes_per_line = scaler_out_bytes_per_line;
- display_screen_box.width = display_bytes_per_line * 8;
- display_lines_per_buffer = DISPLAY_BUFFER_SIZE / display_bytes_per_line;
- fg_make_box(box,screen.x,screen.y,screen.x+screen.width-1,screen.y+screen.height-1);
- fg_msm_hidecursor();
- fg_fillbox(FG_WHITE,FG_MODE_SET,~0,box); /* draw blank page */
- fg_make_box(box,0,0,screen.width-1,0);
- for (i = skip_it = 0 ; i < screen.height ; i++) /* scale file to screen */
- {
- if ((i % display_lines_per_buffer) == 0)
- { /* need another array */
- if ((display_buffers[display_buffer_count] = (unsigned char *) malloc(DISPLAY_BUFFER_SIZE)) == NULL)
- {
- display_free();
- close_scaler();
- free(src_buffer);
- close(src_fh);
- fg_msm_showcursor();
- message_box("Out of memory.");
- return 0;
- }
- p = display_buffers[display_buffer_count];
- display_buffer_count++;
- }
- if (skip_it)
- memset(p,0,scaler_out_bytes_per_line);
- else if (!scaler(p))
- skip_it = 1;
- fg_drawmatrix(FG_BLACK,FG_MODE_SET,~0,FG_ROT0,screen.x,screen.y+screen.height-i-1,(char *)p,box,fg.displaybox);
- p += scaler_out_bytes_per_line;
- }
- fg_msm_showcursor();
- fg_flush();
- close_scaler();
- free(src_buffer);
- close(src_fh);
- return 1;
- }
-
-
- /************************************************
- * function: void display_free(void)
- * free display resources
- * parameters: none
- * returns: nothing
- ************************************************/
- void display_free(void)
- {
- int i;
-
- if (display_buffer_count > 0)
- { /* clear out previous buffers */
- for (i = 0 ; i < display_buffer_count ; i++)
- free(display_buffers[i]);
- display_buffer_count = 0;
- }
- if (display_sample_ptr != NULL) /* clear sample buffer */
- free(display_sample_ptr);
- }
-
-
- /************************************************
- * function: unsigned char *display_sample(int *samplex,int *sampley,int *dx,int *dy)
- * gets info on image sampled while scaling
- * parameters: pointers to x/y samples and x/y extents
- * returns: pointer to image base or NULL if none
- ************************************************/
- unsigned char *display_sample(int *samplex,int *sampley,int *dx,int *dy)
- {
- *samplex = xsample;
- *sampley = ysample;
- *dx = xdelta;
- *dy = ydelta;
- return display_sample_ptr;
- }
-
-
- /************************************************
- * function: void display_numbered_box_close(void)
- * clean up resources for numbered boxes
- * parameters: none
- * returns: nothing
- ************************************************/
- void display_numbered_box_close(void)
- {
- NUMBERED_BOX *p,*q;
-
- for (p = numbered_boxes ; p != NULL ; p = q)
- {
- q = p->next;
- free(p);
- }
- numbered_boxes = NULL;
- }
-
-
- /************************************************
- * function: void display_numbered_box(int x1,int y1,int x2,int y2,int num)
- * draws a numbered box around a region, coordinates are relative to file
- * parameters: x/y corners of the box and number of box
- * returns: nothing
- ************************************************/
- void display_numbered_box(int x1,int y1,int x2,int y2,int num)
- {
- fg_box_t box;
- fg_line_t line;
- char str[16];
- int len,x,y,wide_screen,num_width,num_height,retry,pass;
- NUMBERED_BOX *p,*q;
-
- /* scale to screen */
- x1 = (int) (((long)x1 * 100L + 50L) / (long) scaler_xscale);
- y1 = (int) (((long)y1 * 100L + 50L) / (long) scaler_yscale);
- x2 = (int) (((long)x2 * 100L + 50L) / (long) scaler_xscale);
- y2 = (int) (((long)y2 * 100L + 50L) / (long) scaler_yscale);
- /* outline box */
- fg_msm_hidecursor();
- fg_make_box(box,display_screen_box.x+x1,
- display_screen_box.y+display_screen_box.height-y2-1,
- display_screen_box.x+x2,
- display_screen_box.y+display_screen_box.height-y1-1);
- if (fg.nsimulcolor < 16)
- fg_drawbox(FG_BLACK,FG_MODE_SET,~0,FG_LINE_DENSE_DOTTED,box,fg.displaybox);
- else
- fg_drawbox(FG_LIGHT_RED,FG_MODE_SET,~0,FG_LINE_SOLID,box,fg.displaybox);
- sprintf(str,"%d",num);
- len = strlen(str);
- num_width = len * gui_char_width;
- num_height = gui_char_height;
- if (x2-x1+1 >= num_width && y2-y1+1 >= (2*num_height)/3)
- { /* put number in upper left of box */
- fg_make_box(box,display_screen_box.x+x1,
- display_screen_box.y+display_screen_box.height-y1-num_height,
- display_screen_box.x+x1+num_width-1,
- display_screen_box.y+display_screen_box.height-y1-1);
- fg_boxclip(fg.displaybox,box,box);
- if (fg.nsimulcolor < 16)
- {
- fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
- fg_puts(FG_WHITE,FG_MODE_SET,~0,FG_ROT0,display_screen_box.x+x1,
- display_screen_box.y+display_screen_box.height-y1-num_height,str,box);
- }
- else
- {
- fg_fillbox(FG_RED,FG_MODE_SET,~0,box);
- fg_puts(FG_YELLOW,FG_MODE_SET,~0,FG_ROT0,display_screen_box.x+x1,
- display_screen_box.y+display_screen_box.height-y1-num_height,str,box);
- }
- }
- else
- { /* draw line between number and box */
- if (display_screen_box.x == 0)
- { /* wide screen */
- wide_screen = 1;
- x = x1;
- if (y1 < display_screen_box.height/2) /* above */
- y = display_screen_box.y + display_screen_box.height + gui_char_height;
- else /* underneath */
- y = display_screen_box.y - 2 * gui_char_height;
- }
- else
- { /* tall screen */
- wide_screen = 0;
- y = display_screen_box.height-y1-1-gui_char_height;
- if (x1 < display_screen_box.width/2) /* left */
- x = display_screen_box.x - 4 * gui_char_width;
- else /* right */
- x = display_screen_box.x + display_screen_box.width + 2 * gui_char_width;
- }
- if (x < 0) /* size to screen */
- x = 0;
- if (x > gui_screen_width-2*gui_char_width)
- x = gui_screen_width-2*gui_char_width;
- if (y < 0)
- y = 0;
- if (y > gui_screen_height-3*gui_char_height)
- y = gui_screen_height-3*gui_char_height;
- for (p=numbered_boxes, pass=retry=0 ; pass < 64 ; p = p->next)
- { /* resolve overlaps */
- if (p->next == NULL)
- q = p;
- if (p == NULL)
- {
- if (retry == 0)
- break;
- retry = 0;
- p = numbered_boxes;
- }
- if (abs(p->x - x) < num_width && abs(p->y - y) < num_height)
- { /* have an overlap */
- if (wide_screen == 1)
- {
- x = p->x + p->width + gui_char_width; /* move right */
- if (x > gui_screen_width-num_width)
- { /* no more room */
- if (pass == 0)
- y = p->x - num_width - gui_char_width;
- else
- x = display_screen_box.width/2;
- }
- }
- else
- {
- y = p->y - num_height - 1; /* move down */
- if (y < 0)
- { /* no more room */
- if (pass == 0)
- y = p->y + num_height + 1;
- else
- y = display_screen_box.height/2;
- }
- }
- retry = 1;
- pass++;
- }
- }
- p = (NUMBERED_BOX *) malloc(sizeof(NUMBERED_BOX));
- if (p != NULL)
- {
- if (numbered_boxes == NULL)
- numbered_boxes = p;
- else
- q->next = p;
- p->next = NULL;
- p->x = x;
- p->y = y;
- p->width = num_width;
- p->height = num_height;
- fg_make_line(line,p->x+p->width/2,p->y+p->height/2,
- display_screen_box.x+x1+(x2-x1)/2,
- display_screen_box.y+display_screen_box.height-y1-1-(y2-y1)/2);
- fg_make_box(box,p->x,p->y,p->x+p->width-1,p->y+p->height-1);
- fg_boxclip(fg.displaybox,box,box);
- if (fg.nsimulcolor < 16)
- {
- fg_drawline(FG_BLACK,FG_MODE_SET,~0,FG_LINE_DENSE_DOTTED,line);
- line[FG_X1]--;
- line[FG_X2]--;
- line[FG_Y1]++;
- line[FG_Y2]++;
- fg_drawline(FG_WHITE,FG_MODE_SET,~0,FG_LINE_DENSE_DOTTED,line);
- fg_fillbox(FG_WHITE,FG_MODE_SET,~0,box);
- fg_puts(FG_BLACK,FG_MODE_SET,~0,FG_ROT0,p->x,p->y,str,box);
- }
- else
- {
- fg_drawline(FG_BLUE,FG_MODE_SET,~0,FG_LINE_DENSE_DOTTED,line);
- line[FG_X1]--;
- line[FG_X2]--;
- line[FG_Y1]++;
- line[FG_Y2]++;
- fg_drawline(FG_LIGHT_WHITE,FG_MODE_SET,~0,FG_LINE_DENSE_DOTTED,line);
- fg_fillbox(FG_RED,FG_MODE_SET,~0,box);
- fg_puts(FG_YELLOW,FG_MODE_SET,~0,FG_ROT0,p->x,p->y,str,box);
- }
- }
- }
- fg_msm_showcursor();
- fg_flush();
- }
-
-
- /************************************************
- * function: int display_redraw(void)
- * redraws image
- * parameters: none
- * returns: 1 if redrawn, 0 if nothing to draw
- ************************************************/
- int display_redraw(void)
- {
- fg_box_t box;
- int top,i,j,lines;
-
- if (display_buffer_count == 0)
- return 0;
- top = gui_screen_height - 2 * gui_char_height;
- fg_msm_hidecursor();
- if (display_screen_box.x == 0)
- { /* clear above and below */
- fg_make_box(box,0,0,gui_screen_width-1,display_screen_box.y-1);
- fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
- fg_make_box(box,0,display_screen_box.y+display_screen_box.height-1,
- gui_screen_width-1,top);
- fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
- }
- else
- {
- fg_make_box(box,0,0,display_screen_box.x-1,top);
- fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
- fg_make_box(box,display_screen_box.x+display_screen_box.width,0,
- gui_screen_width-1,top);
- fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
- }
- fg_make_box(box,display_screen_box.x,display_screen_box.y,
- display_screen_box.x+display_screen_box.width-1,
- display_screen_box.y+display_screen_box.height-1);
- fg_fillbox(FG_WHITE,FG_MODE_SET,~0,box);
- for (i=j=0 ; i < display_buffer_count ; i++, j+=display_lines_per_buffer)
- {
- if (j+display_lines_per_buffer > display_screen_box.height)
- lines = display_screen_box.height - j;
- else
- lines = display_lines_per_buffer;
- fg_make_box(box,0,0,display_screen_box.width-1,lines-1);
- fg_drawmatrix(FG_BLACK,FG_MODE_SET,~0,FG_ROT0,display_screen_box.x,
- display_screen_box.y+display_screen_box.height-j-lines,
- (char *)display_buffers[i],box,fg.displaybox);
- }
- fg_msm_showcursor();
- fg_flush();
- return 1;
- }
-
-
- /**************** LOCAL FUNCTIONS ****************/
-
- /************************************************
- * function: static unsigned int read_source_buffer(void)
- * parameters: none
- * returns: (unsigned int) -1 if EOF or failure, else returns amount read
- ************************************************/
- static unsigned int read_source_buffer(void)
- {
- src_size = read(src_fh,src_buffer,PCX_READ_BUFFER);
- src_bytes = 0;
- if (src_size <= 0)
- src_size = (unsigned int) -1;
- return src_size;
- }
-
-
- /* pcx structure and defines */
-
- #define PCX_HEADER_SIZE 128
- #define PCX_HEADER_USED 72
- #pragma ZTC align 1
- typedef struct
- {
- /* constants */
- unsigned char manuf; /* always 10 decimal */
- unsigned char hardvers; /* version */
- unsigned char pcxencodmode; /* 1 if run length encoding */
- /* calculated */
- unsigned char bitsppix;
- unsigned short x1;
- unsigned short y1;
- unsigned short x2;
- unsigned short y2;
- unsigned short hres; /* card horizontal res. */
- unsigned short vres; /* card vertical res. */
- unsigned char clrpa[16][3]; /* palette info */
- unsigned char vmode; /* ignored, should be 0 */
- unsigned char nplanes; /* number or planes */
- unsigned short bplin; /* bytes per line */
- unsigned short page_start;
- unsigned short page_length; /* page length in pixels */
- unsigned char reserved[PCX_HEADER_SIZE-PCX_HEADER_USED];
- } PCX_HEADER;
- #pragma ZTC align
-
- #define MAX_PCX_ENC_LEN (63) /* maximum pcx run length */
- #define PCX_MANUFACTURER 10 /* manufacturer's code */
- #define PCX_RUN_LENGTH 1 /* encoding type */
- #define PCX_8_BITS_PER_PIX 1 /* code for 8 bits per pixel */
- #define DCX_ID 987654321L /* dcx id code */
-
- /************************************************
- * function: int get_pcx_header(int fh)
- * read pcx header
- * parameters: fh = file handle
- * returns: 1 if success or 0 if error
- ************************************************/
- static int get_pcx_header(int fh)
- {
- PCX_HEADER header;
- long *l,src_offset;
-
- if ((src_offset = lseek(fh,0L,SEEK_CUR)) == -1)
- return 0;
- if (read(fh,(void *) &header,sizeof(header)) != sizeof(header))
- return 0;
- l = (long *) &header;
- if (*l == DCX_ID)
- {
- if (lseek(fh,*(++l)+src_offset,SEEK_SET) == -1)
- return 0;
- if (read(fh,(void *) &header,sizeof(header)) != sizeof(header))
- return 0;
- }
- if (header.manuf!=PCX_MANUFACTURER || header.pcxencodmode!=PCX_RUN_LENGTH ||
- header.bitsppix!=PCX_8_BITS_PER_PIX || header.nplanes != 1 ||
- header.x1>header.x2 || header.y1>header.y2)
- {
- return 0;
- }
- bytes_per_line = header.bplin;
- lines_per_page = header.page_length;
- return 1;
- }
-
-
- /* macro for accessing buffer */
- #define bget() \
- ((src_bytes < src_size) ? *(src_buffer+(src_bytes++)) : \
- ((read_source_buffer() == (unsigned int) -1) ? ((unsigned int) -1) : \
- (*(src_buffer+(src_bytes++)))))
- /************************************************
- * function: unsigned int read_pcx(unsigned char *buffer,unsigned int number_of_bytes)
- * parameters: buffer to read lines into and the number of bytes to read.
- * returns: size put into buffer if OK or -1 if failed or EOF
- ************************************************/
- static unsigned int read_pcx(unsigned char *buffer,unsigned int number_of_bytes)
- {
- unsigned int count,byt,cnt;
-
- count = 0;
- while (count < number_of_bytes)
- {
- if((byt=bget()) == (unsigned int) -1)
- return count;
- if((byt&0xc0) == 0xc0)
- {
- cnt = 0x3f & byt;
- if((byt=bget()) == (unsigned int) -1)
- return (unsigned int) -1;
- memset(buffer+count,(~byt)&0xff,cnt);
- }
- else
- {
- cnt = 1;
- *(buffer+count) = (~byt)&0xff;
- }
- count += cnt;
- }
- return count;
- }
-
-
- /************************************************
- * function: static int open_scaler(int xscale,int yscale,DISPLAY_BOX *screen,DISPLAY_BOX *file)
- * allocate scaler resources and preset scale values
- * parameters: scale factors in x & y, fixed point .00, screen and file sizes
- * returns: 1 if OK or 0 if failed cuz no memory
- ************************************************/
- static int open_scaler(int xscale,int yscale,DISPLAY_BOX *screen,DISPLAY_BOX *file)
- {
- unsigned int buffer_size,i;
- short pixel;
- unsigned short bit_pattern;
-
- if (!open_sampler(file)) /* set up sampler */
- return 0;
- scaler_lines = yscale/100; /* set up scale values */
- scaler_delta = yscale % 100;
- scaler_error = scaler_delta;
- scaler_in_bytes_per_line = (file->width + 7) / 8;
- scaler_out_bytes_per_line = (screen->width + 7) / 8;
- scaler_buffer_size = scaler_in_bytes_per_line * scaler_lines;
- buffer_size = scaler_buffer_size + scaler_in_bytes_per_line;
- if ((scaler_buffer = (unsigned char *) malloc(buffer_size)) == NULL)
- return 0; /* allocate line buffer */
- buffer_size = scaler_out_bytes_per_line * 8 * sizeof(short *);
- if ((scaler_offset = (short *) malloc(buffer_size)) == NULL)
- { /* allocate offset buffer */
- free(scaler_buffer);
- return 0;
- }
- buffer_size = scaler_out_bytes_per_line * 8 * sizeof(short);
- if ((scaler_mask = (unsigned short *) malloc(buffer_size)) == NULL)
- { /* allocate mask buffer */
- free(scaler_buffer);
- free(scaler_offset);
- return 0;
- }
- scaler_xscale = xscale;
- scaler_yscale = yscale;
- if (xscale < 1650) /* pattern of n bits in a word */
- bit_pattern = 0xffff << (16 - (xscale+50)/100);
- else
- bit_pattern = 0xffff;
- if (bit_pattern == 0)
- bit_pattern = 0x8000;
- for (i = 0 ; i < scaler_out_bytes_per_line * 8 ; i++)
- { /* set up offsets and masks */
- pixel = (short)(((long)i*(long)xscale)/100L);
- scaler_offset[i] = pixel/8;
- scaler_mask[i] = bit_pattern >> (pixel-(scaler_offset[i])*8);
- scaler_mask[i] = (scaler_mask[i]>>8) | (scaler_mask[i]<<8); /* intel byte order */
- }
- return 1;
- }
-
-
- /************************************************
- * function: static int scaler(unsigned char *buffer)
- * scales scan lines using ratios from open_scaler()
- * parameters: pointer to buffer for scaled line
- * returns: 1 if OK or 0 if all done scaling
- ************************************************/
- static int scaler(unsigned char *buffer)
- {
- unsigned int buffer_size,read_size,x,y,cutoff,accum,ylines;
- int retval;
- unsigned short bit_pattern;
- unsigned char *p;
- static unsigned char bit_mask[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
- static unsigned char bit_count[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
- 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
- 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
-
- retval = 1;
- if (scaler_error >= 50) /* (n+1) y lines */
- {
- buffer_size = scaler_buffer_size + scaler_in_bytes_per_line;
- ylines = scaler_lines + 1;
- scaler_error -= (100-scaler_delta);
- }
- else /* (n) y lines */
- {
- buffer_size = scaler_buffer_size;
- ylines = scaler_lines;
- scaler_error += scaler_delta;
- }
- memset(buffer,0,scaler_out_bytes_per_line); /* white out line */
- if ((read_size = read_pcx(scaler_buffer,buffer_size)) != buffer_size)
- { /* partial read */
- memset(scaler_buffer+read_size,0,buffer_size-read_size); /* white out remaining */
- retval = 0;
- }
- get_sample(scaler_buffer,ylines); /* get a sample */
- #if I_LOVE_BLACK
- if (scaler_xscale >= 1650) /* how many bits in accum are significant? */
- cutoff = (ylines * 16) / 3;
- else
- cutoff = (((scaler_xscale+50)*ylines)/3)/100;
- #else
- if (scaler_xscale >= 1650) /* how many bits in accum are significant? */
- cutoff = (ylines * 16) / 2;
- else
- cutoff = (((scaler_xscale+50)*ylines)/2)/100;
- #endif
- if (cutoff == 0)
- cutoff = 1;
- for (x = 0 ; x < (scaler_out_bytes_per_line << 3) ; x++)
- { /* for each output bit */
- for (y = accum = 0, p = scaler_buffer ; y < ylines ; y++, p+=scaler_in_bytes_per_line)
- { /* for each y line in the set */
- bit_pattern = *((unsigned short *)(p + scaler_offset[x])) & scaler_mask[x];
- accum += (bit_count[bit_pattern>>8] + bit_count[bit_pattern&0x00ff]);
- }
- if (accum >= cutoff) /* if significant, mask it in */
- buffer[x>>3] |= bit_mask[x&7];
- }
- return retval;
- }
-
-
- /************************************************
- * function: static void close_scaler(void)
- * clean up scaler resources
- * parameters: none
- * returns: none
- ************************************************/
- static void close_scaler(void)
- {
- free(scaler_buffer);
- free(scaler_offset);
- free(scaler_mask);
- }
-
-
- /************************************************
- * function: static int open_sampler(DISPLAY_BOX *file)
- * parameters: pointer to file extent struct
- * returns: 1 if OK or 0 if failed, non memory
- ************************************************/
- static int open_sampler(DISPLAY_BOX *file)
- {
- xsample = SAMPLE_200_X; /* set sample sizes */
- ysample = SAMPLE_200_Y;
- xdelta = file->width / xsample; /* extent of sample */
- ydelta = file->height / ysample;
- while (((long)xdelta * (long)ydelta) > MAX_MALLOC)
- { /* adjust sampling to fit memory restrictions */
- xsample++;
- ysample++;
- xdelta = file->width / xsample;
- ydelta = file->height / ysample;
- }
- /* allocate sample buffer */
- if ((display_sample_ptr = malloc(xdelta * ydelta)) == NULL)
- return 0;
- memset(display_sample_ptr,WHITE,xdelta * ydelta); /* set to white */
- sample_line = 0;
- return 1;
- }
-
-
- /************************************************
- * function: static void get_sample(unsigned char *scaler_buffer,int ylines)
- * sample the buffer
- * parameters: pointer to buffer full of raw image, number of scanlines in image
- * returns: nothing
- ************************************************/
- static void get_sample(unsigned char *buffer,int ylines)
- {
- static unsigned char bit_mask[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
- unsigned char *line_ptr,*sample_ptr;
- unsigned int x,y;
-
- for (y=0, line_ptr=buffer ; y < ylines ; y++, sample_line++, line_ptr+=scaler_in_bytes_per_line)
- {
- if ((sample_line % (ysample/2)) == 0) /* right line for scaling? */
- {
- sample_ptr = display_sample_ptr + ((sample_line/ysample) * xdelta);
- if (xsample >= 8)
- { /* byte sampling */
- for (x = 0 ; x < xdelta*xsample ; x += xsample, sample_ptr++)
- if (*(line_ptr+(x>>3)))
- *sample_ptr = BLACK; /* if byte has black, set sample */
- }
- else
- { /* bit sampling */
- for (x = 0 ; x < xdelta*xsample ; x += xsample, sample_ptr++)
- if (*(line_ptr+(x>>3)) & bit_mask[x&7])
- *sample_ptr = BLACK; /* if bit is black, set sample */
- }
- }
- }
- }