home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume13 / imagemagic / part04 < prev    next >
Internet Message Format  |  1991-05-22  |  75KB

  1. Path: uunet!cs.utexas.edu!sun-barr!newstop!exodus!dupont.com!cristy
  2. From: cristy@dupont.com
  3. Newsgroups: comp.sources.x
  4. Subject: v13i020: ImageMagick - Graphics display programs, Part04/21
  5. Message-ID: <13790@exodus.Eng.Sun.COM>
  6. Date: 22 May 91 08:57:29 GMT
  7. References: <csx-13i017:imagemagic@uunet.UU.NET>
  8. Sender: news@exodus.Eng.Sun.COM
  9. Lines: 2555
  10. Approved: argv@sun.com
  11.  
  12. Submitted-by: cristy@dupont.com
  13. Posting-number: Volume 13, Issue 20
  14. Archive-name: imagemagic/part04
  15.  
  16. #!/bin/sh
  17. # this is img.04 (part 4 of ImageMagick)
  18. # do not concatenate these parts, unpack them in order with /bin/sh
  19. # file ImageMagick/image.c continued
  20. #
  21. if test ! -r _shar_seq_.tmp; then
  22.     echo 'Please unpack part 1 first!'
  23.     exit 1
  24. fi
  25. (read Scheck
  26.  if test "$Scheck" != 4; then
  27.     echo Please unpack part "$Scheck" next!
  28.     exit 1
  29.  else
  30.     exit 0
  31.  fi
  32. ) < _shar_seq_.tmp || exit 1
  33. if test ! -f _shar_wnt_.tmp; then
  34.     echo 'x - still skipping ImageMagick/image.c'
  35. else
  36. echo 'x - continuing file ImageMagick/image.c'
  37. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/image.c' &&
  38. %                                                                             %
  39. %                                                                             %
  40. %                                                                             %
  41. %   D e s t r o y I m a g e                                                   %
  42. %                                                                             %
  43. %                                                                             %
  44. %                                                                             %
  45. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  46. %
  47. %  Function DestroyImage deallocates memory associated with an image.
  48. %
  49. %  The format of the DestroyImage routine is:
  50. %
  51. %      DestroyImage(image)
  52. %
  53. %  A description of each parameter follows:
  54. %
  55. %    o image: The address of a structure of type Image.
  56. %
  57. %
  58. */
  59. void DestroyImage(image)
  60. Image
  61. X  *image;
  62. {
  63. X  /*
  64. X    Deallocate the image colormap.
  65. X  */
  66. X  if (image->colormap != (ColorPacket *) NULL)
  67. X    (void) free((char *) image->colormap);
  68. X  /*
  69. X    Deallocate the image pixels.
  70. X  */
  71. X  if (image->pixels != (RunlengthPacket *) NULL)
  72. X    (void) free((char *) image->pixels);
  73. X  /*
  74. X    Deallocate the image comments.
  75. X  */
  76. X  if (image->comments != (char *) NULL)
  77. X    (void) free((char *) image->comments);
  78. X  /*
  79. X    Deallocate the image structure.
  80. X  */
  81. X  (void) free((char *) image);
  82. }
  83. X
  84. /*
  85. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  86. %                                                                             %
  87. %                                                                             %
  88. %     E n h a n c e I m a g e                                                 %
  89. %                                                                             %
  90. %                                                                             %
  91. %                                                                             %
  92. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  93. %
  94. %  Function EnhanceImage creates a new image that is a copy of an existing
  95. %  one with the noise reduced.  It allocates the memory necessary for the new
  96. %  Image structure and returns a pointer to the new image.
  97. %
  98. %  EnhanceImage does a weighted average of pixels in a 5x5 cell around each
  99. %  target pixel.  Only pixels in the 5x5 cell that are within a RGB distance
  100. %  threshold of the target pixel are averaged.
  101. %
  102. %  Weights assume that the importance of neighboring pixels is inversely
  103. %  proportional to the square of their distance from the target pixel.
  104. %
  105. %  The scan only processes pixels that have a full set of neighbors.  Pixels
  106. %  in the top, bottom, left, and right pairs of rows and columns are omitted
  107. %  from the scan.
  108. %
  109. %  The format of the EnhanceImage routine is:
  110. %
  111. %      enhanced_image=EnhanceImage(image)
  112. %
  113. %  A description of each parameter follows:
  114. %
  115. %    o enhanced_image: Function EnhanceImage returns a pointer to the image
  116. %      after it is enhanced.  A null image is returned if there is a memory
  117. %      shortage.
  118. %
  119. %    o image: The address of a structure of type Image;  returned from
  120. %      ReadImage.
  121. %
  122. %
  123. */
  124. Image *EnhanceImage(image)
  125. Image
  126. X  *image;
  127. {
  128. #define Esum(weight) \
  129. X  red_distance=s->red-red; \
  130. X  green_distance=s->green-green; \
  131. X  blue_distance=s->blue-blue; \
  132. X  distance=red_distance*red_distance+green_distance*green_distance+ \
  133. X    blue_distance*blue_distance; \
  134. X  if (distance < Threshold) \
  135. X    { \
  136. X      total_red+=weight*(s->red); \
  137. X      total_green+=weight*(s->green); \
  138. X      total_blue+=weight*(s->blue); \
  139. X      total_weight+=weight; \
  140. X    } \
  141. X  s++;
  142. #define Threshold  2500
  143. X
  144. X  ColorPacket
  145. X    *scanline;
  146. X
  147. X  Image
  148. X    *enhanced_image;
  149. X
  150. X  int
  151. X    blue_distance,
  152. X    green_distance,
  153. X    red_distance;
  154. X
  155. X  register ColorPacket
  156. X    *s,
  157. X    *s0,
  158. X    *s1,
  159. X    *s2,
  160. X    *s3,
  161. X    *s4;
  162. X
  163. X  register RunlengthPacket
  164. X    *p,
  165. X    *q;
  166. X
  167. X  register unsigned int
  168. X    x;
  169. X
  170. X  unsigned char
  171. X    blue,
  172. X    green,
  173. X    red;
  174. X
  175. X  unsigned int
  176. X    y;
  177. X
  178. X  unsigned long
  179. X    distance,
  180. X    total_blue,
  181. X    total_green,
  182. X    total_red,
  183. X    total_weight;
  184. X
  185. X  if ((image->columns < 5) || (image->rows < 5))
  186. X    {
  187. X      Warning("unable to enhance image","image size must exceed 4x4");
  188. X      return((Image *) NULL);
  189. X    }
  190. X  /*
  191. X    Initialize enhanced image attributes.
  192. X  */
  193. X  enhanced_image=CopyImage(image,image->columns,image->rows);
  194. X  if (enhanced_image == (Image *) NULL)
  195. X    {
  196. X      Warning("unable to enhance image","memory allocation failed");
  197. X      return((Image *) NULL);
  198. X    }
  199. X  enhanced_image->class=DirectClass;
  200. X  /*
  201. X    Allocate scan line buffer for 5 rows of the image.
  202. X  */
  203. X  scanline=(ColorPacket *) malloc(5*image->columns*sizeof(ColorPacket));
  204. X  if (scanline == (ColorPacket *) NULL)
  205. X    {
  206. X      Warning("unable to enhance image","memory allocation failed");
  207. X      DestroyImage(enhanced_image);
  208. X      return((Image *) NULL);
  209. X    }
  210. X  /*
  211. X    Read the first 4 rows of the image.
  212. X  */
  213. X  p=image->pixels;
  214. X  image->runlength=p->length+1;
  215. X  s=scanline;
  216. X  for (x=0; x < (image->columns*4); x++)
  217. X  {
  218. X    if (image->runlength > 0)
  219. X      image->runlength--;
  220. X    else
  221. X      {
  222. X        p++;
  223. X        image->runlength=p->length;
  224. X      }
  225. X    s->red=p->red;
  226. X    s->green=p->green;
  227. X    s->blue=p->blue;
  228. X    s->index=p->index;
  229. X    s++;
  230. X  }
  231. X  /*
  232. X    Dump first 2 scanlines of image.
  233. X  */
  234. X  enhanced_image->packets=0;
  235. X  q=enhanced_image->pixels;
  236. X  q->length=MaxRunlength;
  237. X  s=scanline;
  238. X  for (x=0; x < (2*image->columns); x++)
  239. X  {
  240. X    if ((s->red == q->red) && (s->green == q->green) && (s->blue == q->blue) &&
  241. X        (q->length < MaxRunlength))
  242. X      q->length++;
  243. X    else
  244. X      {
  245. X        if (enhanced_image->packets > 0)
  246. X          q++;
  247. X        enhanced_image->packets++;
  248. X        q->red=s->red;
  249. X        q->green=s->green;
  250. X        q->blue=s->blue;
  251. X        q->index=s->index;
  252. X        q->length=0;
  253. X      }
  254. X    s++;
  255. X  }
  256. X  /*
  257. X    Enhance each row.
  258. X  */
  259. X  for (y=2; y < (image->rows-2); y++)
  260. X  {
  261. X    /*
  262. X      Initialize sliding window pointers.
  263. X    */
  264. X    s0=scanline+image->columns*((y-2) % 5);
  265. X    s1=scanline+image->columns*((y-1) % 5);
  266. X    s2=scanline+image->columns*(y % 5);
  267. X    s3=scanline+image->columns*((y+1) % 5);
  268. X    s4=scanline+image->columns*((y+2) % 5);
  269. X    /*
  270. X      Read another scan line.
  271. X    */
  272. X    s=s4;
  273. X    for (x=0; x < image->columns; x++)
  274. X    {
  275. X      if (image->runlength > 0)
  276. X        image->runlength--;
  277. X      else
  278. X        {
  279. X          p++;
  280. X          image->runlength=p->length;
  281. X        }
  282. X      s->red=p->red;
  283. X      s->green=p->green;
  284. X      s->blue=p->blue;
  285. X      s->index=p->index;
  286. X      s++;
  287. X    }
  288. X    /*
  289. X      Transfer first 2 pixels of the scanline.
  290. X    */
  291. X    s=s2;
  292. X    for (x=0; x < 2; x++)
  293. X    {
  294. X      if ((s->red == q->red) && (s->green == q->green) && 
  295. X          (s->blue == q->blue) && (q->length < MaxRunlength))
  296. X        q->length++;
  297. X      else
  298. X        {
  299. X          if (enhanced_image->packets > 0)
  300. X            q++;
  301. X          enhanced_image->packets++;
  302. X          q->red=0;
  303. X          q->green=0;
  304. X          q->blue=0;
  305. X          q->index=0;
  306. X          q->length=0;
  307. X        }
  308. X      s++;
  309. X    }
  310. X    for (x=2; x < (image->columns-2); x++)
  311. X    {
  312. X      /*
  313. X        Compute weighted average of target pixel color components.
  314. X      */
  315. X      total_red=0;
  316. X      total_green=0;
  317. X      total_blue=0;
  318. X      total_weight=0;
  319. X      s=s2+2;
  320. X      red=s->red;
  321. X      green=s->green;
  322. X      blue=s->blue;
  323. X      s=s0;
  324. X      Esum(5);  Esum(8);  Esum(10); Esum(8);  Esum(5);
  325. X      s=s1;
  326. X      Esum(8);  Esum(20); Esum(40); Esum(20); Esum(8);
  327. X      s=s2;
  328. X      Esum(10); Esum(40); Esum(80); Esum(40); Esum(10);
  329. X      s=s3;
  330. X      Esum(8);  Esum(20); Esum(40); Esum(20); Esum(8);
  331. X      s=s4;
  332. X      Esum(5);  Esum(8);  Esum(10); Esum(8);  Esum(5);
  333. X      red=(unsigned char) ((total_red+(total_weight >> 1)-1)/total_weight);
  334. X      green=(unsigned char) ((total_green+(total_weight >> 1)-1)/total_weight);
  335. X      blue=(unsigned char) ((total_blue+(total_weight >> 1)-1)/total_weight);
  336. X      if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
  337. X          (q->length < MaxRunlength))
  338. X        q->length++;
  339. X      else
  340. X        {
  341. X          if (enhanced_image->packets > 0)
  342. X            q++;
  343. X          enhanced_image->packets++;
  344. X          q->red=red;
  345. X          q->green=green;
  346. X          q->blue=blue;
  347. X          q->index=0;
  348. X          q->length=0;
  349. X        }
  350. X      s0++;
  351. X      s1++;
  352. X      s2++;
  353. X      s3++;
  354. X      s4++;
  355. X    }
  356. X    /*
  357. X      Transfer last 2 pixels of the scanline.
  358. X    */
  359. X    s=s2;
  360. X    for (x=0; x < 2; x++)
  361. X    {
  362. X      if ((s->red == q->red) && (s->green == q->green) && 
  363. X          (s->blue == q->blue) && (q->length < MaxRunlength))
  364. X        q->length++;
  365. X      else
  366. X        {
  367. X          if (enhanced_image->packets > 0)
  368. X            q++;
  369. X          enhanced_image->packets++;
  370. X          q->red=s->red;
  371. X          q->green=s->green;
  372. X          q->blue=s->blue;
  373. X          q->index=s->index;
  374. X          q->length=0;
  375. X        }
  376. X      s++;
  377. X    }
  378. X  }
  379. X  /*
  380. X    Dump last 2 scanlines of pixels.
  381. X  */
  382. X  s=scanline+image->columns*(y % 3);
  383. X  for (x=0; x < (2*image->columns); x++)
  384. X  {
  385. X    if ((s->red == q->red) && (s->green == q->green) && 
  386. X        (s->blue == q->blue) && (q->length < MaxRunlength))
  387. X      q->length++;
  388. X    else
  389. X      {
  390. X        if (enhanced_image->packets > 0)
  391. X          q++;
  392. X        enhanced_image->packets++;
  393. X        q->red=s->red;
  394. X        q->green=s->green;
  395. X        q->blue=s->blue;
  396. X        q->index=s->index;
  397. X        q->length=0;
  398. X      }
  399. X    s++;
  400. X  }
  401. X  (void) free((char *) scanline);
  402. X  enhanced_image->pixels=(RunlengthPacket *) realloc((char *)
  403. X    enhanced_image->pixels,enhanced_image->packets*sizeof(RunlengthPacket));
  404. X  return(enhanced_image);
  405. }
  406. X
  407. /*
  408. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  409. %                                                                             %
  410. %                                                                             %
  411. %     G a m m a I m a g e                                                     %
  412. %                                                                             %
  413. %                                                                             %
  414. %                                                                             %
  415. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  416. %
  417. %  Procedure GammaImage converts the reference image to gamma corrected colors.
  418. %
  419. %  The format of the GammaImage routine is:
  420. %
  421. %      GammaImage(image,gamma)
  422. %
  423. %  A description of each parameter follows:
  424. %
  425. %    o image: The address of a structure of type Image;  returned from
  426. %      ReadImage.
  427. %
  428. %    o gamma: A double precision value indicating the level of gamma
  429. %      correction.
  430. %
  431. %
  432. */
  433. void GammaImage(image,gamma)
  434. Image
  435. X  *image;
  436. X
  437. double
  438. X  gamma;
  439. {
  440. X  register int
  441. X    i;
  442. X
  443. X  register RunlengthPacket
  444. X    *p;
  445. X
  446. X  unsigned char
  447. X    gamma_map[MaxRgb+1];
  448. X
  449. X  /*
  450. X    Initialize gamma table.
  451. X  */
  452. X  for (i=0; i <= MaxRgb; i++)
  453. X    gamma_map[i]=(unsigned char)
  454. X      ((pow((double) i/MaxRgb,1.0/gamma)*MaxRgb)+0.5);
  455. X  switch (image->class)
  456. X  {
  457. X    case DirectClass:
  458. X    {
  459. X      /*
  460. X        Gamma-correct DirectClass image.
  461. X      */
  462. X      p=image->pixels;
  463. X      for (i=0; i < image->packets; i++)
  464. X      {
  465. X        p->red=gamma_map[p->red];
  466. X        p->green=gamma_map[p->green];
  467. X        p->blue=gamma_map[p->blue];
  468. X        p++;
  469. X      }
  470. X      break;
  471. X    }
  472. X    case PseudoClass:
  473. X    {
  474. X      register unsigned short
  475. X        index;
  476. X
  477. X      /*
  478. X        Gamma-correct PseudoClass image.
  479. X      */
  480. X      for (i=0; i < image->colors; i++)
  481. X      {
  482. X        image->colormap[i].red=gamma_map[image->colormap[i].red];
  483. X        image->colormap[i].green=gamma_map[image->colormap[i].green];
  484. X        image->colormap[i].blue=gamma_map[image->colormap[i].blue];
  485. X      }
  486. X      p=image->pixels;
  487. X      for (i=0; i < image->packets; i++)
  488. X      {
  489. X        index=p->index;
  490. X        p->red=image->colormap[index].red;
  491. X        p->green=image->colormap[index].green;
  492. X        p->blue=image->colormap[index].blue;
  493. X        p++;
  494. X      }
  495. X      break;
  496. X    }
  497. X  }
  498. }
  499. X
  500. /*
  501. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  502. %                                                                             %
  503. %                                                                             %
  504. %     G r a y I m a g e                                                       %
  505. %                                                                             %
  506. %                                                                             %
  507. %                                                                             %
  508. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  509. %
  510. %  Procedure GrayImage converts the reference image to gray scale colors.
  511. %
  512. %  The format of the GrayImage routine is:
  513. %
  514. %      GrayImage(image)
  515. %
  516. %  A description of each parameter follows:
  517. %
  518. %    o image: The address of a structure of type Image;  returned from
  519. %      ReadImage.
  520. %
  521. %
  522. */
  523. void GrayImage(image)
  524. Image
  525. X  *image;
  526. {
  527. X  register int
  528. X    i;
  529. X
  530. X  register RunlengthPacket
  531. X    *p;
  532. X
  533. X  register unsigned char
  534. X    gray_value;
  535. X
  536. X  switch (image->class)
  537. X  {
  538. X    case DirectClass:
  539. X    {
  540. X      /*
  541. X        Convert DirectClass packets to grayscale.
  542. X      */
  543. X      p=image->pixels;
  544. X      for (i=0; i < image->packets; i++)
  545. X      {
  546. X        gray_value=Intensity(*p);
  547. X        p->red=gray_value;
  548. X        p->green=gray_value;
  549. X        p->blue=gray_value;
  550. X        p++;
  551. X      }
  552. X      break;
  553. X    }
  554. X    case PseudoClass:
  555. X    {
  556. X      register unsigned short
  557. X        index;
  558. X
  559. X      /*
  560. X        Convert PseudoClass packets to grayscale.
  561. X      */
  562. X      for (i=0; i < image->colors; i++)
  563. X      {
  564. X        gray_value=Intensity(image->colormap[i]);
  565. X        image->colormap[i].red=gray_value;
  566. X        image->colormap[i].green=gray_value;
  567. X        image->colormap[i].blue=gray_value;
  568. X      }
  569. X      p=image->pixels;
  570. X      for (i=0; i < image->packets; i++)
  571. X      {
  572. X        index=p->index;
  573. X        p->red=image->colormap[index].red;
  574. X        p->green=image->colormap[index].green;
  575. X        p->blue=image->colormap[index].blue;
  576. X        p++;
  577. X      }
  578. X      break;
  579. X    }
  580. X  }
  581. }
  582. X
  583. /*
  584. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  585. %                                                                             %
  586. %                                                                             %
  587. %     I n v e r s e I m a g e                                                 %
  588. %                                                                             %
  589. %                                                                             %
  590. %                                                                             %
  591. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  592. %
  593. %  Procedure InverseImage inverses the colors in the reference image.
  594. %
  595. %  The format of the InverseImage routine is:
  596. %
  597. %      InverseImage(image)
  598. %
  599. %  A description of each parameter follows:
  600. %
  601. %    o image: The address of a structure of type Image;  returned from
  602. %      ReadImage.
  603. %
  604. %
  605. */
  606. void InverseImage(image)
  607. Image
  608. X  *image;
  609. {
  610. X  register int
  611. X    i;
  612. X
  613. X  register RunlengthPacket
  614. X    *p;
  615. X
  616. X  switch (image->class)
  617. X  {
  618. X    case DirectClass:
  619. X    {
  620. X      /*
  621. X        Inverse DirectClass packets.
  622. X      */
  623. X      p=image->pixels;
  624. X      for (i=0; i < image->packets; i++)
  625. X      {
  626. X        p->red=(~p->red);
  627. X        p->green=(~p->green);
  628. X        p->blue=(~p->blue);
  629. X        p++;
  630. X      }
  631. X      break;
  632. X    }
  633. X    case PseudoClass:
  634. X    {
  635. X      register unsigned short
  636. X        index;
  637. X
  638. X      /*
  639. X        Inverse PseudoClass packets.
  640. X      */
  641. X      for (i=0; i < image->colors; i++)
  642. X      {
  643. X        image->colormap[i].red=(~image->colormap[i].red);
  644. X        image->colormap[i].green=(~image->colormap[i].green);
  645. X        image->colormap[i].blue=(~image->colormap[i].blue);
  646. X      }
  647. X      p=image->pixels;
  648. X      for (i=0; i < image->packets; i++)
  649. X      {
  650. X        index=p->index;
  651. X        p->red=image->colormap[index].red;
  652. X        p->green=image->colormap[index].green;
  653. X        p->blue=image->colormap[index].blue;
  654. X        p++;
  655. X      }
  656. X      break;
  657. X    }
  658. X  }
  659. }
  660. X
  661. /*
  662. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  663. %                                                                             %
  664. %                                                                             %
  665. %                                                                             %
  666. %   L i n e a r C o l o r m a p                                               %
  667. %                                                                             %
  668. %                                                                             %
  669. %                                                                             %
  670. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  671. %
  672. %  Function LinearColormap sorts the colormap of a PseudoClass image by
  673. %  linearly increasing intensity.
  674. %
  675. %  The format of the LinearColormap routine is:
  676. %
  677. %      LinearColormap(image)
  678. %
  679. %  A description of each parameter follows:
  680. %
  681. %    o image: A pointer to a Image structure.
  682. %
  683. %
  684. */
  685. static int LinearCompare(color_1,color_2)
  686. register ColorPacket
  687. X  *color_1,
  688. X  *color_2;
  689. {
  690. X  return((int) Intensity(*color_1)-(int) Intensity(*color_2));
  691. }
  692. X
  693. void LinearColormap(image)
  694. Image
  695. X  *image;
  696. {
  697. X  register int
  698. X    i;
  699. X
  700. X  register RunlengthPacket
  701. X    *p;
  702. X
  703. X  register unsigned short
  704. X    index;
  705. X
  706. X  unsigned int
  707. X    *pixels;
  708. X
  709. X  if (image->class == DirectClass)
  710. X    return;
  711. X  /*
  712. X    Allocate memory for pixel indexes.
  713. X  */
  714. X  pixels=(unsigned int *) malloc(image->colors*sizeof(unsigned int));
  715. X  if (pixels == (unsigned int *) NULL)
  716. X    {
  717. X      Warning("unable to sort colormap","memory allocation failed");
  718. X      return;
  719. X    }
  720. X  /*
  721. X    Assign index values to colormap entries.
  722. X  */
  723. X  for (i=0; i < image->colors; i++)
  724. X    image->colormap[i].index=i;
  725. X  /*
  726. X    Sort image colormap by increasing intensity.
  727. X  */
  728. X  qsort((char *) image->colormap,(int) image->colors,sizeof(ColorPacket),
  729. X    LinearCompare);
  730. X  /*
  731. X    Update image colormap indexes to sorted colormap order.
  732. X  */
  733. X  for (i=0; i < image->colors; i++)
  734. X    pixels[image->colormap[i].index]=i;
  735. X  p=image->pixels;
  736. X  for (i=0; i < image->packets; i++)
  737. X  {
  738. X    index=pixels[p->index];
  739. X    p->red=image->colormap[index].red;
  740. X    p->green=image->colormap[index].green;
  741. X    p->blue=image->colormap[index].blue;
  742. X    p->index=index;
  743. X    p++;
  744. X  }
  745. X  (void) free((char *) pixels);
  746. }
  747. X
  748. /*
  749. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  750. %                                                                             %
  751. %                                                                             %
  752. %     N o i s y I m a g e                                                     %
  753. %                                                                             %
  754. %                                                                             %
  755. %                                                                             %
  756. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  757. %
  758. %  Function NoisyImage creates a new image that is a copy of an existing
  759. %  one with the noise reduced with a noise peak elimination filter.  It
  760. %  allocates the memory necessary for the new Image structure and returns a
  761. %  pointer to the new image.
  762. %
  763. %  The principal function of noise peak elimination filter is to smooth the
  764. %  objects within an image without losing edge information and without
  765. %  creating undesired structures.  The central idea of the algorithm is to
  766. %  replace a pixel with its next neighbor in value within a 3 x 3 window,
  767. %  if this pixel has been found to be noise.  A pixel is defined as noise
  768. %  if and only if this pixel is a maximum or minimum within the 3 x 3
  769. %  window.
  770. %
  771. %  The format of the NoisyImage routine is:
  772. %
  773. %      noisy_image=NoisyImage(image)
  774. %
  775. %  A description of each parameter follows:
  776. %
  777. %    o noisy_image: Function NoisyImage returns a pointer to the image after
  778. %      the noise is reduced.  A null image is returned if there is a memory
  779. %      shortage.
  780. %
  781. %    o image: The address of a structure of type Image;  returned from
  782. %      ReadImage.
  783. %
  784. %
  785. */
  786. static int NoisyCompare(color_1,color_2)
  787. register ColorPacket
  788. X  *color_1,
  789. X  *color_2;
  790. {
  791. X  return((int) Intensity(*color_1)-(int) Intensity(*color_2));
  792. }
  793. X
  794. Image *NoisyImage(image)
  795. Image
  796. X  *image;
  797. {
  798. X  ColorPacket
  799. X    pixel,
  800. X    *scanline,
  801. X    window[9];
  802. X
  803. X  Image
  804. X    *noisy_image;
  805. X
  806. X  int
  807. X    i;
  808. X
  809. X  register ColorPacket
  810. X    *s,
  811. X    *s0,
  812. X    *s1,
  813. X    *s2;
  814. X
  815. X  register RunlengthPacket
  816. X    *p,
  817. X    *q;
  818. X
  819. X  register unsigned int
  820. X    x;
  821. X
  822. X  unsigned int
  823. X    y;
  824. X
  825. X  if ((image->columns < 3) || (image->rows < 3))
  826. X    {
  827. X      Warning("unable to reduce noise","the image size must exceed 2x2");
  828. X      return((Image *) NULL);
  829. X    }
  830. X  /*
  831. X    Initialize noisy image attributes.
  832. X  */
  833. X  noisy_image=CopyImage(image,image->columns,image->rows);
  834. X  if (noisy_image == (Image *) NULL)
  835. X    {
  836. X      Warning("unable to reduce noise","memory allocation failed");
  837. X      return((Image *) NULL);
  838. X    }
  839. X  /*
  840. X    Allocate scanline buffer for 3 rows of the image.
  841. X  */
  842. X  scanline=(ColorPacket *) malloc(3*image->columns*sizeof(ColorPacket));
  843. X  if (scanline == (ColorPacket *) NULL)
  844. X    {
  845. X      Warning("unable to reduce noise","memory allocation failed");
  846. X      DestroyImage(noisy_image);
  847. X      return((Image *) NULL);
  848. X    }
  849. X  /*
  850. X    Preload the first 2 rows of the image.
  851. X  */
  852. X  p=image->pixels;
  853. X  image->runlength=p->length+1;
  854. X  s=scanline;
  855. X  for (x=0; x < (2*image->columns); x++)
  856. X  {
  857. X    if (image->runlength > 0)
  858. X      image->runlength--;
  859. X    else
  860. X      {
  861. X        p++;
  862. X        image->runlength=p->length;
  863. X      }
  864. X    s->red=p->red;
  865. X    s->green=p->green;
  866. X    s->blue=p->blue;
  867. X    s->index=p->index;
  868. X    s++;
  869. X  }
  870. X  /*
  871. X    Dump first scanline of image.
  872. X  */
  873. X  noisy_image->packets=0;
  874. X  q=noisy_image->pixels;
  875. X  q->length=MaxRunlength;
  876. X  s=scanline;
  877. X  for (x=0; x < image->columns; x++)
  878. X  {
  879. X    if ((s->red == q->red) && (s->green == q->green) && (s->blue == q->blue) &&
  880. X        (q->length < MaxRunlength))
  881. X      q->length++;
  882. X    else
  883. X      {
  884. X        if (noisy_image->packets > 0)
  885. X          q++;
  886. X        noisy_image->packets++;
  887. X        q->red=s->red;
  888. X        q->green=s->green;
  889. X        q->blue=s->blue;
  890. X        q->index=s->index;
  891. X        q->length=0;
  892. X      }
  893. X    s++;
  894. X  }
  895. X  /*
  896. X    Reduce noise in each row.
  897. X  */
  898. X  for (y=1; y < (image->rows-1); y++)
  899. X  {
  900. X    /*
  901. X      Initialize sliding window pointers.
  902. X    */
  903. X    s0=scanline+image->columns*((y-1) % 3);
  904. X    s1=scanline+image->columns*(y % 3);
  905. X    s2=scanline+image->columns*((y+1) % 3);
  906. X    /*
  907. X      Read another scan line.
  908. X    */
  909. X    s=s2;
  910. X    for (x=0; x < image->columns; x++)
  911. X    {
  912. X      if (image->runlength > 0)
  913. X        image->runlength--;
  914. X      else
  915. X        {
  916. X          p++;
  917. X          image->runlength=p->length;
  918. X        }
  919. X      s->red=p->red;
  920. X      s->green=p->green;
  921. X      s->blue=p->blue;
  922. X      s->index=p->index;
  923. X      s++;
  924. X    }
  925. X    /*
  926. X      Transfer first pixel of the scanline.
  927. X    */
  928. X    s=s1;
  929. X    if ((s->red == q->red) && (s->green == q->green) &&
  930. X        (s->blue == q->blue) && (q->length < MaxRunlength))
  931. X      q->length++;
  932. X    else
  933. X      {
  934. X        if (noisy_image->packets > 0)
  935. X          q++;
  936. X        noisy_image->packets++;
  937. X        q->red=s->red;
  938. X        q->green=s->green;
  939. X        q->blue=s->blue;
  940. X        q->index=s->index;
  941. X        q->length=0;
  942. X      }
  943. X    for (x=1; x < (image->columns-1); x++)
  944. X    {
  945. X      /*
  946. X        Sort window pixels by increasing intensity.
  947. X      */
  948. X      s=s0;
  949. X      window[0]=(*s++);
  950. X      window[1]=(*s++);
  951. X      window[2]=(*s++);
  952. X      s=s1;
  953. X      window[3]=(*s++);
  954. X      window[4]=(*s++);
  955. X      window[5]=(*s++);
  956. X      s=s2;
  957. X      window[6]=(*s++);
  958. X      window[7]=(*s++);
  959. X      window[8]=(*s++);
  960. X      qsort((char *) window,9,sizeof(ColorPacket),NoisyCompare);
  961. X      pixel=(*(s1+1));
  962. X      if (Intensity(pixel) == Intensity(window[0]))
  963. X        {
  964. X          /*
  965. X            Pixel is minimum noise; replace with next neighbor in value.
  966. X          */
  967. X          for (i=1; i < 8; i++)
  968. X            if (Intensity(window[i]) != Intensity(window[0]))
  969. X              break;
  970. X          pixel=window[i];
  971. X        }
  972. X      else
  973. X        if (Intensity(pixel) == Intensity(window[8]))
  974. X          {
  975. X            /*
  976. X              Pixel is maximum noise; replace with next neighbor in value.
  977. X            */
  978. X            for (i=7; i > 0; i--)
  979. X              if (Intensity(window[i]) != Intensity(window[8]))
  980. X                break;
  981. X            pixel=window[i];
  982. X          }
  983. X      if ((pixel.red == q->red) && (pixel.green == q->green) &&
  984. X          (pixel.blue == q->blue) && (q->length < MaxRunlength))
  985. X        q->length++;
  986. X      else
  987. X        {
  988. X          if (noisy_image->packets > 0)
  989. X            q++;
  990. X          noisy_image->packets++;
  991. X          q->red=pixel.red;
  992. X          q->green=pixel.green;
  993. X          q->blue=pixel.blue;
  994. X          q->index=pixel.index;
  995. X          q->length=0;
  996. X        }
  997. X      s0++;
  998. X      s1++;
  999. X      s2++;
  1000. X    }
  1001. X    /*
  1002. X      Transfer last pixel of the scanline.
  1003. X    */
  1004. X    s=s1;
  1005. X    if ((s->red == q->red) && (s->green == q->green) &&
  1006. X        (s->blue == q->blue) && (q->length < MaxRunlength))
  1007. X      q->length++;
  1008. X    else
  1009. X      {
  1010. X        if (noisy_image->packets > 0)
  1011. X          q++;
  1012. X        noisy_image->packets++;
  1013. X        q->red=s->red;
  1014. X        q->green=s->green;
  1015. X        q->blue=s->blue;
  1016. X        q->index=s->index;
  1017. X        q->length=0;
  1018. X      }
  1019. X  }
  1020. X  /*
  1021. X    Dump last scanline of pixels.
  1022. X  */
  1023. X  s=scanline+image->columns*(y % 3);
  1024. X  for (x=0; x < image->columns; x++)
  1025. X  {
  1026. X    if ((s->red == q->red) && (s->green == q->green) && (s->blue == q->blue) &&
  1027. X        (q->length < MaxRunlength))
  1028. X      q->length++;
  1029. X    else
  1030. X      {
  1031. X        if (noisy_image->packets > 0)
  1032. X          q++;
  1033. X        noisy_image->packets++;
  1034. X        q->red=s->red;
  1035. X        q->green=s->green;
  1036. X        q->blue=s->blue;
  1037. X        q->index=s->index;
  1038. X        q->length=0;
  1039. X      }
  1040. X    s++;
  1041. X  }
  1042. X  (void) free((char *) scanline);
  1043. X  noisy_image->pixels=(RunlengthPacket *) realloc((char *)
  1044. X    noisy_image->pixels,noisy_image->packets*sizeof(RunlengthPacket));
  1045. X  return(noisy_image);
  1046. }
  1047. X
  1048. /*
  1049. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1050. %                                                                             %
  1051. %                                                                             %
  1052. %     N o r m a l i z e I m a g e                                             %
  1053. %                                                                             %
  1054. %                                                                             %
  1055. %                                                                             %
  1056. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1057. %
  1058. %  Procedure NormalizeImage normalizes the pixel values to span the full
  1059. %  range of color values.
  1060. %
  1061. %  The format of the NormalizeImage routine is:
  1062. %
  1063. %      NormalizeImage(image)
  1064. %
  1065. %  A description of each parameter follows:
  1066. %
  1067. %    o image: The address of a structure of type Image;  returned from
  1068. %      ReadImage.
  1069. %
  1070. %
  1071. */
  1072. void NormalizeImage(image)
  1073. Image
  1074. X  *image;
  1075. {
  1076. X  double
  1077. X    factor;
  1078. X
  1079. X  register int
  1080. X    i;
  1081. X
  1082. X  register int
  1083. X    max_intensity,
  1084. X    min_intensity,
  1085. X    intensity;
  1086. X
  1087. X  register RunlengthPacket
  1088. X    *p;
  1089. X
  1090. X  unsigned char
  1091. X    normalize_map[MaxRgb+1];
  1092. X
  1093. X  switch (image->class)
  1094. X  {
  1095. X    case DirectClass:
  1096. X    {
  1097. X      /*
  1098. X        Determine min and max intensity.
  1099. X      */
  1100. X      p=image->pixels;
  1101. X      min_intensity=p->red;
  1102. X      max_intensity=p->red;
  1103. X      for (i=0; i < image->packets; i++)
  1104. X      {
  1105. X        if (p->red < min_intensity)
  1106. X          min_intensity=p->red;
  1107. X        else
  1108. X          if (p->red > max_intensity)
  1109. X            max_intensity=p->red;
  1110. X        if (p->green < min_intensity)
  1111. X          min_intensity=p->green;
  1112. X        else
  1113. X          if (p->green > max_intensity)
  1114. X            max_intensity=p->green;
  1115. X        if (p->blue < min_intensity)
  1116. X          min_intensity=p->blue;
  1117. X        else
  1118. X          if (p->blue > max_intensity)
  1119. X            max_intensity=p->blue;
  1120. X        p++;
  1121. X      }
  1122. X      if ((min_intensity == 0) && (max_intensity == MaxRgb))
  1123. X        break;
  1124. X      /*
  1125. X        Initialize normalize table.
  1126. X      */
  1127. X      factor=(double) MaxRgb/(double) (max_intensity-min_intensity);
  1128. X      for (i=min_intensity; i <= max_intensity; i++)
  1129. X      {
  1130. X        intensity=(i-min_intensity)*factor;
  1131. X        if (intensity < 0)
  1132. X          intensity=0;
  1133. X        else
  1134. X          if (intensity > MaxRgb)
  1135. X            intensity=MaxRgb;
  1136. X        normalize_map[i]=(unsigned char) intensity;
  1137. X      }
  1138. X      /*
  1139. X        Normalize DirectClass image.
  1140. X      */
  1141. X      p=image->pixels;
  1142. X      for (i=0; i < image->packets; i++)
  1143. X      {
  1144. X        p->red=normalize_map[p->red];
  1145. X        p->green=normalize_map[p->green];
  1146. X        p->blue=normalize_map[p->blue];
  1147. X        p++;
  1148. X      }
  1149. X      break;
  1150. X    }
  1151. X    case PseudoClass:
  1152. X    {
  1153. X      register unsigned short
  1154. X        index;
  1155. X
  1156. X      /*
  1157. X        Determine min and max intensity.
  1158. X      */
  1159. X      min_intensity=image->colormap[0].red;
  1160. X      max_intensity=image->colormap[0].red;
  1161. X      for (i=0; i < image->colors; i++)
  1162. X      {
  1163. X        if (image->colormap[i].red < min_intensity)
  1164. X          min_intensity=image->colormap[i].red;
  1165. X        else
  1166. X          if (image->colormap[i].red > max_intensity)
  1167. X            max_intensity=image->colormap[i].red;
  1168. X        if (image->colormap[i].green < min_intensity)
  1169. X          min_intensity=image->colormap[i].green;
  1170. X        else
  1171. X          if (image->colormap[i].green > max_intensity)
  1172. X            max_intensity=image->colormap[i].green;
  1173. X        if (image->colormap[i].blue < min_intensity)
  1174. X          min_intensity=image->colormap[i].blue;
  1175. X        else
  1176. X          if (image->colormap[i].blue > max_intensity)
  1177. X            max_intensity=image->colormap[i].blue;
  1178. X      }
  1179. X      if ((min_intensity == 0) && (max_intensity == MaxRgb))
  1180. X        break;
  1181. X      /*
  1182. X        Initialize normalize table.
  1183. X      */
  1184. X      factor=(double) MaxRgb/(double) (max_intensity-min_intensity);
  1185. X      for (i=min_intensity; i <= max_intensity; i++)
  1186. X      {
  1187. X        intensity=(i-min_intensity)*factor;
  1188. X        if (intensity < 0)
  1189. X          intensity=0;
  1190. X        else
  1191. X          if (intensity > MaxRgb)
  1192. X            intensity=MaxRgb;
  1193. X        normalize_map[i]=(unsigned char) intensity;
  1194. X      }
  1195. X      /*
  1196. X        Normalize PseudoClass image.
  1197. X      */
  1198. X      for (i=0; i < image->colors; i++)
  1199. X      {
  1200. X        image->colormap[i].red=normalize_map[image->colormap[i].red];
  1201. X        image->colormap[i].green=normalize_map[image->colormap[i].green];
  1202. X        image->colormap[i].blue=normalize_map[image->colormap[i].blue];
  1203. X      }
  1204. X      p=image->pixels;
  1205. X      for (i=0; i < image->packets; i++)
  1206. X      {
  1207. X        index=p->index;
  1208. X        p->red=image->colormap[index].red;
  1209. X        p->green=image->colormap[index].green;
  1210. X        p->blue=image->colormap[index].blue;
  1211. X        p++;
  1212. X      }
  1213. X      break;
  1214. X    }
  1215. X  }
  1216. }
  1217. X
  1218. /*
  1219. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1220. %                                                                             %
  1221. %                                                                             %
  1222. %                                                                             %
  1223. %   P r i n t I m a g e                                                       %
  1224. %                                                                             %
  1225. %                                                                             %
  1226. %                                                                             %
  1227. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1228. %
  1229. %  Function PrintImage translates a MIFF image to encapsulated Postscript for
  1230. %  printing.  If the supplied geometry is null, the image is centered on the
  1231. %  Postscript page.  Otherwise, the image is positioned as specified by the
  1232. %  geometry.
  1233. %
  1234. %  The format of the PrintImage routine is:
  1235. %
  1236. %      status=PrintImage(image,geometry)
  1237. %
  1238. %  A description of each parameter follows:
  1239. %
  1240. %    o status: Function PrintImage return True if the image is printed.
  1241. %      False is returned if the image file cannot be opened for printing.
  1242. %
  1243. %    o image: The address of a structure of type Image;  returned from
  1244. %      ReadImage.
  1245. %
  1246. %    o geometry: A pointer to a standard window geometry string.
  1247. %
  1248. %
  1249. */
  1250. unsigned int PrintImage(image,geometry)
  1251. Image
  1252. X  *image;
  1253. X
  1254. char
  1255. X  *geometry;
  1256. {
  1257. #define PageBottomMargin 92
  1258. #define PageLeftMargin 16
  1259. #define PageWidth  612
  1260. #define PageHeight 792
  1261. X
  1262. X  static char
  1263. X    *Postscript[]=
  1264. X    {
  1265. X      "%",
  1266. X      "% Display a color image.  The image is displayed in color on",
  1267. X      "% Postscript viewers or printers that support color, otherwise",
  1268. X      "% it is displayed as grayscale.",
  1269. X      "%",
  1270. X      "/buffer 512 string def",
  1271. X      "/byte 1 string def",
  1272. X      "/color_packet 3 string def",
  1273. X      "/compression 1 string def",
  1274. X      "/gray_packet 1 string def",
  1275. X      "/pixels 768 string def",
  1276. X      "",
  1277. X      "/DirectClassPacket",
  1278. X      "{",
  1279. X      "  %",
  1280. X      "  % Get a DirectClass packet.",
  1281. X      "  %",
  1282. X      "  % Parameters: ",
  1283. X      "  %   red.",
  1284. X      "  %   green.",
  1285. X      "  %   blue.",
  1286. X      "  %   length: number of pixels minus one of this color (optional).",
  1287. X      "  %",
  1288. X      "  currentfile color_packet readhexstring pop pop",
  1289. X      "  compression 0 gt",
  1290. X      "  {",
  1291. X      "    /number_pixels 3 def",
  1292. X      "  }",
  1293. X      "  {",
  1294. X      "    currentfile byte readhexstring pop 0 get",
  1295. X      "    /number_pixels exch 1 add 3 mul def",
  1296. X      "  } ifelse",
  1297. X      "  0 3 number_pixels 1 sub",
  1298. X      "  {",
  1299. X      "    pixels exch color_packet putinterval",
  1300. X      "  } for",
  1301. X      "  pixels 0 number_pixels getinterval",
  1302. X      "} bind def",
  1303. X      "",
  1304. X      "/DirectClassImage",
  1305. X      "{",
  1306. X      "  %",
  1307. X      "  % Display a DirectClass image.",
  1308. X      "  %",
  1309. X      "  systemdict /colorimage known",
  1310. X      "  {",
  1311. X      "    columns rows 8",
  1312. X      "    [",
  1313. X      "      columns 0 0",
  1314. X      "      rows neg 0 rows",
  1315. X      "    ]",
  1316. X      "    { DirectClassPacket } false 3 colorimage",
  1317. X      "  }",
  1318. X      "  {",
  1319. X      "    %",
  1320. X      "    % No colorimage operator;  convert to grayscale.",
  1321. X      "    %",
  1322. X      "    columns rows 8",
  1323. X      "    [",
  1324. X      "      columns 0 0",
  1325. X      "      rows neg 0 rows",
  1326. X      "    ]",
  1327. X      "    { GrayDirectClassPacket } image",
  1328. X      "  } ifelse",
  1329. X      "} bind def",
  1330. X      "",
  1331. X      "/GrayDirectClassPacket",
  1332. X      "{",
  1333. X      "  %",
  1334. X      "  % Get a DirectClass packet;  convert to grayscale.",
  1335. X      "  %",
  1336. X      "  % Parameters: ",
  1337. X      "  %   red",
  1338. X      "  %   green",
  1339. X      "  %   blue",
  1340. X      "  %   length: number of pixels minus one of this color (optional).",
  1341. X      "  %",
  1342. X      "  currentfile color_packet readhexstring pop pop",
  1343. X      "  color_packet 0 get 0.299 mul",
  1344. X      "  color_packet 1 get 0.587 mul add",
  1345. X      "  color_packet 2 get 0.114 mul add",
  1346. X      "  cvi",
  1347. X      "  /gray_packet exch def",
  1348. X      "  compression 0 gt",
  1349. X      "  {",
  1350. X      "    /number_pixels 1 def",
  1351. X      "  }",
  1352. X      "  {",
  1353. X      "    currentfile byte readhexstring pop 0 get",
  1354. X      "    /number_pixels exch 1 add def",
  1355. X      "  } ifelse",
  1356. X      "  0 1 number_pixels 1 sub",
  1357. X      "  {",
  1358. X      "    pixels exch gray_packet put",
  1359. X      "  } for",
  1360. X      "  pixels 0 number_pixels getinterval",
  1361. X      "} bind def",
  1362. X      "",
  1363. X      "/GrayPseudoClassPacket",
  1364. X      "{",
  1365. X      "  %",
  1366. X      "  % Get a PseudoClass packet;  convert to grayscale.",
  1367. X      "  %",
  1368. X      "  % Parameters: ",
  1369. X      "  %   index: index into the colormap.",
  1370. X      "  %   length: number of pixels minus one of this color (optional).",
  1371. X      "  %",
  1372. X      "  currentfile byte readhexstring pop 0 get",
  1373. X      "  /offset exch 3 mul def",
  1374. X      "  /color_packet colormap offset 3 getinterval def",
  1375. X      "  color_packet 0 get 0.299 mul",
  1376. X      "  color_packet 1 get 0.587 mul add",
  1377. X      "  color_packet 2 get 0.114 mul add",
  1378. X      "  cvi",
  1379. X      "  /gray_packet exch def",
  1380. X      "  compression 0 gt",
  1381. X      "  {",
  1382. X      "    /number_pixels 1 def",
  1383. X      "  }",
  1384. X      "  {",
  1385. X      "    currentfile byte readhexstring pop 0 get",
  1386. X      "    /number_pixels exch 1 add def",
  1387. X      "  } ifelse",
  1388. X      "  0 1 number_pixels 1 sub",
  1389. X      "  {",
  1390. X      "    pixels exch gray_packet put",
  1391. X      "  } for",
  1392. X      "  pixels 0 number_pixels getinterval",
  1393. X      "} bind def",
  1394. X      "",
  1395. X      "/PseudoClassPacket",
  1396. X      "{",
  1397. X      "  %",
  1398. X      "  % Get a PseudoClass packet.",
  1399. X      "  %",
  1400. X      "  % Parameters: ",
  1401. X      "  %   index: index into the colormap.",
  1402. X      "  %   length: number of pixels minus one of this color (optional).",
  1403. X      "  %",
  1404. X      "  %",
  1405. X      "  currentfile byte readhexstring pop 0 get",
  1406. X      "  /offset exch 3 mul def",
  1407. X      "  /color_packet colormap offset 3 getinterval def",
  1408. X      "  compression 0 gt",
  1409. X      "  {",
  1410. X      "    /number_pixels 3 def",
  1411. X      "  }",
  1412. X      "  {",
  1413. X      "    currentfile byte readhexstring pop 0 get",
  1414. X      "    /number_pixels exch 1 add 3 mul def",
  1415. X      "  } ifelse",
  1416. X      "  0 3 number_pixels 1 sub",
  1417. X      "  {",
  1418. X      "    pixels exch color_packet putinterval",
  1419. X      "  } for",
  1420. X      "  pixels 0 number_pixels getinterval",
  1421. X      "} bind def",
  1422. X      "",
  1423. X      "/PseudoClassImage",
  1424. X      "{",
  1425. X      "  %",
  1426. X      "  % Display a PseudoClass image.",
  1427. X      "  %",
  1428. X      "  % Parameters: ",
  1429. X      "  %   colors: number of colors in the colormap.",
  1430. X      "  %   colormap: red, green, blue color packets.",
  1431. X      "  %",
  1432. X      "  currentfile buffer readline pop",
  1433. X      "  token pop /colors exch def pop",
  1434. X      "  /colors colors 3 mul def",
  1435. X      "  /colormap colors string def",
  1436. X      "  currentfile colormap readhexstring pop pop",
  1437. X      "  systemdict /colorimage known",
  1438. X      "  {",
  1439. X      "    columns rows 8",
  1440. X      "    [",
  1441. X      "      columns 0 0",
  1442. X      "      rows neg 0 rows",
  1443. X      "    ]",
  1444. X      "    { PseudoClassPacket } false 3 colorimage",
  1445. X      "  }",
  1446. X      "  {",
  1447. X      "    %",
  1448. X      "    % No colorimage operator;  convert to grayscale.",
  1449. X      "    %",
  1450. X      "    columns rows 8",
  1451. X      "    [",
  1452. X      "      columns 0 0",
  1453. X      "      rows neg 0 rows",
  1454. X      "    ]",
  1455. X      "    { GrayPseudoClassPacket } image",
  1456. X      "  } ifelse",
  1457. X      "} bind def",
  1458. X      "",
  1459. X      "/DisplayImage",
  1460. X      "{",
  1461. X      "  %",
  1462. X      "  % Display a DirectClass or PseudoClass image.",
  1463. X      "  %",
  1464. X      "  % Parameters: ",
  1465. X      "  %   x & y translation.",
  1466. X      "  %   x & y scale.",
  1467. X      "  %   image columns & rows.",
  1468. X      "  %   class: 0-DirectClass or 1-PseudoClass.",
  1469. X      "  %   compression: 0-RunlengthEncodedCompression or 1-NoCompression.",
  1470. X      "  %   hex color packets.",
  1471. X      "  %",
  1472. X      "  gsave",
  1473. X      "  currentfile buffer readline pop",
  1474. X      "  token pop /x exch def",
  1475. X      "  token pop /y exch def pop",
  1476. X      "  x y translate",
  1477. X      "  currentfile buffer readline pop",
  1478. X      "  token pop /x exch def",
  1479. X      "  token pop /y exch def pop",
  1480. X      "  x y scale",
  1481. X      "  currentfile buffer readline pop",
  1482. X      "  token pop /columns exch def",
  1483. X      "  token pop /rows exch def pop",
  1484. X      "  currentfile buffer readline pop",
  1485. X      "  token pop /class exch def pop",
  1486. X      "  currentfile buffer readline pop",
  1487. X      "  token pop /compression exch def pop",
  1488. X      "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
  1489. X      "  grestore",
  1490. X      "  showpage",
  1491. X      "} bind def",
  1492. X      "",
  1493. X      "DisplayImage",
  1494. X      NULL
  1495. X    };
  1496. X
  1497. X  char
  1498. X    **q;
  1499. X
  1500. X  int
  1501. X    center,
  1502. X    x,
  1503. X    y;
  1504. X
  1505. X  register RunlengthPacket
  1506. X    *p;
  1507. X
  1508. X  register int
  1509. X    i,
  1510. X    j;
  1511. X
  1512. X  unsigned int
  1513. X    height,
  1514. X    width;
  1515. X
  1516. X  /*
  1517. X    Open output image file.
  1518. X  */
  1519. X  if (*image->filename == '-')
  1520. X    image->file=stdout;
  1521. X  else
  1522. X    image->file=fopen(image->filename,"w");
  1523. X  if (image->file == (FILE *) NULL)
  1524. X    {
  1525. X      (void) fprintf(stderr,"%s: unable to print image, cannot open %s.\n",
  1526. X        application_name,image->filename);
  1527. X      return(False);
  1528. X    }
  1529. X  width=image->columns;
  1530. X  height=image->rows;
  1531. X  center=True;
  1532. X  if (geometry != (char *) NULL)
  1533. X    {
  1534. X      int
  1535. X        flags;
  1536. X
  1537. X      /*
  1538. X        User specified Postscript page position.
  1539. X      */
  1540. X      x=0;
  1541. X      y=0;
  1542. X      flags=XParseGeometry(geometry,&x,&y,&width,&height);
  1543. X      center=(flags & (XValue | YValue)) == 0;
  1544. X      if (flags & XValue)
  1545. X        if (flags & XNegative)
  1546. X          x=PageWidth+x-width;
  1547. X      if (flags & YValue)
  1548. X        if (flags & YNegative)
  1549. X          y=PageHeight+y-height;
  1550. X      y=PageHeight-y-height;
  1551. X    }
  1552. X  if (center)
  1553. X    {
  1554. X      int
  1555. X        delta_x,
  1556. X        delta_y;
  1557. X
  1558. X      unsigned long
  1559. X        scale;
  1560. X
  1561. X      /*
  1562. X        Center image on Postscript page.
  1563. X      */
  1564. X      if (width > (PageWidth-(2*PageLeftMargin)))
  1565. X        {
  1566. X          scale=((PageWidth-(2*PageLeftMargin)) << 14)/width;
  1567. X          width=(width*scale) >> 14;
  1568. X          height=(height*scale) >> 14;
  1569. X        }
  1570. X      if (height > (PageHeight-(2*PageBottomMargin)))
  1571. X        {
  1572. X          scale=((PageHeight-(2*PageBottomMargin)) << 14)/height;
  1573. X          width=(width*scale) >> 14;
  1574. X          height=(height*scale) >> 14;
  1575. X        }
  1576. X      delta_x=PageWidth-(width+(2*PageLeftMargin));
  1577. X      delta_y=PageHeight-(height+(2*PageBottomMargin));
  1578. X      if (delta_x >= 0)
  1579. X        x=delta_x/2+PageLeftMargin;
  1580. X      else
  1581. X        x=PageLeftMargin;
  1582. X      if (delta_y >= 0)
  1583. X        y=delta_y/2+PageBottomMargin;
  1584. X      else
  1585. X        y=PageBottomMargin;
  1586. X    }
  1587. X  /*
  1588. X    Output encapsulated Postscript header.
  1589. X  */
  1590. X  (void) fprintf(image->file,"%%!PS-Adobe-2.0 EPSF-2.0\n");
  1591. X  (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",x,y,x+width,
  1592. X    y+height);
  1593. X  (void) fprintf(image->file,"%%%%Creator: ImageMagick\n");
  1594. X  (void) fprintf(image->file,"%%%%Title: %s\n",image->filename);
  1595. X  (void) fprintf(image->file,"%%%%EndComments\n");
  1596. X  /*
  1597. X    Output encapsulated Postscript commands.
  1598. X  */
  1599. X  for (q=Postscript; *q; q++)
  1600. X    (void) fprintf(image->file,"%s\n",*q);
  1601. X  /*
  1602. X    Output image data.
  1603. X  */
  1604. X  (void) fprintf(image->file,"%d %d\n%d %d\n%d %d\n%d\n%d\n",x,y,width,height,
  1605. X    image->columns,image->rows,(image->class == PseudoClass),
  1606. X    image->compression == NoCompression);
  1607. X  x=0;
  1608. X  p=image->pixels;
  1609. X  switch (image->class)
  1610. X  {
  1611. X    case DirectClass:
  1612. X    {
  1613. X      switch (image->compression)
  1614. X      {
  1615. X        case RunlengthEncodedCompression:
  1616. X        default:
  1617. X        {
  1618. X          /*
  1619. X            Dump runlength-encoded DirectColor packets.
  1620. X          */
  1621. X          for (i=0; i < image->packets; i++)
  1622. X          {
  1623. X            x++;
  1624. X            (void) fprintf(image->file,"%02x%02x%02x%02x",p->red,p->green,
  1625. X              p->blue,p->length);
  1626. X            if (x == 9)
  1627. X              {
  1628. X                x=0;
  1629. X                (void) fprintf(image->file,"\n");
  1630. X              }
  1631. X            p++;
  1632. X          }
  1633. X          break;
  1634. X        }
  1635. X        case NoCompression:
  1636. X        {
  1637. X          /*
  1638. X            Dump DirectColor packets.
  1639. X          */
  1640. X          for (i=0; i < image->packets; i++)
  1641. X          {
  1642. X            for (j=0; j <= p->length; j++)
  1643. X            {
  1644. X              x++;
  1645. X              (void) fprintf(image->file,"%02x%02x%02x",p->red,p->green,
  1646. X                p->blue);
  1647. X              if (x == 12)
  1648. X                {
  1649. X                  x=0;
  1650. X                  (void) fprintf(image->file,"\n");
  1651. X                }
  1652. X            }
  1653. X            p++;
  1654. X          }
  1655. X          break;
  1656. X        }
  1657. X      }
  1658. X      break;
  1659. X    }
  1660. X    case PseudoClass:
  1661. X    {
  1662. X      /*
  1663. X        Dump number of colors, colormap, PseudoColor packets.
  1664. X      */
  1665. X      (void) fprintf(image->file,"%d\n",image->colors);
  1666. X      for (i=0; i < image->colors; i++)
  1667. X        (void) fprintf(image->file,"%02x%02x%02x\n",image->colormap[i].red,
  1668. X          image->colormap[i].green,image->colormap[i].blue);
  1669. X      switch (image->compression)
  1670. X      {
  1671. X        case RunlengthEncodedCompression:
  1672. X        default:
  1673. X        {
  1674. X          for (i=0; i < image->packets; i++)
  1675. X          {
  1676. X            x++;
  1677. X            (void) fprintf(image->file,"%02x%02x",p->index,p->length);
  1678. X            if (x == 18)
  1679. X              {
  1680. X                x=0;
  1681. X                (void) fprintf(image->file,"\n");
  1682. X              }
  1683. X            p++;
  1684. X          }
  1685. X          break;
  1686. X        }
  1687. X        case NoCompression:
  1688. X        {
  1689. X          for (i=0; i < image->packets; i++)
  1690. X          {
  1691. X            for (j=0; j <= p->length; j++)
  1692. X            {
  1693. X              x++;
  1694. X              (void) fprintf(image->file,"%02x",p->index);
  1695. X              if (x == 36)
  1696. X                {
  1697. X                  x=0;
  1698. X                  (void) fprintf(image->file,"\n");
  1699. X                }
  1700. X            }
  1701. X            p++;
  1702. X          }
  1703. X        }
  1704. X        break;
  1705. X      }
  1706. X    }
  1707. X  }
  1708. X  (void) fprintf(image->file,"\n\n");
  1709. X  (void) fprintf(image->file,"%%%%Trailer\n");
  1710. X  if (image->file != stdin)
  1711. X    (void) fclose(image->file);
  1712. X  return(True);
  1713. }
  1714. X
  1715. /*
  1716. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1717. %                                                                             %
  1718. %                                                                             %
  1719. %                                                                             %
  1720. %  R e a d D a t a                                                            %
  1721. %                                                                             %
  1722. %                                                                             %
  1723. %                                                                             %
  1724. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1725. %
  1726. %  Function ReadData reads data from the image file and returns it.  If it
  1727. %  cannot read the requested number of items, False is returned indicating
  1728. %  an error.
  1729. %
  1730. %  The format of the ReadData routine is:
  1731. %
  1732. %      status=ReadData(data,size,number_items,file)
  1733. %
  1734. %  A description of each parameter follows:
  1735. %
  1736. %    o status:  Function ReadData returns True if all the data requested
  1737. %      is obtained without error, otherwise False.
  1738. %
  1739. %    o data:  Specifies an area to place the information reuested from
  1740. %      the file.
  1741. %
  1742. %    o size:  Specifies an integer representing the length of an
  1743. %      individual item to be read from the file.
  1744. %
  1745. %    o numer_items:  Specifies an integer representing the number of items
  1746. %      to read from the file.
  1747. %
  1748. %    o file:  Specifies a file to read the data.
  1749. %
  1750. %
  1751. */
  1752. unsigned int ReadData(data,size,number_items,file)
  1753. char
  1754. X  *data;
  1755. X
  1756. int
  1757. X  size,
  1758. X  number_items;
  1759. X
  1760. FILE
  1761. X  *file;
  1762. {
  1763. X  size*=number_items;
  1764. X  while (size > 0)
  1765. X  {
  1766. X    number_items=fread(data,1,size,file);
  1767. X    if (number_items <= 0)
  1768. X      return(False);
  1769. X    size-=number_items;
  1770. X    data+=number_items;
  1771. X  }
  1772. X  return(True);
  1773. }
  1774. X
  1775. /*
  1776. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1777. %                                                                             %
  1778. %                                                                             %
  1779. %                                                                             %
  1780. %   R e a d I m a g e                                                         %
  1781. %                                                                             %
  1782. %                                                                             %
  1783. %                                                                             %
  1784. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1785. %
  1786. %  Function ReadImage reads an image file and returns it.  It allocates the
  1787. %  memory necessary for the new Image structure and returns a pointer to the
  1788. %  new image.
  1789. %
  1790. %  The format of the ReadImage routine is:
  1791. %
  1792. %      image=ReadImage(filename)
  1793. %
  1794. %  A description of each parameter follows:
  1795. %
  1796. %    o image: Function ReadImage returns a pointer to the image after reading.
  1797. %      A null image is returned if there is a a memory shortage or if the
  1798. %      image cannot be read.
  1799. %
  1800. %    o filename: Specifies the name of the image to read.
  1801. %
  1802. %
  1803. */
  1804. Image *ReadImage(filename)
  1805. char
  1806. X  *filename;
  1807. {
  1808. #define MaxKeywordLength  256
  1809. X
  1810. X  char
  1811. X    keyword[MaxKeywordLength],
  1812. X    value[MaxKeywordLength];
  1813. X
  1814. X  Image
  1815. X    *image;
  1816. X
  1817. X  long int
  1818. X    count;
  1819. X
  1820. X  register int
  1821. X    c,
  1822. X    i;
  1823. X
  1824. X  register RunlengthPacket
  1825. X    *q;
  1826. X
  1827. X  register unsigned char
  1828. X    blue,
  1829. X    green,
  1830. X    *p,
  1831. X    red;
  1832. X
  1833. X  unsigned char
  1834. X    *pixels;
  1835. X
  1836. X  unsigned int
  1837. X    packets,
  1838. X    packet_size,
  1839. X    status;
  1840. X
  1841. X  /*
  1842. X    Allocate image structure.
  1843. X  */
  1844. X  image=(Image *) malloc(sizeof(Image));
  1845. X  if (image == (Image *) NULL)
  1846. X    return((Image *) NULL);
  1847. X  /*
  1848. X    Initialize Image structure.
  1849. X  */
  1850. X  image->id=UnknownId;
  1851. X  image->class=DirectClass;
  1852. X  image->compression=NoCompression;
  1853. X  image->columns=0;
  1854. X  image->rows=0;
  1855. X  image->packets=0;
  1856. X  image->colors=0;
  1857. X  image->scene=0;
  1858. X  image->colormap=(ColorPacket *) NULL;
  1859. X  image->pixels=(RunlengthPacket *) NULL;
  1860. X  image->comments=(char *) NULL;
  1861. X  /*
  1862. X    Open image file.
  1863. X  */
  1864. X  (void) strcpy(image->filename,filename);
  1865. X  if (*image->filename == '-')
  1866. X    image->file=stdin;
  1867. X  else
  1868. X    if (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0)
  1869. X      image->file=fopen(image->filename,"r");
  1870. X    else
  1871. X      {
  1872. X        char
  1873. X          command[256];
  1874. X
  1875. X        /*
  1876. X          Image file is compressed-- uncompress it.
  1877. X        */
  1878. X        (void) sprintf(command,"uncompress -c %s",image->filename);
  1879. X        image->file=(FILE *) popen(command,"r");
  1880. X      }
  1881. X  if (image->file == (FILE *) NULL)
  1882. X    {
  1883. X      Warning("unable to open file",image->filename);
  1884. X      (void) DestroyImage(image);
  1885. X      return((Image *) NULL);
  1886. X    }
  1887. X  /*
  1888. X    Decode image header;  header terminates one character beyond a ':'.
  1889. X  */
  1890. X  do { c=fgetc(image->file); } while (isspace(c));
  1891. X  while ((c > 0) && (c != ':'))
  1892. X  {
  1893. X    register char
  1894. X      *p;
  1895. X
  1896. X    if (c == '{')
  1897. X      {
  1898. X        register char
  1899. X          *q;
  1900. X
  1901. X        /*
  1902. X          Comment.
  1903. X        */
  1904. X        if (image->comments == (char *) NULL)
  1905. X          {
  1906. X            /*
  1907. X              Allocate initial memory for a comment.
  1908. X            */
  1909. X            image->comments=(char *) malloc(256);
  1910. X            if (image->comments == (char *) NULL)
  1911. X              {
  1912. X                Warning("unable to read image","memory allocation failed");
  1913. X                DestroyImage(image);
  1914. X                return((Image *) NULL);
  1915. X              }
  1916. X            *image->comments=(char) NULL;
  1917. X          }
  1918. X        p=image->comments+strlen(image->comments);
  1919. X        q=p+(255-(strlen(image->comments) % 256));
  1920. X        c=fgetc(image->file);
  1921. X        while ((c > 0) && (c != '}'))
  1922. X        {
  1923. X          if (p == q)
  1924. X            {
  1925. X              /*
  1926. X                Allocate more memory for the comment.
  1927. X              */
  1928. X              image->comments=(char *) realloc((char *) image->comments,
  1929. X                (unsigned int) (strlen(image->comments)+256));
  1930. X              if (image->comments == (char *) NULL)
  1931. X                {
  1932. X                  Warning("unable to read image","memory allocation failed");
  1933. X                  DestroyImage(image);
  1934. X                  return((Image *) NULL);
  1935. X                }
  1936. X              q=p+255;
  1937. X            }
  1938. X          *p++=c;
  1939. X          c=fgetc(image->file);
  1940. X        }
  1941. X        *p=(char) NULL;
  1942. X        c=fgetc(image->file);
  1943. X      }
  1944. X    else
  1945. X      if (isalnum(c))
  1946. X        {
  1947. X          /*
  1948. X            Determine a keyword and its value.
  1949. X          */
  1950. X          p=keyword;
  1951. X          do
  1952. X          {
  1953. X            if ((p-keyword) < (MaxKeywordLength-1))
  1954. X              *p++=c;
  1955. X            c=fgetc(image->file);
  1956. X          } while (isalnum(c));
  1957. X          *p=(char) NULL;
  1958. X          while (isspace(c) || (c == '='))
  1959. X            c=fgetc(image->file);
  1960. X          p=value;
  1961. X          while (isalnum(c))
  1962. X          {
  1963. X            if ((p-value) < (MaxKeywordLength-1))
  1964. X              *p++=c;
  1965. X            c=fgetc(image->file);
  1966. X          }
  1967. X          *p=(char) NULL;
  1968. X          /*
  1969. X            Assign a value to the specified keyword.
  1970. X          */
  1971. X          if (strcmp(keyword,"class") == 0)
  1972. X            if (strcmp(value,"PseudoClass") == 0)
  1973. X              image->class=PseudoClass;
  1974. X            else
  1975. X              if (strcmp(value,"DirectClass") == 0)
  1976. X                image->class=DirectClass;
  1977. X              else
  1978. X                image->class=UnknownClass;
  1979. X          if (strcmp(keyword,"compression") == 0)
  1980. X            if (strcmp(value,"QEncoded") == 0)
  1981. X              image->compression=QEncodedCompression;
  1982. X            else
  1983. X              if (strcmp(value,"RunlengthEncoded") == 0)
  1984. X                image->compression=RunlengthEncodedCompression;
  1985. X              else
  1986. X                image->compression=UnknownCompression;
  1987. X          if (strcmp(keyword,"colors") == 0)
  1988. X            image->colors=(unsigned int) atoi(value);
  1989. X          if (strcmp(keyword,"columns") == 0)
  1990. X            image->columns=(unsigned int) atoi(value);
  1991. X          if (strcmp(keyword,"id") == 0)
  1992. X            if ((strcmp(value,"ImageMagick") == 0) ||
  1993. X                (strcmp(value,"XImager") == 0))
  1994. X              image->id=ImageMagickId;
  1995. X            else
  1996. X              image->id=UnknownId;
  1997. X          if (strcmp(keyword,"packets") == 0)
  1998. X            image->packets=(unsigned int) atoi(value);
  1999. X          if (strcmp(keyword,"rows") == 0)
  2000. X            image->rows=(unsigned int) atoi(value);
  2001. X          if (strcmp(keyword,"scene") == 0)
  2002. X            image->scene=(unsigned int) atoi(value);
  2003. X        }
  2004. X      else
  2005. X        c=fgetc(image->file);
  2006. X    while (isspace(c))
  2007. X      c=fgetc(image->file);
  2008. X  }
  2009. X  (void) fgetc(image->file);
  2010. X  /*
  2011. X    Verify that required image information is valid.
  2012. X  */
  2013. X  if ((image->id == UnknownId) ||
  2014. X      (image->class == UnknownClass) ||
  2015. X      (image->compression == UnknownCompression) ||
  2016. X      ((image->columns*image->rows) == 0))
  2017. X    {
  2018. X      Warning("incorrect image header in file",image->filename);
  2019. X      DestroyImage(image);
  2020. X      return((Image *) NULL);
  2021. X    }
  2022. X  if ((image->columns*image->rows) > MaxImageSize)
  2023. X    {
  2024. X      Warning("unable to read image","image size too large");
  2025. X      DestroyImage(image);
  2026. X      return((Image *) NULL);
  2027. X    }
  2028. X  /*
  2029. X    Read image from disk and convert to runlength-encoded packets.
  2030. X  */
  2031. X  switch (image->class)
  2032. X  {
  2033. X    case DirectClass:
  2034. X    {
  2035. X      /*
  2036. X        Transfer pixels to DirectClass image pixel buffer.
  2037. X      */
  2038. X      switch (image->compression)
  2039. X      {
  2040. X        case NoCompression:
  2041. X        {
  2042. X          /*
  2043. X            Allocate image buffers and read image from disk.
  2044. X          */
  2045. X          image->packets=image->columns*image->rows;
  2046. X          packet_size=3;
  2047. X          pixels=(unsigned char *)
  2048. X            malloc((unsigned int) image->packets*packet_size);
  2049. X          image->pixels=(RunlengthPacket *)
  2050. X            malloc(image->packets*sizeof(RunlengthPacket));
  2051. X          if ((pixels == (unsigned char *) NULL) ||
  2052. X              (image->pixels == (RunlengthPacket *) NULL))
  2053. X            {
  2054. X              Warning("unable to read image","memory allocation failed");
  2055. X              DestroyImage(image);
  2056. X              return((Image *) NULL);
  2057. X            }
  2058. X          status=ReadData((char *) pixels,(int) packet_size,(int)
  2059. X            image->packets,image->file);
  2060. X          if (status == False)
  2061. X            {
  2062. X              Warning("insufficient image data in file",image->filename);
  2063. X              DestroyImage(image);
  2064. X              return((Image *) NULL);
  2065. X            }
  2066. X          /*
  2067. X            Convert to runlength-encoded DirectClass packets.
  2068. X          */
  2069. X          image->packets=image->columns*image->rows;
  2070. X          p=pixels;
  2071. X          q=image->pixels;
  2072. X          for (i=0; i < image->packets; i++)
  2073. X          {
  2074. X            q->red=(*p++);
  2075. X            q->green=(*p++);
  2076. X            q->blue=(*p++);
  2077. X            q->index=0;
  2078. X            q->length=0;
  2079. X            q++;
  2080. X          }
  2081. X          break;
  2082. X        }
  2083. X        case QEncodedCompression:
  2084. X        {
  2085. X          extern unsigned int
  2086. X            QDecodeImage();
  2087. X
  2088. X          unsigned char
  2089. X            *compressed_pixels;
  2090. X
  2091. X          /*
  2092. X            Allocate image buffers and read image from disk.
  2093. X          */
  2094. X          packet_size=1;
  2095. X          if (image->packets == 0)
  2096. X            image->packets=image->columns*image->rows*3;
  2097. X          pixels=(unsigned char *)
  2098. X            malloc((unsigned int) image->packets*packet_size);
  2099. X          image->pixels=(RunlengthPacket *)
  2100. X            malloc(image->columns*image->rows*sizeof(RunlengthPacket));
  2101. X          if ((pixels == (unsigned char *) NULL) ||
  2102. X              (image->pixels == (RunlengthPacket *) NULL))
  2103. X            {
  2104. X              Warning("unable to read image","memory allocation failed");
  2105. X              DestroyImage(image);
  2106. X              return((Image *) NULL);
  2107. X            }
  2108. X          status=ReadData((char *) pixels,(int) packet_size,
  2109. X            (int) image->packets,image->file);
  2110. X          /*
  2111. X            Uncompress image.
  2112. X          */
  2113. X          image->packets=image->columns*image->rows;
  2114. X          packet_size=3;
  2115. X          compressed_pixels=pixels;
  2116. X          pixels=(unsigned char *)
  2117. X            malloc((unsigned int) image->packets*packet_size);
  2118. X          if (pixels == (unsigned char *) NULL)
  2119. X            {
  2120. X              Warning("unable to read image","memory allocation failed");
  2121. X              DestroyImage(image);
  2122. X              return((Image *) NULL);
  2123. X            }
  2124. X          packets=QDecodeImage(compressed_pixels,pixels,
  2125. X            image->columns*(int) packet_size,image->rows);
  2126. X          if (packets != (image->packets*packet_size))
  2127. X            {
  2128. X              Warning("insufficient image data in file",image->filename);
  2129. X              DestroyImage(image);
  2130. X              return((Image *) NULL);
  2131. X            }
  2132. X          (void) free((char *) compressed_pixels);
  2133. X          /*
  2134. X            Convert to runlength-encoded DirectClass packets.
  2135. X          */
  2136. X          p=pixels;
  2137. X          image->packets=0;
  2138. X          q=image->pixels;
  2139. X          q->length=MaxRunlength;
  2140. X          for (i=0; i < (image->columns*image->rows); i++)
  2141. X          {
  2142. X            red=(*p++);
  2143. X            green=(*p++);
  2144. X            blue=(*p++);
  2145. X            if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
  2146. X                (q->length < MaxRunlength))
  2147. X              q->length++;
  2148. X            else
  2149. X              {
  2150. X                if (image->packets > 0)
  2151. X                  q++;
  2152. X                image->packets++;
  2153. X                q->red=red;
  2154. X                q->green=green;
  2155. X                q->blue=blue;
  2156. X                q->index=0;
  2157. X                q->length=0;
  2158. X              }
  2159. X          }
  2160. X          image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,
  2161. X            image->packets*sizeof(RunlengthPacket));
  2162. X          break;
  2163. X        }
  2164. X        case RunlengthEncodedCompression:
  2165. X        {
  2166. X          /*
  2167. X            Allocate image buffers and read image from disk.
  2168. X          */
  2169. X          packet_size=4;
  2170. X          if (image->packets == 0)
  2171. X            {
  2172. X              /*
  2173. X                Number of packets is unspecified.
  2174. X              */
  2175. X              pixels=(unsigned char *)
  2176. X                malloc((unsigned int) (image->columns*image->rows*packet_size));
  2177. X              image->pixels=(RunlengthPacket *)
  2178. X                malloc(image->columns*image->rows*sizeof(RunlengthPacket));
  2179. X              if ((pixels == (unsigned char *) NULL) ||
  2180. X                  (image->pixels == (RunlengthPacket *) NULL))
  2181. X                {
  2182. X                  Warning("unable to read image","memory allocation failed");
  2183. X                  DestroyImage(image);
  2184. X                  return((Image *) NULL);
  2185. X                }
  2186. X              count=0;
  2187. X              image->packets=0;
  2188. X              p=pixels;
  2189. X              do
  2190. X              {
  2191. X                (void) ReadData((char *) p,(int) packet_size,1,image->file);
  2192. X                image->packets++;
  2193. X                p+=(packet_size-1);
  2194. X                count+=(*p+1);
  2195. X                p++;
  2196. X              }
  2197. X              while (count < (image->columns*image->rows));
  2198. X              p=pixels;
  2199. X            }
  2200. X          else
  2201. X            {
  2202. X              pixels=(unsigned char *)
  2203. X                malloc((unsigned int) image->packets*packet_size);
  2204. X              image->pixels=(RunlengthPacket *)
  2205. X                malloc(image->packets*sizeof(RunlengthPacket));
  2206. X              if ((pixels == (unsigned char *) NULL) ||
  2207. X                  (image->pixels == (RunlengthPacket *) NULL))
  2208. X                {
  2209. X                  Warning("unable to read image","memory allocation failed");
  2210. X                  DestroyImage(image);
  2211. X                  return((Image *) NULL);
  2212. X                }
  2213. X              (void) ReadData((char *) pixels,(int) packet_size,
  2214. X                (int) image->packets,image->file);
  2215. X            }
  2216. X          count=0;
  2217. X          p=pixels;
  2218. X          q=image->pixels;
  2219. X          for (i=0; i < image->packets; i++)
  2220. X          {
  2221. X            q->red=(*p++);
  2222. X            q->green=(*p++);
  2223. X            q->blue=(*p++);
  2224. X            q->index=0;
  2225. X            q->length=(*p++);
  2226. X            count+=(q->length+1);
  2227. X            q++;
  2228. X          }
  2229. X          /*
  2230. X            Guarentee the correct number of runlength packets.
  2231. X          */
  2232. X          if (count > (image->columns*image->rows))
  2233. X            {
  2234. X              Warning("insufficient image data in file",image->filename);
  2235. X              DestroyImage(image);
  2236. X              return((Image *) NULL);
  2237. X            }
  2238. X          else
  2239. X            if (count < (image->columns*image->rows))
  2240. X              {
  2241. X                Warning("too much image data in file",image->filename);
  2242. X                DestroyImage(image);
  2243. X                return((Image *) NULL);
  2244. X              }
  2245. X          break;
  2246. X        }
  2247. X      }
  2248. X      break;
  2249. X    }
  2250. X    case PseudoClass:
  2251. X    {
  2252. X      register unsigned short
  2253. X        index;
  2254. X
  2255. X      if (image->colors == 0)
  2256. X        {
  2257. X          /*
  2258. X            Create grayscale map.
  2259. X          */
  2260. X          image->colors=256;
  2261. X          image->colormap=(ColorPacket *)
  2262. X            malloc(image->colors*sizeof(ColorPacket));
  2263. X          if (image->colormap == (ColorPacket *) NULL)
  2264. X            {
  2265. X              Warning("unable to read image","memory allocation failed");
  2266. X              DestroyImage(image);
  2267. X              return((Image *) NULL);
  2268. X            }
  2269. X          for (i=0; i < image->colors; i++)
  2270. X          {
  2271. X            image->colormap[i].red=(unsigned char) i;
  2272. X            image->colormap[i].green=(unsigned char) i;
  2273. X            image->colormap[i].blue=(unsigned char) i;
  2274. X          }
  2275. X        }
  2276. X      else
  2277. X        {
  2278. X          unsigned char
  2279. X            *colormap;
  2280. X
  2281. X          /*
  2282. X            Read colormap from disk.
  2283. X          */
  2284. X          packet_size=3;
  2285. X          colormap=(unsigned char *)
  2286. X            malloc((unsigned int) image->colors*packet_size);
  2287. X          image->colormap=(ColorPacket *)
  2288. X            malloc(image->colors*sizeof(ColorPacket));
  2289. X          if ((colormap == (unsigned char *) NULL) ||
  2290. X              (image->colormap == (ColorPacket *) NULL))
  2291. X            {
  2292. X              Warning("unable to read image","memory allocation failed");
  2293. X              DestroyImage(image);
  2294. X              return((Image *) NULL);
  2295. X            }
  2296. X          (void) ReadData((char *) colormap,(int) packet_size,
  2297. X            (int) image->colors,image->file);
  2298. X          p=colormap;
  2299. X          for (i=0; i < image->colors; i++)
  2300. X          {
  2301. X            image->colormap[i].red=(*p++);
  2302. X            image->colormap[i].green=(*p++);
  2303. X            image->colormap[i].blue=(*p++);
  2304. X          }
  2305. X          (void) free((char *) colormap);
  2306. X        }
  2307. X      /*
  2308. X        Transfer pixels to PseudoClass image pixel buffer.
  2309. X      */
  2310. X      switch (image->compression)
  2311. X      {
  2312. X        case NoCompression:
  2313. X        {
  2314. X          /*
  2315. X            Allocate image buffers and read image from disk.
  2316. X          */
  2317. X          image->packets=image->columns*image->rows;
  2318. X          packet_size=1;
  2319. X          if (image->colors > 256)
  2320. X            packet_size++;
  2321. X          pixels=(unsigned char *)
  2322. X            malloc((unsigned int) image->packets*packet_size);
  2323. X          image->pixels=(RunlengthPacket *)
  2324. X            malloc(image->packets*sizeof(RunlengthPacket));
  2325. X          if ((pixels == (unsigned char *) NULL) ||
  2326. X              (image->pixels == (RunlengthPacket *) NULL))
  2327. X            {
  2328. X              Warning("unable to read image","memory allocation failed");
  2329. X              DestroyImage(image);
  2330. X              return((Image *) NULL);
  2331. X            }
  2332. X          status=ReadData((char *) pixels,(int) packet_size,
  2333. X            (int) (image->columns*image->rows),image->file);
  2334. X          if (status == False)
  2335. X            {
  2336. X              Warning("insufficient image data in file",image->filename);
  2337. X              DestroyImage(image);
  2338. X              return((Image *) NULL);
  2339. X            }
  2340. X          /*
  2341. X            Convert to runlength-encoded PseudoClass packets.
  2342. X          */
  2343. X          image->packets=image->columns*image->rows;
  2344. X          p=pixels;
  2345. X          q=image->pixels;
  2346. X          if (image->colors <= 256)
  2347. X            for (i=0; i < image->packets; i++)
  2348. X            {
  2349. X              index=(*p++);
  2350. X              q->red=image->colormap[index].red;
  2351. X              q->green=image->colormap[index].green;
  2352. X              q->blue=image->colormap[index].blue;
  2353. X              q->index=index;
  2354. X              q->length=0;
  2355. X              q++;
  2356. X            }
  2357. X          else
  2358. X            for (i=0; i < image->packets; i++)
  2359. X            {
  2360. X              index=(*p++) << 8;
  2361. X              index|=(*p++);
  2362. X              q->red=image->colormap[index].red;
  2363. X              q->green=image->colormap[index].green;
  2364. X              q->blue=image->colormap[index].blue;
  2365. X              q->index=index;
  2366. X              q->length=0;
  2367. X              q++;
  2368. X            }
  2369. X          break;
  2370. X        }
  2371. X        case QEncodedCompression:
  2372. X        {
  2373. X          extern unsigned int
  2374. X            QDecodeImage();
  2375. X
  2376. X          unsigned char
  2377. X            *compressed_pixels;
  2378. X
  2379. X          /*
  2380. X            Allocate image buffers and read image from disk.
  2381. X          */
  2382. X          packet_size=1;
  2383. X          if (image->packets == 0)
  2384. X            image->packets=(image->columns*image->rows)*
  2385. X              (image->colors > 256 ? 2 : 1);
  2386. X          pixels=(unsigned char *)
  2387. X            malloc((unsigned int) image->packets*packet_size);
  2388. X          image->pixels=(RunlengthPacket *)
  2389. X            malloc(image->columns*image->rows*sizeof(RunlengthPacket));
  2390. X          if ((pixels == (unsigned char *) NULL) ||
  2391. X              (image->pixels == (RunlengthPacket *) NULL))
  2392. X            {
  2393. X              Warning("unable to allocate memory",(char *) NULL);
  2394. X              DestroyImage(image);
  2395. X              return((Image *) NULL);
  2396. X            }
  2397. X          status=ReadData((char *) pixels,(int) packet_size,
  2398. X            (int) image->packets,image->file);
  2399. X          /*
  2400. X            Uncompress image.
  2401. X          */
  2402. X          image->packets=image->columns*image->rows;
  2403. X          packet_size=1;
  2404. X          if (image->colors > 256)
  2405. X            packet_size++;
  2406. X          compressed_pixels=pixels;
  2407. X          pixels=(unsigned char *)
  2408. X            malloc((unsigned int) image->packets*packet_size);
  2409. X          if (pixels == (unsigned char *) NULL)
  2410. X            {
  2411. X              Warning("unable to read image","memory allocation failed");
  2412. X              DestroyImage(image);
  2413. X              return((Image *) NULL);
  2414. X            }
  2415. X          packets=QDecodeImage(compressed_pixels,pixels,image->columns*
  2416. X            (int) packet_size,image->rows);
  2417. X          if (packets != (image->packets*packet_size))
  2418. X            {
  2419. X              Warning("insufficient image data in file",image->filename);
  2420. X              DestroyImage(image);
  2421. X              return((Image *) NULL);
  2422. X            }
  2423. X          (void) free((char *) compressed_pixels);
  2424. X          /*
  2425. X            Convert to runlength-encoded PseudoClass packets.
  2426. X          */
  2427. X          p=pixels;
  2428. X          image->packets=0;
  2429. X          q=image->pixels;
  2430. X          q->length=MaxRunlength;
  2431. X          if (image->colors <= 256)
  2432. X            for (i=0; i < (image->columns*image->rows); i++)
  2433. X            {
  2434. X              index=(*p++);
  2435. X              red=image->colormap[index].red;
  2436. X              green=image->colormap[index].green;
  2437. X              blue=image->colormap[index].blue;
  2438. X              if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
  2439. X                  (q->length < MaxRunlength))
  2440. X                q->length++;
  2441. X              else
  2442. X                {
  2443. X                  if (image->packets > 0)
  2444. X                    q++;
  2445. X                  image->packets++;
  2446. X                  q->red=red;
  2447. X                  q->green=green;
  2448. X                  q->blue=blue;
  2449. X                  q->index=index;
  2450. X                  q->length=0;
  2451. X                }
  2452. X            }
  2453. X          else
  2454. X            for (i=0; i < (image->columns*image->rows); i++)
  2455. X            {
  2456. X              index=(*p++) << 8;
  2457. X              index|=(*p++);
  2458. X              red=image->colormap[index].red;
  2459. X              green=image->colormap[index].green;
  2460. X              blue=image->colormap[index].blue;
  2461. X              if ((red == q->red) && (green == q->green) && (blue == q->blue) &&
  2462. X                  (q->length < MaxRunlength))
  2463. X                q->length++;
  2464. X              else
  2465. X                {
  2466. X                  if (image->packets > 0)
  2467. X                    q++;
  2468. X                  image->packets++;
  2469. X                  q->red=red;
  2470. X                  q->green=green;
  2471. X                  q->blue=blue;
  2472. X                  q->index=index;
  2473. X                  q->length=0;
  2474. X                }
  2475. X            }
  2476. X          image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,
  2477. X            image->packets*sizeof(RunlengthPacket));
  2478. X          break;
  2479. X        }
  2480. X        case RunlengthEncodedCompression:
  2481. X        {
  2482. X          packet_size=2;
  2483. X          if (image->colors > 256)
  2484. X            packet_size++;
  2485. X          if (image->packets == 0)
  2486. X            {
  2487. X              /*
  2488. X                Number of packets is unspecified.
  2489. X              */
  2490. X              pixels=(unsigned char *)
  2491. X                malloc((unsigned int) (image->columns*image->rows*packet_size));
  2492. X              image->pixels=(RunlengthPacket *)
  2493. X                malloc((unsigned int) packets*sizeof(RunlengthPacket));
  2494. X              if ((pixels == (unsigned char *) NULL) ||
  2495. X                  (image->pixels == (RunlengthPacket *) NULL))
  2496. X                {
  2497. X                  Warning("unable to read image","memory allocation failed");
  2498. X                  DestroyImage(image);
  2499. X                  return((Image *) NULL);
  2500. X                }
  2501. X              count=0;
  2502. X              image->packets=0;
  2503. X              p=pixels;
  2504. X              do
  2505. X              {
  2506. X                (void) ReadData((char *) p,(int) packet_size,1,image->file);
  2507. X                image->packets++;
  2508. X                p+=(packet_size-1);
  2509. X                count+=(*p+1);
  2510. X                p++;
  2511. X              }
  2512. X              while (count < (image->columns*image->rows));
  2513. X            }
  2514. X          else
  2515. X            {
  2516. X              pixels=(unsigned char *)
  2517. X                malloc((unsigned int) image->packets*packet_size);
  2518. X              image->pixels=(RunlengthPacket *)
  2519. X                malloc(image->packets*sizeof(RunlengthPacket));
  2520. X              if ((pixels == (unsigned char *) NULL) ||
  2521. X                  (image->pixels == (RunlengthPacket *) NULL))
  2522. X                {
  2523. X                  Warning("unable to read image","memory allocation failed");
  2524. X                  DestroyImage(image);
  2525. X                  return((Image *) NULL);
  2526. X                }
  2527. X              (void) ReadData((char *) pixels,(int) packet_size,
  2528. X                (int) image->packets,image->file);
  2529. X            }
  2530. X          count=0;
  2531. X          p=pixels;
  2532. X          q=image->pixels;
  2533. X          if (image->colors <= 256)
  2534. X            for (i=0; i < image->packets; i++)
  2535. X            {
  2536. X              index=(*p++);
  2537. X              q->red=image->colormap[index].red;
  2538. X              q->green=image->colormap[index].green;
  2539. X              q->blue=image->colormap[index].blue;
  2540. X              q->index=index;
  2541. X              q->length=(*p++);
  2542. X              count+=(q->length+1);
  2543. X              q++;
  2544. X            }
  2545. X          else
  2546. X            for (i=0; i < image->packets; i++)
  2547. X            {
  2548. X              index=(*p++) << 8;
  2549. X              index|=(*p++);
  2550. X              q->red=image->colormap[index].red;
  2551. X              q->green=image->colormap[index].green;
  2552. X              q->blue=image->colormap[index].blue;
  2553. X              q->index=index;
  2554. X              q->length=(*p++);
  2555. SHAR_EOF
  2556. true || echo 'restore of ImageMagick/image.c failed'
  2557. fi
  2558. echo 'End of ImageMagick part 4'
  2559. echo 'File ImageMagick/image.c is continued in part 5'
  2560. echo 5 > _shar_seq_.tmp
  2561. exit 0
  2562. --
  2563. Dan Heller
  2564. O'Reilly && Associates       Z-Code Software    Comp-sources-x:
  2565. Senior Writer                President          comp-sources-x@uunet.uu.net
  2566. argv@ora.com                 argv@zipcode.com
  2567.