home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume20 / imagemgc / part28 < prev    next >
Encoding:
Text File  |  1993-07-13  |  50.6 KB  |  1,912 lines

  1. Newsgroups: comp.sources.x
  2. From: cristy@eplrx7.es.duPont.com (Cristy)
  3. Subject: v20i084:  imagemagic - X11 image processing and display, Part28/38
  4. Message-ID: <1993Jul14.232053.22711@sparky.sterling.com>
  5. X-Md4-Signature: 746ea467a6e42a8730ec2c56b1a693aa
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Wed, 14 Jul 1993 23:20:53 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: cristy@eplrx7.es.duPont.com (Cristy)
  12. Posting-number: Volume 20, Issue 84
  13. Archive-name: imagemagic/part28
  14. Environment: X11
  15. Supersedes: imagemagic: Volume 13, Issue 17-37
  16.  
  17. #!/bin/sh
  18. # this is magick.28 (part 28 of ImageMagick)
  19. # do not concatenate these parts, unpack them in order with /bin/sh
  20. # file ImageMagick/image.c continued
  21. #
  22. if test ! -r _shar_seq_.tmp; then
  23.     echo 'Please unpack part 1 first!'
  24.     exit 1
  25. fi
  26. (read Scheck
  27.  if test "$Scheck" != 28; then
  28.     echo Please unpack part "$Scheck" next!
  29.     exit 1
  30.  else
  31.     exit 0
  32.  fi
  33. ) < _shar_seq_.tmp || exit 1
  34. if test ! -f _shar_wnt_.tmp; then
  35.     echo 'x - still skipping ImageMagick/image.c'
  36. else
  37. echo 'x - continuing file ImageMagick/image.c'
  38. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/image.c' &&
  39. X  {
  40. X    *q=(*s);
  41. X    q->length=0;
  42. X    q++;
  43. X    s++;
  44. X  }
  45. X  (void) free((char *) scanline);
  46. X  return(enhanced_image);
  47. }
  48. X
  49. /*
  50. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  51. %                                                                             %
  52. %                                                                             %
  53. %                                                                             %
  54. %   F r a m e I m a g e                                                       %
  55. %                                                                             %
  56. %                                                                             %
  57. %                                                                             %
  58. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  59. %
  60. %  Function FrameImage takes an image and puts a frame around it of a
  61. %  particular color.  It allocates the memory necessary for the new Image
  62. %  structure and returns a pointer to the new image.  Set the border and
  63. %  highlight to the same color to get a solid frame.
  64. %
  65. %  The format of the FrameImage routine is:
  66. %
  67. %      framed_image=FrameImage(image,frame_info,border_width,border_color,
  68. %        highlight_color)
  69. %
  70. %  A description of each parameter follows:
  71. %
  72. %    o framed_image: Function FrameImage returns a pointer to the framed
  73. %      image.  A null image is returned if there is a a memory shortage.
  74. %
  75. %    o image: The address of a structure of type Image.
  76. %
  77. %    o frame_info: Specifies a pointer to a XRectangle which defines the
  78. %      framed region.
  79. %
  80. %    o border_width: An unsigned integer that is the width of the border of
  81. %      the frame.
  82. %
  83. %    o border_color: A pointer to a ColorPacket which contains the red,
  84. %      green, and blue components of the border color.
  85. %
  86. %    o highlight_color: A pointer to a ColorPacket which contains the red,
  87. %      green, and blue components of the highlight color.
  88. %
  89. %
  90. */
  91. Image *FrameImage(image,frame_info,border_width,border_color,highlight_color)
  92. Image
  93. X  *image;
  94. X
  95. RectangleInfo
  96. X  *frame_info;
  97. X
  98. unsigned int
  99. X  border_width;
  100. X
  101. ColorPacket
  102. X  *border_color,
  103. X  *highlight_color;
  104. {
  105. X  Image
  106. X    *framed_image;
  107. X
  108. X  int
  109. X    height,
  110. X    width;
  111. X
  112. X  register int
  113. X    x,
  114. X    y;
  115. X
  116. X  register RunlengthPacket
  117. X    *p,
  118. X    *q;
  119. X
  120. X  RunlengthPacket
  121. X    black,
  122. X    border,
  123. X    highlight,
  124. X    lowlight;
  125. X
  126. X  /*
  127. X    Check frame geometry.
  128. X  */
  129. X  width=(int) frame_info->width-frame_info->x-4*border_width;
  130. X  height=(int) frame_info->height-frame_info->y-4*border_width;
  131. X  if ((width < image->columns) || (height < image->rows))
  132. X    {
  133. X      Warning("unable to frame image","frame is less than image size");
  134. X      return((Image *) NULL);
  135. X    }
  136. X  /*
  137. X    Initialize framed image attributes.
  138. X  */
  139. X  framed_image=CopyImage(image,frame_info->width,frame_info->height,False);
  140. X  if (framed_image == (Image *) NULL)
  141. X    {
  142. X      Warning("unable to border image","memory allocation failed");
  143. X      return((Image *) NULL);
  144. X    }
  145. X  image->class=DirectClass;
  146. X  /*
  147. X    Initialize frame colors.
  148. X  */
  149. X  black.red=0;
  150. X  black.green=0;
  151. X  black.blue=0;
  152. X  black.index=0;
  153. X  black.length=0;
  154. X  border.red=border_color->red;
  155. X  border.green=border_color->green;
  156. X  border.blue=border_color->blue;
  157. X  border.index=0;
  158. X  border.length=0;
  159. X  lowlight.red=highlight_color->red ^ 0x45;
  160. X  lowlight.green=highlight_color->green ^ 0x45;
  161. X  lowlight.blue=highlight_color->blue ^ 0x45;
  162. X  lowlight.index=0;
  163. X  lowlight.length=0;
  164. X  highlight.red=highlight_color->red;
  165. X  highlight.green=highlight_color->green;
  166. X  highlight.blue=highlight_color->blue;
  167. X  highlight.index=0;
  168. X  highlight.length=0;
  169. X  /*
  170. X    Copy image and put an ornamental border around it.
  171. X  */
  172. X  q=framed_image->pixels;
  173. X  for (x=0; x < framed_image->columns; x++)
  174. X    *q++=black;
  175. X  for (y=0; y < (border_width-1); y++)
  176. X  {
  177. X    *q++=black;
  178. X    for (x=0; x < (framed_image->columns-y-2); x++)
  179. X      *q++=highlight;
  180. X    for ( ; x < (framed_image->columns-2); x++)
  181. X      *q++=lowlight;
  182. X    *q++=black;
  183. X  }
  184. X  for (y=0; y < (frame_info->y-2*border_width); y++)
  185. X  {
  186. X    *q++=black;
  187. X    for (x=0; x < (border_width-1); x++)
  188. X      *q++=highlight;
  189. X    for (x=0; x < (framed_image->columns-2*border_width); x++)
  190. X      *q++=border;
  191. X    for (x=0; x < (border_width-1); x++)
  192. X      *q++=lowlight;
  193. X    *q++=black;
  194. X  }
  195. X  for (y=0; y < (border_width-1); y++)
  196. X  {
  197. X    *q++=black;
  198. X    for (x=0; x < (border_width-1); x++)
  199. X      *q++=highlight;
  200. X    for (x=0; x < (frame_info->x-2*border_width); x++)
  201. X      *q++=border;
  202. X    for (x=0; x < (image->columns+2*border_width-y); x++)
  203. X      *q++=lowlight;
  204. X    for ( ; x < (image->columns+2*border_width); x++)
  205. X      *q++=highlight;
  206. X    width=frame_info->width-frame_info->x-image->columns-2*border_width;
  207. X    for (x=0; x < width; x++)
  208. X      *q++=border;
  209. X    for (x=0; x < (border_width-1); x++)
  210. X      *q++=lowlight;
  211. X    *q++=black;
  212. X  }
  213. X  *q++=black;
  214. X  for (x=0; x < (border_width-1); x++)
  215. X    *q++=highlight;
  216. X  for (x=0; x < (frame_info->x-2*border_width); x++)
  217. X    *q++=border;
  218. X  for (x=0; x < (border_width-1); x++)
  219. X    *q++=lowlight;
  220. X  for (x=0; x < (image->columns+2); x++)
  221. X    *q++=black;
  222. X  for (x=0; x < (border_width-1); x++)
  223. X    *q++=highlight;
  224. X  width=frame_info->width-frame_info->x-image->columns-2*border_width;
  225. X  for (x=0; x < width; x++)
  226. X    *q++=border;
  227. X  for (x=0; x < (border_width-1); x++)
  228. X    *q++=lowlight;
  229. X  *q++=black;
  230. X  p=image->pixels;
  231. X  image->runlength=p->length+1;
  232. X  for (y=0; y < image->rows; y++)
  233. X  {
  234. X    /*
  235. X      Initialize scanline with border color.
  236. X    */
  237. X    *q++=black;
  238. X    for (x=0; x < (border_width-1); x++)
  239. X      *q++=highlight;
  240. X    for (x=0; x < (frame_info->x-2*border_width); x++)
  241. X      *q++=border;
  242. X    for (x=0; x < (border_width-1); x++)
  243. X      *q++=lowlight;
  244. X    *q++=black;
  245. X    /*
  246. X      Transfer scanline.
  247. X    */
  248. X    for (x=0; x < image->columns; x++)
  249. X    {
  250. X      if (image->runlength != 0)
  251. X        image->runlength--;
  252. X      else
  253. X        {
  254. X          p++;
  255. X          image->runlength=p->length;
  256. X        }
  257. X      *q=(*p);
  258. X      q->length=0;
  259. X      q++;
  260. X    }
  261. X    *q++=black;
  262. X    for (x=0; x < (border_width-1); x++)
  263. X      *q++=highlight;
  264. X    width=frame_info->width-frame_info->x-image->columns-2*border_width;
  265. X    for (x=0; x < width; x++)
  266. X      *q++=border;
  267. X    for (x=0; x < (border_width-1); x++)
  268. X      *q++=lowlight;
  269. X    *q++=black;
  270. X  }
  271. X  *q++=black;
  272. X  for (x=0; x < (border_width-1); x++)
  273. X    *q++=highlight;
  274. X  for (x=0; x < (frame_info->x-2*border_width); x++)
  275. X    *q++=border;
  276. X  for (x=0; x < (border_width-1); x++)
  277. X    *q++=lowlight;
  278. X  for (x=0; x < (image->columns+2); x++)
  279. X    *q++=black;
  280. X  for (x=0; x < (border_width-1); x++)
  281. X    *q++=highlight;
  282. X  width=frame_info->width-frame_info->x-image->columns-2*border_width;
  283. X  for (x=0; x < width; x++)
  284. X    *q++=border;
  285. X  for (x=0; x < (border_width-1); x++)
  286. X    *q++=lowlight;
  287. X  *q++=black;
  288. X  for (y=border_width-2; y >= 0; y--)
  289. X  {
  290. X    *q++=black;
  291. X    for (x=0; x < (border_width-1); x++)
  292. X      *q++=highlight;
  293. X    for (x=0; x < (frame_info->x-2*border_width); x++)
  294. X      *q++=border;
  295. X    for (x=0; x < y; x++)
  296. X      *q++=lowlight;
  297. X    for ( ; x < (image->columns+2*border_width); x++)
  298. X      *q++=highlight;
  299. X    width=frame_info->width-frame_info->x-image->columns-2*border_width;
  300. X    for (x=0; x < width; x++)
  301. X      *q++=border;
  302. X    for (x=0; x < (border_width-1); x++)
  303. X      *q++=lowlight;
  304. X    *q++=black;
  305. X  }
  306. X  height=frame_info->height-frame_info->y-image->rows-2*border_width;
  307. X  for (y=0; y < height; y++)
  308. X  {
  309. X    *q++=black;
  310. X    for (x=0; x < (border_width-1); x++)
  311. X      *q++=highlight;
  312. X    for (x=0; x < (framed_image->columns-2*border_width); x++)
  313. X      *q++=border;
  314. X    for (x=0; x < (border_width-1); x++)
  315. X      *q++=lowlight;
  316. X    *q++=black;
  317. X  }
  318. X  for (y=border_width-2; y >= 0; y--)
  319. X  {
  320. X    *q++=black;
  321. X    for (x=0; x < y; x++)
  322. X      *q++=highlight;
  323. X    for ( ; x < (framed_image->columns-2); x++)
  324. X      *q++=lowlight;
  325. X    *q++=black;
  326. X  }
  327. X  for (x=0; x < framed_image->columns; x++)
  328. X    *q++=black;
  329. X  return(framed_image);
  330. }
  331. X
  332. /*
  333. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  334. %                                                                             %
  335. %                                                                             %
  336. %     G a m m a I m a g e                                                     %
  337. %                                                                             %
  338. %                                                                             %
  339. %                                                                             %
  340. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  341. %
  342. %  Procedure GammaImage converts the reference image to gamma corrected colors.
  343. %
  344. %  The format of the GammaImage routine is:
  345. %
  346. %      GammaImage(image,gamma)
  347. %
  348. %  A description of each parameter follows:
  349. %
  350. %    o image: The address of a structure of type Image;  returned from
  351. %      ReadImage.
  352. %
  353. %    o gamma: A double precision value indicating the level of gamma
  354. %      correction.
  355. %
  356. %
  357. */
  358. void GammaImage(image,gamma)
  359. Image
  360. X  *image;
  361. X
  362. double
  363. X  gamma;
  364. {
  365. X  register int
  366. X    i;
  367. X
  368. X  register RunlengthPacket
  369. X    *p;
  370. X
  371. X  unsigned char
  372. X    gamma_map[MaxRGB+1];
  373. X
  374. X  /*
  375. X    Initialize gamma table.
  376. X  */
  377. X  for (i=0; i <= MaxRGB; i++)
  378. X    gamma_map[i]=(unsigned char)
  379. X      ((pow((double) i/MaxRGB,1.0/gamma)*MaxRGB)+0.5);
  380. X  switch (image->class)
  381. X  {
  382. X    case DirectClass:
  383. X    {
  384. X      /*
  385. X        Gamma-correct DirectClass image.
  386. X      */
  387. X      p=image->pixels;
  388. X      for (i=0; i < image->packets; i++)
  389. X      {
  390. X        p->red=gamma_map[p->red];
  391. X        p->green=gamma_map[p->green];
  392. X        p->blue=gamma_map[p->blue];
  393. X        p++;
  394. X      }
  395. X      break;
  396. X    }
  397. X    case PseudoClass:
  398. X    {
  399. X      /*
  400. X        Gamma-correct PseudoClass image.
  401. X      */
  402. X      for (i=0; i < image->colors; i++)
  403. X      {
  404. X        image->colormap[i].red=gamma_map[image->colormap[i].red];
  405. X        image->colormap[i].green=gamma_map[image->colormap[i].green];
  406. X        image->colormap[i].blue=gamma_map[image->colormap[i].blue];
  407. X      }
  408. X      SyncImage(image);
  409. X      break;
  410. X    }
  411. X  }
  412. }
  413. X
  414. /*
  415. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  416. %                                                                             %
  417. %                                                                             %
  418. %                                                                             %
  419. %   G e t A l i e n I n f o                                                   %
  420. %                                                                             %
  421. %                                                                             %
  422. %                                                                             %
  423. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  424. %
  425. %  Function GetImageInfo initializes the ImageInfo structure.
  426. %
  427. %  The format of the GetImageInfo routine is:
  428. %
  429. %      GetImageInfo(image_info)
  430. %
  431. %  A description of each parameter follows:
  432. %
  433. %    o image_info: Specifies a pointer to a ImageInfo structure.
  434. %
  435. %
  436. */
  437. void GetImageInfo(image_info)
  438. ImageInfo
  439. X  *image_info;
  440. {
  441. X  image_info->server_name=(char *) NULL;
  442. X  image_info->font=(char *) NULL;
  443. X  image_info->geometry=(char *) NULL;
  444. X  image_info->density=(char *) NULL;
  445. X  image_info->page=(char *) NULL;
  446. X  image_info->border_color=(char *) NULL;
  447. X  image_info->interlace=NoneInterlace;
  448. X  image_info->monochrome=False;
  449. X  image_info->quality=75;
  450. X  image_info->verbose=False;
  451. X  image_info->undercolor=(char *) NULL;
  452. }
  453. X
  454. /*
  455. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  456. %                                                                             %
  457. %                                                                             %
  458. %     I n v e r s e I m a g e                                                 %
  459. %                                                                             %
  460. %                                                                             %
  461. %                                                                             %
  462. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  463. %
  464. %  Procedure InverseImage inverses the colors in the reference image.
  465. %
  466. %  The format of the InverseImage routine is:
  467. %
  468. %      InverseImage(image)
  469. %
  470. %  A description of each parameter follows:
  471. %
  472. %    o image: The address of a structure of type Image;  returned from
  473. %      ReadImage.
  474. %
  475. %
  476. */
  477. void InverseImage(image)
  478. Image
  479. X  *image;
  480. {
  481. X  register int
  482. X    i;
  483. X
  484. X  register RunlengthPacket
  485. X    *p;
  486. X
  487. X  switch (image->class)
  488. X  {
  489. X    case DirectClass:
  490. X    {
  491. X      /*
  492. X        Inverse DirectClass packets.
  493. X      */
  494. X      p=image->pixels;
  495. X      for (i=0; i < image->packets; i++)
  496. X      {
  497. X        p->red=(~p->red);
  498. X        p->green=(~p->green);
  499. X        p->blue=(~p->blue);
  500. X        p++;
  501. X      }
  502. X      break;
  503. X    }
  504. X    case PseudoClass:
  505. X    {
  506. X      /*
  507. X        Inverse PseudoClass packets.
  508. X      */
  509. X      for (i=0; i < image->colors; i++)
  510. X      {
  511. X        image->colormap[i].red=(~image->colormap[i].red);
  512. X        image->colormap[i].green=(~image->colormap[i].green);
  513. X        image->colormap[i].blue=(~image->colormap[i].blue);
  514. X      }
  515. X      SyncImage(image);
  516. X      break;
  517. X    }
  518. X  }
  519. }
  520. X
  521. /*
  522. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  523. %                                                                             %
  524. %                                                                             %
  525. %     N o i s y I m a g e                                                     %
  526. %                                                                             %
  527. %                                                                             %
  528. %                                                                             %
  529. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  530. %
  531. %  Function NoisyImage creates a new image that is a copy of an existing
  532. %  one with the noise reduced with a noise peak elimination filter.  It
  533. %  allocates the memory necessary for the new Image structure and returns a
  534. %  pointer to the new image.
  535. %
  536. %  The principal function of noise peak elimination filter is to smooth the
  537. %  objects within an image without losing edge information and without
  538. %  creating undesired structures.  The central idea of the algorithm is to
  539. %  replace a pixel with its next neighbor in value within a 3 x 3 window,
  540. %  if this pixel has been found to be noise.  A pixel is defined as noise
  541. %  if and only if this pixel is a maximum or minimum within the 3 x 3
  542. %  window.
  543. %
  544. %  The format of the NoisyImage routine is:
  545. %
  546. %      noisy_image=NoisyImage(image)
  547. %
  548. %  A description of each parameter follows:
  549. %
  550. %    o noisy_image: Function NoisyImage returns a pointer to the image after
  551. %      the noise is reduced.  A null image is returned if there is a memory
  552. %      shortage.
  553. %
  554. %    o image: The address of a structure of type Image;  returned from
  555. %      ReadImage.
  556. %
  557. %
  558. */
  559. static int NoisyCompare(x,y)
  560. const void
  561. X  *x,
  562. X  *y;
  563. {
  564. X  ColorPacket
  565. X    *color_1,
  566. X    *color_2;
  567. X
  568. X  color_1=(ColorPacket *) x;
  569. X  color_2=(ColorPacket *) y;
  570. X  return((int) Intensity(*color_1)-(int) Intensity(*color_2));
  571. }
  572. X
  573. Image *NoisyImage(image)
  574. Image
  575. X  *image;
  576. {
  577. X  Image
  578. X    *noisy_image;
  579. X
  580. X  int
  581. X    i;
  582. X
  583. X  register RunlengthPacket
  584. X    *p,
  585. X    *q,
  586. X    *s,
  587. X    *s0,
  588. X    *s1,
  589. X    *s2;
  590. X
  591. X  register unsigned int
  592. X    x;
  593. X
  594. X  RunlengthPacket
  595. X    pixel,
  596. X    *scanline,
  597. X    window[9];
  598. X
  599. X  unsigned int
  600. X    y;
  601. X
  602. X  if ((image->columns < 3) || (image->rows < 3))
  603. X    {
  604. X      Warning("unable to reduce noise","the image size must exceed 2x2");
  605. X      return((Image *) NULL);
  606. X    }
  607. X  /*
  608. X    Initialize noisy image attributes.
  609. X  */
  610. X  noisy_image=CopyImage(image,image->columns,image->rows,False);
  611. X  if (noisy_image == (Image *) NULL)
  612. X    {
  613. X      Warning("unable to reduce noise","memory allocation failed");
  614. X      return((Image *) NULL);
  615. X    }
  616. X  /*
  617. X    Allocate scanline buffer for 3 rows of the image.
  618. X  */
  619. X  scanline=(RunlengthPacket *) malloc(3*image->columns*sizeof(RunlengthPacket));
  620. X  if (scanline == (RunlengthPacket *) NULL)
  621. X    {
  622. X      Warning("unable to reduce noise","memory allocation failed");
  623. X      DestroyImage(noisy_image);
  624. X      return((Image *) NULL);
  625. X    }
  626. X  /*
  627. X    Preload the first 2 rows of the image.
  628. X  */
  629. X  p=image->pixels;
  630. X  image->runlength=p->length+1;
  631. X  s=scanline;
  632. X  for (x=0; x < (2*image->columns); x++)
  633. X  {
  634. X    if (image->runlength != 0)
  635. X      image->runlength--;
  636. X    else
  637. X      {
  638. X        p++;
  639. X        image->runlength=p->length;
  640. X      }
  641. X    *s=(*p);
  642. X    s++;
  643. X  }
  644. X  /*
  645. X    Dump first scanline of image.
  646. X  */
  647. X  q=noisy_image->pixels;
  648. X  s=scanline;
  649. X  for (x=0; x < image->columns; x++)
  650. X  {
  651. X    *q=(*s);
  652. X    q->length=0;
  653. X    q++;
  654. X    s++;
  655. X  }
  656. X  /*
  657. X    Reduce noise in each row.
  658. X  */
  659. X  for (y=1; y < (image->rows-1); y++)
  660. X  {
  661. X    /*
  662. X      Initialize sliding window pointers.
  663. X    */
  664. X    s0=scanline+image->columns*((y-1) % 3);
  665. X    s1=scanline+image->columns*(y % 3);
  666. X    s2=scanline+image->columns*((y+1) % 3);
  667. X    /*
  668. X      Read another scan line.
  669. X    */
  670. X    s=s2;
  671. X    for (x=0; x < image->columns; x++)
  672. X    {
  673. X      if (image->runlength != 0)
  674. X        image->runlength--;
  675. X      else
  676. X        {
  677. X          p++;
  678. X          image->runlength=p->length;
  679. X        }
  680. X      *s=(*p);
  681. X      s++;
  682. X    }
  683. X    /*
  684. X      Transfer first pixel of the scanline.
  685. X    */
  686. X    s=s1;
  687. X    *q=(*s);
  688. X    q->length=0;
  689. X    q++;
  690. X    for (x=1; x < (image->columns-1); x++)
  691. X    {
  692. X      /*
  693. X        Sort window pixels by increasing intensity.
  694. X      */
  695. X      s=s0;
  696. X      window[0]=(*s++);
  697. X      window[1]=(*s++);
  698. X      window[2]=(*s++);
  699. X      s=s1;
  700. X      window[3]=(*s++);
  701. X      window[4]=(*s++);
  702. X      window[5]=(*s++);
  703. X      s=s2;
  704. X      window[6]=(*s++);
  705. X      window[7]=(*s++);
  706. X      window[8]=(*s++);
  707. X      pixel=window[4];
  708. X      (void) qsort((void *) window,9,sizeof(RunlengthPacket),NoisyCompare);
  709. X      if (Intensity(pixel) == Intensity(window[0]))
  710. X        {
  711. X          /*
  712. X            Pixel is minimum noise; replace with next neighbor in value.
  713. X          */
  714. X          for (i=1; i < 8; i++)
  715. X            if (Intensity(window[i]) != Intensity(window[0]))
  716. X              break;
  717. X          pixel=window[i];
  718. X        }
  719. X      else
  720. X        if (Intensity(pixel) == Intensity(window[8]))
  721. X          {
  722. X            /*
  723. X              Pixel is maximum noise; replace with next neighbor in value.
  724. X            */
  725. X            for (i=7; i > 0; i--)
  726. X              if (Intensity(window[i]) != Intensity(window[8]))
  727. X                break;
  728. X            pixel=window[i];
  729. X          }
  730. X      *q=pixel;
  731. X      q->length=0;
  732. X      q++;
  733. X      s0++;
  734. X      s1++;
  735. X      s2++;
  736. X    }
  737. X    /*
  738. X      Transfer last pixel of the scanline.
  739. X    */
  740. X    s=s1;
  741. X    *q=(*s);
  742. X    q->length=0;
  743. X    q++;
  744. X  }
  745. X  /*
  746. X    Dump last scanline of pixels.
  747. X  */
  748. X  s=scanline+image->columns*(y % 3);
  749. X  for (x=0; x < image->columns; x++)
  750. X  {
  751. X    *q=(*s);
  752. X    q->length=0;
  753. X    q++;
  754. X    s++;
  755. X  }
  756. X  (void) free((char *) scanline);
  757. X  return(noisy_image);
  758. }
  759. X
  760. /*
  761. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  762. %                                                                             %
  763. %                                                                             %
  764. %     N o r m a l i z e I m a g e                                             %
  765. %                                                                             %
  766. %                                                                             %
  767. %                                                                             %
  768. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  769. %
  770. %  Procedure NormalizeImage normalizes the pixel values to span the full
  771. %  range of color values.  This is a contrast enhancement technique.
  772. %
  773. %  The format of the NormalizeImage routine is:
  774. %
  775. %      NormalizeImage(image)
  776. %
  777. %  A description of each parameter follows:
  778. %
  779. %    o image: The address of a structure of type Image;  returned from
  780. %      ReadImage.
  781. %
  782. %
  783. */
  784. void NormalizeImage(image)
  785. Image
  786. X  *image;
  787. {
  788. X  int
  789. X    histogram[MaxRGB+1],
  790. X    threshold_intensity;
  791. X
  792. X  register int
  793. X    i,
  794. X    intensity;
  795. X
  796. X  register RunlengthPacket
  797. X    *p;
  798. X
  799. X  unsigned char
  800. X    gray_value,
  801. X    high,
  802. X    low,
  803. X    normalize_map[MaxRGB+1];
  804. X
  805. X  /*
  806. X    Form histogram.
  807. X  */
  808. X  for (i=0; i <= MaxRGB; i++)
  809. X    histogram[i]=0;
  810. X  p=image->pixels;
  811. X  for (i=0; i < image->packets; i++)
  812. X  {
  813. X    gray_value=Intensity(*p);
  814. X    histogram[gray_value]+=p->length+1;
  815. X    p++;
  816. X  }
  817. X  /*
  818. X    Find the histogram boundaries by locating the 1 percent levels.
  819. X  */
  820. X  threshold_intensity=(image->columns*image->rows)/100;
  821. X  intensity=0;
  822. X  for (low=0; low < MaxRGB; low++)
  823. X  {
  824. X    intensity+=histogram[low];
  825. X    if (intensity > threshold_intensity)
  826. X      break;
  827. X  }
  828. X  intensity=0;
  829. X  for (high=MaxRGB; high != 0; high--)
  830. X  {
  831. X    intensity+=histogram[high];
  832. X    if (intensity > threshold_intensity)
  833. X      break;
  834. X  }
  835. X  if (low == high)
  836. X    {
  837. X      /*
  838. X        Unreasonable contrast;  use zero threshold to determine boundaries.
  839. X      */
  840. X      threshold_intensity=0;
  841. X      intensity=0;
  842. X      for (low=0; low < MaxRGB; low++)
  843. X      {
  844. X        intensity+=histogram[low];
  845. X        if (intensity > threshold_intensity)
  846. X          break;
  847. X      }
  848. X      intensity=0;
  849. X      for (high=MaxRGB; high != 0; high--)
  850. X      {
  851. X        intensity+=histogram[high];
  852. X        if (intensity > threshold_intensity)
  853. X          break;
  854. X      }
  855. X      if (low == high)
  856. X        return;  /* zero span bound */
  857. X    }
  858. X  /*
  859. X    Stretch the histogram to create the normalized image mapping.
  860. X  */
  861. X  for (i=0; i <= MaxRGB; i++)
  862. X    if (i < (int) low)
  863. X      normalize_map[i]=0;
  864. X    else
  865. X      if (i > (int) high)
  866. X        normalize_map[i]=MaxRGB-1;
  867. X      else
  868. X        normalize_map[i]=(MaxRGB-1)*(i-(int) low)/(int) (high-low);
  869. X  /*
  870. X    Normalize the image.
  871. X  */
  872. X  switch (image->class)
  873. X  {
  874. X    case DirectClass:
  875. X    {
  876. X      /*
  877. X        Normalize DirectClass image.
  878. X      */
  879. X      p=image->pixels;
  880. X      for (i=0; i < image->packets; i++)
  881. X      {
  882. X        p->red=normalize_map[p->red];
  883. X        p->green=normalize_map[p->green];
  884. X        p->blue=normalize_map[p->blue];
  885. X        p++;
  886. X      }
  887. X      break;
  888. X    }
  889. X    case PseudoClass:
  890. X    {
  891. X      /*
  892. X        Normalize PseudoClass image.
  893. X      */
  894. X      for (i=0; i < image->colors; i++)
  895. X      {
  896. X        image->colormap[i].red=normalize_map[image->colormap[i].red];
  897. X        image->colormap[i].green=normalize_map[image->colormap[i].green];
  898. X        image->colormap[i].blue=normalize_map[image->colormap[i].blue];
  899. X      }
  900. X      SyncImage(image);
  901. X      break;
  902. X    }
  903. X  }
  904. }
  905. X
  906. /*
  907. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  908. %                                                                             %
  909. %                                                                             %
  910. %                                                                             %
  911. %   O p e n I m a g e                                                         %
  912. %                                                                             %
  913. %                                                                             %
  914. %                                                                             %
  915. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  916. %
  917. %  Function OpenImage open a file associated with the image.
  918. %
  919. %  The format of the OpenImage routine is:
  920. %
  921. %      OpenImage(image,type)
  922. %
  923. %  A description of each parameter follows:
  924. %
  925. %    o image: The address of a structure of type Image.
  926. %
  927. %    o type: 'r' for reading; 'w' for writing.
  928. %
  929. */
  930. void OpenImage(image,type)
  931. Image
  932. X  *image;
  933. X
  934. char
  935. X  *type;
  936. {
  937. X  /*
  938. X    Open image file.
  939. X  */
  940. X  if (*image->filename == '-')
  941. X    image->file=(*type == 'r') ? stdin : stdout;
  942. X  else
  943. X    if (((int) strlen(image->filename) < 3) ||
  944. X        ((strcmp(image->filename+strlen(image->filename)-2,".gz") != 0) &&
  945. X         (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0)))
  946. X      image->file=fopen(image->filename,type);
  947. X    else
  948. X      {
  949. X        char
  950. X          command[2048];
  951. X
  952. X        /*
  953. X          Image file is compressed-- uncompress it.
  954. X        */
  955. X        if (strcmp(image->filename+strlen(image->filename)-2,".Z") == 0)
  956. X          {
  957. X            if (*type == 'r')
  958. X              (void) sprintf(command,"uncompress -c %s",image->filename);
  959. X            else
  960. X              (void) sprintf(command,"compress -c > %s",image->filename);
  961. X          }
  962. X        else
  963. X          if (*type == 'r')
  964. X            (void) sprintf(command,"gunzip -c %s",image->filename);
  965. X          else
  966. X            (void) sprintf(command,"gzip -c > %s",image->filename);
  967. X        image->file=(FILE *) popen(command,type);
  968. X      }
  969. X  image->status=False;
  970. }
  971. X
  972. /*
  973. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  974. %                                                                             %
  975. %                                                                             %
  976. %                                                                             %
  977. %   R e d u c e I m a g e                                                     %
  978. %                                                                             %
  979. %                                                                             %
  980. %                                                                             %
  981. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  982. %
  983. %  Function ReduceImage creates a new image that is a integral size less than
  984. %  an existing one.  It allocates the memory necessary for the new Image
  985. %  structure and returns a pointer to the new image.
  986. %
  987. %  ReduceImage scans the reference image to create a reduced image by computing
  988. %  the weighted average of a 4x4 cell centered at each reference pixel.  The
  989. %  target pixel requires two columns and two rows of the reference pixels.
  990. %  Therefore the reduced image columns and rows become:
  991. %
  992. %    number_columns/2
  993. %    number_rows/2
  994. %
  995. %  Weights assume that the importance of neighboring pixels is inversely
  996. %  proportional to the square of their distance from the target pixel.
  997. %
  998. %  The scan only processes pixels that have a full set of neighbors.  Pixels
  999. %  in the top, bottom, left, and right pairs of rows and columns are omitted
  1000. %  from the scan.
  1001. %
  1002. %  The format of the ReduceImage routine is:
  1003. %
  1004. %      reduced_image=ReduceImage(image)
  1005. %
  1006. %  A description of each parameter follows:
  1007. %
  1008. %    o reduced_image: Function ReduceImage returns a pointer to the image
  1009. %      after reducing.  A null image is returned if there is a a memory
  1010. %      shortage or if the image size is less than IconSize*2.
  1011. %
  1012. %    o image: The address of a structure of type Image.
  1013. %
  1014. %
  1015. */
  1016. static Image *ReduceImage(image)
  1017. Image
  1018. X  *image;
  1019. {
  1020. #define Rsum(weight) \
  1021. X  total_red+=weight*(s->red); \
  1022. X  total_green+=weight*(s->green); \
  1023. X  total_blue+=weight*(s->blue); \
  1024. X  total_alpha+=weight*(s->index); \
  1025. X  s++;
  1026. X
  1027. X  Image
  1028. X    *reduced_image;
  1029. X
  1030. X  register RunlengthPacket
  1031. X    *p,
  1032. X    *q,
  1033. X    *s,
  1034. X    *s0,
  1035. X    *s1,
  1036. X    *s2,
  1037. X    *s3;
  1038. X
  1039. X  register unsigned int
  1040. X    x;
  1041. X
  1042. X  RunlengthPacket
  1043. X    *scanline;
  1044. X
  1045. X  unsigned int
  1046. X    y;
  1047. X
  1048. X  unsigned long
  1049. X    total_alpha,
  1050. X    total_blue,
  1051. X    total_green,
  1052. X    total_red;
  1053. X
  1054. X  if ((image->columns < 4) || (image->rows < 4))
  1055. X    {
  1056. X      Warning("unable to reduce image","image size must exceed 3x3");
  1057. X      return((Image *) NULL);
  1058. X    }
  1059. X  /*
  1060. X    Initialize reduced image attributes.
  1061. X  */
  1062. X  reduced_image=CopyImage(image,image->columns >> 1,image->rows >> 1,False);
  1063. X  if (reduced_image == (Image *) NULL)
  1064. X    {
  1065. X      Warning("unable to reduce image","memory allocation failed");
  1066. X      return((Image *) NULL);
  1067. X    }
  1068. X  reduced_image->class=DirectClass;
  1069. X  /*
  1070. X    Allocate image buffer and scanline buffer for 4 rows of the image.
  1071. X  */
  1072. X  scanline=(RunlengthPacket *) malloc(4*image->columns*sizeof(RunlengthPacket));
  1073. X  if (scanline == (RunlengthPacket *) NULL)
  1074. X    {
  1075. X      Warning("unable to reduce image","memory allocation failed");
  1076. X      DestroyImage(reduced_image);
  1077. X      return((Image *) NULL);
  1078. X    }
  1079. X  /*
  1080. X    Preload the first 2 rows of the image.
  1081. X  */
  1082. X  p=image->pixels;
  1083. X  image->runlength=p->length+1;
  1084. X  s=scanline;
  1085. X  for (x=0; x < (2*image->columns); x++)
  1086. X  {
  1087. X    if (image->runlength != 0)
  1088. X      image->runlength--;
  1089. X    else
  1090. X      {
  1091. X        p++;
  1092. X        image->runlength=p->length;
  1093. X      }
  1094. X    *s=(*p);
  1095. X    s++;
  1096. X  }
  1097. X  /*
  1098. X    Reduce each row.
  1099. X  */
  1100. X  p=image->pixels;
  1101. X  image->runlength=p->length+1;
  1102. X  q=reduced_image->pixels;
  1103. X  for (y=0; y < (image->rows-1); y+=2)
  1104. X  {
  1105. X    /*
  1106. X      Initialize sliding window pointers.
  1107. X    */
  1108. X    s0=scanline+image->columns*((y+0) % 4);
  1109. X    s1=scanline+image->columns*((y+1) % 4);
  1110. X    s2=scanline+image->columns*((y+2) % 4);
  1111. X    s3=scanline+image->columns*((y+3) % 4);
  1112. X    /*
  1113. X      Read another scan line.
  1114. X    */
  1115. X    s=s2;
  1116. X    for (x=0; x < image->columns; x++)
  1117. X    {
  1118. X      if (image->runlength != 0)
  1119. X        image->runlength--;
  1120. X      else
  1121. X        {
  1122. X          p++;
  1123. X          image->runlength=p->length;
  1124. X        }
  1125. X      *s=(*p);
  1126. X      s++;
  1127. X    }
  1128. X    /*
  1129. X      Read another scan line.
  1130. X    */
  1131. X    s=s3;
  1132. X    for (x=0; x < image->columns; x++)
  1133. X    {
  1134. X      if (image->runlength != 0)
  1135. X        image->runlength--;
  1136. X      else
  1137. X        {
  1138. X          p++;
  1139. X          image->runlength=p->length;
  1140. X        }
  1141. X      *s=(*p);
  1142. X      s++;
  1143. X    }
  1144. X    for (x=0; x < (image->columns-1); x+=2)
  1145. X    {
  1146. X      /*
  1147. X        Compute weighted average of target pixel color components.
  1148. X
  1149. X        These particular coefficients total to 128.  Use 128/2-1 or 63 to
  1150. X        insure correct round off.
  1151. X      */
  1152. X      total_red=0;
  1153. X      total_green=0;
  1154. X      total_blue=0;
  1155. X      total_alpha=0;
  1156. X      s=s0;
  1157. X      Rsum(3); Rsum(7);  Rsum(7);  Rsum(3);
  1158. X      s=s1;
  1159. X      Rsum(7); Rsum(15); Rsum(15); Rsum(7);
  1160. X      s=s2;
  1161. X      Rsum(7); Rsum(15); Rsum(15); Rsum(7);
  1162. X      s=s3;
  1163. X      Rsum(3); Rsum(7);  Rsum(7);  Rsum(3);
  1164. X      s0+=2;
  1165. X      s1+=2;
  1166. X      s2+=2;
  1167. X      s3+=2;
  1168. X      q->red=(unsigned char) ((total_red+63) >> 7);
  1169. X      q->green=(unsigned char) ((total_green+63) >> 7);
  1170. X      q->blue=(unsigned char) ((total_blue+63) >> 7);
  1171. X      q->index=(unsigned char) ((total_alpha+63) >> 7);
  1172. X      q->length=0;
  1173. X      q++;
  1174. X    }
  1175. X  }
  1176. X  (void) free((char *) scanline);
  1177. X  return(reduced_image);
  1178. }
  1179. X
  1180. /*
  1181. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1182. %                                                                             %
  1183. %                                                                             %
  1184. %                                                                             %
  1185. %   R e f l e c t I m a g e                                                   %
  1186. %                                                                             %
  1187. %                                                                             %
  1188. %                                                                             %
  1189. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1190. %
  1191. %  Function ReflectImage creates a new image that refelects each scanline of an
  1192. %  existing one.  It allocates the memory necessary for the new Image structure
  1193. %  and returns a pointer to the new image.
  1194. %
  1195. %  The format of the ReflectImage routine is:
  1196. %
  1197. %      reflected_image=ReflectImage(image)
  1198. %
  1199. %  A description of each parameter follows:
  1200. %
  1201. %    o reflected_image: Function ReflectImage returns a pointer to the image
  1202. %      after reflecting.  A null image is returned if there is a memory
  1203. %      shortage.
  1204. %
  1205. %    o image: The address of a structure of type Image.
  1206. %
  1207. %
  1208. */
  1209. Image *ReflectImage(image)
  1210. Image
  1211. X  *image;
  1212. {
  1213. X  Image
  1214. X    *reflected_image;
  1215. X
  1216. X  register RunlengthPacket
  1217. X    *p,
  1218. X    *q,
  1219. X    *s;
  1220. X
  1221. X  register unsigned int
  1222. X    x,
  1223. X    y;
  1224. X
  1225. X  RunlengthPacket
  1226. X    *scanline;
  1227. X
  1228. X  /*
  1229. X    Initialize reflected image attributes.
  1230. X  */
  1231. X  reflected_image=CopyImage(image,image->columns,image->rows,False);
  1232. X  if (reflected_image == (Image *) NULL)
  1233. X    {
  1234. X      Warning("unable to reflect image","memory allocation failed");
  1235. X      return((Image *) NULL);
  1236. X    }
  1237. X  /*
  1238. X    Allocate scan line buffer and column offset buffers.
  1239. X  */
  1240. X  scanline=(RunlengthPacket *) malloc(image->columns*sizeof(RunlengthPacket));
  1241. X  if (scanline == (RunlengthPacket *) NULL)
  1242. X    {
  1243. X      Warning("unable to reflect image","memory allocation failed");
  1244. X      DestroyImage(reflected_image);
  1245. X      return((Image *) NULL);
  1246. X    }
  1247. X  /*
  1248. X    Reflect each row.
  1249. X  */
  1250. X  p=image->pixels;
  1251. X  image->runlength=p->length+1;
  1252. X  q=reflected_image->pixels;
  1253. X  for (y=0; y < reflected_image->rows; y++)
  1254. X  {
  1255. X    /*
  1256. X      Read a scan line.
  1257. X    */
  1258. X    s=scanline;
  1259. X    for (x=0; x < image->columns; x++)
  1260. X    {
  1261. X      if (image->runlength != 0)
  1262. X        image->runlength--;
  1263. X      else
  1264. X        {
  1265. X          p++;
  1266. X          image->runlength=p->length;
  1267. X        }
  1268. X      *s=(*p);
  1269. X      s++;
  1270. X    }
  1271. X    /*
  1272. X      Reflect each column.
  1273. X    */
  1274. X    s=scanline+image->columns;
  1275. X    for (x=0; x < reflected_image->columns; x++)
  1276. X    {
  1277. X      s--;
  1278. X      *q=(*s);
  1279. X      q->length=0;
  1280. X      q++;
  1281. X    }
  1282. X  }
  1283. X  (void) free((char *) scanline);
  1284. X  return(reflected_image);
  1285. }
  1286. X
  1287. /*
  1288. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1289. %                                                                             %
  1290. %                                                                             %
  1291. %     R G B T r a n s f o r m I m a g e                                       %
  1292. %                                                                             %
  1293. %                                                                             %
  1294. %                                                                             %
  1295. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1296. %
  1297. %  Procedure RGBTransformImage converts the reference image from RGB to
  1298. %  an alternate colorspace.
  1299. %
  1300. %  The format of the RGBTransformImage routine is:
  1301. %
  1302. %      RGBTransformImage(image,colorspace)
  1303. %
  1304. %  A description of each parameter follows:
  1305. %
  1306. %    o image: The address of a structure of type Image;  returned from
  1307. %      ReadImage.
  1308. %
  1309. %    o colorspace: An unsigned integer value that indicates which colorspace
  1310. %      to transform the image.
  1311. %
  1312. %
  1313. */
  1314. void RGBTransformImage(image,colorspace)
  1315. Image
  1316. X  *image;
  1317. X
  1318. unsigned int
  1319. X  colorspace;
  1320. {
  1321. #define X 0
  1322. #define Y (MaxRGB+1)
  1323. #define Z (MaxRGB+1)*2
  1324. X
  1325. X  long
  1326. X    tx,
  1327. X    ty,
  1328. X    tz,
  1329. X    *x,
  1330. X    *y,
  1331. X    *z;
  1332. X
  1333. X  register int
  1334. X    blue,
  1335. X    green,
  1336. X    i,
  1337. X    red;
  1338. X
  1339. X  register RunlengthPacket
  1340. X    *p;
  1341. X
  1342. X  register unsigned char
  1343. X    *range_limit;
  1344. X
  1345. X  unsigned char
  1346. X    *range_table;
  1347. X
  1348. X  if (colorspace == RGBColorspace)
  1349. X    return;
  1350. X  /*
  1351. X    Allocate the tables.
  1352. X  */
  1353. X  x=(long *) malloc(3*(MaxRGB+1)*sizeof(long));
  1354. X  y=(long *) malloc(3*(MaxRGB+1)*sizeof(long));
  1355. X  z=(long *) malloc(3*(MaxRGB+1)*sizeof(long));
  1356. X  range_table=(unsigned char *) malloc(3*(MaxRGB+1)*sizeof(unsigned char));
  1357. X  if ((x == (long *) NULL) || (y == (long *) NULL) ||
  1358. X      (z == (long *) NULL) || (range_table == (unsigned char *) NULL))
  1359. X    {
  1360. X      Warning("unable to transform color space","memory allocation failed");
  1361. X      return;
  1362. X    }
  1363. X  /*
  1364. X    Pre-compute conversion tables.
  1365. X  */
  1366. X  for (i=0; i <= MaxRGB; i++)
  1367. X  {
  1368. X    range_table[i]=0;
  1369. X    range_table[i+(MaxRGB+1)]=(unsigned char) i;
  1370. X    range_table[i+(MaxRGB+1)*2]=MaxRGB;
  1371. X  }
  1372. X  range_limit=range_table+(MaxRGB+1);
  1373. X  tx=0;
  1374. X  ty=0;
  1375. X  tz=0;
  1376. X  switch (colorspace)
  1377. X  {
  1378. X    case GRAYColorspace:
  1379. X    {
  1380. X      /*
  1381. X        Initialize GRAY tables:
  1382. X
  1383. X          G = 0.29900*R+0.58700*G+0.11400*B
  1384. X      */
  1385. X      for (i=0; i <= MaxRGB; i++)
  1386. X      {
  1387. X        x[i+X]=UpShifted(0.29900)*i;
  1388. X        y[i+X]=UpShifted(0.58700)*i;
  1389. X        z[i+X]=UpShifted(0.11400)*i;
  1390. X        x[i+Y]=UpShifted(0.29900)*i;
  1391. X        y[i+Y]=UpShifted(0.58700)*i;
  1392. X        z[i+Y]=UpShifted(0.11400)*i;
  1393. X        x[i+Z]=UpShifted(0.29900)*i;
  1394. X        y[i+Z]=UpShifted(0.58700)*i;
  1395. X        z[i+Z]=UpShifted(0.11400)*i;
  1396. X      }
  1397. X      break;
  1398. X    }
  1399. X    case YCbCrColorspace:
  1400. X    {
  1401. X      /*
  1402. X        Initialize YCbCr tables:
  1403. X
  1404. X          Y =  0.29900*R+0.58700*G+0.11400*B
  1405. X          Cb= -0.16864*R-0.33126*G+0.50000*B
  1406. X          Cr=  0.50000*R-0.41869*G-0.08131*B
  1407. X
  1408. X        Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
  1409. X        through MaxRGB.
  1410. X      */
  1411. X      ty=UpShifted((MaxRGB+1)/2);
  1412. X      tz=UpShifted((MaxRGB+1)/2);
  1413. X      for (i=0; i <= MaxRGB; i++)
  1414. X      {
  1415. X        x[i+X]=UpShifted(0.29900)*i;
  1416. X        y[i+X]=UpShifted(0.58700)*i;
  1417. X        z[i+X]=UpShifted(0.11400)*i;
  1418. X        x[i+Y]=(-UpShifted(0.16874))*i;
  1419. X        y[i+Y]=(-UpShifted(0.33126))*i;
  1420. X        z[i+Y]=UpShifted(0.50000)*i;
  1421. X        x[i+Z]=UpShifted(0.50000)*i;
  1422. X        y[i+Z]=(-UpShifted(0.41869))*i;
  1423. X        z[i+Z]=(-UpShifted(0.08131))*i;
  1424. X      }
  1425. X      break;
  1426. X    }
  1427. X    case YIQColorspace:
  1428. X    {
  1429. X      /*
  1430. X        Initialize YIQ tables:
  1431. X
  1432. X          Y = 0.29900*R+0.58700*G+0.11400*B
  1433. X          I = 0.59600*R-0.27400*G-0.32200*B
  1434. X          Q = 0.21100*R-0.52300*G+0.31200*B
  1435. X      */
  1436. X      for (i=0; i <= MaxRGB; i++)
  1437. X      {
  1438. X        x[i+X]=UpShifted(0.29900)*i;
  1439. X        y[i+X]=UpShifted(0.58700)*i;
  1440. X        z[i+X]=UpShifted(0.11400)*i;
  1441. X        x[i+Y]=UpShifted(0.59600)*i;
  1442. X        y[i+Y]=(-UpShifted(0.27400))*i;
  1443. X        z[i+Y]=(-UpShifted(0.32200))*i;
  1444. X        x[i+Z]=UpShifted(0.21100)*i;
  1445. X        y[i+Z]=(-UpShifted(0.52300))*i;
  1446. X        z[i+Z]=UpShifted(0.31200)*i;
  1447. X      }
  1448. X      break;
  1449. X    }
  1450. X    case YUVColorspace:
  1451. X    default:
  1452. X    {
  1453. X      /*
  1454. X        Initialize YUV tables:
  1455. X
  1456. X          Y =  0.29900*R+0.58700*G+0.11400*B
  1457. X          U = -0.14740*R-0.28950*G+0.43690*B
  1458. X          V =  0.61500*R-0.51500*G-0.10000*B
  1459. X
  1460. X        U and V, normally -0.5 through 0.5, are normalized to the range 0
  1461. X        through MaxRGB.
  1462. X      */
  1463. X      ty=UpShifted((MaxRGB+1)/2);
  1464. X      tz=UpShifted((MaxRGB+1)/2);
  1465. X      for (i=0; i <= MaxRGB; i++)
  1466. X      {
  1467. X        x[i+X]=UpShifted(0.29900)*i;
  1468. X        y[i+X]=UpShifted(0.58700)*i;
  1469. X        z[i+X]=UpShifted(0.11400)*i;
  1470. X        x[i+Y]=(-UpShifted(0.14740))*i;
  1471. X        y[i+Y]=(-UpShifted(0.28950))*i;
  1472. X        z[i+Y]=UpShifted(0.43690)*i;
  1473. X        x[i+Z]=UpShifted(0.61500)*i;
  1474. X        y[i+Z]=(-UpShifted(0.51500))*i;
  1475. X        z[i+Z]=(-UpShifted(0.10000))*i;
  1476. X      }
  1477. X      break;
  1478. X    }
  1479. X    case XYZColorspace:
  1480. X    {
  1481. X      /*
  1482. X        Initialize XYZ tables:
  1483. X
  1484. X          X = 0.49000*R+0.31000*G+0.20000*B
  1485. X          Y = 0.17700*R+0.81300*G+0.01100*B
  1486. X          Z = 0.00000*R+0.01000*G+0.99000*B
  1487. X      */
  1488. X      for (i=0; i <= MaxRGB; i++)
  1489. X      {
  1490. X        x[i+X]=UpShifted(0.49000)*i;
  1491. X        y[i+X]=UpShifted(0.31000)*i;
  1492. X        z[i+X]=UpShifted(0.20000)*i;
  1493. X        x[i+Y]=UpShifted(0.17700)*i;
  1494. X        y[i+Y]=UpShifted(0.81300)*i;
  1495. X        z[i+Y]=UpShifted(0.01100)*i;
  1496. X        x[i+Z]=0;
  1497. X        y[i+Z]=UpShifted(0.01000)*i;
  1498. X        z[i+Z]=UpShifted(0.99000)*i;
  1499. X      }
  1500. X      break;
  1501. X    }
  1502. X  }
  1503. X  /*
  1504. X    Convert from RGB.
  1505. X  */
  1506. X  switch (image->class)
  1507. X  {
  1508. X    case DirectClass:
  1509. X    {
  1510. X      /*
  1511. X        Convert DirectClass image.
  1512. X      */
  1513. X      p=image->pixels;
  1514. X      for (i=0; i < image->packets; i++)
  1515. X      {
  1516. X        red=p->red;
  1517. X        green=p->green;
  1518. X        blue=p->blue;
  1519. X        p->red=range_limit[DownShift(x[red+X]+y[green+X]+z[blue+X]+tx)];
  1520. X        p->green=range_limit[DownShift(x[red+Y]+y[green+Y]+z[blue+Y]+ty)];
  1521. X        p->blue=range_limit[DownShift(x[red+Z]+y[green+Z]+z[blue+Z]+tz)];
  1522. X        p++;
  1523. X      }
  1524. X      break;
  1525. X    }
  1526. X    case PseudoClass:
  1527. X    {
  1528. X      /*
  1529. X        Convert PseudoClass image.
  1530. X      */
  1531. X      for (i=0; i < image->colors; i++)
  1532. X      {
  1533. X        red=image->colormap[i].red;
  1534. X        green=image->colormap[i].green;
  1535. X        blue=image->colormap[i].blue;
  1536. X        image->colormap[i].red=
  1537. X          range_limit[DownShift(x[red+X]+y[green+X]+z[blue+X]+tx)];
  1538. X        image->colormap[i].green=
  1539. X          range_limit[DownShift(x[red+Y]+y[green+Y]+z[blue+Y]+ty)];
  1540. X        image->colormap[i].blue=
  1541. X          range_limit[DownShift(x[red+Z]+y[green+Z]+z[blue+Z]+tz)];
  1542. X      }
  1543. X      SyncImage(image);
  1544. X      break;
  1545. X    }
  1546. X  }
  1547. X  /*
  1548. X    Free allocated memory.
  1549. X  */
  1550. X  (void) free((char *) range_table);
  1551. X  (void) free((char *) z);
  1552. X  (void) free((char *) y);
  1553. X  (void) free((char *) x);
  1554. }
  1555. X
  1556. /*
  1557. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1558. %                                                                             %
  1559. %                                                                             %
  1560. %                                                                             %
  1561. %   R o l l I m a g e                                                         %
  1562. %                                                                             %
  1563. %                                                                             %
  1564. %                                                                             %
  1565. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1566. %
  1567. %  Function RollImage rolls an image vertically and horizontally.  It
  1568. %  allocates the memory necessary for the new Image structure and returns a
  1569. %  pointer to the new image.
  1570. %
  1571. %  The format of the RollImage routine is:
  1572. %
  1573. %      rolled_image=RollImage(image,columns,rows)
  1574. %
  1575. %  A description of each parameter follows:
  1576. %
  1577. %    o rolled_image: Function RollImage returns a pointer to the image after
  1578. %      rolling.  A null image is returned if there is a memory shortage.
  1579. %
  1580. %    o image: The address of a structure of type Image.
  1581. %
  1582. %    o x_offset: An integer that specifies the number of columns to roll
  1583. %      in the horizonal direction.
  1584. %
  1585. %    o y_offset: An integer that specifies the number of rows to roll in the
  1586. %      veritical direction.
  1587. %
  1588. %
  1589. */
  1590. Image *RollImage(image,x_offset,y_offset)
  1591. Image
  1592. X  *image;
  1593. X
  1594. int
  1595. X  x_offset,
  1596. X  y_offset;
  1597. {
  1598. X  Image
  1599. X    *rolled_image;
  1600. X
  1601. X  register RunlengthPacket
  1602. X    *p,
  1603. X    *q;
  1604. X
  1605. X  register unsigned int
  1606. X    packets,
  1607. X    x;
  1608. X
  1609. X  unsigned int
  1610. X    y;
  1611. X
  1612. X  /*
  1613. X    Initialize rolled image attributes.
  1614. X  */
  1615. X  rolled_image=CopyImage(image,image->columns,image->rows,False);
  1616. X  if (rolled_image == (Image *) NULL)
  1617. X    {
  1618. X      Warning("unable to roll image","memory allocation failed");
  1619. X      return((Image *) NULL);
  1620. X    }
  1621. X  /*
  1622. X    Roll image.
  1623. X  */
  1624. X  p=image->pixels;
  1625. X  image->runlength=p->length+1;
  1626. X  packets=image->columns*image->rows;
  1627. X  for (y=0; y < image->rows; y++)
  1628. X  {
  1629. X    /*
  1630. X      Transfer scanline.
  1631. X    */
  1632. X    for (x=0; x < image->columns; x++)
  1633. X    {
  1634. X      if (image->runlength != 0)
  1635. X        image->runlength--;
  1636. X      else
  1637. X        {
  1638. X          p++;
  1639. X          image->runlength=p->length;
  1640. X        }
  1641. X      q=rolled_image->pixels+(y_offset+y)*image->columns+x+x_offset;
  1642. X      if (q < rolled_image->pixels)
  1643. X        q+=packets;
  1644. X      else
  1645. X        if (q >= (rolled_image->pixels+packets))
  1646. X          q-=packets;
  1647. X      *q=(*p);
  1648. X      q->length=0;
  1649. X    }
  1650. X  }
  1651. X  return(rolled_image);
  1652. }
  1653. X
  1654. /*
  1655. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1656. %                                                                             %
  1657. %                                                                             %
  1658. %                                                                             %
  1659. %   S c a l e I m a g e                                                       %
  1660. %                                                                             %
  1661. %                                                                             %
  1662. %                                                                             %
  1663. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1664. %
  1665. %  Function ScaleImage creates a new image that is a scaled size of an
  1666. %  existing one using pixel replication.  It allocates the memory necessary
  1667. %  for the new Image structure and returns a pointer to the new image.
  1668. %
  1669. %  The format of the ScaleImage routine is:
  1670. %
  1671. %      scaled_image=ScaleImage(image,columns,rows)
  1672. %
  1673. %  A description of each parameter follows:
  1674. %
  1675. %    o scaled_image: Function ScaleImage returns a pointer to the image after
  1676. %      scaling.  A null image is returned if there is a memory shortage.
  1677. %
  1678. %    o image: The address of a structure of type Image.
  1679. %
  1680. %    o columns: An integer that specifies the number of columns in the scaled
  1681. %      image.
  1682. %
  1683. %    o rows: An integer that specifies the number of rows in the scaled
  1684. %      image.
  1685. %
  1686. %
  1687. */
  1688. Image *ScaleImage(image,columns,rows)
  1689. Image
  1690. X  *image;
  1691. X
  1692. unsigned int
  1693. X  columns,
  1694. X  rows;
  1695. {
  1696. X  Image
  1697. X    *scaled_image;
  1698. X
  1699. X  register RunlengthPacket
  1700. X    *p,
  1701. X    *q,
  1702. X    *s;
  1703. X
  1704. X  register unsigned int
  1705. X    x;
  1706. X
  1707. X  RunlengthPacket
  1708. X    *scanline;
  1709. X
  1710. X  unsigned int
  1711. X    *x_offset,
  1712. X    y,
  1713. X    *y_offset;
  1714. X
  1715. X  unsigned long
  1716. X    scale_factor;
  1717. X
  1718. X  if ((columns == 0) || (rows == 0))
  1719. X    {
  1720. X      Warning("unable to scale image","image dimensions are zero");
  1721. X      return((Image *) NULL);
  1722. X    }
  1723. X  if ((columns > MaxImageSize) || (rows > MaxImageSize))
  1724. X    {
  1725. X      Warning("unable to scale image","image too large");
  1726. X      return((Image *) NULL);
  1727. X    }
  1728. X  /*
  1729. X    Initialize scaled image attributes.
  1730. X  */
  1731. X  scaled_image=CopyImage(image,columns,rows,False);
  1732. X  if (scaled_image == (Image *) NULL)
  1733. X    {
  1734. X      Warning("unable to scale image","memory allocation failed");
  1735. X      return((Image *) NULL);
  1736. X    }
  1737. X  /*
  1738. X    Allocate scan line buffer and column offset buffers.
  1739. X  */
  1740. X  scanline=(RunlengthPacket *) malloc(image->columns*sizeof(RunlengthPacket));
  1741. X  x_offset=(unsigned int *) malloc(scaled_image->columns*sizeof(unsigned int));
  1742. X  y_offset=(unsigned int *) malloc(scaled_image->rows*sizeof(unsigned int));
  1743. X  if ((scanline == (RunlengthPacket *) NULL) ||
  1744. X      (x_offset == (unsigned int *) NULL) ||
  1745. X      (y_offset == (unsigned int *) NULL))
  1746. X    {
  1747. X      Warning("unable to scale image","memory allocation failed");
  1748. X      DestroyImage(scaled_image);
  1749. X      return((Image *) NULL);
  1750. X    }
  1751. X  /*
  1752. X    Initialize column pixel offsets.
  1753. X  */
  1754. X  scale_factor=UpShift(image->columns-1)/scaled_image->columns;
  1755. X  columns=0;
  1756. X  for (x=0; x < scaled_image->columns; x++)
  1757. X  {
  1758. X    x_offset[x]=DownShift((x+1)*scale_factor)-columns;
  1759. X    columns+=x_offset[x];
  1760. X  }
  1761. X  /*
  1762. X    Initialize row pixel offsets.
  1763. X  */
  1764. X  scale_factor=UpShift(image->rows-1)/scaled_image->rows;
  1765. X  rows=0;
  1766. X  for (y=0; y < scaled_image->rows; y++)
  1767. X  {
  1768. X    y_offset[y]=DownShift((y+1)*scale_factor)-rows;
  1769. X    rows+=y_offset[y];
  1770. X  }
  1771. X  /*
  1772. X    Preload first scanline.
  1773. X  */
  1774. X  p=image->pixels;
  1775. X  image->runlength=p->length+1;
  1776. X  s=scanline;
  1777. X  for (x=0; x < image->columns; x++)
  1778. X  {
  1779. X    if (image->runlength != 0)
  1780. X      image->runlength--;
  1781. X    else
  1782. X      {
  1783. X        p++;
  1784. X        image->runlength=p->length;
  1785. X      }
  1786. X    *s=(*p);
  1787. X    s++;
  1788. X  }
  1789. X  /*
  1790. X    Scale each row.
  1791. X  */
  1792. X  q=scaled_image->pixels;
  1793. X  for (y=0; y < scaled_image->rows; y++)
  1794. X  {
  1795. X    /*
  1796. X      Scale each column.
  1797. X    */
  1798. X    s=scanline;
  1799. X    for (x=0; x < scaled_image->columns; x++)
  1800. X    {
  1801. X      *q=(*s);
  1802. X      q->length=0;
  1803. X      q++;
  1804. X      s+=x_offset[x];
  1805. X    }
  1806. X    if (y_offset[y] != 0)
  1807. X      {
  1808. X        /*
  1809. X          Skip a scan line.
  1810. X        */
  1811. X        for (x=0; x < (image->columns*(y_offset[y]-1)); x++)
  1812. X          if (image->runlength != 0)
  1813. X            image->runlength--;
  1814. X          else
  1815. X            {
  1816. X              p++;
  1817. X              image->runlength=p->length;
  1818. X            }
  1819. X        /*
  1820. X          Read a scan line.
  1821. X        */
  1822. X        s=scanline;
  1823. X        for (x=0; x < image->columns; x++)
  1824. X        {
  1825. X          if (image->runlength != 0)
  1826. X            image->runlength--;
  1827. X          else
  1828. X            {
  1829. X              p++;
  1830. X              image->runlength=p->length;
  1831. X            }
  1832. X          *s=(*p);
  1833. X          s++;
  1834. X        }
  1835. X      }
  1836. X  }
  1837. X  (void) free((char *) scanline);
  1838. X  (void) free((char *) x_offset);
  1839. X  (void) free((char *) y_offset);
  1840. X  return(scaled_image);
  1841. }
  1842. X
  1843. /*
  1844. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1845. %                                                                             %
  1846. %                                                                             %
  1847. %                                                                             %
  1848. %   S o r t C o l o r m a p B y I n t e n t s i t y                           %
  1849. %                                                                             %
  1850. %                                                                             %
  1851. %                                                                             %
  1852. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1853. %
  1854. %  Function SortColormapByIntensity sorts the colormap of a PseudoClass image
  1855. %  by decreasing color intensity.
  1856. %
  1857. %  The format of the SortColormapByIntensity routine is:
  1858. %
  1859. %      SortColormapByIntensity(image)
  1860. %
  1861. %  A description of each parameter follows:
  1862. %
  1863. %    o image: A pointer to a Image structure.
  1864. %
  1865. %
  1866. */
  1867. static int IntensityCompare(x,y)
  1868. const void
  1869. X  *x,
  1870. X  *y;
  1871. {
  1872. X  ColorPacket
  1873. X    *color_1,
  1874. X    *color_2;
  1875. X
  1876. X  color_1=(ColorPacket *) x;
  1877. X  color_2=(ColorPacket *) y;
  1878. X  return((int) Intensity(*color_2)-(int) Intensity(*color_1));
  1879. }
  1880. X
  1881. void SortColormapByIntensity(image)
  1882. Image
  1883. X  *image;
  1884. {
  1885. X  register int
  1886. X    i;
  1887. X
  1888. X  register RunlengthPacket
  1889. X    *p;
  1890. X
  1891. X  register unsigned short
  1892. X    index;
  1893. X
  1894. X  unsigned short
  1895. X    *pixels;
  1896. X
  1897. X  if (image->class != PseudoClass)
  1898. SHAR_EOF
  1899. true || echo 'restore of ImageMagick/image.c failed'
  1900. fi
  1901. echo 'End of ImageMagick part 28'
  1902. echo 'File ImageMagick/image.c is continued in part 29'
  1903. echo 29 > _shar_seq_.tmp
  1904. exit 0
  1905.  
  1906. exit 0 # Just in case...
  1907. -- 
  1908.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1909. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  1910.  "It's intuitively obvious to the |
  1911.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1912.