home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume25 / pclcomp / part02 < prev    next >
Encoding:
Text File  |  1991-11-03  |  27.6 KB  |  1,059 lines

  1. Newsgroups: comp.sources.misc
  2. From: tony@sdd.hp.com (Tony Parkhurst)
  3. Subject:  v25i011:  pclcomp - HP-PCL Compression Filter, Part02/02
  4. Message-ID: <1991Nov3.233755.10922@sparky.imd.sterling.com>
  5. X-Md4-Signature: ff5f11338b028d52a63b24ab669003af
  6. Date: Sun, 3 Nov 1991 23:37:55 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: tony@sdd.hp.com (Tony Parkhurst)
  10. Posting-number: Volume 25, Issue 11
  11. Archive-name: pclcomp/part02
  12. Environment: LaserJet
  13. Supersedes: pclcomp: Volume 19, Issue 13-14
  14.  
  15. #!/bin/sh
  16. # this is Part.02 (part 2 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file pclcomp.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 2; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping pclcomp.c'
  34. else
  35. echo 'x - continuing file pclcomp.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'pclcomp.c' &&
  37. X      input_char;               /* Byte to be replicated. */
  38. X
  39. X   unsigned int
  40. X      read_bytes,               /* Local copy of input_bytes. */
  41. X      write_bytes;              /* Local copy of output_bytes. */
  42. X
  43. X   int
  44. X      replicate_count;          /* Number of times to replicate data. */
  45. X
  46. X   /* CODE */
  47. X
  48. X   /* Initialize the local variables. */
  49. X
  50. X   read_bytes = input_bytes;
  51. X   write_bytes = output_bytes;
  52. X   store_ptr = address;
  53. X   
  54. X   /* Check for an even input count. */
  55. X
  56. X   if ((read_bytes % 2) == 0)
  57. X   {
  58. X      /* Even so input data is in pairs as required. So store the data. */
  59. X   
  60. X      while ((read_bytes != 0) && (write_bytes != 0))
  61. X      {
  62. X         /* First get the replicate count and the byte to store. */
  63. X
  64. X         replicate_count = (unsigned char) Get_Character();
  65. X         input_char = Get_Character();
  66. X         read_bytes -= 2;
  67. X      
  68. X         /* Since write_bytes was 0 there is room to store the byte. */
  69. X
  70. X         *store_ptr++ = input_char;
  71. X         write_bytes--;
  72. X         
  73. X         /* Now make sure there is room for the replicated data. */
  74. X
  75. X         if (replicate_count > write_bytes)
  76. X         {
  77. X            /* Too much so limit to the room available. */
  78. X
  79. X            replicate_count = write_bytes;
  80. X         }
  81. X            
  82. X         /* Update the amount to be written. */
  83. X
  84. X         write_bytes -= replicate_count;
  85. X
  86. X         /* Then replicate it. */
  87. X
  88. X         while (replicate_count != 0)
  89. X         {
  90. X            /* Store the byte the decrement the count. */
  91. X
  92. X            *store_ptr++ = input_char;
  93. X         
  94. X            replicate_count--;
  95. X         }
  96. X      }
  97. X
  98. X   }
  99. X   /* Discard any left over input. */
  100. X    /* OR */
  101. X   /* Discard all of the input data as odd byte count. */
  102. X
  103. X   Discard_Block(read_bytes);
  104. X
  105. X   read_bytes = store_ptr - address;  /* how much was done? */
  106. X
  107. X   /* zero fill if needed */
  108. X   memset(store_ptr, 0, write_bytes);
  109. X         
  110. X   return(read_bytes);
  111. }
  112. X
  113. X
  114. /*-----------------------------------------------------------------------*\
  115. X |                                                                       |
  116. X |  Function Name: Mode_2_Graphics                                       |
  117. X |                                                                       |
  118. X |  Description:                                                         |
  119. X |                                                                       |
  120. X |  This is the routine that handles a Mode 2 graphics block transfer    |
  121. X |  to the Formatter Module.  Mode 2 graphics is a compacted mode.       |
  122. X |  The data in Mode 2 is of one of two types.  The first type is a      |
  123. X |  class type and the second type is a data type.  The class type is    |
  124. X |  a single byte which is a combination of replicate count and a sub    |
  125. X |  mode.  There are two sub modes within mode 2, sub mode 0 and sub     |
  126. X |  mode 1.  These sub modes are flagged by the MSB of the class type    |
  127. X |  byte.  If the MSB = 0 then the replicate count is the value of the   |
  128. X |  class type byte.  In sub mode 0 the replicate count ranges from 1    |
  129. X |  to 127.  In sub mode 0 the next byte and then the replicate count    |
  130. X |  of bytes are of the data type and stored.  If the MSB = 1 then the   |
  131. X |  sub mode is 1 and the replicate count is the negative value of the   |
  132. X |  class type.  In sub mode 1 the replicate count is stored in 2s       |
  133. X |  compliment form and ranges from -1 to -127.  In sub mode 1 the       |
  134. X |  next byte is of the data type and is stored.  That data byte is      |
  135. X |  then replicated and stored the replicate count.  If the class type   |
  136. X |  byte is 128 then there is no data type byte.                         |
  137. X |                                                                       |
  138. \*-----------------------------------------------------------------------*/
  139. X
  140. /* FUNCTION */
  141. X
  142. Mode_2_Graphics(input_bytes, output_bytes, address)
  143. X
  144. unsigned int
  145. X   input_bytes,                 /* Count of bytes to be read. */
  146. X   output_bytes;                /* Count of bytes to be stored. */
  147. X
  148. unsigned char
  149. X   *address;                    /* Pointer to where to store bytes. */
  150. X
  151. {
  152. X   /* LOCAL VARIABLES */
  153. X
  154. X   unsigned char
  155. X      *store_ptr,               /* Pointer to where to store the byte. */
  156. X      input_char,               /* Byte to be replicated. */
  157. X      sub_mode;                 /* Flag if sub mode is 0 or 1. */
  158. X
  159. X   unsigned int
  160. X      read_bytes,               /* Local copy of input_bytes. */
  161. X      write_bytes;              /* Local copy of output_bytes. */
  162. X
  163. X   int
  164. X      replicate_count;          /* Number of times to replicate data. */
  165. X
  166. X   /* CODE */
  167. X
  168. X   /* Initialize the local variables. */
  169. X
  170. X   read_bytes = input_bytes;
  171. X   write_bytes = output_bytes;
  172. X   store_ptr = address;
  173. X   
  174. X   while ((read_bytes > 1) && (write_bytes != 0))
  175. X   {
  176. X      /* First get the class type byte and the first data type byte. */
  177. X
  178. X      replicate_count = Get_Character();
  179. X
  180. X      /* First check that this not an ignore class type. */
  181. X
  182. X      if (replicate_count != 128)
  183. X      {
  184. X         /* Not ignore so get the data class byte. */
  185. X
  186. X         input_char = Get_Character();
  187. X         read_bytes -= 2;
  188. X         
  189. X        /* Since write_bytes wasn't 0 there is room to store the byte. */
  190. X
  191. X         *store_ptr++ = input_char;
  192. X         write_bytes--;
  193. X
  194. X         /* Determine the sub mode. */
  195. X   
  196. X         if (replicate_count > 128)
  197. X         {
  198. X            /* Sub mode 1. */
  199. X   
  200. X            sub_mode = 1;
  201. X            /* replicate count was unsigned char */
  202. X            replicate_count = 256 - replicate_count;
  203. X         }
  204. X         else
  205. X         {
  206. X            /* Sub mode 0. */
  207. X   
  208. X            sub_mode = 0;
  209. X
  210. X            /* See if there is enoungh input left for the data byte count. */
  211. X
  212. X            if (replicate_count > read_bytes)
  213. X            {
  214. X               /* Too many data bytes so limit to the input left. */
  215. X
  216. X               replicate_count = read_bytes;
  217. X            }
  218. X         }
  219. X            
  220. X         /* Now make sure there is room for the replicated data. */
  221. X   
  222. X         if (replicate_count > write_bytes)
  223. X         {
  224. X            /* Too much so limit to the room available. */
  225. X   
  226. X            replicate_count = write_bytes;
  227. X         }
  228. X               
  229. X         /* Update the amount to be written. */
  230. X   
  231. X         write_bytes -= replicate_count;
  232. X   
  233. X         /* Then replicate it. */
  234. X   
  235. X         if (sub_mode == 0)
  236. X         {
  237. X            /* Sub mode 0 so get the replicate count of data bytes. */
  238. X   
  239. X              Transfer_Block(replicate_count, store_ptr);
  240. X
  241. X            read_bytes -= replicate_count;
  242. X            
  243. X            /* Find the last byte stored. */
  244. X   
  245. X            store_ptr += replicate_count;
  246. X         }
  247. X         else
  248. X         {
  249. X            /* Sub mode 1 so just duplicate the original byte. */
  250. X   
  251. X            while (replicate_count != 0)
  252. X            {
  253. X               /* Store the byte the decrement the count. */
  254. X   
  255. X               *store_ptr++ = input_char;
  256. X            
  257. X               replicate_count--;
  258. X            }
  259. X         }
  260. X      }
  261. X      else
  262. X      {
  263. X         /* Ignore class so don't get the data class byte. */
  264. X
  265. X         read_bytes--;
  266. X      }
  267. X   }
  268. X
  269. X   /* Now discard any left over input. */
  270. X
  271. X   Discard_Block(read_bytes);
  272. X
  273. X   read_bytes = store_ptr - address;
  274. X
  275. X   /* zero fill if needed */
  276. X   memset(store_ptr, 0, write_bytes);
  277. X         
  278. X   
  279. X   return(read_bytes);
  280. }
  281. X
  282. X
  283. /*-----------------------------------------------------------------------*\
  284. X |                                                                       |
  285. X |  Function Name: Mode_3_Graphics                                       |
  286. X |                                                                       |
  287. X |  Description:                                                         |
  288. X |                                                                       |
  289. X |  This is the routine that handles a Mode 3 graphics block transfer    |
  290. X |  to the Formatter Module.  Mode 3 graphics is a compacted mode.       |
  291. X |  Mode 3 data is a difference from one row to the next.  In order to   |
  292. X |  work, each row must be saved to be a seed for the next.  This        |
  293. X |  mode is used in conjuction with other compaction modes when the      |
  294. X |  data remains fairly constant between pairs of rows.                  |
  295. X |  The data is in the form:                                             |
  296. X |  <command byte>[<optional offset bytes>]<1 to 8 replacement bytes>    |
  297. X |  The command byte is in the form:                                     |
  298. X |    Bits 5-7: Number of bytes to replace (1 - 8)                       |
  299. X |    Bits 0-4: Relative offset from last byte.                          |
  300. X |       (If the offset is 31, then add the following bytes for offset   |
  301. X |       until an offset byte of less then 255 (but inclusive)           |
  302. X |                                                                       |
  303. \*-----------------------------------------------------------------------*/
  304. X
  305. /* FUNCTION */
  306. X
  307. Mode_3_Graphics(input_bytes, output_bytes, address)
  308. X
  309. unsigned int
  310. X   input_bytes,                 /* Count of bytes to be read. */
  311. X   output_bytes;                /* Count of bytes to be stored. */
  312. X
  313. unsigned char
  314. X   *address;                    /* Pointer to where to store bytes. */
  315. X
  316. {
  317. X   /* LOCAL VARIABLES */
  318. X
  319. X   unsigned char
  320. X      *store_ptr,               /* Pointer to where to store the byte. */
  321. X      input_char;               /* Byte to be changed. */
  322. X
  323. X   unsigned int
  324. X      read_bytes,               /* Local copy of input_bytes. */
  325. X      write_bytes;              /* Local copy of output_bytes. */
  326. X
  327. X   unsigned int
  328. X      replace,            /* number of bytes to replace, 1-8 */
  329. X      offset;            /* relative offset */
  330. X
  331. #if BITFIELDS
  332. X   union comtype {
  333. X      unsigned char comchar;    /* command byte as char */
  334. X      struct btype {
  335. X     unsigned repcount:3;    /* replace count 1-8 */
  336. X     unsigned roff:5;    /* relative offset 0-30 */
  337. X      } bitf;
  338. X   } command;
  339. #else
  340. X    unsigned char    command;
  341. #endif
  342. X
  343. X   /* CODE */
  344. X
  345. X   /* Initialize the local variables. */
  346. X
  347. X   read_bytes = input_bytes;
  348. X   write_bytes = output_bytes;
  349. X   store_ptr = address;
  350. X
  351. /* read_bytes has to be at least 2 to be valid */
  352. X
  353. X   while ( read_bytes > 1 && write_bytes > 0 ){
  354. X
  355. X      /* start by getting the command byte */
  356. X
  357. X      read_bytes--;
  358. X
  359. #if BITFIELDS
  360. X      command.comchar = Get_Character();
  361. X
  362. X      replace = command.bitf.repcount + 1;    /* replace count 1-8 */
  363. X
  364. X      offset = command.bitf.roff;        /* offset 0-30, 31= extend */
  365. #else
  366. X    command = Get_Character();
  367. X    replace = (command >> 5) + 1;
  368. X    offset = command & 0x1f;
  369. #endif
  370. X
  371. X      store_ptr += offset;
  372. X      write_bytes -= offset;
  373. X
  374. X      if ( offset == 31 )        /* get more offsets */
  375. X     do{
  376. X
  377. X        offset = Get_Character();
  378. X
  379. X        read_bytes--;
  380. X            if ( read_bytes == 0 )        /* premature finish? */
  381. X           return;                /* no zero fill wih 3 */
  382. X
  383. X        store_ptr += offset;
  384. X            write_bytes -= offset;
  385. X
  386. X     } while (offset == 255);    /* 255 = keep going */
  387. X      
  388. X      /* now do the byte replacement */
  389. X
  390. X      while ( replace-- && write_bytes > 0 && read_bytes > 0 ){
  391. X     
  392. X     *store_ptr++ = Get_Character();
  393. X
  394. X     read_bytes--;
  395. X     write_bytes--;
  396. X      }
  397. X   }
  398. X   
  399. X   /* don't do any zero fill with mode 3 */
  400. X
  401. X   /* discard any leftover input */
  402. X
  403. X   Discard_Block(read_bytes);
  404. X
  405. X   return( store_ptr - address );
  406. }
  407. X
  408. X
  409. Discard_Block(count)
  410. unsigned int count;
  411. {
  412. X    while ( count-- )
  413. X        getchar();
  414. }
  415. X
  416. Transfer_Block( count, dest )
  417. unsigned int count;
  418. unsigned char *dest;
  419. {
  420. X    fread(dest, 1, count, stdin);
  421. }
  422. X
  423. X
  424. /*
  425. **  Output_0() does mode 0 compression (which is a no compression).
  426. */
  427. X
  428. Output_0(src, dest, count)
  429. unsigned char *src, *dest;
  430. int count;
  431. {
  432. X    memcpy(dest, src, count);
  433. X
  434. X    if ( zerostrip )
  435. X        while ( count && dest[count-1] == 0 )
  436. X            count--;
  437. X
  438. X    return(count);
  439. X
  440. }
  441. X
  442. X
  443. X
  444. /*
  445. **  Output_1() does mode 1 compression (run length encoding)
  446. */
  447. X
  448. Output_1(src, dest, count)
  449. unsigned char *src, *dest;
  450. register int count;
  451. {
  452. X    unsigned char *optr = dest, *iptr;
  453. X    int k,c;
  454. X
  455. X    if ( zerostrip )            /* strip zeros */
  456. X    {
  457. X        iptr = src + count - 1;        /* point to end of data */
  458. X
  459. X        while ( count > 0 && *iptr-- == 0 )    /* hunt thru 0's */
  460. X            count--;
  461. X    }
  462. X
  463. X    iptr = src;
  464. X
  465. X    while ( count ){
  466. X        
  467. X        c = *iptr++;        /* get value to work with */
  468. X        count--;
  469. X
  470. X        k = 0;
  471. X
  472. X        while ( *iptr == c && k < 255 && count ){
  473. X            k++;
  474. X            iptr++;
  475. X            count--;
  476. X        }
  477. X
  478. X        *optr++ = k;        /* output repeat count */
  479. X        *optr++ = c;        /* output value */
  480. X    }
  481. X
  482. X    count = optr - dest;        /* for return value */
  483. X
  484. X    return ( count );
  485. }
  486. X
  487. X
  488. /*
  489. ******************************************************************************
  490. **
  491. **       Output_2() does PCL compression mode 2 on the data. 
  492. **       This mode is a combination of modes 0 and 1.
  493. **
  494. ******************************************************************************
  495. */
  496. X
  497. Output_2(src, dest, count)
  498. unsigned char *src, *dest;
  499. register int count;
  500. {
  501. X    unsigned char    *outptr, *inptr;
  502. X    unsigned char    *saveptr;
  503. X
  504. X    unsigned char    data;            /* data byte */
  505. X    unsigned char    lastbyte;        /* last byte */
  506. X    int        repcount;        /* repeat count */
  507. X    int        litcount;        /* literal count */
  508. X
  509. X    /*
  510. X    **  src points to the intput data.
  511. X    **  dest points to the output buffer.
  512. X    **  count is the number of intput bytes.
  513. X    */
  514. X
  515. X    inptr = src;
  516. X    outptr = dest;
  517. X
  518. X    /*
  519. X    **  Start loop thru data.  Check for possible repeat at beginning.
  520. X    */
  521. X
  522. X    while ( count )
  523. X    {
  524. X        data = *inptr++;    /* get value to work with */
  525. X        count--;
  526. X
  527. X        repcount = 0;        /* no repeat count yet */
  528. X
  529. X
  530. X        /* 
  531. X        **  Check for repeat, since we are not in the middle
  532. X        **  of a literal run, it does not have to be more than
  533. X        **  two bytes of similar data.
  534. X        */
  535. X
  536. X        while ( count && *inptr == data )
  537. X        {
  538. X            repcount++;
  539. X            inptr++;
  540. X            count--;
  541. X        }
  542. X
  543. X        /*
  544. X        **  Now, if we are out of data (count == 0), then
  545. X        **  if the repeated byte was zero, then ignore it
  546. X        **  completely (don't bother outputing the trailing zeros).
  547. X        **
  548. X        **  To always strip zero's, simply remove the "zerostrip"
  549. X        **  from the test.
  550. X        */
  551. X
  552. X        if ( count == 0 && data == 0 && zerostrip)
  553. X            break;            /* done */
  554. X
  555. X
  556. X        /*
  557. X        **  If there was a repeat (repcount > 0), then we
  558. X        **  can output the command here, otherwise, we
  559. X        **  need to go into literal run mode.
  560. X        **
  561. X        **  Note:  This is a while loop because the repeat count
  562. X        **  may actually be greater than 127.
  563. X        */
  564. X
  565. X        if ( repcount >= 1 )        /* repeat mode */
  566. X        {
  567. X            while (repcount > 127)
  568. X            {
  569. X                *outptr++ = 129;        /* count 127 */
  570. X                *outptr++ = data;        /* value */
  571. X                repcount-= 128;            /* offset */
  572. X            }
  573. X
  574. X            if (repcount > 0)
  575. X            {
  576. X                *outptr++ = 256 - repcount;    /* count */
  577. X                *outptr++ = data;        /* value */
  578. X
  579. X                /*
  580. X                **  Now pop to the top of the loop 
  581. X                **  looking for more repeat counts.
  582. X                */
  583. X
  584. X                continue;            /* top of loop */
  585. X            }
  586. X
  587. X            /*
  588. X            **  Special case.  If we have arrived at this point,
  589. X            **  then repcount is now equal to 0.  This means
  590. X            **  that when we entered this section, repcount
  591. X            **  was a multiple of 128 (i.e. 128 :-).
  592. X            **
  593. X            **  This means that there were 129 identical bytes,
  594. X            **  so the output does a replicate of 127 which
  595. X            **  gives 128 bytes, and we now have one byte left
  596. X            **  over which should NOT be output as a repeat
  597. X            **  run, rather it should be merged into the following
  598. X            **  literal run (if it exists).
  599. X            **
  600. X            **  So, we will simply fall thru to the next section
  601. X            **  of code which assumes that we are working on 
  602. X            **  a literal run.
  603. X            */
  604. X
  605. X        }
  606. X
  607. X        /*
  608. X        **  Literal run.  At this point, the current data byte
  609. X        **  does NOT match the following byte.  We will transfer
  610. X        **  these non-identical bytes until:
  611. X        **
  612. X        **       1)  we run out of input data (count == 0).
  613. X        **       2)  we run out of room in this output block (128)
  614. X        **       3)  we come across a value which occurs at least
  615. X        **           three times in a row.  A value occuring only
  616. X        **           twice in a row does NOT justify dropping
  617. X        **           out of a literal run.
  618. X        **
  619. X        **  Special case:  If we run out of room in the output block
  620. X        **  (which is 128 bytes), the last two values are the same,
  621. X        **  AND there is more input, it makes sense to restart
  622. X        **  the repeat detector in case the following bytes are
  623. X        **  repeats of the two.  A simple check of the following
  624. X        **  byte will determine this.
  625. X        **  (This case falls out with the test for triples below).
  626. X        **
  627. X        **  Special case:  If we run out of room in the output block
  628. X        **  (which is 128 bytes), the last value is the same as
  629. X        **  the next one on the input, then it is better to let
  630. X        **  that byte be used in a possible replicate run following
  631. X        **  the literal run.  If the last byte matches ONLY the
  632. X        **  following byte, (and not the one after that, it is
  633. X        **  a wash, but for best results, we will test the
  634. X        **  following two bytes.
  635. X        **
  636. X        */
  637. X
  638. X        litcount = 0;
  639. X        saveptr = outptr++;    /* save location of the command byte */
  640. X
  641. X        *outptr++ = data;    /* save the first byte. */
  642. X
  643. X        lastbyte = data;    /* remember for testing */
  644. X
  645. X        while ( count && litcount < 127 )
  646. X        {
  647. X            data = *inptr++;
  648. X            count--;
  649. X            litcount++;
  650. X            *outptr++ = data;
  651. X
  652. X            /*
  653. X            **  Test to see if this byte matched the last one.
  654. X            **  If so, check the next one for a triple.
  655. X            */
  656. X
  657. X            if ( lastbyte == data && count && *inptr == data )
  658. X            {
  659. X                /*
  660. X                **  We have a triple, adjust accordingly.
  661. X                **
  662. X                **  Add two bytes back onto the input.
  663. X                */
  664. X
  665. X                count += 2;
  666. X                inptr -= 2;
  667. X                outptr -= 2;
  668. X                litcount -= 2;
  669. X
  670. X                break;        /* out of loop */
  671. X            }
  672. X
  673. X            lastbyte = data;    /* save data byte */
  674. X        }
  675. X
  676. X        /*
  677. X        **  Check the special case number 2 above.
  678. X        */
  679. X
  680. X        if ( litcount == 127  &&  count > 1  &&  data == *inptr
  681. X            &&  data == inptr[1] )
  682. X        {
  683. X            /*  Restore the last byte to the input stream */
  684. X
  685. X            count += 1;
  686. X            inptr -= 1;
  687. X            outptr -= 1;
  688. X            litcount -= 1;
  689. X        }
  690. X
  691. X
  692. X        /*
  693. X        **  Save the literal run count.
  694. X        */
  695. X
  696. X        *saveptr = litcount;
  697. X
  698. X        /*
  699. X        **  Now go back to the top and look for repeats.
  700. X        */
  701. X    }
  702. X
  703. X    count = outptr - dest;        /* for return value */
  704. X
  705. X    return ( count );
  706. }
  707. X
  708. X
  709. X
  710. /*
  711. **  Output_3() does mode 3 compression (delta row encoding).
  712. */
  713. X
  714. Output_3(seed, new, dest, count)
  715. unsigned char *seed, *new, *dest;
  716. int count;
  717. {
  718. X    unsigned char *sptr=seed, *nptr=new, *dptr=dest;
  719. X    int i,j;
  720. X
  721. X
  722. #if BITFIELDS
  723. X   union comtype {
  724. X      unsigned char comchar;    /* command byte as char */
  725. X      struct btype {
  726. X     unsigned repcount:3;    /* replace count 1-8 */
  727. X     unsigned roff:5;    /* relative offset 0-30 */
  728. X      } bitf;
  729. X   } command;
  730. #else
  731. X    unsigned char    command;
  732. #endif
  733. X
  734. X    while ( count > 0 ){
  735. X        i = 0;
  736. X
  737. X                    /* find first diff */
  738. X        while ( *sptr == *nptr && i < count ){
  739. X            i++;
  740. X            sptr++;
  741. X            nptr++;
  742. X        }
  743. X
  744. X        if ( i >= count )    /* too far to find diff */
  745. X            return(dptr - dest);    /* bail */
  746. X
  747. X        count -= i;
  748. X        
  749. X        /* now count how many bytes to change */
  750. X
  751. X        for ( j = 1; j < 8; j++)    /* j == 0 is already known */
  752. X            if ( j > count || sptr[j] == nptr[j] )
  753. X                break;
  754. X        
  755. X        j--;    /* adjust */
  756. X
  757. #if BITFIELDS
  758. X        command.bitf.repcount = j;    /* 0-7 ==> 1-8 */
  759. X
  760. X        command.bitf.roff = MIN ( i, 31 );
  761. X
  762. X        *dptr++ = command.comchar;    /* output command */
  763. #else
  764. X        command = (j << 5);
  765. X        command += MIN( i, 31 );
  766. X        *dptr++ = command;
  767. #endif
  768. X
  769. X        if ( i == 31 )
  770. X            *dptr++ = 0;
  771. X        
  772. X        i -= MIN (i, 31);
  773. X
  774. X        while( i ){
  775. X            *dptr++ = MIN ( i, 255 );
  776. X
  777. X            if ( i == 255 )
  778. X                *dptr++ = 0;
  779. X            
  780. X            i -= MIN ( i, 255 );
  781. X        }
  782. X
  783. X        while (j-- >= 0){
  784. X            *dptr++ = *nptr++;
  785. X            sptr++;
  786. X            count--;
  787. X        }
  788. X    }
  789. X
  790. X    return ( dptr - dest );
  791. }
  792. X
  793. X
  794. /*----------------------------------------------------------------------*\
  795. X * This is here in case <ESC>*rU is sent after <ESC>*r#A, in which case *
  796. X * we must deallocate the memory to provide for a different amount of   *
  797. X * planes when graphics are sent.                                       *
  798. \*----------------------------------------------------------------------*/
  799. X
  800. free_mem()    
  801. {
  802. X    int r;
  803. X
  804. X
  805. X    if ( !memflag )
  806. X        return;        /* no memory to free */
  807. X
  808. X    free(new_row);
  809. X
  810. X    for(r = MAXMODES -1; r >= 0; r--)
  811. X        free(out_row[r]);
  812. X
  813. X    for(r = num_planes - 1; r >= 0; r--)
  814. X        free(seed_row[r]);
  815. X
  816. X    memflag = FALSE;
  817. }
  818. X
  819. /*
  820. **  Get_Frac() simply gets the fractional part of a value.  This is here
  821. **  because scanf() will consume a trailing 'e' or 'E', which is a problem
  822. **  in PCL.
  823. */
  824. X
  825. static float    Get_Frac()
  826. {
  827. X    float    result = 0.0;
  828. X    int    c;
  829. X    float    position = 10.0;
  830. X
  831. X    while ( (c = getchar()) != EOF )
  832. X    {
  833. X        /*
  834. X        **  Do we have a digit?
  835. X        */
  836. X
  837. X        if ( !isdigit(c) )        /* not a digit */
  838. X        {
  839. X            ungetc( c, stdin );    /* put it back */
  840. X            break;            /* quit */
  841. X        }
  842. X
  843. X        result += ((c - '0') / position);
  844. X
  845. X        position *= 10.0;
  846. X    }
  847. X
  848. X    return ( result );
  849. }
  850. SHAR_EOF
  851. echo 'File pclcomp.c is complete' &&
  852. chmod 0444 pclcomp.c ||
  853. echo 'restore of pclcomp.c failed'
  854. Wc_c="`wc -c < 'pclcomp.c'`"
  855. test 64599 -eq "$Wc_c" ||
  856.     echo 'pclcomp.c: original size 64599, current size' "$Wc_c"
  857. rm -f _shar_wnt_.tmp
  858. fi
  859. # ============= pclcomp.man ==============
  860. if test -f 'pclcomp.man' -a X"$1" != X"-c"; then
  861.     echo 'x - skipping pclcomp.man (File already exists)'
  862.     rm -f _shar_wnt_.tmp
  863. else
  864. > _shar_wnt_.tmp
  865. echo 'x - extracting pclcomp.man (Text)'
  866. sed 's/^X//' << 'SHAR_EOF' > 'pclcomp.man' &&
  867. X
  868. X
  869. X
  870. X     PCLCOMP(1)                         PCLCOMP(1)
  871. X
  872. X
  873. X
  874. X     NAME
  875. X      pclcomp - Compress PCL graphics files.
  876. X
  877. X     SYNOPSIS
  878. X      pclcomp [ -0123drsvxz ] [ -n num ] [ inputfile [ outputfile ]]
  879. X
  880. X
  881. X     DESCRIPTION
  882. X      Pclcomp compresses (or decompresses) HP-PCL (Printer Control
  883. X      Language) graphics data.  The supported compression modes
  884. X      are 0 (uncompressed), 1, 2 and 3.  Pclcomp will read files
  885. X      using any of the modes 0 through 3, and will output using
  886. X      the modes which will give the best compression.  This
  887. X      compressed version of the file may be sent directly to a PCL
  888. X      compatible printer, thus reducing I/O bandwidth.  Pictures
  889. X      may also be saved in compressed form, reducing disk usage.
  890. X      In addition, PCL "imaging" files for the PaintJet XL are
  891. X      also supported.
  892. X
  893. X      The options to pclcomp control the compression modes.  By
  894. X      default, pclcomp will use modes 0, 2 and 3, but the user may
  895. X      restrict which output modes it uses by specifying them on
  896. X      the command line with the -0, -1, -2 and -3 options.    To
  897. X      decompress a file, simply specify -0 as the only mode to use
  898. X      for output.  Mode 0 ( -0 ) should always be allowed since
  899. X      modes 1, 2 and 3 cannot be guaranteed to be better than mode
  900. X      0 for all types of pictures.
  901. X
  902. X      The -z option disables the zero "strip" feature.  Since most
  903. X      printers do zero "filling", pclcomp, by default, "strips"
  904. X      the trailing zeros of each row (or plane) of data.  Some
  905. X      printers or programs may require that zero "stripping" be
  906. X      disabled.
  907. X
  908. X      By default, pclcomp expects the input raster width to be
  909. X      2400 pixels (8" at 300 dpi), and if it is different (e.g.
  910. X      PaintJet), then the raster width should be specified by the
  911. X      Source Raster Width escape sequence <esc*r#S>. However, many
  912. X      applications do not set the width and assume a default,
  913. X      therefore, the user may use the -n option to pclcomp to
  914. X      specify a new default raster width.  For PaintJet (8" at 180
  915. X      dpi), the number should be 1440.  If the PCL file contains
  916. X      the Source Raster Width escape sequence, it will override
  917. X      this default.  If pclcomp thinks that more data is coming in
  918. X      than the specified width, it will generate a warning, and
  919. X      continue processing (and perhaps truncating) data.
  920. X
  921. X      The -x option will cause pclcomp to remove any horizontal
  922. X      offset sequences from the data.  Only use this option if
  923. X      white is defined to be zero (as with LaserJets).  This will
  924. X      shrink the data more if modes 2 or 3 are used.
  925. X
  926. X
  927. X
  928. X
  929. X                   - 1 -Formatted:  September 10, 1991
  930. X
  931. X
  932. X
  933. X
  934. X
  935. X
  936. X     PCLCOMP(1)                         PCLCOMP(1)
  937. X
  938. X
  939. X
  940. X      The -r option causes pclcomp to append a reset sequence
  941. X      (<esc>E) to the end of the job.
  942. X
  943. X      Use the -d option to pclcomp if the output is to be sent to
  944. X      a DeskJet printer.
  945. X
  946. X      Some applications erroneously send <esc>*rB and <esc>*rA
  947. X      sequences between every row of graphics data.  The -s option
  948. X      to pclcomp will "strip" all <esc>*rB sequences, and all
  949. X      <esc>*rA sequences after the first occurrence of this
  950. X      sequence. In addition, text and control characters residing
  951. X      between <esc>*rA and <esc>*rB sequences will be discarded.
  952. X      While this will work well for many jobs, it may have
  953. X      problems on multi-page or complex jobs.
  954. X
  955. X      The -v option simply gives statistics to stderr about which
  956. X      compression modes were used.
  957. X
  958. X     EXAMPLES
  959. X      To compress a PCL file for LaserJet III, use:
  960. X           pclcomp infile outfile
  961. X
  962. X      To compress a PCL file for the PaintJet (A size page at 180 dpi), use:
  963. X           pclcomp -01 -n 1440 infile outfile
  964. X
  965. X      To compress a PCL file for DeskJet, use:
  966. X           pclcomp -d012 infile outfile
  967. X
  968. X      To fully decompress a PCL file, use:
  969. X           pclcomp -0z < infile > outfile
  970. X
  971. X     WARNINGS
  972. X      The -z option can cause the output to be larger than the
  973. X      input.
  974. X
  975. X      The -s option is useful, but it can cause erroneous output.
  976. X
  977. X      The -x option can cause black areas on the left side of the
  978. X      picture on color printers.
  979. X
  980. X     AUTHOR
  981. X      Tony Parkhurst, Hewlett-Packard, San Diego Division
  982. X      (tony@sdd.hp.com)
  983. X
  984. X
  985. X
  986. X
  987. X
  988. X
  989. X
  990. X
  991. X
  992. X
  993. X
  994. X
  995. X                   - 2 -Formatted:  September 10, 1991
  996. X
  997. X
  998. X
  999. SHAR_EOF
  1000. chmod 0664 pclcomp.man ||
  1001. echo 'restore of pclcomp.man failed'
  1002. Wc_c="`wc -c < 'pclcomp.man'`"
  1003. test 4059 -eq "$Wc_c" ||
  1004.     echo 'pclcomp.man: original size 4059, current size' "$Wc_c"
  1005. rm -f _shar_wnt_.tmp
  1006. fi
  1007. # ============= printer.note ==============
  1008. if test -f 'printer.note' -a X"$1" != X"-c"; then
  1009.     echo 'x - skipping printer.note (File already exists)'
  1010.     rm -f _shar_wnt_.tmp
  1011. else
  1012. > _shar_wnt_.tmp
  1013. echo 'x - extracting printer.note (Text)'
  1014. sed 's/^X//' << 'SHAR_EOF' > 'printer.note' &&
  1015. X
  1016. X
  1017. Here is a list of printers and the compression modes they support:
  1018. X
  1019. X
  1020. X
  1021. Printer            Modes
  1022. -------            -----
  1023. X
  1024. LaserJet        0
  1025. LaserJet+        0
  1026. LaserJet 500        0
  1027. LaserJet 2000        0
  1028. LaserJet II        0
  1029. LaserJet IIP        0 1 2
  1030. LaserJet III        0 1 2 3
  1031. LaserJet IIIP        0 1 2 3 5  (Method 5 is not supported by pclcomp)
  1032. X
  1033. DeskJet            0 1 2
  1034. DeskJet+        0 1 2
  1035. DeskJet 500        0 1 2 3
  1036. X
  1037. PaintJet        0 1
  1038. PaintJet XL        0 1 2 3
  1039. X
  1040. X
  1041. Mode 0 is uncompressed graphics data.
  1042. SHAR_EOF
  1043. chmod 0664 printer.note ||
  1044. echo 'restore of printer.note failed'
  1045. Wc_c="`wc -c < 'printer.note'`"
  1046. test 415 -eq "$Wc_c" ||
  1047.     echo 'printer.note: original size 415, current size' "$Wc_c"
  1048. rm -f _shar_wnt_.tmp
  1049. fi
  1050. rm -f _shar_seq_.tmp
  1051. echo You have unpacked the last part
  1052. exit 0
  1053. exit 0 # Just in case...
  1054. -- 
  1055. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1056. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1057. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1058. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1059.