home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sources / misc / 4173 < prev    next >
Encoding:
Text File  |  1992-12-13  |  57.5 KB  |  2,113 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: cristy@eplrx7.es.duPont.com (John Cristy)
  4. Subject:  v34i033:  imagemagick - X11 image processing and display v2.2, Part05/26
  5. Message-ID: <1992Dec13.202648.9232@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 510097b0011bcb4070f4c97bc9e47121
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v34i028=imagemagick.141926@sparky.IMD.Sterling.COM>
  11. Date: Sun, 13 Dec 1992 20:26:48 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 2098
  14.  
  15. Submitted-by: cristy@eplrx7.es.duPont.com (John Cristy)
  16. Posting-number: Volume 34, Issue 33
  17. Archive-name: imagemagick/part05
  18. Environment: UNIX, VMS, X11, SGI, DEC, Cray, Sun, Vax
  19.  
  20. #!/bin/sh
  21. # this is Part.05 (part 5 of a multipart archive)
  22. # do not concatenate these parts, unpack them in order with /bin/sh
  23. # file ImageMagick/image.c continued
  24. #
  25. if test ! -r _shar_seq_.tmp; then
  26.     echo 'Please unpack part 1 first!'
  27.     exit 1
  28. fi
  29. (read Scheck
  30.  if test "$Scheck" != 5; then
  31.     echo Please unpack part "$Scheck" next!
  32.     exit 1
  33.  else
  34.     exit 0
  35.  fi
  36. ) < _shar_seq_.tmp || exit 1
  37. if test ! -f _shar_wnt_.tmp; then
  38.     echo 'x - still skipping ImageMagick/image.c'
  39. else
  40. echo 'x - continuing file ImageMagick/image.c'
  41. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/image.c' &&
  42. %                                                                             %
  43. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  44. %
  45. %  Function CompressImage compresses an image to the minimum number of
  46. %  runlength-encoded packets.
  47. %
  48. %  The format of the CompressImage routine is:
  49. %
  50. %      CompressImage(image)
  51. %
  52. %  A description of each parameter follows:
  53. %
  54. %    o image: The address of a structure of type Image.
  55. %
  56. %
  57. */
  58. void CompressImage(image)
  59. Image
  60. X  *image;
  61. {
  62. X  register int
  63. X    i;
  64. X
  65. X  register RunlengthPacket
  66. X    *p,
  67. X    *q;
  68. X
  69. X  /*
  70. X    Compress image.
  71. X  */
  72. X  p=image->pixels;
  73. X  image->runlength=p->length+1;
  74. X  image->packets=0;
  75. X  q=image->pixels;
  76. X  q->length=MaxRunlength;
  77. X  for (i=0; i < (image->columns*image->rows); i++)
  78. X  {
  79. X    if (image->runlength > 0)
  80. X      image->runlength--;
  81. X    else
  82. X      {
  83. X        p++;
  84. X        image->runlength=p->length;
  85. X      }
  86. X    if ((p->red == q->red) && (p->green == q->green) &&
  87. X        (p->blue == q->blue) && (q->length < MaxRunlength))
  88. X      q->length++;
  89. X    else
  90. X      {
  91. X        if (image->packets > 0)
  92. X          q++;
  93. X        image->packets++;
  94. X        q->red=p->red;
  95. X        q->green=p->green;
  96. X        q->blue=p->blue;
  97. X        q->index=p->index;
  98. X        q->length=0;
  99. X      }
  100. X  }
  101. X  image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,
  102. X    (unsigned int) image->packets*sizeof(RunlengthPacket));
  103. X  /*
  104. X    Runlength-encode only if it consumes less memory than no compression.
  105. X  */
  106. X  if (image->compression == RunlengthEncodedCompression)
  107. X    if (image->class == DirectClass)
  108. X      {
  109. X        if (image->packets >= ((image->columns*image->rows*3) >> 2))
  110. X          image->compression=NoCompression;
  111. X      }
  112. X    else
  113. X      if (image->packets >= ((image->columns*image->rows) >> 1))
  114. X        image->compression=NoCompression;
  115. }
  116. X
  117. /*
  118. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  119. %                                                                             %
  120. %                                                                             %
  121. %                                                                             %
  122. %   C o m p o s i t e I m a g e                                               %
  123. %                                                                             %
  124. %                                                                             %
  125. %                                                                             %
  126. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  127. %
  128. %  Function CompositeImage returns the second image composited onto the
  129. %  first at the specified offsets.
  130. %
  131. %  The format of the CompositeImage routine is:
  132. %
  133. %      CompositeImage(image,compose,composite_image,x_offset,y_offset)
  134. %
  135. %  A description of each parameter follows:
  136. %
  137. %    o image: The address of a structure of type Image.
  138. %
  139. %    o compose: Specifies an image composite operator.
  140. %
  141. %    o composite_image: The address of a structure of type Image.
  142. %
  143. %    o x_offset: An integer that specifies the column offset of the composited
  144. %      image.
  145. %
  146. %    o y_offset: An integer that specifies the row offset of the composited
  147. %      image.
  148. %
  149. %
  150. */
  151. void CompositeImage(image,compose,composite_image,x_offset,y_offset)
  152. Image
  153. X  *image;
  154. X
  155. unsigned int
  156. X  compose;
  157. X
  158. Image
  159. X  *composite_image;
  160. X
  161. int
  162. X  x_offset,
  163. X  y_offset;
  164. {
  165. X  int
  166. X    blue,
  167. X    green,
  168. X    red;
  169. X
  170. X  register int
  171. X    i,
  172. X    x,
  173. X    y;
  174. X
  175. X  register RunlengthPacket
  176. X    *p,
  177. X    *q;
  178. X
  179. X  register short int
  180. X    index;
  181. X
  182. X  /*
  183. X    Check composite geometry.
  184. X  */
  185. X  if (((x_offset+(int) image->columns) < 0) ||
  186. X      ((y_offset+(int) image->rows) < 0) ||
  187. X      (x_offset > (int) image->columns) || (y_offset > (int) image->rows))
  188. X    {
  189. X      Warning("unable to composite image","geometry does not contain image");
  190. X      return;
  191. X    }
  192. X  /*
  193. X    Image must be uncompressed.
  194. X  */
  195. X  if (image->packets != (image->columns*image->rows))
  196. X    if (!UncompressImage(image))
  197. X      return;
  198. X  if (!image->alpha)
  199. X    {
  200. X      /*
  201. X        Initialize image 1 alpha data.
  202. X      */
  203. X      q=image->pixels;
  204. X      for (i=0; i < image->packets; i++)
  205. X      {
  206. X        q->index=MaxRGB;
  207. X        q++;
  208. X      }
  209. X      image->class=DirectClass;
  210. X      image->alpha=True;
  211. X    }
  212. X  if (!composite_image->alpha)
  213. X    {
  214. X      /*
  215. X        Initialize composite image alpha data.
  216. X      */
  217. X      p=composite_image->pixels;
  218. X      red=(p+composite_image->packets-1)->red;
  219. X      green=(p+composite_image->packets-1)->green;
  220. X      blue=(p+composite_image->packets-1)->blue;
  221. X      if ((p->red != red) || (p->green != green) || (p->blue != blue))
  222. X        for (i=0; i < composite_image->packets; i++)
  223. X        {
  224. X          p->index=MaxRGB;
  225. X          p++;
  226. X        }
  227. X      else
  228. X        for (i=0; i < composite_image->packets; i++)
  229. X        {
  230. X          p->index=MaxRGB;
  231. X          if ((p->red == red) && (p->green == green) && (p->blue == blue))
  232. X            p->index=0;
  233. X          p++;
  234. X        }
  235. X      composite_image->class=DirectClass;
  236. X      composite_image->alpha=True;
  237. X    }
  238. X  /*
  239. X    Initialize composited image.
  240. X  */
  241. X  p=composite_image->pixels;
  242. X  composite_image->runlength=p->length+1;
  243. X  for (y=0; y < composite_image->rows; y++)
  244. X  {
  245. X    if (((y_offset+y) < 0) || ((y_offset+y) >= image->rows))
  246. X      continue;
  247. X    q=image->pixels+(y_offset+y)*image->columns+x_offset;
  248. X    for (x=0; x < composite_image->columns; x++)
  249. X    {
  250. X      if (composite_image->runlength > 0)
  251. X        composite_image->runlength--;
  252. X      else
  253. X        {
  254. X          p++;
  255. X          composite_image->runlength=p->length;
  256. X        }
  257. X      if (((x_offset+x) < 0) || ((x_offset+x) >= image->columns))
  258. X        {
  259. X          q++;
  260. X          continue;
  261. X        }
  262. X      switch (compose)
  263. X      {
  264. X        case OverCompositeOp:
  265. X        default:
  266. X        {
  267. X          if (p->index == 0)
  268. X            {
  269. X              red=q->red;
  270. X              green=q->green;
  271. X              blue=q->blue;
  272. X              index=q->index;
  273. X            }
  274. X          else
  275. X            if (p->index == MaxRGB)
  276. X              {
  277. X                red=p->red;
  278. X                green=p->green;
  279. X                blue=p->blue;
  280. X                index=p->index;
  281. X              }
  282. X            else
  283. X              {
  284. X                red=(int) (p->red*MaxRGB+q->red*(MaxRGB-p->index))/MaxRGB;
  285. X                green=(int) (p->green*MaxRGB+q->green*(MaxRGB-p->index))/MaxRGB;
  286. X                blue=(int) (p->blue*MaxRGB+q->blue*(MaxRGB-p->index))/MaxRGB;
  287. X                index=(int) (p->index*MaxRGB+q->index*(MaxRGB-p->index))/MaxRGB;
  288. X              }
  289. X          break;
  290. X        }
  291. X        case InCompositeOp:
  292. X        {
  293. X          red=(int) (p->red*q->index)/MaxRGB;
  294. X          green=(int) (p->green*q->index)/MaxRGB;
  295. X          blue=(int) (p->blue*q->index)/MaxRGB;
  296. X          index=(int) (p->index*q->index)/MaxRGB;
  297. X          break;
  298. X        }
  299. X        case OutCompositeOp:
  300. X        {
  301. X          red=(int) (p->red*(MaxRGB-q->index))/MaxRGB;
  302. X          green=(int) (p->green*(MaxRGB-q->index))/MaxRGB;
  303. X          blue=(int) (p->blue*(MaxRGB-q->index))/MaxRGB;
  304. X          index=(int) (p->index*(MaxRGB-q->index))/MaxRGB;
  305. X          break;
  306. X        }
  307. X        case AtopCompositeOp:
  308. X        {
  309. X          red=(int) (p->red*q->index+q->red*(MaxRGB-p->index))/MaxRGB;
  310. X          green=(int) (p->green*q->index+q->green*(MaxRGB-p->index))/MaxRGB;
  311. X          blue=(int) (p->blue*q->index+q->blue*(MaxRGB-p->index))/MaxRGB;
  312. X          index=(int) (p->index*q->index+q->index*(MaxRGB-p->index))/MaxRGB;
  313. X          break;
  314. X        }
  315. X        case XorCompositeOp:
  316. X        {
  317. X          red=(int) (p->red*(MaxRGB-q->index)+q->red*(MaxRGB-p->index))/MaxRGB;
  318. X          green=(int) (p->green*(MaxRGB-q->index)+q->green*(MaxRGB-p->index))/
  319. X            MaxRGB;
  320. X          blue=(int) (p->blue*(MaxRGB-q->index)+q->blue*(MaxRGB-p->index))/
  321. X            MaxRGB;
  322. X          index=(int) (p->index*(MaxRGB-q->index)+q->index*(MaxRGB-p->index))/
  323. X            MaxRGB;
  324. X          break;
  325. X        }
  326. X        case PlusCompositeOp:
  327. X        {
  328. X          red=(int) p->red+(int) q->red;
  329. X          green=(int) p->green+(int) q->green;
  330. X          blue=(int) p->blue+(int) q->blue;
  331. X          index=(int) p->index+(int) q->index;
  332. X          break;
  333. X        }
  334. X        case MinusCompositeOp:
  335. X        {
  336. X          red=(int) p->red-(int) q->red;
  337. X          green=(int) p->green-(int) q->green;
  338. X          blue=(int) p->blue-(int) q->blue;
  339. X          index=255;
  340. X          break;
  341. X        }
  342. X        case AddCompositeOp:
  343. X        {
  344. X          red=(int) p->red+(int) q->red;
  345. X          if (red > MaxRGB)
  346. X            red-=(MaxRGB+1);
  347. X          green=(int) p->green+(int) q->green;
  348. X          if (green > MaxRGB)
  349. X            green-=(MaxRGB+1);
  350. X          blue=(int) p->blue+(int) q->blue;
  351. X          if (blue > MaxRGB)
  352. X            blue-=(MaxRGB+1);
  353. X          index=(int) p->index+(int) q->index;
  354. X          if (index > MaxRGB)
  355. X            index-=(MaxRGB+1);
  356. X          break;
  357. X        }
  358. X        case SubtractCompositeOp:
  359. X        {
  360. X          red=(int) p->red-(int) q->red;
  361. X          if (red < 0)
  362. X            red+=(MaxRGB+1);
  363. X          green=(int) p->green-(int) q->green;
  364. X          if (green < 0)
  365. X            green+=(MaxRGB+1);
  366. X          blue=(int) p->blue-(int) q->blue;
  367. X          if (blue < 0)
  368. X            blue+=(MaxRGB+1);
  369. X          index=(int) p->index-(int) q->index;
  370. X          if (index < 0)
  371. X            index+=(MaxRGB+1);
  372. X          break;
  373. X        }
  374. X        case DifferenceCompositeOp:
  375. X        {
  376. X          red=AbsoluteValue((int) p->red-(int) q->red);
  377. X          green=AbsoluteValue((int) p->green-(int) q->green);
  378. X          blue=AbsoluteValue((int) p->blue-(int) q->blue);
  379. X          index=AbsoluteValue((int) p->index-(int) q->index);
  380. X          break;
  381. X        }
  382. X        case ReplaceCompositeOp:
  383. X        {
  384. X          red=p->red;
  385. X          green=p->green;
  386. X          blue=p->blue;
  387. X          index=p->index;
  388. X          break;
  389. X        }
  390. X      }
  391. X      if (red > MaxRGB)
  392. X        q->red=MaxRGB;
  393. X      else
  394. X        if (red < 0)
  395. X          q->red=0;
  396. X        else
  397. X          q->red=red;
  398. X      if (green > MaxRGB)
  399. X        q->green=MaxRGB;
  400. X      else
  401. X        if (green < 0)
  402. X          q->green=0;
  403. X        else
  404. X          q->green=green;
  405. X      if (blue > MaxRGB)
  406. X        q->blue=MaxRGB;
  407. X      else
  408. X        if (blue < 0)
  409. X          q->blue=0;
  410. X        else
  411. X          q->blue=blue;
  412. X      if (index > 255)
  413. X        q->index=255;
  414. X      else
  415. X        if (index < 0)
  416. X          q->index=0;
  417. X        else
  418. X          q->index=index;
  419. X      q->length=0;
  420. X      q++;
  421. X    }
  422. X  }
  423. }
  424. X
  425. /*
  426. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  427. %                                                                             %
  428. %                                                                             %
  429. %                                                                             %
  430. %   C o p y I m a g e                                                         %
  431. %                                                                             %
  432. %                                                                             %
  433. %                                                                             %
  434. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  435. %
  436. %  Function CopyImage returns a copy of all fields of the input image.  The
  437. %  the pixel memory is allocated but the pixel data is not copied.
  438. %
  439. %  The format of the CopyImage routine is:
  440. %
  441. %      copy_image=CopyImage(image,columns,rows,copy_pixels)
  442. %
  443. %  A description of each parameter follows:
  444. %
  445. %    o copy_image: Function CopyImage returns a pointer to the image after
  446. %      copying.  A null image is returned if there is a memory shortage.
  447. %
  448. %    o image: The address of a structure of type Image.
  449. %
  450. %    o columns: An integer that specifies the number of columns in the copied
  451. %      image.
  452. %
  453. %    o rows: An integer that specifies the number of rows in the copied
  454. %      image.
  455. %
  456. %    o copy_pixels: Specifies whether the pixel data is copied.  Must be
  457. %      either True or False;
  458. %
  459. %
  460. */
  461. Image *CopyImage(image,columns,rows,copy_pixels)
  462. Image
  463. X  *image;
  464. X
  465. unsigned int
  466. X  columns,
  467. X  rows,
  468. X  copy_pixels;
  469. {
  470. X  Image
  471. X    *copy_image;
  472. X
  473. X  register int
  474. X    i;
  475. X
  476. X  /*
  477. X    Allocate image structure.
  478. X  */
  479. X  copy_image=(Image *) malloc(sizeof(Image));
  480. X  if (copy_image == (Image *) NULL)
  481. X    return((Image *) NULL);
  482. X  *copy_image=(*image);
  483. X  if (image->comments != (char *) NULL)
  484. X    {
  485. X      /*
  486. X        Allocate and copy the image comments.
  487. X      */
  488. X      copy_image->comments=(char *)
  489. X        malloc(((strlen(image->comments)+1)*sizeof(char)));
  490. X      if (copy_image->comments == (char *) NULL)
  491. X        return((Image *) NULL);
  492. X      (void) strcpy(copy_image->comments,image->comments);
  493. X    }
  494. X  if (image->label != (char *) NULL)
  495. X    {
  496. X      /*
  497. X        Allocate and copy the image label.
  498. X      */
  499. X      copy_image->label=(char *)
  500. X        malloc(((strlen(image->label)+1)*sizeof(char)));
  501. X      if (copy_image->label == (char *) NULL)
  502. X        return((Image *) NULL);
  503. X      (void) strcpy(copy_image->label,image->label);
  504. X    }
  505. X  copy_image->columns=columns;
  506. X  copy_image->rows=rows;
  507. X  if (image->montage != (char *) NULL)
  508. X    if ((image->columns != columns) || (image->rows != rows))
  509. X      copy_image->montage=(char *) NULL;
  510. X    else
  511. X      {
  512. X        /*
  513. X          Allocate and copy the image montage.
  514. X        */
  515. X        copy_image->montage=(char *)
  516. X          malloc(((strlen(image->montage)+1)*sizeof(char)));
  517. X        if (copy_image->montage == (char *) NULL)
  518. X          return((Image *) NULL);
  519. X        (void) strcpy(copy_image->montage,image->montage);
  520. X      }
  521. X  if (image->directory != (char *) NULL)
  522. X    if ((image->columns != columns) || (image->rows != rows))
  523. X      copy_image->directory=(char *) NULL;
  524. X    else
  525. X      {
  526. X        /*
  527. X          Allocate and copy the image directory.
  528. X        */
  529. X        copy_image->directory=(char *)
  530. X          malloc(((strlen(image->directory)+1)*sizeof(char)));
  531. X        if (copy_image->directory == (char *) NULL)
  532. X          return((Image *) NULL);
  533. X        (void) strcpy(copy_image->directory,image->directory);
  534. X      }
  535. X  if (image->colormap != (ColorPacket *) NULL)
  536. X    {
  537. X      /*
  538. X        Allocate and copy the image colormap.
  539. X      */
  540. X      copy_image->colormap=(ColorPacket *)
  541. X        malloc(image->colors*sizeof(ColorPacket));
  542. X      if (copy_image->colormap == (ColorPacket *) NULL)
  543. X        return((Image *) NULL);
  544. X      for (i=0; i < image->colors; i++)
  545. X        copy_image->colormap[i]=image->colormap[i];
  546. X    }
  547. X  if (image->signature != (char *) NULL)
  548. X    {
  549. X      /*
  550. X        Allocate and copy the image signature.
  551. X      */
  552. X      copy_image->signature=(char *)
  553. X        malloc(((strlen(image->signature)+1)*sizeof(char)));
  554. X      if (copy_image->signature == (char *) NULL)
  555. X        return((Image *) NULL);
  556. X      (void) strcpy(copy_image->signature,image->signature);
  557. X    }
  558. X  /*
  559. X    Allocate the image pixels.
  560. X  */
  561. X  if (!copy_pixels)
  562. X    copy_image->packets=copy_image->columns*copy_image->rows;
  563. X  copy_image->pixels=(RunlengthPacket *)
  564. X    malloc((unsigned int) copy_image->packets*sizeof(RunlengthPacket));
  565. X  if (copy_image->pixels == (RunlengthPacket *) NULL)
  566. X    return((Image *) NULL);
  567. X  if (copy_pixels)
  568. X    {
  569. X      register RunlengthPacket
  570. X        *p,
  571. X        *q;
  572. X
  573. X      if ((image->columns != columns) || (image->rows != rows))
  574. X        return((Image *) NULL);
  575. X      /*
  576. X        Copy the image pixels.
  577. X      */
  578. X      p=image->pixels;
  579. X      q=copy_image->pixels;
  580. X      for (i=0; i < image->packets; i++)
  581. X        *q++=(*p++);
  582. X    }
  583. X  if (!image->orphan)
  584. X    {
  585. X      /*
  586. X        Link image into image list.
  587. X      */
  588. X      if (copy_image->last != (Image *) NULL)
  589. X        copy_image->last->next=copy_image;
  590. X      if (copy_image->next != (Image *) NULL)
  591. X        copy_image->next->last=copy_image;
  592. X    }
  593. X  return(copy_image);
  594. }
  595. X
  596. /*
  597. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  598. %                                                                             %
  599. %                                                                             %
  600. %                                                                             %
  601. %   D e s t r o y I m a g e                                                   %
  602. %                                                                             %
  603. %                                                                             %
  604. %                                                                             %
  605. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  606. %
  607. %  Function DestroyImage deallocates memory associated with an image.
  608. %
  609. %  The format of the DestroyImage routine is:
  610. %
  611. %      DestroyImage(image)
  612. %
  613. %  A description of each parameter follows:
  614. %
  615. %    o image: The address of a structure of type Image.
  616. %
  617. %
  618. */
  619. void DestroyImage(image)
  620. Image
  621. X  *image;
  622. {
  623. X  if (image->file != (FILE *) NULL)
  624. X    if (image->file != stdin)
  625. X      if (((int) strlen(image->filename) < 3) ||
  626. X          (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0))
  627. X        (void) fclose(image->file);
  628. X      else
  629. X        (void) pclose(image->file);
  630. X  /*
  631. X    Deallocate the image comments.
  632. X  */
  633. X  if (image->comments != (char *) NULL)
  634. X    (void) free((char *) image->comments);
  635. X  /*
  636. X    Deallocate the image label.
  637. X  */
  638. X  if (image->label != (char *) NULL)
  639. X    (void) free((char *) image->label);
  640. X  /*
  641. X    Deallocate the image montage directory.
  642. X  */
  643. X  if (image->montage != (char *) NULL)
  644. X    (void) free((char *) image->montage);
  645. X  if (image->directory != (char *) NULL)
  646. X    (void) free((char *) image->directory);
  647. X  /*
  648. X    Deallocate the image colormap.
  649. X  */
  650. X  if (image->colormap != (ColorPacket *) NULL)
  651. X    (void) free((char *) image->colormap);
  652. X  /*
  653. X    Deallocate the image signature.
  654. X  */
  655. X  if (image->signature != (char *) NULL)
  656. X    (void) free((char *) image->signature);
  657. X  /*
  658. X    Deallocate the image pixels.
  659. X  */
  660. X  if (image->pixels != (RunlengthPacket *) NULL)
  661. X    (void) free((char *) image->pixels);
  662. X  if (image->packed_pixels != (unsigned char *) NULL)
  663. X    (void) free((char *) image->packed_pixels);
  664. X  /*
  665. X    Deallocate the image structure.
  666. X  */
  667. X  (void) free((char *) image);
  668. X  image=(Image *) NULL;
  669. }
  670. X
  671. /*
  672. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  673. %                                                                             %
  674. %                                                                             %
  675. %                                                                             %
  676. %   D e s t r o y I m a g e s                                                 %
  677. %                                                                             %
  678. %                                                                             %
  679. %                                                                             %
  680. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  681. %
  682. %  Function DestroyImages deallocates memory associated with a linked list
  683. %  of images.
  684. %
  685. %  The format of the DestroyImages routine is:
  686. %
  687. %      DestroyImages(image)
  688. %
  689. %  A description of each parameter follows:
  690. %
  691. %    o image: The address of a structure of type Image.
  692. %
  693. %
  694. */
  695. void DestroyImages(image)
  696. Image
  697. X  *image;
  698. {
  699. X  Image
  700. X    *next_image;
  701. X
  702. X  /*
  703. X    Proceed to the top of the image list.
  704. X  */
  705. X  while (image->last != (Image *) NULL)
  706. X    image=image->last;
  707. X  do
  708. X  {
  709. X    /*
  710. X      Destroy this image.
  711. X    */
  712. X    next_image=image->next;
  713. X    DestroyImage(image);
  714. X    image=next_image;
  715. X  } while (image != (Image *) NULL);
  716. }
  717. X
  718. /*
  719. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  720. %                                                                             %
  721. %                                                                             %
  722. %     E n h a n c e I m a g e                                                 %
  723. %                                                                             %
  724. %                                                                             %
  725. %                                                                             %
  726. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  727. %
  728. %  Function EnhanceImage creates a new image that is a copy of an existing
  729. %  one with the noise reduced.  It allocates the memory necessary for the new
  730. %  Image structure and returns a pointer to the new image.
  731. %
  732. %  EnhanceImage does a weighted average of pixels in a 5x5 cell around each
  733. %  target pixel.  Only pixels in the 5x5 cell that are within a RGB distance
  734. %  threshold of the target pixel are averaged.
  735. %
  736. %  Weights assume that the importance of neighboring pixels is inversely
  737. %  proportional to the square of their distance from the target pixel.
  738. %
  739. %  The scan only processes pixels that have a full set of neighbors.  Pixels
  740. %  in the top, bottom, left, and right pairs of rows and columns are omitted
  741. %  from the scan.
  742. %
  743. %  The format of the EnhanceImage routine is:
  744. %
  745. %      enhanced_image=EnhanceImage(image)
  746. %
  747. %  A description of each parameter follows:
  748. %
  749. %    o enhanced_image: Function EnhanceImage returns a pointer to the image
  750. %      after it is enhanced.  A null image is returned if there is a memory
  751. %      shortage.
  752. %
  753. %    o image: The address of a structure of type Image;  returned from
  754. %      ReadImage.
  755. %
  756. %
  757. */
  758. Image *EnhanceImage(image)
  759. Image
  760. X  *image;
  761. {
  762. #define Esum(weight) \
  763. X  red_distance=s->red-red; \
  764. X  green_distance=s->green-green; \
  765. X  blue_distance=s->blue-blue; \
  766. X  distance=red_distance*red_distance+green_distance*green_distance+ \
  767. X    blue_distance*blue_distance; \
  768. X  if (distance < Threshold) \
  769. X    { \
  770. X      total_red+=weight*(s->red); \
  771. X      total_green+=weight*(s->green); \
  772. X      total_blue+=weight*(s->blue); \
  773. X      total_weight+=weight; \
  774. X    } \
  775. X  s++;
  776. #define Threshold  2500
  777. X
  778. X  ColorPacket
  779. X    *scanline;
  780. X
  781. X  Image
  782. X    *enhanced_image;
  783. X
  784. X  int
  785. X    blue_distance,
  786. X    green_distance,
  787. X    red_distance;
  788. X
  789. X  register ColorPacket
  790. X    *s,
  791. X    *s0,
  792. X    *s1,
  793. X    *s2,
  794. X    *s3,
  795. X    *s4;
  796. X
  797. X  register RunlengthPacket
  798. X    *p,
  799. X    *q;
  800. X
  801. X  register unsigned int
  802. X    x;
  803. X
  804. X  unsigned char
  805. X    blue,
  806. X    green,
  807. X    red;
  808. X
  809. X  unsigned int
  810. X    y;
  811. X
  812. X  unsigned long
  813. X    distance,
  814. X    total_blue,
  815. X    total_green,
  816. X    total_red,
  817. X    total_weight;
  818. X
  819. X  if ((image->columns < 5) || (image->rows < 5))
  820. X    {
  821. X      Warning("unable to enhance image","image size must exceed 4x4");
  822. X      return((Image *) NULL);
  823. X    }
  824. X  /*
  825. X    Initialize enhanced image attributes.
  826. X  */
  827. X  enhanced_image=CopyImage(image,image->columns,image->rows,False);
  828. X  if (enhanced_image == (Image *) NULL)
  829. X    {
  830. X      Warning("unable to enhance image","memory allocation failed");
  831. X      return((Image *) NULL);
  832. X    }
  833. X  enhanced_image->class=DirectClass;
  834. X  /*
  835. X    Allocate scan line buffer for 5 rows of the image.
  836. X  */
  837. X  scanline=(ColorPacket *) malloc(5*image->columns*sizeof(ColorPacket));
  838. X  if (scanline == (ColorPacket *) NULL)
  839. X    {
  840. X      Warning("unable to enhance image","memory allocation failed");
  841. X      DestroyImage(enhanced_image);
  842. X      return((Image *) NULL);
  843. X    }
  844. X  /*
  845. X    Read the first 4 rows of the image.
  846. X  */
  847. X  p=image->pixels;
  848. X  image->runlength=p->length+1;
  849. X  s=scanline;
  850. X  for (x=0; x < (image->columns*4); x++)
  851. X  {
  852. X    if (image->runlength > 0)
  853. X      image->runlength--;
  854. X    else
  855. X      {
  856. X        p++;
  857. X        image->runlength=p->length;
  858. X      }
  859. X    s->red=p->red;
  860. X    s->green=p->green;
  861. X    s->blue=p->blue;
  862. X    s->index=p->index;
  863. X    s++;
  864. X  }
  865. X  /*
  866. X    Dump first 2 scanlines of image.
  867. X  */
  868. X  q=enhanced_image->pixels;
  869. X  s=scanline;
  870. X  for (x=0; x < (2*image->columns); x++)
  871. X  {
  872. X    q->red=s->red;
  873. X    q->green=s->green;
  874. X    q->blue=s->blue;
  875. X    q->index=s->index;
  876. X    q->length=0;
  877. X    q++;
  878. X    s++;
  879. X  }
  880. X  /*
  881. X    Enhance each row.
  882. X  */
  883. X  for (y=2; y < (image->rows-2); y++)
  884. X  {
  885. X    /*
  886. X      Initialize sliding window pointers.
  887. X    */
  888. X    s0=scanline+image->columns*((y-2) % 5);
  889. X    s1=scanline+image->columns*((y-1) % 5);
  890. X    s2=scanline+image->columns*(y % 5);
  891. X    s3=scanline+image->columns*((y+1) % 5);
  892. X    s4=scanline+image->columns*((y+2) % 5);
  893. X    /*
  894. X      Read another scan line.
  895. X    */
  896. X    s=s4;
  897. X    for (x=0; x < image->columns; x++)
  898. X    {
  899. X      if (image->runlength > 0)
  900. X        image->runlength--;
  901. X      else
  902. X        {
  903. X          p++;
  904. X          image->runlength=p->length;
  905. X        }
  906. X      s->red=p->red;
  907. X      s->green=p->green;
  908. X      s->blue=p->blue;
  909. X      s->index=p->index;
  910. X      s++;
  911. X    }
  912. X    /*
  913. X      Transfer first 2 pixels of the scanline.
  914. X    */
  915. X    s=s2;
  916. X    for (x=0; x < 2; x++)
  917. X    {
  918. X      q->red=0;
  919. X      q->green=0;
  920. X      q->blue=0;
  921. X      q->index=0;
  922. X      q->length=0;
  923. X      q++;
  924. X      s++;
  925. X    }
  926. X    for (x=2; x < (image->columns-2); x++)
  927. X    {
  928. X      /*
  929. X        Compute weighted average of target pixel color components.
  930. X      */
  931. X      total_red=0;
  932. X      total_green=0;
  933. X      total_blue=0;
  934. X      total_weight=0;
  935. X      s=s2+2;
  936. X      red=s->red;
  937. X      green=s->green;
  938. X      blue=s->blue;
  939. X      s=s0;
  940. X      Esum(5);  Esum(8);  Esum(10); Esum(8);  Esum(5);
  941. X      s=s1;
  942. X      Esum(8);  Esum(20); Esum(40); Esum(20); Esum(8);
  943. X      s=s2;
  944. X      Esum(10); Esum(40); Esum(80); Esum(40); Esum(10);
  945. X      s=s3;
  946. X      Esum(8);  Esum(20); Esum(40); Esum(20); Esum(8);
  947. X      s=s4;
  948. X      Esum(5);  Esum(8);  Esum(10); Esum(8);  Esum(5);
  949. X      q->red=(unsigned char) ((total_red+(total_weight >> 1)-1)/total_weight);
  950. X      q->green=
  951. X        (unsigned char) ((total_green+(total_weight >> 1)-1)/total_weight);
  952. X      q->blue=(unsigned char) ((total_blue+(total_weight >> 1)-1)/total_weight);
  953. X      q->index=0;
  954. X      q->length=0;
  955. X      q++;
  956. X      s0++;
  957. X      s1++;
  958. X      s2++;
  959. X      s3++;
  960. X      s4++;
  961. X    }
  962. X    /*
  963. X      Transfer last 2 pixels of the scanline.
  964. X    */
  965. X    s=s2;
  966. X    for (x=0; x < 2; x++)
  967. X    {
  968. X      q->red=s->red;
  969. X      q->green=s->green;
  970. X      q->blue=s->blue;
  971. X      q->index=s->index;
  972. X      q->length=0;
  973. X      q++;
  974. X      s++;
  975. X    }
  976. X  }
  977. X  /*
  978. X    Dump last 2 scanlines of pixels.
  979. X  */
  980. X  s=scanline+image->columns*(y % 3);
  981. X  for (x=0; x < (2*image->columns); x++)
  982. X  {
  983. X    q->red=s->red;
  984. X    q->green=s->green;
  985. X    q->blue=s->blue;
  986. X    q->index=s->index;
  987. X    q->length=0;
  988. X    q++;
  989. X    s++;
  990. X  }
  991. X  (void) free((char *) scanline);
  992. X  return(enhanced_image);
  993. }
  994. X
  995. /*
  996. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  997. %                                                                             %
  998. %                                                                             %
  999. %     G a m m a I m a g e                                                     %
  1000. %                                                                             %
  1001. %                                                                             %
  1002. %                                                                             %
  1003. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1004. %
  1005. %  Procedure GammaImage converts the reference image to gamma corrected colors.
  1006. %
  1007. %  The format of the GammaImage routine is:
  1008. %
  1009. %      GammaImage(image,gamma)
  1010. %
  1011. %  A description of each parameter follows:
  1012. %
  1013. %    o image: The address of a structure of type Image;  returned from
  1014. %      ReadImage.
  1015. %
  1016. %    o gamma: A double precision value indicating the level of gamma
  1017. %      correction.
  1018. %
  1019. %
  1020. */
  1021. void GammaImage(image,gamma)
  1022. Image
  1023. X  *image;
  1024. X
  1025. double
  1026. X  gamma;
  1027. {
  1028. X  register int
  1029. X    i;
  1030. X
  1031. X  register RunlengthPacket
  1032. X    *p;
  1033. X
  1034. X  unsigned char
  1035. X    gamma_map[MaxRGB+1];
  1036. X
  1037. X  /*
  1038. X    Initialize gamma table.
  1039. X  */
  1040. X  for (i=0; i <= MaxRGB; i++)
  1041. X    gamma_map[i]=(unsigned char)
  1042. X      ((pow((double) i/MaxRGB,1.0/gamma)*MaxRGB)+0.5);
  1043. X  switch (image->class)
  1044. X  {
  1045. X    case DirectClass:
  1046. X    {
  1047. X      /*
  1048. X        Gamma-correct DirectClass image.
  1049. X      */
  1050. X      p=image->pixels;
  1051. X      for (i=0; i < image->packets; i++)
  1052. X      {
  1053. X        p->red=gamma_map[p->red];
  1054. X        p->green=gamma_map[p->green];
  1055. X        p->blue=gamma_map[p->blue];
  1056. X        p++;
  1057. X      }
  1058. X      break;
  1059. X    }
  1060. X    case PseudoClass:
  1061. X    {
  1062. X      register unsigned short
  1063. X        index;
  1064. X
  1065. X      /*
  1066. X        Gamma-correct PseudoClass image.
  1067. X      */
  1068. X      for (i=0; i < image->colors; i++)
  1069. X      {
  1070. X        image->colormap[i].red=gamma_map[image->colormap[i].red];
  1071. X        image->colormap[i].green=gamma_map[image->colormap[i].green];
  1072. X        image->colormap[i].blue=gamma_map[image->colormap[i].blue];
  1073. X      }
  1074. X      p=image->pixels;
  1075. X      for (i=0; i < image->packets; i++)
  1076. X      {
  1077. X        index=p->index;
  1078. X        p->red=image->colormap[index].red;
  1079. X        p->green=image->colormap[index].green;
  1080. X        p->blue=image->colormap[index].blue;
  1081. X        p++;
  1082. X      }
  1083. X      break;
  1084. X    }
  1085. X  }
  1086. }
  1087. X
  1088. /*
  1089. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1090. %                                                                             %
  1091. %                                                                             %
  1092. %     I n v e r s e I m a g e                                                 %
  1093. %                                                                             %
  1094. %                                                                             %
  1095. %                                                                             %
  1096. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1097. %
  1098. %  Procedure InverseImage inverses the colors in the reference image.
  1099. %
  1100. %  The format of the InverseImage routine is:
  1101. %
  1102. %      InverseImage(image)
  1103. %
  1104. %  A description of each parameter follows:
  1105. %
  1106. %    o image: The address of a structure of type Image;  returned from
  1107. %      ReadImage.
  1108. %
  1109. %
  1110. */
  1111. void InverseImage(image)
  1112. Image
  1113. X  *image;
  1114. {
  1115. X  register int
  1116. X    i;
  1117. X
  1118. X  register RunlengthPacket
  1119. X    *p;
  1120. X
  1121. X  switch (image->class)
  1122. X  {
  1123. X    case DirectClass:
  1124. X    {
  1125. X      /*
  1126. X        Inverse DirectClass packets.
  1127. X      */
  1128. X      p=image->pixels;
  1129. X      for (i=0; i < image->packets; i++)
  1130. X      {
  1131. X        p->red=(~p->red);
  1132. X        p->green=(~p->green);
  1133. X        p->blue=(~p->blue);
  1134. X        p++;
  1135. X      }
  1136. X      break;
  1137. X    }
  1138. X    case PseudoClass:
  1139. X    {
  1140. X      register unsigned short
  1141. X        index;
  1142. X
  1143. X      /*
  1144. X        Inverse PseudoClass packets.
  1145. X      */
  1146. X      for (i=0; i < image->colors; i++)
  1147. X      {
  1148. X        image->colormap[i].red=(~image->colormap[i].red);
  1149. X        image->colormap[i].green=(~image->colormap[i].green);
  1150. X        image->colormap[i].blue=(~image->colormap[i].blue);
  1151. X      }
  1152. X      p=image->pixels;
  1153. X      for (i=0; i < image->packets; i++)
  1154. X      {
  1155. X        index=p->index;
  1156. X        p->red=image->colormap[index].red;
  1157. X        p->green=image->colormap[index].green;
  1158. X        p->blue=image->colormap[index].blue;
  1159. X        p++;
  1160. X      }
  1161. X      break;
  1162. X    }
  1163. X  }
  1164. }
  1165. X
  1166. /*
  1167. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1168. %                                                                             %
  1169. %                                                                             %
  1170. %     N o i s y I m a g e                                                     %
  1171. %                                                                             %
  1172. %                                                                             %
  1173. %                                                                             %
  1174. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1175. %
  1176. %  Function NoisyImage creates a new image that is a copy of an existing
  1177. %  one with the noise reduced with a noise peak elimination filter.  It
  1178. %  allocates the memory necessary for the new Image structure and returns a
  1179. %  pointer to the new image.
  1180. %
  1181. %  The principal function of noise peak elimination filter is to smooth the
  1182. %  objects within an image without losing edge information and without
  1183. %  creating undesired structures.  The central idea of the algorithm is to
  1184. %  replace a pixel with its next neighbor in value within a 3 x 3 window,
  1185. %  if this pixel has been found to be noise.  A pixel is defined as noise
  1186. %  if and only if this pixel is a maximum or minimum within the 3 x 3
  1187. %  window.
  1188. %
  1189. %  The format of the NoisyImage routine is:
  1190. %
  1191. %      noisy_image=NoisyImage(image)
  1192. %
  1193. %  A description of each parameter follows:
  1194. %
  1195. %    o noisy_image: Function NoisyImage returns a pointer to the image after
  1196. %      the noise is reduced.  A null image is returned if there is a memory
  1197. %      shortage.
  1198. %
  1199. %    o image: The address of a structure of type Image;  returned from
  1200. %      ReadImage.
  1201. %
  1202. %
  1203. */
  1204. static int NoisyCompare(x,y)
  1205. const void
  1206. X  *x,
  1207. X  *y;
  1208. {
  1209. X  ColorPacket
  1210. X    *color_1,
  1211. X    *color_2;
  1212. X
  1213. X  color_1=(ColorPacket *) x;
  1214. X  color_2=(ColorPacket *) y;
  1215. X  return((int) Intensity(*color_1)-(int) Intensity(*color_2));
  1216. }
  1217. X
  1218. Image *NoisyImage(image)
  1219. Image
  1220. X  *image;
  1221. {
  1222. X  ColorPacket
  1223. X    pixel,
  1224. X    *scanline,
  1225. X    window[9];
  1226. X
  1227. X  Image
  1228. X    *noisy_image;
  1229. X
  1230. X  int
  1231. X    i;
  1232. X
  1233. X  register ColorPacket
  1234. X    *s,
  1235. X    *s0,
  1236. X    *s1,
  1237. X    *s2;
  1238. X
  1239. X  register RunlengthPacket
  1240. X    *p,
  1241. X    *q;
  1242. X
  1243. X  register unsigned int
  1244. X    x;
  1245. X
  1246. X  unsigned int
  1247. X    y;
  1248. X
  1249. X  if ((image->columns < 3) || (image->rows < 3))
  1250. X    {
  1251. X      Warning("unable to reduce noise","the image size must exceed 2x2");
  1252. X      return((Image *) NULL);
  1253. X    }
  1254. X  /*
  1255. X    Initialize noisy image attributes.
  1256. X  */
  1257. X  noisy_image=CopyImage(image,image->columns,image->rows,False);
  1258. X  if (noisy_image == (Image *) NULL)
  1259. X    {
  1260. X      Warning("unable to reduce noise","memory allocation failed");
  1261. X      return((Image *) NULL);
  1262. X    }
  1263. X  /*
  1264. X    Allocate scanline buffer for 3 rows of the image.
  1265. X  */
  1266. X  scanline=(ColorPacket *) malloc(3*image->columns*sizeof(ColorPacket));
  1267. X  if (scanline == (ColorPacket *) NULL)
  1268. X    {
  1269. X      Warning("unable to reduce noise","memory allocation failed");
  1270. X      DestroyImage(noisy_image);
  1271. X      return((Image *) NULL);
  1272. X    }
  1273. X  /*
  1274. X    Preload the first 2 rows of the image.
  1275. X  */
  1276. X  p=image->pixels;
  1277. X  image->runlength=p->length+1;
  1278. X  s=scanline;
  1279. X  for (x=0; x < (2*image->columns); x++)
  1280. X  {
  1281. X    if (image->runlength > 0)
  1282. X      image->runlength--;
  1283. X    else
  1284. X      {
  1285. X        p++;
  1286. X        image->runlength=p->length;
  1287. X      }
  1288. X    s->red=p->red;
  1289. X    s->green=p->green;
  1290. X    s->blue=p->blue;
  1291. X    s->index=p->index;
  1292. X    s++;
  1293. X  }
  1294. X  /*
  1295. X    Dump first scanline of image.
  1296. X  */
  1297. X  q=noisy_image->pixels;
  1298. X  s=scanline;
  1299. X  for (x=0; x < image->columns; x++)
  1300. X  {
  1301. X    q->red=s->red;
  1302. X    q->green=s->green;
  1303. X    q->blue=s->blue;
  1304. X    q->index=s->index;
  1305. X    q->length=0;
  1306. X    q++;
  1307. X    s++;
  1308. X  }
  1309. X  /*
  1310. X    Reduce noise in each row.
  1311. X  */
  1312. X  for (y=1; y < (image->rows-1); y++)
  1313. X  {
  1314. X    /*
  1315. X      Initialize sliding window pointers.
  1316. X    */
  1317. X    s0=scanline+image->columns*((y-1) % 3);
  1318. X    s1=scanline+image->columns*(y % 3);
  1319. X    s2=scanline+image->columns*((y+1) % 3);
  1320. X    /*
  1321. X      Read another scan line.
  1322. X    */
  1323. X    s=s2;
  1324. X    for (x=0; x < image->columns; x++)
  1325. X    {
  1326. X      if (image->runlength > 0)
  1327. X        image->runlength--;
  1328. X      else
  1329. X        {
  1330. X          p++;
  1331. X          image->runlength=p->length;
  1332. X        }
  1333. X      s->red=p->red;
  1334. X      s->green=p->green;
  1335. X      s->blue=p->blue;
  1336. X      s->index=p->index;
  1337. X      s++;
  1338. X    }
  1339. X    /*
  1340. X      Transfer first pixel of the scanline.
  1341. X    */
  1342. X    s=s1;
  1343. X    q->red=s->red;
  1344. X    q->green=s->green;
  1345. X    q->blue=s->blue;
  1346. X    q->index=s->index;
  1347. X    q->length=0;
  1348. X    q++;
  1349. X    for (x=1; x < (image->columns-1); x++)
  1350. X    {
  1351. X      /*
  1352. X        Sort window pixels by increasing intensity.
  1353. X      */
  1354. X      s=s0;
  1355. X      window[0]=(*s++);
  1356. X      window[1]=(*s++);
  1357. X      window[2]=(*s++);
  1358. X      s=s1;
  1359. X      window[3]=(*s++);
  1360. X      window[4]=(*s++);
  1361. X      window[5]=(*s++);
  1362. X      s=s2;
  1363. X      window[6]=(*s++);
  1364. X      window[7]=(*s++);
  1365. X      window[8]=(*s++);
  1366. X      pixel=window[4];
  1367. X      (void) qsort((void *) window,9,sizeof(ColorPacket),NoisyCompare);
  1368. X      if (Intensity(pixel) == Intensity(window[0]))
  1369. X        {
  1370. X          /*
  1371. X            Pixel is minimum noise; replace with next neighbor in value.
  1372. X          */
  1373. X          for (i=1; i < 8; i++)
  1374. X            if (Intensity(window[i]) != Intensity(window[0]))
  1375. X              break;
  1376. X          pixel=window[i];
  1377. X        }
  1378. X      else
  1379. X        if (Intensity(pixel) == Intensity(window[8]))
  1380. X          {
  1381. X            /*
  1382. X              Pixel is maximum noise; replace with next neighbor in value.
  1383. X            */
  1384. X            for (i=7; i > 0; i--)
  1385. X              if (Intensity(window[i]) != Intensity(window[8]))
  1386. X                break;
  1387. X            pixel=window[i];
  1388. X          }
  1389. X      q->red=pixel.red;
  1390. X      q->green=pixel.green;
  1391. X      q->blue=pixel.blue;
  1392. X      q->index=pixel.index;
  1393. X      q->length=0;
  1394. X      q++;
  1395. X      s0++;
  1396. X      s1++;
  1397. X      s2++;
  1398. X    }
  1399. X    /*
  1400. X      Transfer last pixel of the scanline.
  1401. X    */
  1402. X    s=s1;
  1403. X    q->red=s->red;
  1404. X    q->green=s->green;
  1405. X    q->blue=s->blue;
  1406. X    q->index=s->index;
  1407. X    q->length=0;
  1408. X    q++;
  1409. X  }
  1410. X  /*
  1411. X    Dump last scanline of pixels.
  1412. X  */
  1413. X  s=scanline+image->columns*(y % 3);
  1414. X  for (x=0; x < image->columns; x++)
  1415. X  {
  1416. X    q->red=s->red;
  1417. X    q->green=s->green;
  1418. X    q->blue=s->blue;
  1419. X    q->index=s->index;
  1420. X    q->length=0;
  1421. X    q++;
  1422. X    s++;
  1423. X  }
  1424. X  (void) free((char *) scanline);
  1425. X  return(noisy_image);
  1426. }
  1427. X
  1428. /*
  1429. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1430. %                                                                             %
  1431. %                                                                             %
  1432. %     N o r m a l i z e I m a g e                                             %
  1433. %                                                                             %
  1434. %                                                                             %
  1435. %                                                                             %
  1436. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1437. %
  1438. %  Procedure NormalizeImage normalizes the pixel values to span the full
  1439. %  range of color values.  This is a contrast enhancement technique.
  1440. %
  1441. %  The format of the NormalizeImage routine is:
  1442. %
  1443. %      NormalizeImage(image)
  1444. %
  1445. %  A description of each parameter follows:
  1446. %
  1447. %    o image: The address of a structure of type Image;  returned from
  1448. %      ReadImage.
  1449. %
  1450. %
  1451. */
  1452. void NormalizeImage(image)
  1453. Image
  1454. X  *image;
  1455. {
  1456. X  int
  1457. X    histogram[MaxRGB+1],
  1458. X    threshold_intensity;
  1459. X
  1460. X  register int
  1461. X    i,
  1462. X    intensity;
  1463. X
  1464. X  register RunlengthPacket
  1465. X    *p;
  1466. X
  1467. X  unsigned char
  1468. X    gray_value,
  1469. X    high,
  1470. X    low,
  1471. X    normalize_map[MaxRGB+1];
  1472. X
  1473. X  /*
  1474. X    Form histogram.
  1475. X  */
  1476. X  for (i=0; i <= MaxRGB; i++)
  1477. X    histogram[i]=0;
  1478. X  p=image->pixels;
  1479. X  for (i=0; i < image->packets; i++)
  1480. X  {
  1481. X    gray_value=Intensity(*p);
  1482. X    histogram[gray_value]+=p->length+1;
  1483. X    p++;
  1484. X  }
  1485. X  /*
  1486. X    Find the histogram boundaries by locating the 1 percent levels.
  1487. X  */
  1488. X  threshold_intensity=(image->columns*image->rows)/100;
  1489. X  intensity=0;
  1490. X  for (low=0; low < MaxRGB; low++)
  1491. X  {
  1492. X    intensity+=histogram[low];
  1493. X    if (intensity > threshold_intensity)
  1494. X      break;
  1495. X  }
  1496. X  intensity=0;
  1497. X  for (high=MaxRGB; high > 0; high--)
  1498. X  {
  1499. X    intensity+=histogram[high];
  1500. X    if (intensity > threshold_intensity)
  1501. X      break;
  1502. X  }
  1503. X  if (low == high)
  1504. X    {
  1505. X      /*
  1506. X        Unreasonable contrast;  use zero threshold to determine boundaries.
  1507. X      */
  1508. X      threshold_intensity=0;
  1509. X      intensity=0;
  1510. X      for (low=0; low < MaxRGB; low++)
  1511. X      {
  1512. X        intensity+=histogram[low];
  1513. X        if (intensity > threshold_intensity)
  1514. X          break;
  1515. X      }
  1516. X      intensity=0;
  1517. X      for (high=MaxRGB; high > 0; high--)
  1518. X      {
  1519. X        intensity+=histogram[high];
  1520. X        if (intensity > threshold_intensity)
  1521. X          break;
  1522. X      }
  1523. X      if (low == high)
  1524. X        return;  /* zero span bound */
  1525. X    }
  1526. X  /*
  1527. X    Stretch the histogram to create the normalized image mapping.
  1528. X  */
  1529. X  for (i=0; i <= MaxRGB; i++)
  1530. X    if (i < (int) low)
  1531. X      normalize_map[i]=0;
  1532. X    else
  1533. X      if (i > (int) high)
  1534. X        normalize_map[i]=MaxRGB-1;
  1535. X      else
  1536. X        normalize_map[i]=(MaxRGB-1)*(i-(int) low)/(int) (high-low);
  1537. X  /*
  1538. X    Normalize the image.
  1539. X  */
  1540. X  switch (image->class)
  1541. X  {
  1542. X    case DirectClass:
  1543. X    {
  1544. X      /*
  1545. X        Normalize DirectClass image.
  1546. X      */
  1547. X      p=image->pixels;
  1548. X      for (i=0; i < image->packets; i++)
  1549. X      {
  1550. X        p->red=normalize_map[p->red];
  1551. X        p->green=normalize_map[p->green];
  1552. X        p->blue=normalize_map[p->blue];
  1553. X        p++;
  1554. X      }
  1555. X      break;
  1556. X    }
  1557. X    case PseudoClass:
  1558. X    {
  1559. X      register unsigned short
  1560. X        index;
  1561. X
  1562. X      /*
  1563. X        Normalize PseudoClass image.
  1564. X      */
  1565. X      for (i=0; i < image->colors; i++)
  1566. X      {
  1567. X        image->colormap[i].red=normalize_map[image->colormap[i].red];
  1568. X        image->colormap[i].green=normalize_map[image->colormap[i].green];
  1569. X        image->colormap[i].blue=normalize_map[image->colormap[i].blue];
  1570. X      }
  1571. X      p=image->pixels;
  1572. X      for (i=0; i < image->packets; i++)
  1573. X      {
  1574. X        index=p->index;
  1575. X        p->red=image->colormap[index].red;
  1576. X        p->green=image->colormap[index].green;
  1577. X        p->blue=image->colormap[index].blue;
  1578. X        p++;
  1579. X      }
  1580. X      break;
  1581. X    }
  1582. X  }
  1583. }
  1584. X
  1585. /*
  1586. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1587. %                                                                             %
  1588. %                                                                             %
  1589. %                                                                             %
  1590. %   O p e n I m a g e                                                         %
  1591. %                                                                             %
  1592. %                                                                             %
  1593. %                                                                             %
  1594. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1595. %
  1596. %  Function OpenImage open a file associated with the image.
  1597. %
  1598. %  The format of the OpenImage routine is:
  1599. %
  1600. %      OpenImage(image,type)
  1601. %
  1602. %  A description of each parameter follows:
  1603. %
  1604. %    o image: The address of a structure of type Image.
  1605. %
  1606. %    o type: 'r' for reading; 'w' for writing.
  1607. %
  1608. */
  1609. void OpenImage(image,type)
  1610. Image
  1611. X  *image;
  1612. X
  1613. char
  1614. X  *type;
  1615. {
  1616. X  if (*image->filename == '-')
  1617. X    image->file=(*type == 'r') ? stdin : stdout;
  1618. X  else
  1619. X    if (((int) strlen(image->filename) < 3) ||
  1620. X        (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0))
  1621. X      image->file=fopen(image->filename,type);
  1622. X    else
  1623. X      {
  1624. X        char
  1625. X          command[2048];
  1626. X
  1627. X        /*
  1628. X          Image file is compressed-- uncompress it.
  1629. X        */
  1630. X        if (*type == 'r')
  1631. X          (void) sprintf(command,"uncompress -c %s\0",image->filename);
  1632. X        else
  1633. X          (void) sprintf(command,"compress -c > %s\0",image->filename);
  1634. X        image->file=(FILE *) popen(command,type);
  1635. X      }
  1636. }
  1637. X
  1638. /*
  1639. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1640. %                                                                             %
  1641. %                                                                             %
  1642. %                                                                             %
  1643. %   P a c k I m a g e                                                         %
  1644. %                                                                             %
  1645. %                                                                             %
  1646. %                                                                             %
  1647. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1648. %
  1649. %  Function PackImage packs the runlength-encoded pixel packets into the
  1650. %  minimum number of bytes.
  1651. %
  1652. %  The format of the PackImage routine is:
  1653. %
  1654. %      status=PackImage(image)
  1655. %
  1656. %  A description of each parameter follows:
  1657. %
  1658. %    o status: Function PackImage return True if the image is packed.  False
  1659. %      is returned if an error occurs.
  1660. %
  1661. %    o image: The address of a structure of type Image.
  1662. %
  1663. %
  1664. */
  1665. unsigned int PackImage(image)
  1666. Image
  1667. X  *image;
  1668. {
  1669. X  register int
  1670. X    i,
  1671. X    j;
  1672. X
  1673. X  register RunlengthPacket
  1674. X    *p;
  1675. X
  1676. X  register unsigned char
  1677. X    *q;
  1678. X
  1679. X  unsigned long int
  1680. X    count,
  1681. X    packets;
  1682. X
  1683. X  if (image->pixels == (RunlengthPacket *) NULL)
  1684. X    {
  1685. X      Warning("unable to pack pixels","no image pixels");
  1686. X      return(False);
  1687. X    }
  1688. X  /*
  1689. X    Runlength-encode only if it consumes less memory than no compression.
  1690. X  */
  1691. X  if (image->compression == RunlengthEncodedCompression)
  1692. X    if (image->class == DirectClass)
  1693. X      {
  1694. X        if (image->packets >= ((image->columns*image->rows*3) >> 2))
  1695. X          image->compression=NoCompression;
  1696. X      }
  1697. X    else
  1698. X      if (image->packets >= ((image->columns*image->rows) >> 1))
  1699. X        image->compression=NoCompression;
  1700. X  /*
  1701. X    Determine packed packet size.
  1702. X  */
  1703. X  if (image->class == PseudoClass)
  1704. X    {
  1705. X      image->packet_size=1;
  1706. X      if (image->colors > 256)
  1707. X        image->packet_size++;
  1708. X    }
  1709. X  else
  1710. X    {
  1711. X      image->packet_size=3;
  1712. X      if (image->alpha)
  1713. X        image->packet_size++;
  1714. X    }
  1715. X  if (image->compression == RunlengthEncodedCompression)
  1716. X    image->packet_size++;
  1717. X  /*
  1718. X    Allocate packed pixel memory.
  1719. X  */
  1720. X  if (image->packed_pixels != (unsigned char *) NULL)
  1721. X    (void) free((char *) image->packed_pixels);
  1722. X  packets=image->packets;
  1723. X  if (image->compression != RunlengthEncodedCompression)
  1724. X    packets=image->columns*image->rows;
  1725. X  image->packed_pixels=(unsigned char *)
  1726. X    malloc((unsigned int) packets*image->packet_size*sizeof(unsigned char));
  1727. X  if (image->packed_pixels == (unsigned char *) NULL)
  1728. X    {
  1729. X      Warning("unable to pack pixels","memory allocation failed");
  1730. X      return(False);
  1731. X    }
  1732. X  /*
  1733. X    Packs the runlength-encoded pixel packets into the minimum number of bytes.
  1734. X  */
  1735. X  p=image->pixels;
  1736. X  q=image->packed_pixels;
  1737. X  count=0;
  1738. X  if (image->class == DirectClass)
  1739. X    {
  1740. X      register int
  1741. X        alpha;
  1742. X
  1743. X      alpha=image->alpha;
  1744. X      if (image->compression == RunlengthEncodedCompression)
  1745. X        for (i=0; i < image->packets; i++)
  1746. X        {
  1747. X          *q++=p->red;
  1748. X          *q++=p->green;
  1749. X          *q++=p->blue;
  1750. X          if (alpha)
  1751. X            *q++=(unsigned char) p->index;
  1752. X          *q++=p->length;
  1753. X          count+=(p->length+1);
  1754. X          p++;
  1755. X        }
  1756. X      else
  1757. X        for (i=0; i < image->packets; i++)
  1758. X        {
  1759. X          for (j=0; j <= ((int) p->length); j++)
  1760. X          {
  1761. X            *q++=p->red;
  1762. X            *q++=p->green;
  1763. X            *q++=p->blue;
  1764. X            if (alpha)
  1765. X              *q++=(unsigned char) p->index;
  1766. X          }
  1767. X          count+=(p->length+1);
  1768. X          p++;
  1769. X        }
  1770. X    }
  1771. X  else
  1772. X    if (image->compression == RunlengthEncodedCompression)
  1773. X      {
  1774. X        if (image->colors <= 256)
  1775. X          for (i=0; i < image->packets; i++)
  1776. X          {
  1777. X            *q++=(unsigned char) p->index;
  1778. X            *q++=p->length;
  1779. X            count+=(p->length+1);
  1780. X            p++;
  1781. X          }
  1782. X        else
  1783. X          for (i=0; i < image->packets; i++)
  1784. X          {
  1785. X            *q++=(unsigned char) (p->index >> 8);
  1786. X            *q++=(unsigned char) p->index;
  1787. X            *q++=p->length;
  1788. X            count+=(p->length+1);
  1789. X            p++;
  1790. X          }
  1791. X      }
  1792. X    else
  1793. X      if (image->colors <= 256)
  1794. X        for (i=0; i < image->packets; i++)
  1795. X        {
  1796. X          for (j=0; j <= ((int) p->length); j++)
  1797. X            *q++=(unsigned char) p->index;
  1798. X          count+=(p->length+1);
  1799. X          p++;
  1800. X        }
  1801. X      else
  1802. X        {
  1803. X          register unsigned char
  1804. X            xff00,
  1805. X            xff;
  1806. X
  1807. X          for (i=0; i < image->packets; i++)
  1808. X          {
  1809. X            xff00=(unsigned char) (p->index >> 8);
  1810. X            xff=(unsigned char) p->index;
  1811. X            for (j=0; j <= ((int) p->length); j++)
  1812. X            {
  1813. X              *q++=xff00;
  1814. X              *q++=xff;
  1815. X            }
  1816. X            count+=(p->length+1);
  1817. X            p++;
  1818. X          }
  1819. X        }
  1820. X  /*
  1821. X    Guarentee the correct number of pixel packets.
  1822. X  */
  1823. X  if (count < (image->columns*image->rows))
  1824. X    {
  1825. X      Warning("insufficient image data in",image->filename);
  1826. X      return(False);
  1827. X    }
  1828. X  else
  1829. X    if (count > (image->columns*image->rows))
  1830. X      {
  1831. X        Warning("too much image data in",image->filename);
  1832. X        return(False);
  1833. X      }
  1834. X  return(True);
  1835. }
  1836. X
  1837. /*
  1838. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1839. %                                                                             %
  1840. %                                                                             %
  1841. %                                                                             %
  1842. %   P r i n t I m a g e                                                       %
  1843. %                                                                             %
  1844. %                                                                             %
  1845. %                                                                             %
  1846. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1847. %
  1848. %  Function PrintImage translates a MIFF image to encapsulated Postscript for
  1849. %  printing.  If the supplied geometry is null, the image is centered on the
  1850. %  Postscript page.  Otherwise, the image is positioned as specified by the
  1851. %  geometry.
  1852. %
  1853. %  The format of the PrintImage routine is:
  1854. %
  1855. %      status=PrintImage(image,geometry)
  1856. %
  1857. %  A description of each parameter follows:
  1858. %
  1859. %    o status: Function PrintImage return True if the image is printed.
  1860. %      False is returned if the image file cannot be opened for printing.
  1861. %
  1862. %    o image: The address of a structure of type Image;  returned from
  1863. %      ReadImage.
  1864. %
  1865. %    o geometry: A pointer to a standard window geometry string.
  1866. %
  1867. %
  1868. */
  1869. unsigned int PrintImage(image,geometry)
  1870. Image
  1871. X  *image;
  1872. X
  1873. char
  1874. X  *geometry;
  1875. {
  1876. #define PageSideMargin 16
  1877. #define PageTopMargin 92
  1878. #define PageWidth  612
  1879. #define PageHeight 792
  1880. X
  1881. X  static char
  1882. X    *Postscript[]=
  1883. X    {
  1884. X      "%",
  1885. X      "% Display a color image.  The image is displayed in color on",
  1886. X      "% Postscript viewers or printers that support color, otherwise",
  1887. X      "% it is displayed as grayscale.",
  1888. X      "%",
  1889. X      "/buffer 512 string def",
  1890. X      "/byte 1 string def",
  1891. X      "/color_packet 3 string def",
  1892. X      "/compression 1 string def",
  1893. X      "/gray_packet 1 string def",
  1894. X      "/pixels 768 string def",
  1895. X      "",
  1896. X      "/DirectClassPacket",
  1897. X      "{",
  1898. X      "  %",
  1899. X      "  % Get a DirectClass packet.",
  1900. X      "  %",
  1901. X      "  % Parameters: ",
  1902. X      "  %   red.",
  1903. X      "  %   green.",
  1904. X      "  %   blue.",
  1905. X      "  %   length: number of pixels minus one of this color (optional).",
  1906. X      "  %",
  1907. X      "  currentfile color_packet readhexstring pop pop",
  1908. X      "  compression 0 gt",
  1909. X      "  {",
  1910. X      "    /number_pixels 3 def",
  1911. X      "  }",
  1912. X      "  {",
  1913. X      "    currentfile byte readhexstring pop 0 get",
  1914. X      "    /number_pixels exch 1 add 3 mul def",
  1915. X      "  } ifelse",
  1916. X      "  0 3 number_pixels 1 sub",
  1917. X      "  {",
  1918. X      "    pixels exch color_packet putinterval",
  1919. X      "  } for",
  1920. X      "  pixels 0 number_pixels getinterval",
  1921. X      "} bind def",
  1922. X      "",
  1923. X      "/DirectClassImage",
  1924. X      "{",
  1925. X      "  %",
  1926. X      "  % Display a DirectClass image.",
  1927. X      "  %",
  1928. X      "  systemdict /colorimage known",
  1929. X      "  {",
  1930. X      "    columns rows 8",
  1931. X      "    [",
  1932. X      "      columns 0 0",
  1933. X      "      rows neg 0 rows",
  1934. X      "    ]",
  1935. X      "    { DirectClassPacket } false 3 colorimage",
  1936. X      "  }",
  1937. X      "  {",
  1938. X      "    %",
  1939. X      "    % No colorimage operator;  convert to grayscale.",
  1940. X      "    %",
  1941. X      "    columns rows 8",
  1942. X      "    [",
  1943. X      "      columns 0 0",
  1944. X      "      rows neg 0 rows",
  1945. X      "    ]",
  1946. X      "    { GrayDirectClassPacket } image",
  1947. X      "  } ifelse",
  1948. X      "} bind def",
  1949. X      "",
  1950. X      "/GrayDirectClassPacket",
  1951. X      "{",
  1952. X      "  %",
  1953. X      "  % Get a DirectClass packet;  convert to grayscale.",
  1954. X      "  %",
  1955. X      "  % Parameters: ",
  1956. X      "  %   red",
  1957. X      "  %   green",
  1958. X      "  %   blue",
  1959. X      "  %   length: number of pixels minus one of this color (optional).",
  1960. X      "  %",
  1961. X      "  currentfile color_packet readhexstring pop pop",
  1962. X      "  color_packet 0 get 0.299 mul",
  1963. X      "  color_packet 1 get 0.587 mul add",
  1964. X      "  color_packet 2 get 0.114 mul add",
  1965. X      "  cvi",
  1966. X      "  /gray_packet exch def",
  1967. X      "  compression 0 gt",
  1968. X      "  {",
  1969. X      "    /number_pixels 1 def",
  1970. X      "  }",
  1971. X      "  {",
  1972. X      "    currentfile byte readhexstring pop 0 get",
  1973. X      "    /number_pixels exch 1 add def",
  1974. X      "  } ifelse",
  1975. X      "  0 1 number_pixels 1 sub",
  1976. X      "  {",
  1977. X      "    pixels exch gray_packet put",
  1978. X      "  } for",
  1979. X      "  pixels 0 number_pixels getinterval",
  1980. X      "} bind def",
  1981. X      "",
  1982. X      "/GrayPseudoClassPacket",
  1983. X      "{",
  1984. X      "  %",
  1985. X      "  % Get a PseudoClass packet;  convert to grayscale.",
  1986. X      "  %",
  1987. X      "  % Parameters: ",
  1988. X      "  %   index: index into the colormap.",
  1989. X      "  %   length: number of pixels minus one of this color (optional).",
  1990. X      "  %",
  1991. X      "  currentfile byte readhexstring pop 0 get",
  1992. X      "  /offset exch 3 mul def",
  1993. X      "  /color_packet colormap offset 3 getinterval def",
  1994. X      "  color_packet 0 get 0.299 mul",
  1995. X      "  color_packet 1 get 0.587 mul add",
  1996. X      "  color_packet 2 get 0.114 mul add",
  1997. X      "  cvi",
  1998. X      "  /gray_packet exch def",
  1999. X      "  compression 0 gt",
  2000. X      "  {",
  2001. X      "    /number_pixels 1 def",
  2002. X      "  }",
  2003. X      "  {",
  2004. X      "    currentfile byte readhexstring pop 0 get",
  2005. X      "    /number_pixels exch 1 add def",
  2006. X      "  } ifelse",
  2007. X      "  0 1 number_pixels 1 sub",
  2008. X      "  {",
  2009. X      "    pixels exch gray_packet put",
  2010. X      "  } for",
  2011. X      "  pixels 0 number_pixels getinterval",
  2012. X      "} bind def",
  2013. X      "",
  2014. X      "/PseudoClassPacket",
  2015. X      "{",
  2016. X      "  %",
  2017. X      "  % Get a PseudoClass packet.",
  2018. X      "  %",
  2019. X      "  % Parameters: ",
  2020. X      "  %   index: index into the colormap.",
  2021. X      "  %   length: number of pixels minus one of this color (optional).",
  2022. X      "  %",
  2023. X      "  currentfile byte readhexstring pop 0 get",
  2024. X      "  /offset exch 3 mul def",
  2025. X      "  /color_packet colormap offset 3 getinterval def",
  2026. X      "  compression 0 gt",
  2027. X      "  {",
  2028. X      "    /number_pixels 3 def",
  2029. X      "  }",
  2030. X      "  {",
  2031. X      "    currentfile byte readhexstring pop 0 get",
  2032. X      "    /number_pixels exch 1 add 3 mul def",
  2033. X      "  } ifelse",
  2034. X      "  0 3 number_pixels 1 sub",
  2035. X      "  {",
  2036. X      "    pixels exch color_packet putinterval",
  2037. X      "  } for",
  2038. X      "  pixels 0 number_pixels getinterval",
  2039. X      "} bind def",
  2040. X      "",
  2041. X      "/PseudoClassImage",
  2042. X      "{",
  2043. X      "  %",
  2044. X      "  % Display a PseudoClass image.",
  2045. X      "  %",
  2046. X      "  % Parameters: ",
  2047. X      "  %   colors: number of colors in the colormap.",
  2048. X      "  %   colormap: red, green, blue color packets.",
  2049. X      "  %",
  2050. X      "  currentfile buffer readline pop",
  2051. X      "  token pop /colors exch def pop",
  2052. X      "  /colors colors 3 mul def",
  2053. X      "  /colormap colors string def",
  2054. X      "  currentfile colormap readhexstring pop pop",
  2055. X      "  systemdict /colorimage known",
  2056. X      "  {",
  2057. X      "    columns rows 8",
  2058. X      "    [",
  2059. X      "      columns 0 0",
  2060. X      "      rows neg 0 rows",
  2061. X      "    ]",
  2062. X      "    { PseudoClassPacket } false 3 colorimage",
  2063. X      "  }",
  2064. X      "  {",
  2065. X      "    %",
  2066. X      "    % No colorimage operator;  convert to grayscale.",
  2067. X      "    %",
  2068. X      "    columns rows 8",
  2069. X      "    [",
  2070. X      "      columns 0 0",
  2071. X      "      rows neg 0 rows",
  2072. X      "    ]",
  2073. X      "    { GrayPseudoClassPacket } image",
  2074. X      "  } ifelse",
  2075. X      "} bind def",
  2076. X      "",
  2077. X      "/DisplayImage",
  2078. X      "{",
  2079. X      "  %",
  2080. X      "  % Display a DirectClass or PseudoClass image.",
  2081. X      "  %",
  2082. X      "  % Parameters: ",
  2083. X      "  %   x & y translation.",
  2084. X      "  %   x & y scale.",
  2085. X      "  %   image columns & rows.",
  2086. X      "  %   class: 0-DirectClass or 1-PseudoClass.",
  2087. X      "  %   compression: 0-RunlengthEncodedCompression or 1-NoCompression.",
  2088. X      "  %   hex color packets.",
  2089. X      "  %",
  2090. X      "  gsave",
  2091. X      "  currentfile buffer readline pop",
  2092. X      "  token pop /x exch def",
  2093. X      "  token pop /y exch def pop",
  2094. X      "  x y translate",
  2095. X      "  currentfile buffer readline pop",
  2096. X      "  token pop /x exch def",
  2097. X      "  token pop /y exch def pop",
  2098. X      "  x y scale",
  2099. X      "  currentfile buffer readline pop",
  2100. X      "  token pop /columns exch def",
  2101. X      "  token pop /rows exch def pop",
  2102. X      "  currentfile buffer readline pop",
  2103. X      "  token pop /class exch def pop",
  2104. X      "  currentfile buffer readline pop",
  2105. SHAR_EOF
  2106. true || echo 'restore of ImageMagick/image.c failed'
  2107. fi
  2108. echo 'End of  part 5'
  2109. echo 'File ImageMagick/image.c is continued in part 6'
  2110. echo 6 > _shar_seq_.tmp
  2111. exit 0
  2112. exit 0 # Just in case...
  2113.