home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume34 / imagemagick / part05 < prev    next >
Text File  |  1992-12-14  |  59KB  |  2,107 lines

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