/* * dvipage: DVI Previewer Program for Suns * * Neil Hunt (hunt@spar.slb.com) * * This program is based, in part, upon the program dvisun, * distributed by the UnixTeX group, extensively modified by * Neil Hunt at the Schlumberger Palo Alto Research Laboratories * of Schlumberger Technologies, Inc. * * Copyright (c) 1988 Schlumberger Technologies, Inc 1988. * Anyone can use this software in any manner they choose, * including modification and redistribution, provided they make * no charge for it, and these conditions remain unchanged. * * This program is distributed as is, with all faults (if any), and * without any warranty. No author or distributor accepts responsibility * to anyone for the consequences of using it, or for whether it serves any * particular purpose at all, or any other reason. * * $Log: sample.c,v $ * Revision 1.1 88/11/28 18:41:24 hunt * Initial revision * * Split out of dvipage.c version 1.4. */ #include #include /* For MAXPATHLEN */ #include #include #include "dvipage.h" forward struct pixrect * pr_alloc(); forward struct pixrect * pr_free(); forward struct pixrect * pr_check(); forward struct pixrect * pr_link(); forward struct pixrect * pr_sample_4(); forward struct pixrect * pr_sample_34(); forward struct pixrect * pr_sample_3(); forward struct pixrect * pr_sample_2(); forward void pw_cover(); forward void pr_rect(); forward void pw_rect(); /* * sample_page: * Filter and sample down page according to current sampling rate, * and prepare for display. */ void sample_page() { #ifdef TIMING start_time(); #endif TIMING switch(sampling) { default: case 1: sample_pr = pr_link(&page_mpr, &sample_mpr); break; case 2: if(! (sample_pr = pr_sample_2(&page_mpr, &sample_mpr))) message("Out of memory for resampling image"); break; case 3: if(! (sample_pr = pr_sample_3(&page_mpr, &sample_mpr))) message("Out of memory for resampling image"); break; case 4: if(! (sample_pr = pr_sample_4(&page_mpr, &sample_mpr))) message("Out of memory for resampling image"); break; case 5: if(! (sample_pr = pr_sample_34(&page_mpr, &sample_mpr))) message("Out of memory for resampling image"); break; } #ifdef TIMING stop_time("Sampling one page"); #endif TIMING } /* * Here follow some functions to deal with pixrects under the special case * assumption that they are mem_pixrects, where the mpr_data is part * of a parent structure. */ extern struct pixrectops mem_ops; /* * pr_alloc: * Allocate memory for a pixrect of size w, h, d. * Returns a pointer to the pixrect structure. */ struct pixrect * pr_alloc(mpr, w, h, d) struct mem_pixrect *mpr; int w, h, d; { int size; int linebytes; short *image; /* * Compute the size of memory needed, and alloc it. */ linebytes = mpr_linebytes(w, d); size = linebytes * h; if(! (image = (short *)malloc(size))) return (struct pixrect *)NULL; /* * Set up the pr. */ mpr->mpr_pr.pr_ops = &mem_ops; mpr->mpr_pr.pr_width = w; mpr->mpr_pr.pr_height = h; mpr->mpr_pr.pr_depth = d; mpr->mpr_pr.pr_data = (caddr_t)&mpr->mpr_data; /* * Set up the mpr_data */ mpr->mpr_data.md_linebytes = linebytes; mpr->mpr_data.md_image = image; mpr->mpr_data.md_offset.x = 0; mpr->mpr_data.md_offset.y = 0; mpr->mpr_data.md_primary = TRUE; mpr->mpr_data.md_flags = 0; /* * Return the pr. */ return &mpr->mpr_pr; } /* * pr_free: * Free the memory associated with a pixrect. * Returns a pointer to no pixrect structure. */ struct pixrect * pr_free(mpr) struct mem_pixrect *mpr; { short *image; if((image = mpr->mpr_data.md_image)) { if(mpr->mpr_data.md_primary) free(image); mpr->mpr_data.md_image = (short *)NULL; } mpr->mpr_pr.pr_width = 0; mpr->mpr_pr.pr_height = 0; return (struct pixrect *)NULL; } /* * pr_check: * Check that a designated pixrect has memory allocated for an image * of size w, h, d. If not, free any existing memory and allocate * more memory. This is equivalent to, but much faster than, a * sequence of * pr_destroy(mpr); * mpr = mem_create(w, h, d); */ struct pixrect * pr_check(mpr, w, h, d) struct mem_pixrect *mpr; int w, h, d; { /* * If there is an image, check that it is the correct size. */ if(mpr->mpr_data.md_image) { if(mpr->mpr_pr.pr_width == w && mpr->mpr_pr.pr_height == h && mpr->mpr_pr.pr_depth == d) return &mpr->mpr_pr; (void)pr_free(mpr); } return pr_alloc(mpr, w, h, d); } /* * pr_link: * Link the memory of mpr1 to mpr2, making mpr2 a secondary pixrect. */ struct pixrect * pr_link(mpr1, mpr2) struct mem_pixrect *mpr1; struct mem_pixrect *mpr2; { /* * Free the existing memory, if any. */ (void)pr_free(mpr2); /* * Set up the pr. */ mpr2->mpr_pr.pr_ops = &mem_ops; mpr2->mpr_pr.pr_width = mpr1->mpr_pr.pr_width; mpr2->mpr_pr.pr_height = mpr1->mpr_pr.pr_height; mpr2->mpr_pr.pr_depth = mpr1->mpr_pr.pr_depth; mpr2->mpr_pr.pr_data = (caddr_t)&mpr2->mpr_data; /* * Set up the mpr_data */ mpr2->mpr_data.md_linebytes = mpr1->mpr_data.md_linebytes; mpr2->mpr_data.md_image = mpr1->mpr_data.md_image; mpr2->mpr_data.md_offset.x = mpr1->mpr_data.md_offset.x; mpr2->mpr_data.md_offset.y = mpr1->mpr_data.md_offset.y; mpr2->mpr_data.md_primary = FALSE; mpr2->mpr_data.md_flags = 0; /* * Return the pr. */ return &mpr2->mpr_pr; } /* * Colour Map Stuff * ================ */ #define M4F 0 #define M4T (M4F+16) #define M3F (M4T+1) #define M3T (M3F+24) #define M2F (M3T+1) #define M2T (M2F+4) uchar cmap_red[64] = { #ifdef NEVER /* Cmap with GAMMA=2,2,2,20,20,20 */ /* 4x4 from 0 to 16 */ 255, 247, 239, 231, 223, 214, 205, 196, 186, 175, 163, 151, 137, 121, 103, 78, 20, /* 3x3 from 17 to 41 */ 255, 250, 244, 239, 234, 229, 223, 217, 211, 205, 199, 192, 186, 179, 171, 163, 155, 146, 137, 127, 115, 103, 87, 67, 20, /* 2x2 from 42 to 46 */ 255, 223, 186, 137, 20, /* spare */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif NEVER /* Cmap with GAMMA=1.3,1.3,1.3,0,0,0 */ /* 4x4 from 0 to 16 */ 255, 242, 230, 217, 204, 191, 177, 163, 149, 135, 119, 104, 87, 70, 51, 30, 0, /* 3x3 from 17 to 41 */ 255, 246, 238, 230, 221, 213, 204, 195, 186, 177, 168, 159, 149, 139, 130, 119, 109, 98, 87, 76, 64, 51, 37, 22, 0, /* 2x2 from 42 to 46 */ 255, 204, 149, 87, 0, /* spare */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; uchar cmap_green[64] = { /* 4x4 from 0 to 16 */ 255, 242, 230, 217, 204, 191, 177, 163, 149, 135, 119, 104, 87, 70, 51, 30, 0, /* 3x3 from 17 to 41 */ 255, 246, 238, 230, 221, 213, 204, 195, 186, 177, 168, 159, 149, 139, 130, 119, 109, 98, 87, 76, 64, 51, 37, 22, 0, /* 2x2 from 42 to 46 */ 255, 204, 149, 87, 0, /* spare */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; uchar cmap_blue[64] = { /* 4x4 from 0 to 16 */ 255, 242, 230, 217, 204, 191, 177, 163, 149, 135, 119, 104, 87, 70, 51, 30, 0, /* 3x3 from 17 to 41 */ 255, 246, 238, 230, 221, 213, 204, 195, 186, 177, 168, 159, 149, 139, 130, 119, 109, 98, 87, 76, 64, 51, 37, 22, 0, /* 2x2 from 42 to 46 */ 255, 204, 149, 87, 0, /* spare */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; double gamma_red = 2.0; double gamma_green = 2.0; double gamma_blue = 2.0; int min_red = 20; int min_green = 20; int min_blue = 20; forward void make_one_cmap(); void make_cmap() { char *e; if((e = getenv("DVIPAGE_GAMMA")) == NULL) return; min_red = 20; min_green = 20; min_blue = 20; gamma_red = 0.0; gamma_green = 0.0; gamma_blue = 0.0; (void)sscanf(e, " %lf,%lf,%lf,%d,%d,%d ", &gamma_red, &gamma_green, &gamma_blue, &min_red, &min_green, &min_blue); if(gamma_red == 0.0) gamma_red = 1.3; if(gamma_green == 0.0) gamma_green = gamma_red; if(gamma_blue == 0.0) gamma_blue = gamma_red; make_one_cmap(cmap_red, 1.0/gamma_red, min_red); make_one_cmap(cmap_green, 1.0/gamma_green, min_green); make_one_cmap(cmap_blue, 1.0/gamma_blue, min_blue); } void make_one_cmap(cmap, power, mn) uchar cmap[]; double power; int mn; { int i; /* * 4x4 cmap. */ for(i = M4F; i <= M4T; i++) cmap[i] = (uchar)(pow((double)(M4T - i) / (M4T - M4F), power) * (255 - mn) + mn); /* * 3x3 cmap. */ for(i = M3F; i <= M3T; i++) cmap[i] = (uchar)(pow((double)(M3T - i) / (M3T - M3F), power) * (255 - mn) + mn); /* * 2x2 cmap. */ for(i = M2F; i <= M2T; i++) cmap[i] = (uchar)(pow((double)(M2T - i) / (M2T - M2F), power) * (255 - mn) + mn); cmap[63] = mn; } /* * Tally table used to compute the number of bits in packed words. * This is used in computing the number of bits in a 4x4 region of * a packed image. * * The packed word is used as an index into this table; * The most significant 16 bits of the value obtained represent the * number of bits in the upper half of the index, with each bit counted * with a weight of 15. * The least significant 16 bits of the value obtained represent the * number of bits in the l;ower hald of the index, with each bit counted * with a weight of 15. * * By combining the upper and lower halves in a single word, the values * for the four vertically adjacent words can be combined with each other * in a single addition per word, adding simultaneously both the tallies * for the left and the right halves of the word. */ static int tally4[] = { 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x00000001, 0x00000002, 0x00000002, 0x00000003, 0x00000001, 0x00000002, 0x00000002, 0x00000003, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0x00010000, 0x00010001, 0x00010001, 0x00010002, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010002, 0x00010003, 0x00010003, 0x00010004, 0x00010000, 0x00010001, 0x00010001, 0x00010002, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010002, 0x00010003, 0x00010003, 0x00010004, 0x00020000, 0x00020001, 0x00020001, 0x00020002, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020002, 0x00020003, 0x00020003, 0x00020004, 0x00010000, 0x00010001, 0x00010001, 0x00010002, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010002, 0x00010003, 0x00010003, 0x00010004, 0x00020000, 0x00020001, 0x00020001, 0x00020002, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020002, 0x00020003, 0x00020003, 0x00020004, 0x00020000, 0x00020001, 0x00020001, 0x00020002, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020002, 0x00020003, 0x00020003, 0x00020004, 0x00030000, 0x00030001, 0x00030001, 0x00030002, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030002, 0x00030003, 0x00030003, 0x00030004, 0x00010000, 0x00010001, 0x00010001, 0x00010002, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010001, 0x00010002, 0x00010002, 0x00010003, 0x00010002, 0x00010003, 0x00010003, 0x00010004, 0x00020000, 0x00020001, 0x00020001, 0x00020002, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020002, 0x00020003, 0x00020003, 0x00020004, 0x00020000, 0x00020001, 0x00020001, 0x00020002, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020002, 0x00020003, 0x00020003, 0x00020004, 0x00030000, 0x00030001, 0x00030001, 0x00030002, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030002, 0x00030003, 0x00030003, 0x00030004, 0x00020000, 0x00020001, 0x00020001, 0x00020002, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020001, 0x00020002, 0x00020002, 0x00020003, 0x00020002, 0x00020003, 0x00020003, 0x00020004, 0x00030000, 0x00030001, 0x00030001, 0x00030002, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030002, 0x00030003, 0x00030003, 0x00030004, 0x00030000, 0x00030001, 0x00030001, 0x00030002, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030001, 0x00030002, 0x00030002, 0x00030003, 0x00030002, 0x00030003, 0x00030003, 0x00030004, 0x00040000, 0x00040001, 0x00040001, 0x00040002, 0x00040001, 0x00040002, 0x00040002, 0x00040003, 0x00040001, 0x00040002, 0x00040002, 0x00040003, 0x00040002, 0x00040003, 0x00040003, 0x00040004, }; /* * Tally table used to compute the number of bits in packed words. * This is used in computing the number of bits in a 3x3 region of * a packed image. * * The packed word is used as an index into this table; * Bits 23..16 of the value obtained represent the number of bits in * the upper 2.67 bits of the index, with each bit counted with a weight * of 15. etc. etc. * * By combining the three parts in a single word, the values * for the three vertically adjacent words can be combined with each other * in a single addition per word, adding simultaneously both the tallies * for the left and the right halves of the word. */ static int tally3[] = { 0x00000000, 0x00000003, 0x00000003, 0x00000006, 0x00000102, 0x00000105, 0x00000105, 0x00000108, 0x00000300, 0x00000303, 0x00000303, 0x00000306, 0x00000402, 0x00000405, 0x00000405, 0x00000408, 0x00000300, 0x00000303, 0x00000303, 0x00000306, 0x00000402, 0x00000405, 0x00000405, 0x00000408, 0x00000600, 0x00000603, 0x00000603, 0x00000606, 0x00000702, 0x00000705, 0x00000705, 0x00000708, 0x00020100, 0x00020103, 0x00020103, 0x00020106, 0x00020202, 0x00020205, 0x00020205, 0x00020208, 0x00020400, 0x00020403, 0x00020403, 0x00020406, 0x00020502, 0x00020505, 0x00020505, 0x00020508, 0x00020400, 0x00020403, 0x00020403, 0x00020406, 0x00020502, 0x00020505, 0x00020505, 0x00020508, 0x00020700, 0x00020703, 0x00020703, 0x00020706, 0x00020802, 0x00020805, 0x00020805, 0x00020808, 0x00030000, 0x00030003, 0x00030003, 0x00030006, 0x00030102, 0x00030105, 0x00030105, 0x00030108, 0x00030300, 0x00030303, 0x00030303, 0x00030306, 0x00030402, 0x00030405, 0x00030405, 0x00030408, 0x00030300, 0x00030303, 0x00030303, 0x00030306, 0x00030402, 0x00030405, 0x00030405, 0x00030408, 0x00030600, 0x00030603, 0x00030603, 0x00030606, 0x00030702, 0x00030705, 0x00030705, 0x00030708, 0x00050100, 0x00050103, 0x00050103, 0x00050106, 0x00050202, 0x00050205, 0x00050205, 0x00050208, 0x00050400, 0x00050403, 0x00050403, 0x00050406, 0x00050502, 0x00050505, 0x00050505, 0x00050508, 0x00050400, 0x00050403, 0x00050403, 0x00050406, 0x00050502, 0x00050505, 0x00050505, 0x00050508, 0x00050700, 0x00050703, 0x00050703, 0x00050706, 0x00050802, 0x00050805, 0x00050805, 0x00050808, 0x00030000, 0x00030003, 0x00030003, 0x00030006, 0x00030102, 0x00030105, 0x00030105, 0x00030108, 0x00030300, 0x00030303, 0x00030303, 0x00030306, 0x00030402, 0x00030405, 0x00030405, 0x00030408, 0x00030300, 0x00030303, 0x00030303, 0x00030306, 0x00030402, 0x00030405, 0x00030405, 0x00030408, 0x00030600, 0x00030603, 0x00030603, 0x00030606, 0x00030702, 0x00030705, 0x00030705, 0x00030708, 0x00050100, 0x00050103, 0x00050103, 0x00050106, 0x00050202, 0x00050205, 0x00050205, 0x00050208, 0x00050400, 0x00050403, 0x00050403, 0x00050406, 0x00050502, 0x00050505, 0x00050505, 0x00050508, 0x00050400, 0x00050403, 0x00050403, 0x00050406, 0x00050502, 0x00050505, 0x00050505, 0x00050508, 0x00050700, 0x00050703, 0x00050703, 0x00050706, 0x00050802, 0x00050805, 0x00050805, 0x00050808, 0x00060000, 0x00060003, 0x00060003, 0x00060006, 0x00060102, 0x00060105, 0x00060105, 0x00060108, 0x00060300, 0x00060303, 0x00060303, 0x00060306, 0x00060402, 0x00060405, 0x00060405, 0x00060408, 0x00060300, 0x00060303, 0x00060303, 0x00060306, 0x00060402, 0x00060405, 0x00060405, 0x00060408, 0x00060600, 0x00060603, 0x00060603, 0x00060606, 0x00060702, 0x00060705, 0x00060705, 0x00060708, 0x00080100, 0x00080103, 0x00080103, 0x00080106, 0x00080202, 0x00080205, 0x00080205, 0x00080208, 0x00080400, 0x00080403, 0x00080403, 0x00080406, 0x00080502, 0x00080505, 0x00080505, 0x00080508, 0x00080400, 0x00080403, 0x00080403, 0x00080406, 0x00080502, 0x00080505, 0x00080505, 0x00080508, 0x00080700, 0x00080703, 0x00080703, 0x00080706, 0x00080802, 0x00080805, 0x00080805, 0x00080808, }; /* * Tally table used to compute the number of bits in packed words. * This is used in computing the number of bits in a 2x2 region of * a packed image. * * The packed word is used as an index into this table; * The most significant 8 bits of the value obtained represent the * number of bits in the upper half of the index, with each bit counted * with a weight of 15. * ... * The least significant 8 bits of the value obtained represent the * number of bits in the l;ower hald of the index, with each bit counted * with a weight of 15. * * By combining the four pairs of tallies in a single word, the values * for the two vertically adjacent words can be combined with each other * in a single addition per word, adding simultaneously all four tallies * for the four pairs of the word. */ static int tally2[] = { 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x00000100, 0x00000101, 0x00000101, 0x00000102, 0x00000100, 0x00000101, 0x00000101, 0x00000102, 0x00000200, 0x00000201, 0x00000201, 0x00000202, 0x00010000, 0x00010001, 0x00010001, 0x00010002, 0x00010100, 0x00010101, 0x00010101, 0x00010102, 0x00010100, 0x00010101, 0x00010101, 0x00010102, 0x00010200, 0x00010201, 0x00010201, 0x00010202, 0x00010000, 0x00010001, 0x00010001, 0x00010002, 0x00010100, 0x00010101, 0x00010101, 0x00010102, 0x00010100, 0x00010101, 0x00010101, 0x00010102, 0x00010200, 0x00010201, 0x00010201, 0x00010202, 0x00020000, 0x00020001, 0x00020001, 0x00020002, 0x00020100, 0x00020101, 0x00020101, 0x00020102, 0x00020100, 0x00020101, 0x00020101, 0x00020102, 0x00020200, 0x00020201, 0x00020201, 0x00020202, 0x01000000, 0x01000001, 0x01000001, 0x01000002, 0x01000100, 0x01000101, 0x01000101, 0x01000102, 0x01000100, 0x01000101, 0x01000101, 0x01000102, 0x01000200, 0x01000201, 0x01000201, 0x01000202, 0x01010000, 0x01010001, 0x01010001, 0x01010002, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010200, 0x01010201, 0x01010201, 0x01010202, 0x01010000, 0x01010001, 0x01010001, 0x01010002, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010200, 0x01010201, 0x01010201, 0x01010202, 0x01020000, 0x01020001, 0x01020001, 0x01020002, 0x01020100, 0x01020101, 0x01020101, 0x01020102, 0x01020100, 0x01020101, 0x01020101, 0x01020102, 0x01020200, 0x01020201, 0x01020201, 0x01020202, 0x01000000, 0x01000001, 0x01000001, 0x01000002, 0x01000100, 0x01000101, 0x01000101, 0x01000102, 0x01000100, 0x01000101, 0x01000101, 0x01000102, 0x01000200, 0x01000201, 0x01000201, 0x01000202, 0x01010000, 0x01010001, 0x01010001, 0x01010002, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010200, 0x01010201, 0x01010201, 0x01010202, 0x01010000, 0x01010001, 0x01010001, 0x01010002, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010100, 0x01010101, 0x01010101, 0x01010102, 0x01010200, 0x01010201, 0x01010201, 0x01010202, 0x01020000, 0x01020001, 0x01020001, 0x01020002, 0x01020100, 0x01020101, 0x01020101, 0x01020102, 0x01020100, 0x01020101, 0x01020101, 0x01020102, 0x01020200, 0x01020201, 0x01020201, 0x01020202, 0x02000000, 0x02000001, 0x02000001, 0x02000002, 0x02000100, 0x02000101, 0x02000101, 0x02000102, 0x02000100, 0x02000101, 0x02000101, 0x02000102, 0x02000200, 0x02000201, 0x02000201, 0x02000202, 0x02010000, 0x02010001, 0x02010001, 0x02010002, 0x02010100, 0x02010101, 0x02010101, 0x02010102, 0x02010100, 0x02010101, 0x02010101, 0x02010102, 0x02010200, 0x02010201, 0x02010201, 0x02010202, 0x02010000, 0x02010001, 0x02010001, 0x02010002, 0x02010100, 0x02010101, 0x02010101, 0x02010102, 0x02010100, 0x02010101, 0x02010101, 0x02010102, 0x02010200, 0x02010201, 0x02010201, 0x02010202, 0x02020000, 0x02020001, 0x02020001, 0x02020002, 0x02020100, 0x02020101, 0x02020101, 0x02020102, 0x02020100, 0x02020101, 0x02020101, 0x02020102, 0x02020200, 0x02020201, 0x02020201, 0x02020202, }; /* * P_row: * Access macro for obtaining a pointer to the bytes of a pixrect * starting at row `row'. */ #define P_row(mpr, row) \ (uchar *)((int)((mpr)->mpr_data.md_image) + \ (int)((short)(row) * (short)((mpr)->mpr_data.md_linebytes))); /* * pr_sample_4: * Filter and sample mpr1 on a 4x4 basis into mpr2. */ struct pixrect * pr_sample_4(mpr1, mpr2) struct mem_pixrect *mpr1; struct mem_pixrect *mpr2; { int cols, rows; int j; register uchar *p0; /* a5 */ register uchar *p1; /* a4 */ register uchar *p2; /* a3 */ register uchar *p3; /* a2 */ register uchar *pr; register uchar *er; register int tallies; /* d7 */ int line_offset; cols = mpr1->mpr_pr.pr_width / 4; rows = mpr1->mpr_pr.pr_height / 4; if(verbose & DEBUG_IMSIZE) fprintf(stderr, "pr_sample_4: (%d x %d) -> (%d x %d)\n", mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows); /* * Allocate output image. */ if(! pr_check(mpr2, cols, rows, 8)) return (struct pixrect *)NULL; /* * Do the sampling. */ line_offset = mpr1->mpr_data.md_linebytes; for(j = 0; j < rows; j++) { p0 = P_row(mpr1, j*4); p1 = p0 + line_offset; p2 = p1 + line_offset; p3 = p2 + line_offset; pr = P_row(mpr2, j); for(er = pr + cols; pr < er; ) { /* * Test for all zero. if(*p0 == 0 && *p1 == 0 && *p2 == 0 && *p3 == 0) { *pr++ = 0; if(pr >= er) break; *pr++ = 0; } else */ { tallies = tally4[*p0] + tally4[*p1] + tally4[*p2] + tally4[*p3]; /* * High order 4 bits */ *pr++ = (tallies >> 16) + M4F; if(pr >= er) break; /* * Low order 4 bits */ *pr++ = tallies + M4F; } p0++; p1++; p2++; p3++; } } return &mpr2->mpr_pr; } /* * pr_sample_34: * Filter and sample mpr1 on a 2.67x4 basis into mpr2. * Tally count uses M3 table, and gets up to 32 pixels (weighted at 1/3) * divides by two to index into the 0..16 M4 table. */ struct pixrect * pr_sample_34(mpr1, mpr2) struct mem_pixrect *mpr1; struct mem_pixrect *mpr2; { int cols, rows; int j; register uchar *p0; /* a5 */ register uchar *p1; /* a4 */ register uchar *p2; /* a3 */ register uchar *p3; /* a2 */ register uchar *pr; register uchar *er; register int tallies; /* d7 */ int line_offset; cols = mpr1->mpr_pr.pr_width * 3 / 8; rows = mpr1->mpr_pr.pr_height / 4; if(verbose & DEBUG_IMSIZE) fprintf(stderr, "pr_sample_34: (%d x %d) -> (%d x %d)\n", mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows); /* * Allocate output image. */ if(! pr_check(mpr2, cols, rows, 8)) return (struct pixrect *)NULL; /* * Do the sampling. */ line_offset = mpr1->mpr_data.md_linebytes; for(j = 0; j < rows; j++) { p0 = P_row(mpr1, j*4); p1 = p0 + line_offset; p2 = p1 + line_offset; p3 = p2 + line_offset; pr = P_row(mpr2, j); for(er = pr + cols; pr < er; ) { /* * Test for all zero. if(*p0 == 0 && *p1 == 0 && *p2 == 0) { *pr++ = 0; if(pr >= er) break; *pr++ = 0; if(pr >= er) break; *pr++ = 0; } else */ { tallies = tally3[*p0] + tally3[*p1] + tally3[*p2] + tally3[*p3]; /* * High order 3 bits */ *pr++ = (tallies >> (16+1)) + M4F; if(pr >= er) break; *pr++ = (tallies >> (8+1)) + M4F; if(pr >= er) break; /* * Low order 3 bits */ *pr++ = (tallies >> 1) + M4F; } p0++; p1++; p2++; p3++; } } return &mpr2->mpr_pr; } /* * pr_sample_3: * Filter and sample mpr1 on a 3x3 basis into mpr2. * Note that the horizontal sampling is actually 3/8 rather than 1/3. */ struct pixrect * pr_sample_3(mpr1, mpr2) struct mem_pixrect *mpr1; struct mem_pixrect *mpr2; { int cols, rows; int j; register uchar *p0; /* a5 */ register uchar *p1; /* a4 */ register uchar *p2; /* a3 */ register uchar *pr; /* a2 */ register uchar *er; register int tallies; /* d7 */ int line_offset; cols = mpr1->mpr_pr.pr_width * 3 / 8; rows = mpr1->mpr_pr.pr_height / 3; if(verbose & DEBUG_IMSIZE) fprintf(stderr, "pr_sample_3: (%d x %d) -> (%d x %d)\n", mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows); /* * Allocate output image. */ if(! pr_check(mpr2, cols, rows, 8)) return (struct pixrect *)NULL; /* * Do the sampling. */ line_offset = mpr1->mpr_data.md_linebytes; for(j = 0; j < rows; j++) { p0 = P_row(mpr1, j*3); p1 = p0 + line_offset; p2 = p1 + line_offset; pr = P_row(mpr2, j); for(er = pr + cols; pr < er; ) { /* * Test for all zero. if(*p0 == 0 && *p1 == 0 && *p2 == 0) { *pr++ = 0; if(pr >= er) break; *pr++ = 0; if(pr >= er) break; *pr++ = 0; } else */ { tallies = tally3[*p0] + tally3[*p1] + tally3[*p2]; /* * High order 3 bits */ *pr++ = (tallies >> 16) + M3F; if(pr >= er) break; *pr++ = (tallies >> 8) + M3F; if(pr >= er) break; /* * Low order 3 bits */ *pr++ = tallies + M3F; } p0++; p1++; p2++; } } return &mpr2->mpr_pr; } /* * pr_sample_2: * Filter and sample mpr1 on a 2x2 basis into mpr2. */ struct pixrect * pr_sample_2(mpr1, mpr2) struct mem_pixrect *mpr1; struct mem_pixrect *mpr2; { int cols, rows; int j; register uchar *p0; /* a5 */ register uchar *p1; /* a4 */ register uchar *pr; /* a3 */ register uchar *er; /* a2 */ register int tallies; /* d7 */ int line_offset; cols = mpr1->mpr_pr.pr_width / 2; rows = mpr1->mpr_pr.pr_height / 2; if(verbose & DEBUG_IMSIZE) fprintf(stderr, "pr_sample_2: (%d x %d) -> (%d x %d)\n", mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows); /* * Allocate output image. */ if(! pr_check(mpr2, cols, rows, 8)) return (struct pixrect *)NULL; /* * Do the sampling. */ line_offset = mpr1->mpr_data.md_linebytes; for(j = 0; j < rows; j++) { p0 = P_row(mpr1, j*2); p1 = p0 + line_offset; pr = P_row(mpr2, j); for(er = pr + cols; pr < er; ) { /* * Test for all zero. if(*p0 == 0 && *p1 == 0) { *pr++ = 0; if(pr >= er) break; *pr++ = 0; if(pr >= er) break; *pr++ = 0; if(pr >= er) break; *pr++ = 0; } else */ { tallies = tally2[*p0] + tally2[*p1]; /* * Highest two bits */ *pr++ = (tallies >> 24) + M2F; if(pr >= er) break; *pr++ = (tallies >> 16) + M2F; if(pr >= er) break; *pr++ = (tallies >> 8) + M2F; if(pr >= er) break; /* * Lowest two bits */ *pr++ = tallies + M2F; } p0++; p1++; } } return &mpr2->mpr_pr; } /* * pw_cover: * Function which writes a pixrect onto a pixwin; * where there are no src pixels, it writes background colour. */ void pw_cover(dpw, dx, dy, dw, dh, op, spr, sx, sy) Pixwin *dpw; int dx, dy, dw, dh; int op; Pixrect *spr; int sx, sy; { int aw, ah; /* * Handle the left margin. * If the left margin is less than the width to be painted, * paint a margin, else paint the whole region and return. */ if(sx < 0) { if(-sx < dw) { pw_writebackground(dpw, dx, dy, -sx, dh, op); dx -= sx; sx = 0; dw += sx; } else { pw_writebackground(dpw, dx, dy, dw, dh, op); return; } } /* * Handle the top margin. * If the top margin is less thatn the width to be painted, * paint a margin, else paint the whole region and return. */ if(sy < 0) { if(-sy < dh) { pw_writebackground(dpw, dx, dy, dw, -sy, op); dy -= sy; sy = 0; dh += sy; } else { pw_writebackground(dpw, dx, dy, dw, dh, op); return; } } /* * Handle the right margin. * aw = available width of source image. * If available width > 0 paint a margin of dw-aw width, * otherwise paint the whole region. */ aw = spr->pr_width-sx; if(dw > aw) { if(aw > 0) { pw_writebackground(dpw, dx+aw, dy, dw-aw, dh, op); dw = aw; } else { pw_writebackground(dpw, dx, dy, dw, dh, op); return; } } /* * Handle the bottom margin. * ah = available height of source image. * If available height > 0 paint a margin of dh-ah height, * otherwise paint the whole region. */ ah = spr->pr_height-sy; if(dh > ah) { if(ah > 0) { pw_writebackground(dpw, dx, dy+ah, dw, dh-ah, op); dh = ah; } else { pw_writebackground(dpw, dx, dy, dw, dh, op); return; } } /* * Paint the image. */ pw_write(dpw, dx, dy, dw, dh, op, spr, sx, sy); } /* * pr_rect: * Draws a box with op and colour as specified. */ void pr_rect(pr, x, y, w, h, t, op, value) struct pixrect *pr; int x, y, w, h; int t; int op, value; { int i; for(i = 0; i < t; i++) { pr_vector(pr, x, y, x+w-1, y, op, value); pr_vector(pr, x+w-1, y+1, x+w-1, y+h-2, op, value); pr_vector(pr, x, y+h-1, x+w-1, y+h-1, op, value); pr_vector(pr, x, y+1, x, y+h-2, op, value); x += 1; y += 1; w -= 2; h -= 2; if(w <= 0 || h <= 0) break; } } /* * pw_rect: * Draws a box with op and colour as specified. */ void pw_rect(pw, x, y, w, h, t, op, value) Pixwin *pw; int x, y, w, h; int t; int op, value; { int i; Rect r; r.r_left = x; r.r_top = y; r.r_width = w; r.r_height = h; pw_lock(pw, &r); for(i = 0; i < t; i++) { pw_vector(pw, x, y, x+w-1, y, op, value); pw_vector(pw, x+w-1, y+1, x+w-1, y+h-2, op, value); pw_vector(pw, x, y+h-1, x+w-1, y+h-1, op, value); pw_vector(pw, x, y+1, x, y+h-2, op, value); x += 1; y += 1; w -= 2; h -= 2; if(w <= 0 || h <= 0) break; } pw_unlock(pw); }