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

  1. Newsgroups: comp.sources.x
  2. From: cristy@eplrx7.es.duPont.com (Cristy)
  3. Subject: v20i083:  imagemagic - X11 image processing and display, Part27/38
  4. Message-ID: <1993Jul14.232037.22596@sparky.sterling.com>
  5. X-Md4-Signature: d699f2aa6d1f48dc90361d0f37666df3
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Wed, 14 Jul 1993 23:20:37 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: cristy@eplrx7.es.duPont.com (Cristy)
  12. Posting-number: Volume 20, Issue 83
  13. Archive-name: imagemagic/part27
  14. Environment: X11
  15. Supersedes: imagemagic: Volume 13, Issue 17-37
  16.  
  17. #!/bin/sh
  18. # this is magick.27 (part 27 of ImageMagick)
  19. # do not concatenate these parts, unpack them in order with /bin/sh
  20. # file ImageMagick/import.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" != 27; 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/import.c'
  36. else
  37. echo 'x - continuing file ImageMagick/import.c'
  38. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/import.c' &&
  39. X          target_window=argv[i];
  40. X          break;
  41. X        }
  42. X        case 'v':
  43. X        {
  44. X          verbose=(*option == '-');
  45. X          break;
  46. X        }
  47. X        default:
  48. X        {
  49. X          Error("unrecognized option",option);
  50. X          break;
  51. X        }
  52. X      }
  53. X  }
  54. X  if (filename == (char *) NULL)
  55. X    Error("missing an image file name",(char *) NULL);
  56. X  /*
  57. X    Read image from X server.
  58. X  */
  59. X  if (resource_info.delay != 0)
  60. X    (void) sleep(resource_info.delay);
  61. X  start_time=time((time_t *) NULL);
  62. X  image=ReadXImage(target_window,server_name,frame,borders,screen,descend);
  63. X  if (image == (Image *) NULL)
  64. X    exit(1);
  65. X  if ((degrees % 360) != 0)
  66. X    {
  67. X      Image
  68. X        *rotated_image;
  69. X
  70. X      /*
  71. X        Rotate image.
  72. X      */
  73. X      rotated_image=RotateImage(image,(double) degrees,False);
  74. X      if (rotated_image != (Image *) NULL)
  75. X        {
  76. X          DestroyImage(image);
  77. X          image=rotated_image;
  78. X        }
  79. X    }
  80. X  image->scene=scene;
  81. X  if (resource_info.monochrome)
  82. X    QuantizeImage(image,2,8,False,GRAYColorspace,True);
  83. X  if (compression != UndefinedCompression)
  84. X    image->compression=compression;
  85. X  GetImageInfo(&image_info);
  86. X  image_info.server_name=resource_info.server_name;
  87. X  image_info.font=resource_info.font;
  88. X  image_info.geometry=resource_info.image_geometry;
  89. X  image_info.density=density;
  90. X  image_info.page=page_geometry;
  91. X  image_info.interlace=interlace;
  92. X  image_info.monochrome=resource_info.monochrome;
  93. X  image_info.quality=quality;
  94. X  image_info.verbose=verbose;
  95. X  (void) strcpy(image->magick,"PS");
  96. X  (void) strcpy(image->filename,filename);
  97. X  (void) WriteImage(&image_info,image);
  98. X  if (verbose)
  99. X    {
  100. X      /*
  101. X        Display detailed info about the image.
  102. X      */
  103. X      if (image->class == DirectClass)
  104. X        image->colors=NumberColors(image,(FILE *) NULL);
  105. X      (void) fprintf(stderr,"[%u] %s %ux%u",image->scene,image->filename,
  106. X        image->columns,image->rows);
  107. X      if (image->class == DirectClass)
  108. X        (void) fprintf(stderr," DirectClass ");
  109. X      else
  110. X        (void) fprintf(stderr," PseudoClass ");
  111. X      (void) fprintf(stderr,"%dc %s %lds\n",image->colors,image->magick,
  112. X        time((time_t *) NULL)-start_time+1);
  113. X    }
  114. X  DestroyImage(image);
  115. X  XCloseDisplay(display);
  116. X  return(False);
  117. }
  118. SHAR_EOF
  119. echo 'File ImageMagick/import.c is complete' &&
  120. chmod 0644 ImageMagick/import.c ||
  121. echo 'restore of ImageMagick/import.c failed'
  122. Wc_c="`wc -c < 'ImageMagick/import.c'`"
  123. test 22346 -eq "$Wc_c" ||
  124.     echo 'ImageMagick/import.c: original size 22346, current size' "$Wc_c"
  125. rm -f _shar_wnt_.tmp
  126. fi
  127. # ============= ImageMagick/image.c ==============
  128. if test -f 'ImageMagick/image.c' -a X"$1" != X"-c"; then
  129.     echo 'x - skipping ImageMagick/image.c (File already exists)'
  130.     rm -f _shar_wnt_.tmp
  131. else
  132. > _shar_wnt_.tmp
  133. echo 'x - extracting ImageMagick/image.c (Text)'
  134. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/image.c' &&
  135. /*
  136. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  137. %                                                                             %
  138. %                                                                             %
  139. %                                                                             %
  140. %                     IIIII  M   M   AAA   GGGG  EEEEE                        %
  141. %                       I    MM MM  A   A G      E                            %
  142. %                       I    M M M  AAAAA G  GG  EEE                          %
  143. %                       I    M   M  A   A G   G  E                            %
  144. %                     IIIII  M   M  A   A  GGGG  EEEEE                        %
  145. %                                                                             %
  146. %                                                                             %
  147. %                    Utiltity Image Routines for Display                      %
  148. %                                                                             %
  149. %                                                                             %
  150. %                                                                             %
  151. %                           Software Design                                   %
  152. %                             John Cristy                                     %
  153. %                              July 1992                                      %
  154. %                                                                             %
  155. %                                                                             %
  156. %  Copyright 1993 E. I. du Pont de Nemours & Company                          %
  157. %                                                                             %
  158. %  Permission to use, copy, modify, distribute, and sell this software and    %
  159. %  its documentation for any purpose is hereby granted without fee,           %
  160. %  provided that the above Copyright notice appear in all copies and that     %
  161. %  both that Copyright notice and this permission notice appear in            %
  162. %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
  163. %  & Company not be used in advertising or publicity pertaining to            %
  164. %  distribution of the software without specific, written prior               %
  165. %  permission.  E. I. du Pont de Nemours & Company makes no representations   %
  166. %  about the suitability of this software for any purpose.  It is provided    %
  167. %  "as is" without express or implied warranty.                               %
  168. %                                                                             %
  169. %  E. I. du Pont de Nemours & Company disclaims all warranties with regard    %
  170. %  to this software, including all implied warranties of merchantability      %
  171. %  and fitness, in no event shall E. I. du Pont de Nemours & Company be       %
  172. %  liable for any special, indirect or consequential damages or any           %
  173. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  174. %  in an action of contract, negligence or other tortious action, arising     %
  175. %  out of or in connection with the use or performance of this software.      %
  176. %                                                                             %
  177. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  178. %
  179. %
  180. %
  181. */
  182. X
  183. /*
  184. X  Include declarations.
  185. */
  186. #include "display.h"
  187. #include "image.h"
  188. #include "X.h"
  189. #include "compress.h"
  190. #include "utility.h"
  191. X
  192. /*
  193. X  External declarations.
  194. */
  195. extern char
  196. X  *client_name;
  197. X
  198. /*
  199. X  Forward declarations.
  200. */
  201. static Image
  202. X  *ZoomImage _Declare((Image *));
  203. X
  204. /*
  205. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  206. %                                                                             %
  207. %                                                                             %
  208. %                                                                             %
  209. %   A l l o c a t e I m a g e                                                 %
  210. %                                                                             %
  211. %                                                                             %
  212. %                                                                             %
  213. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  214. %
  215. %  Function AllocateImage allocates an Image structure and initializes each
  216. %  field to a default value.
  217. %
  218. %  The format of the AllocateImage routine is:
  219. %
  220. %      allocated_image=AllocateImage(magick)
  221. %
  222. %  A description of each parameter follows:
  223. %
  224. %    o allocated_image: Function AllocateImage returns a pointer to an image
  225. %      structure initialized to default values.  A null image is returned if
  226. %      there is a memory shortage.
  227. %
  228. %    o magick: Specifies the image format (i.e. MIFF, GIF, JPEG, etc.).
  229. %
  230. %
  231. */
  232. Image *AllocateImage(magick)
  233. char
  234. X  *magick;
  235. {
  236. X  Image
  237. X    *allocated_image;
  238. X
  239. X  /*
  240. X    Allocate image structure.
  241. X  */
  242. X  allocated_image=(Image *) malloc(sizeof(Image));
  243. X  if (allocated_image == (Image *) NULL)
  244. X    {
  245. X      Warning("unable to allocate image","memory allocation error");
  246. X      return((Image *) NULL);
  247. X    }
  248. X  /*
  249. X    Initialize Image structure.
  250. X  */
  251. X  allocated_image->file=(FILE *) NULL;
  252. X  allocated_image->status=False;
  253. X  *allocated_image->filename='\0';
  254. X  if (strlen(magick) < sizeof(allocated_image->magick))
  255. X    (void) strcpy(allocated_image->magick,magick);
  256. X  allocated_image->comments=(char *) NULL;
  257. X  allocated_image->label=(char *) NULL;
  258. X  allocated_image->id=UndefinedId;
  259. X  allocated_image->class=DirectClass;
  260. X  allocated_image->alpha=False;
  261. X  allocated_image->compression=RunlengthEncodedCompression;
  262. X  allocated_image->columns=0;
  263. X  allocated_image->rows=0;
  264. X  allocated_image->colors=0;
  265. X  allocated_image->scene=0;
  266. X  allocated_image->montage=(char *) NULL;
  267. X  allocated_image->directory=(char *) NULL;
  268. X  allocated_image->colormap=(ColorPacket *) NULL;
  269. X  allocated_image->signature=(char *) NULL;
  270. X  allocated_image->pixels=(RunlengthPacket *) NULL;
  271. X  allocated_image->packet=(RunlengthPacket *) NULL;
  272. X  allocated_image->packets=0;
  273. X  allocated_image->packet_size=0;
  274. X  allocated_image->packed_pixels=(unsigned char *) NULL;
  275. X  allocated_image->orphan=False;
  276. X  allocated_image->previous=(Image *) NULL;
  277. X  allocated_image->next=(Image *) NULL;
  278. X  return(allocated_image);
  279. }
  280. X
  281. /*
  282. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  283. %                                                                             %
  284. %                                                                             %
  285. %                                                                             %
  286. %   B o r d e r I m a g e                                                     %
  287. %                                                                             %
  288. %                                                                             %
  289. %                                                                             %
  290. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  291. %
  292. %  Function BorderImage takes an image and puts a border around it of a
  293. %  particular color.  It allocates the memory necessary for the new Image
  294. %  structure and returns a pointer to the new image.  Set the border and
  295. %  highlight to the same color to get a solid border.
  296. %
  297. %  The format of the BorderImage routine is:
  298. %
  299. %      bordered_image=BorderImage(image,border_info,border_color,
  300. %        highlight_color)
  301. %
  302. %  A description of each parameter follows:
  303. %
  304. %    o bordered_image: Function BorderImage returns a pointer to the bordered
  305. %      image.  A null image is returned if there is a a memory shortage.
  306. %
  307. %    o image: The address of a structure of type Image.
  308. %
  309. %    o border_info: Specifies a pointer to a XRectangle which defines the
  310. %      border region.
  311. %
  312. %    o border_color: A pointer to a ColorPacket which contains the red,
  313. %      green, and blue components of the border color.
  314. %
  315. %    o highlight_color: A pointer to a ColorPacket which contains the red,
  316. %      green, and blue components of the highlight color.
  317. %
  318. %
  319. */
  320. Image *BorderImage(image,border_info,border_color,highlight_color)
  321. Image
  322. X  *image;
  323. X
  324. RectangleInfo
  325. X  *border_info;
  326. X
  327. ColorPacket
  328. X  *border_color,
  329. X  *highlight_color;
  330. {
  331. X  Image
  332. X    *bordered_image;
  333. X
  334. X  register int
  335. X    x,
  336. X    y;
  337. X
  338. X  register RunlengthPacket
  339. X    *p,
  340. X    *q;
  341. X
  342. X  RunlengthPacket
  343. X    border,
  344. X    highlight;
  345. X
  346. X  /*
  347. X    Check border geometry.
  348. X  */
  349. X  if ((((int) border_info->width-border_info->x) < image->columns) ||
  350. X      (((int) border_info->height-border_info->y) < image->rows))
  351. X    {
  352. X      Warning("unable to border image","border is less than image size");
  353. X      return((Image *) NULL);
  354. X    }
  355. X  /*
  356. X    Initialize bordered image attributes.
  357. X  */
  358. X  bordered_image=CopyImage(image,border_info->width,border_info->height,False);
  359. X  if (bordered_image == (Image *) NULL)
  360. X    {
  361. X      Warning("unable to border image","memory allocation failed");
  362. X      return((Image *) NULL);
  363. X    }
  364. X  /*
  365. X    Initialize border colors.
  366. X  */
  367. X  border.red=border_color->red;
  368. X  border.green=border_color->green;
  369. X  border.blue=border_color->blue;
  370. X  border.index=border_color->index;
  371. X  border.length=0;
  372. X  highlight.red=highlight_color->red;
  373. X  highlight.green=highlight_color->green;
  374. X  highlight.blue=highlight_color->blue;
  375. X  highlight.index=highlight_color->index;
  376. X  highlight.length=0;
  377. X  /*
  378. X    Copy image and put border around it.
  379. X  */
  380. X  q=bordered_image->pixels;
  381. X  for (y=0; y < border_info->y; y++)
  382. X  {
  383. X    for (x=0; x < (bordered_image->columns-y); x++)
  384. X      *q++=highlight;
  385. X    for ( ; x < bordered_image->columns; x++)
  386. X      *q++=border;
  387. X  }
  388. X  p=image->pixels;
  389. X  image->runlength=p->length+1;
  390. X  for (y=0; y < image->rows; y++)
  391. X  {
  392. X    /*
  393. X      Initialize scanline with border color.
  394. X    */
  395. X    for (x=0; x < border_info->x; x++)
  396. X      *q++=highlight;
  397. X    /*
  398. X      Transfer scanline.
  399. X    */
  400. X    for (x=0; x < image->columns; x++)
  401. X    {
  402. X      if (image->runlength != 0)
  403. X        image->runlength--;
  404. X      else
  405. X        {
  406. X          p++;
  407. X          image->runlength=p->length;
  408. X        }
  409. X      *q=(*p);
  410. X      q->length=0;
  411. X      q++;
  412. X    }
  413. X    for (x=0; x < (border_info->width-image->columns-border_info->x); x++)
  414. X      *q++=border;
  415. X  }
  416. X  for (y=(border_info->height-image->rows-border_info->y-1); y >= 0; y--)
  417. X  {
  418. X    for (x=0; x < y; x++)
  419. X      *q++=highlight;
  420. X    for ( ; x < bordered_image->columns; x++)
  421. X      *q++=border;
  422. X  }
  423. X  return(bordered_image);
  424. }
  425. X
  426. /*
  427. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  428. %                                                                             %
  429. %                                                                             %
  430. %                                                                             %
  431. %   C l i p I m a g e                                                         %
  432. %                                                                             %
  433. %                                                                             %
  434. %                                                                             %
  435. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  436. %
  437. %  Function ClipImage creates a new image that is a subregion of an existing
  438. %  one.  It allocates the memory necessary for the new Image structure and
  439. %  returns a pointer to the new image.  The pixels are copied from the source
  440. %  image as defined by the region formed from x_offset, y_offset, width, and
  441. %  height.
  442. %
  443. %  The format of the ClipImage routine is:
  444. %
  445. %      clipped_image=ClipImage(image,clip_info)
  446. %
  447. %  A description of each parameter follows:
  448. %
  449. %    o clipped_image: Function ClipImage returns a pointer to the clipped
  450. %      image.  A null image is returned if there is a a memory shortage or
  451. %      if the image width or height is zero.
  452. %
  453. %    o image: The address of a structure of type Image.
  454. %
  455. %    o clip_info: Specifies a pointer to a RectangleInfo which defines the
  456. %      region of the image to crop.
  457. %
  458. %
  459. */
  460. Image *ClipImage(image,clip_info)
  461. Image
  462. X  *image;
  463. X
  464. RectangleInfo
  465. X  *clip_info;
  466. {
  467. X  Image
  468. X    *clipped_image;
  469. X
  470. X  register int
  471. X    x,
  472. X    y;
  473. X
  474. X  register RunlengthPacket
  475. X    *p,
  476. X    *q;
  477. X
  478. X  /*
  479. X    Check clip geometry.
  480. X  */
  481. X  if ((clip_info->width == 0) || (clip_info->height == 0))
  482. X    {
  483. X      Warning("unable to clip image","image size is zero");
  484. X      return((Image *) NULL);
  485. X    }
  486. X  if (((clip_info->x+(int) clip_info->width) < 0) ||
  487. X      ((clip_info->y+(int) clip_info->height) < 0) ||
  488. X      (clip_info->x > (int) image->columns) ||
  489. X      (clip_info->y > (int) image->rows))
  490. X    {
  491. X      Warning("unable to clip image","geometry does not contain image");
  492. X      return((Image *) NULL);
  493. X    }
  494. X  if ((clip_info->x+(int) clip_info->width) > (int) image->columns)
  495. X    clip_info->width=(unsigned int) ((int) image->columns-clip_info->x);
  496. X  if ((clip_info->y+(int) clip_info->height) > (int) image->rows)
  497. X    clip_info->height=(unsigned int) ((int) image->rows-clip_info->y);
  498. X  if (clip_info->x < 0)
  499. X    {
  500. X      clip_info->width-=(unsigned int) (-clip_info->x);
  501. X      clip_info->x=0;
  502. X    }
  503. X  if (clip_info->y < 0)
  504. X    {
  505. X      clip_info->height-=(unsigned int) (-clip_info->y);
  506. X      clip_info->y=0;
  507. X    }
  508. X  /*
  509. X    Initialize clipped image attributes.
  510. X  */
  511. X  clipped_image=CopyImage(image,clip_info->width,clip_info->height,False);
  512. X  if (clipped_image == (Image *) NULL)
  513. X    {
  514. X      Warning("unable to clip image","memory allocation failed");
  515. X      return((Image *) NULL);
  516. X    }
  517. X  /*
  518. X    Skip pixels up to the clipped image.
  519. X  */
  520. X  p=image->pixels;
  521. X  image->runlength=p->length+1;
  522. X  for (x=0; x < (clip_info->y*image->columns+clip_info->x); x++)
  523. X    if (image->runlength != 0)
  524. X      image->runlength--;
  525. X    else
  526. X      {
  527. X        p++;
  528. X        image->runlength=p->length;
  529. X      }
  530. X  /*
  531. X    Extract clipped image.
  532. X  */
  533. X  q=clipped_image->pixels;
  534. X  for (y=0; y < clipped_image->rows; y++)
  535. X  {
  536. X    /*
  537. X      Transfer scanline.
  538. X    */
  539. X    for (x=0; x < clipped_image->columns; x++)
  540. X    {
  541. X      if (image->runlength != 0)
  542. X        image->runlength--;
  543. X      else
  544. X        {
  545. X          p++;
  546. X          image->runlength=p->length;
  547. X        }
  548. X      *q=(*p);
  549. X      q->length=0;
  550. X      q++;
  551. X    }
  552. X    /*
  553. X      Skip to next scanline.
  554. X    */
  555. X    for (x=0; x < (image->columns-clipped_image->columns); x++)
  556. X      if (image->runlength != 0)
  557. X        image->runlength--;
  558. X      else
  559. X        {
  560. X          p++;
  561. X          image->runlength=p->length;
  562. X        }
  563. X  }
  564. X  return(clipped_image);
  565. }
  566. X
  567. /*
  568. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  569. %                                                                             %
  570. %                                                                             %
  571. %                                                                             %
  572. %   C l o s e I m a g e                                                       %
  573. %                                                                             %
  574. %                                                                             %
  575. %                                                                             %
  576. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  577. %
  578. %  Function CloseImage closes a file associated with the image.
  579. %
  580. %  The format of the CloseImage routine is:
  581. %
  582. %      CloseImage(image)
  583. %
  584. %  A description of each parameter follows:
  585. %
  586. %    o image: The address of a structure of type Image.
  587. %
  588. %
  589. */
  590. void CloseImage(image)
  591. Image
  592. X  *image;
  593. {
  594. X  /*
  595. X    Close image file.
  596. X  */
  597. X  if (image->file != (FILE *) NULL)
  598. X    {
  599. X      image->status=ferror(image->file);
  600. X      if (((int) strlen(image->filename) < 3) ||
  601. X          ((strcmp(image->filename+strlen(image->filename)-2,".gz") != 0) &&
  602. X           (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0)))
  603. X        (void) fclose(image->file);
  604. X      else
  605. X        (void) pclose(image->file);
  606. X    }
  607. X  image->file=(FILE *) NULL;
  608. }
  609. X
  610. /*
  611. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  612. %                                                                             %
  613. %                                                                             %
  614. %                                                                             %
  615. %   C o m p r e s s C o l o r m a p                                           %
  616. %                                                                             %
  617. %                                                                             %
  618. %                                                                             %
  619. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  620. %
  621. %  Function CompressColormap compresses an image colormap removing any
  622. %  unused color entries.
  623. %
  624. %  The format of the CompressColormap routine is:
  625. %
  626. %      CompressColormap(image)
  627. %
  628. %  A description of each parameter follows:
  629. %
  630. %    o image: The address of a structure of type Image.
  631. %
  632. %
  633. */
  634. void CompressColormap(image)
  635. Image
  636. X  *image;
  637. {
  638. X  ColorPacket
  639. X    *colormap;
  640. X
  641. X  int
  642. X    number_colors;
  643. X
  644. X  register int
  645. X    i;
  646. X
  647. X  register RunlengthPacket
  648. X    *p;
  649. X
  650. X  register unsigned short
  651. X    index;
  652. X
  653. X  /*
  654. X    Determine if colormap can be compressed.
  655. X  */
  656. X  if (image->class != PseudoClass)
  657. X    return;
  658. X  number_colors=image->colors;
  659. X  for (i=0; i < image->colors; i++)
  660. X    image->colormap[i].flags=False;
  661. X  image->colors=0;
  662. X  p=image->pixels;
  663. X  for (i=0; i < image->packets; i++)
  664. X  {
  665. X    if (!image->colormap[p->index].flags)
  666. X      {
  667. X        image->colormap[p->index].index=image->colors;
  668. X        image->colormap[p->index].flags=True;
  669. X        image->colors++;
  670. X      }
  671. X    p++;
  672. X  }
  673. X  if (image->colors == number_colors)
  674. X    return;  /* no unused entries */
  675. X  /*
  676. X    Compress colormap.
  677. X  */
  678. X  colormap=(ColorPacket *) malloc(image->colors*sizeof(ColorPacket));
  679. X  if (colormap == (ColorPacket *) NULL)
  680. X    {
  681. X      Warning("unable to compress colormap","memory allocation error");
  682. X      image->colors=number_colors;
  683. X      return;
  684. X    }
  685. X  for (i=0; i < number_colors; i++)
  686. X    if (image->colormap[i].flags)
  687. X      {
  688. X        index=image->colormap[i].index;
  689. X        colormap[index].red=image->colormap[i].red;
  690. X        colormap[index].green=image->colormap[i].green;
  691. X        colormap[index].blue=image->colormap[i].blue;
  692. X      }
  693. X  /*
  694. X    Remap pixels.
  695. X  */
  696. X  p=image->pixels;
  697. X  for (i=0; i < image->packets; i++)
  698. X  {
  699. X    p->index=image->colormap[p->index].index;
  700. X    p++;
  701. X  }
  702. X  (void) free((char *) image->colormap);
  703. X  image->colormap=colormap;
  704. }
  705. X
  706. /*
  707. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  708. %                                                                             %
  709. %                                                                             %
  710. %                                                                             %
  711. %   C o m p r e s s I m a g e                                                 %
  712. %                                                                             %
  713. %                                                                             %
  714. %                                                                             %
  715. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  716. %
  717. %  Function CompressImage compresses an image to the minimum number of
  718. %  runlength-encoded packets.
  719. %
  720. %  The format of the CompressImage routine is:
  721. %
  722. %      CompressImage(image)
  723. %
  724. %  A description of each parameter follows:
  725. %
  726. %    o image: The address of a structure of type Image.
  727. %
  728. %
  729. */
  730. void CompressImage(image)
  731. Image
  732. X  *image;
  733. {
  734. X  register int
  735. X    i;
  736. X
  737. X  register RunlengthPacket
  738. X    *p,
  739. X    *q;
  740. X
  741. X  /*
  742. X    Compress image.
  743. X  */
  744. X  p=image->pixels;
  745. X  image->runlength=p->length+1;
  746. X  image->packets=0;
  747. X  q=image->pixels;
  748. X  q->length=MaxRunlength;
  749. X  if (image->alpha)
  750. X    for (i=0; i < (image->columns*image->rows); i++)
  751. X    {
  752. X      if (image->runlength != 0)
  753. X        image->runlength--;
  754. X      else
  755. X        {
  756. X          p++;
  757. X          image->runlength=p->length;
  758. X        }
  759. X      if ((p->red == q->red) && (p->green == q->green) &&
  760. X          (p->blue == q->blue) && (p->index == q->index) &&
  761. X          (q->length < MaxRunlength))
  762. X        q->length++;
  763. X      else
  764. X        {
  765. X          if (image->packets > 0)
  766. X            q++;
  767. X          image->packets++;
  768. X          *q=(*p);
  769. X          q->length=0;
  770. X        }
  771. X    }
  772. X  else
  773. X    for (i=0; i < (image->columns*image->rows); i++)
  774. X    {
  775. X      if (image->runlength != 0)
  776. X        image->runlength--;
  777. X      else
  778. X        {
  779. X          p++;
  780. X          image->runlength=p->length;
  781. X        }
  782. X      if ((p->red == q->red) && (p->green == q->green) &&
  783. X          (p->blue == q->blue) && (q->length < MaxRunlength))
  784. X        q->length++;
  785. X      else
  786. X        {
  787. X          if (image->packets > 0)
  788. X            q++;
  789. X          image->packets++;
  790. X          *q=(*p);
  791. X          q->length=0;
  792. X        }
  793. X    }
  794. X  image->pixels=(RunlengthPacket *) realloc((char *) image->pixels,
  795. X    (unsigned int) image->packets*sizeof(RunlengthPacket));
  796. X  /*
  797. X    Runlength-encode only if it consumes less memory than no compression.
  798. X  */
  799. X  if (image->compression == RunlengthEncodedCompression)
  800. X    if (image->class == DirectClass)
  801. X      {
  802. X        if (image->packets >= ((image->columns*image->rows*3) >> 2))
  803. X          image->compression=NoCompression;
  804. X      }
  805. X    else
  806. X      if (image->packets >= ((image->columns*image->rows) >> 1))
  807. X        image->compression=NoCompression;
  808. }
  809. X
  810. /*
  811. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  812. %                                                                             %
  813. %                                                                             %
  814. %                                                                             %
  815. %   C o m p o s i t e I m a g e                                               %
  816. %                                                                             %
  817. %                                                                             %
  818. %                                                                             %
  819. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  820. %
  821. %  Function CompositeImage returns the second image composited onto the
  822. %  first at the specified offsets.
  823. %
  824. %  The format of the CompositeImage routine is:
  825. %
  826. %      CompositeImage(image,compose,composite_image,x_offset,y_offset)
  827. %
  828. %  A description of each parameter follows:
  829. %
  830. %    o image: The address of a structure of type Image.
  831. %
  832. %    o compose: Specifies an image composite operator.
  833. %
  834. %    o composite_image: The address of a structure of type Image.
  835. %
  836. %    o x_offset: An integer that specifies the column offset of the composited
  837. %      image.
  838. %
  839. %    o y_offset: An integer that specifies the row offset of the composited
  840. %      image.
  841. %
  842. %
  843. */
  844. void CompositeImage(image,compose,composite_image,x_offset,y_offset)
  845. Image
  846. X  *image;
  847. X
  848. unsigned int
  849. X  compose;
  850. X
  851. Image
  852. X  *composite_image;
  853. X
  854. int
  855. X  x_offset,
  856. X  y_offset;
  857. {
  858. X  int
  859. X    blue,
  860. X    green,
  861. X    red;
  862. X
  863. X  register int
  864. X    i,
  865. X    x,
  866. X    y;
  867. X
  868. X  register RunlengthPacket
  869. X    *p,
  870. X    *q;
  871. X
  872. X  register short
  873. X    index;
  874. X
  875. X  /*
  876. X    Check composite geometry.
  877. X  */
  878. X  if (((x_offset+(int) image->columns) < 0) ||
  879. X      ((y_offset+(int) image->rows) < 0) ||
  880. X      (x_offset > (int) image->columns) || (y_offset > (int) image->rows))
  881. X    {
  882. X      Warning("unable to composite image","geometry does not contain image");
  883. X      return;
  884. X    }
  885. X  /*
  886. X    Image must be uncompressed.
  887. X  */
  888. X  if (!UncompressImage(image))
  889. X    return;
  890. X  if (compose == ReplaceCompositeOp)
  891. X    {
  892. X      /*
  893. X        Promote image to DirectClass if colormaps differ.
  894. X      */
  895. X      if (image->class == PseudoClass)
  896. X        if (composite_image->class == DirectClass)
  897. X          image->class=DirectClass;
  898. X        else
  899. X          {
  900. X            if (image->signature == (char *) NULL)
  901. X              ColormapSignature(image);
  902. X            if (composite_image->signature == (char *) NULL)
  903. X              ColormapSignature(composite_image);
  904. X            if (strcmp(image->signature,composite_image->signature) != 0)
  905. X              image->class=DirectClass;
  906. X          }
  907. X    }
  908. X  else
  909. X    {
  910. X      /*
  911. X        Initialize image alpha data.
  912. X      */
  913. X      if (!image->alpha)
  914. X        {
  915. X          q=image->pixels;
  916. X          for (i=0; i < image->packets; i++)
  917. X          {
  918. X            q->index=MaxRGB;
  919. X            q++;
  920. X          }
  921. X          image->class=DirectClass;
  922. X          image->alpha=True;
  923. X        }
  924. X      if (!composite_image->alpha)
  925. X        {
  926. X          p=composite_image->pixels;
  927. X          red=(p+composite_image->packets-1)->red;
  928. X          green=(p+composite_image->packets-1)->green;
  929. X          blue=(p+composite_image->packets-1)->blue;
  930. X          if ((p->red != red) || (p->green != green) || (p->blue != blue))
  931. X            for (i=0; i < composite_image->packets; i++)
  932. X            {
  933. X              p->index=MaxRGB;
  934. X              p++;
  935. X            }
  936. X          else
  937. X            for (i=0; i < composite_image->packets; i++)
  938. X            {
  939. X              p->index=MaxRGB;
  940. X              if ((p->red == red) && (p->green == green) && (p->blue == blue))
  941. X                p->index=0;
  942. X              p++;
  943. X            }
  944. X          composite_image->class=DirectClass;
  945. X          composite_image->alpha=True;
  946. X        }
  947. X    }
  948. X  /*
  949. X    Initialize composited image.
  950. X  */
  951. X  p=composite_image->pixels;
  952. X  composite_image->runlength=p->length+1;
  953. X  for (y=0; y < composite_image->rows; y++)
  954. X  {
  955. X    if (((y_offset+y) < 0) || ((y_offset+y) >= image->rows))
  956. X      continue;
  957. X    q=image->pixels+(y_offset+y)*image->columns+x_offset;
  958. X    for (x=0; x < composite_image->columns; x++)
  959. X    {
  960. X      if (composite_image->runlength != 0)
  961. X        composite_image->runlength--;
  962. X      else
  963. X        {
  964. X          p++;
  965. X          composite_image->runlength=p->length;
  966. X        }
  967. X      if (((x_offset+x) < 0) || ((x_offset+x) >= image->columns))
  968. X        {
  969. X          q++;
  970. X          continue;
  971. X        }
  972. X      switch (compose)
  973. X      {
  974. X        case OverCompositeOp:
  975. X        default:
  976. X        {
  977. X          if (p->index == 0)
  978. X            {
  979. X              red=q->red;
  980. X              green=q->green;
  981. X              blue=q->blue;
  982. X              index=q->index;
  983. X            }
  984. X          else
  985. X            if (p->index == MaxRGB)
  986. X              {
  987. X                red=p->red;
  988. X                green=p->green;
  989. X                blue=p->blue;
  990. X                index=p->index;
  991. X              }
  992. X            else
  993. X              {
  994. X                red=(int) (p->red*MaxRGB+q->red*(MaxRGB-p->index))/MaxRGB;
  995. X                green=(int) (p->green*MaxRGB+q->green*(MaxRGB-p->index))/MaxRGB;
  996. X                blue=(int) (p->blue*MaxRGB+q->blue*(MaxRGB-p->index))/MaxRGB;
  997. X                index=(int) (p->index*MaxRGB+q->index*(MaxRGB-p->index))/MaxRGB;
  998. X              }
  999. X          break;
  1000. X        }
  1001. X        case InCompositeOp:
  1002. X        {
  1003. X          red=(int) (p->red*q->index)/MaxRGB;
  1004. X          green=(int) (p->green*q->index)/MaxRGB;
  1005. X          blue=(int) (p->blue*q->index)/MaxRGB;
  1006. X          index=(int) (p->index*q->index)/MaxRGB;
  1007. X          break;
  1008. X        }
  1009. X        case OutCompositeOp:
  1010. X        {
  1011. X          red=(int) (p->red*(MaxRGB-q->index))/MaxRGB;
  1012. X          green=(int) (p->green*(MaxRGB-q->index))/MaxRGB;
  1013. X          blue=(int) (p->blue*(MaxRGB-q->index))/MaxRGB;
  1014. X          index=(int) (p->index*(MaxRGB-q->index))/MaxRGB;
  1015. X          break;
  1016. X        }
  1017. X        case AtopCompositeOp:
  1018. X        {
  1019. X          red=(int) (p->red*q->index+q->red*(MaxRGB-p->index))/MaxRGB;
  1020. X          green=(int) (p->green*q->index+q->green*(MaxRGB-p->index))/MaxRGB;
  1021. X          blue=(int) (p->blue*q->index+q->blue*(MaxRGB-p->index))/MaxRGB;
  1022. X          index=(int) (p->index*q->index+q->index*(MaxRGB-p->index))/MaxRGB;
  1023. X          break;
  1024. X        }
  1025. X        case XorCompositeOp:
  1026. X        {
  1027. X          red=(int) (p->red*(MaxRGB-q->index)+q->red*(MaxRGB-p->index))/MaxRGB;
  1028. X          green=(int) (p->green*(MaxRGB-q->index)+q->green*(MaxRGB-p->index))/
  1029. X            MaxRGB;
  1030. X          blue=(int) (p->blue*(MaxRGB-q->index)+q->blue*(MaxRGB-p->index))/
  1031. X            MaxRGB;
  1032. X          index=(int) (p->index*(MaxRGB-q->index)+q->index*(MaxRGB-p->index))/
  1033. X            MaxRGB;
  1034. X          break;
  1035. X        }
  1036. X        case PlusCompositeOp:
  1037. X        {
  1038. X          red=(int) p->red+(int) q->red;
  1039. X          green=(int) p->green+(int) q->green;
  1040. X          blue=(int) p->blue+(int) q->blue;
  1041. X          index=(int) p->index+(int) q->index;
  1042. X          break;
  1043. X        }
  1044. X        case MinusCompositeOp:
  1045. X        {
  1046. X          red=(int) p->red-(int) q->red;
  1047. X          green=(int) p->green-(int) q->green;
  1048. X          blue=(int) p->blue-(int) q->blue;
  1049. X          index=255;
  1050. X          break;
  1051. X        }
  1052. X        case AddCompositeOp:
  1053. X        {
  1054. X          red=(int) p->red+(int) q->red;
  1055. X          if (red > MaxRGB)
  1056. X            red-=(MaxRGB+1);
  1057. X          green=(int) p->green+(int) q->green;
  1058. X          if (green > MaxRGB)
  1059. X            green-=(MaxRGB+1);
  1060. X          blue=(int) p->blue+(int) q->blue;
  1061. X          if (blue > MaxRGB)
  1062. X            blue-=(MaxRGB+1);
  1063. X          index=(int) p->index+(int) q->index;
  1064. X          if (index > MaxRGB)
  1065. X            index-=(MaxRGB+1);
  1066. X          break;
  1067. X        }
  1068. X        case SubtractCompositeOp:
  1069. X        {
  1070. X          red=(int) p->red-(int) q->red;
  1071. X          if (red < 0)
  1072. X            red+=(MaxRGB+1);
  1073. X          green=(int) p->green-(int) q->green;
  1074. X          if (green < 0)
  1075. X            green+=(MaxRGB+1);
  1076. X          blue=(int) p->blue-(int) q->blue;
  1077. X          if (blue < 0)
  1078. X            blue+=(MaxRGB+1);
  1079. X          index=(int) p->index-(int) q->index;
  1080. X          if (index < 0)
  1081. X            index+=(MaxRGB+1);
  1082. X          break;
  1083. X        }
  1084. X        case DifferenceCompositeOp:
  1085. X        {
  1086. X          red=AbsoluteValue((int) p->red-(int) q->red);
  1087. X          green=AbsoluteValue((int) p->green-(int) q->green);
  1088. X          blue=AbsoluteValue((int) p->blue-(int) q->blue);
  1089. X          index=AbsoluteValue((int) p->index-(int) q->index);
  1090. X          break;
  1091. X        }
  1092. X        case ReplaceCompositeOp:
  1093. X        {
  1094. X          red=p->red;
  1095. X          green=p->green;
  1096. X          blue=p->blue;
  1097. X          index=p->index;
  1098. X          break;
  1099. X        }
  1100. X      }
  1101. X      if (red > MaxRGB)
  1102. X        q->red=MaxRGB;
  1103. X      else
  1104. X        if (red < 0)
  1105. X          q->red=0;
  1106. X        else
  1107. X          q->red=red;
  1108. X      if (green > MaxRGB)
  1109. X        q->green=MaxRGB;
  1110. X      else
  1111. X        if (green < 0)
  1112. X          q->green=0;
  1113. X        else
  1114. X          q->green=green;
  1115. X      if (blue > MaxRGB)
  1116. X        q->blue=MaxRGB;
  1117. X      else
  1118. X        if (blue < 0)
  1119. X          q->blue=0;
  1120. X        else
  1121. X          q->blue=blue;
  1122. X      if (index > 255)
  1123. X        q->index=255;
  1124. X      else
  1125. X        if (index < 0)
  1126. X          q->index=0;
  1127. X        else
  1128. X          q->index=index;
  1129. X      q->length=0;
  1130. X      q++;
  1131. X    }
  1132. X  }
  1133. }
  1134. X
  1135. /*
  1136. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1137. %                                                                             %
  1138. %                                                                             %
  1139. %                                                                             %
  1140. %   C o p y I m a g e                                                         %
  1141. %                                                                             %
  1142. %                                                                             %
  1143. %                                                                             %
  1144. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1145. %
  1146. %  Function CopyImage returns a copy of all fields of the input image.  The
  1147. %  the pixel memory is allocated but the pixel data is not copied.
  1148. %
  1149. %  The format of the CopyImage routine is:
  1150. %
  1151. %      copy_image=CopyImage(image,columns,rows,copy_pixels)
  1152. %
  1153. %  A description of each parameter follows:
  1154. %
  1155. %    o copy_image: Function CopyImage returns a pointer to the image after
  1156. %      copying.  A null image is returned if there is a memory shortage.
  1157. %
  1158. %    o image: The address of a structure of type Image.
  1159. %
  1160. %    o columns: An integer that specifies the number of columns in the copied
  1161. %      image.
  1162. %
  1163. %    o rows: An integer that specifies the number of rows in the copied
  1164. %      image.
  1165. %
  1166. %    o copy_pixels: Specifies whether the pixel data is copied.  Must be
  1167. %      either True or False;
  1168. %
  1169. %
  1170. */
  1171. Image *CopyImage(image,columns,rows,copy_pixels)
  1172. Image
  1173. X  *image;
  1174. X
  1175. unsigned int
  1176. X  columns,
  1177. X  rows,
  1178. X  copy_pixels;
  1179. {
  1180. X  Image
  1181. X    *copy_image;
  1182. X
  1183. X  register int
  1184. X    i;
  1185. X
  1186. X  /*
  1187. X    Allocate image structure.
  1188. X  */
  1189. X  copy_image=(Image *) malloc(sizeof(Image));
  1190. X  if (copy_image == (Image *) NULL)
  1191. X    return((Image *) NULL);
  1192. X  *copy_image=(*image);
  1193. X  if (image->comments != (char *) NULL)
  1194. X    {
  1195. X      /*
  1196. X        Allocate and copy the image comments.
  1197. X      */
  1198. X      copy_image->comments=(char *)
  1199. X        malloc(((strlen(image->comments)+1)*sizeof(char)));
  1200. X      if (copy_image->comments == (char *) NULL)
  1201. X        return((Image *) NULL);
  1202. X      (void) strcpy(copy_image->comments,image->comments);
  1203. X    }
  1204. X  if (image->label != (char *) NULL)
  1205. X    {
  1206. X      /*
  1207. X        Allocate and copy the image label.
  1208. X      */
  1209. X      copy_image->label=(char *)
  1210. X        malloc(((strlen(image->label)+1)*sizeof(char)));
  1211. X      if (copy_image->label == (char *) NULL)
  1212. X        return((Image *) NULL);
  1213. X      (void) strcpy(copy_image->label,image->label);
  1214. X    }
  1215. X  copy_image->columns=columns;
  1216. X  copy_image->rows=rows;
  1217. X  if (image->montage != (char *) NULL)
  1218. X    if ((image->columns != columns) || (image->rows != rows))
  1219. X      copy_image->montage=(char *) NULL;
  1220. X    else
  1221. X      {
  1222. X        /*
  1223. X          Allocate and copy the image montage.
  1224. X        */
  1225. X        copy_image->montage=(char *)
  1226. X          malloc(((strlen(image->montage)+1)*sizeof(char)));
  1227. X        if (copy_image->montage == (char *) NULL)
  1228. X          return((Image *) NULL);
  1229. X        (void) strcpy(copy_image->montage,image->montage);
  1230. X      }
  1231. X  if (image->directory != (char *) NULL)
  1232. X    if ((image->columns != columns) || (image->rows != rows))
  1233. X      copy_image->directory=(char *) NULL;
  1234. X    else
  1235. X      {
  1236. X        /*
  1237. X          Allocate and copy the image directory.
  1238. X        */
  1239. X        copy_image->directory=(char *)
  1240. X          malloc(((strlen(image->directory)+1)*sizeof(char)));
  1241. X        if (copy_image->directory == (char *) NULL)
  1242. X          return((Image *) NULL);
  1243. X        (void) strcpy(copy_image->directory,image->directory);
  1244. X      }
  1245. X  if (image->colormap != (ColorPacket *) NULL)
  1246. X    {
  1247. X      /*
  1248. X        Allocate and copy the image colormap.
  1249. X      */
  1250. X      copy_image->colormap=(ColorPacket *)
  1251. X        malloc(image->colors*sizeof(ColorPacket));
  1252. X      if (copy_image->colormap == (ColorPacket *) NULL)
  1253. X        return((Image *) NULL);
  1254. X      for (i=0; i < image->colors; i++)
  1255. X        copy_image->colormap[i]=image->colormap[i];
  1256. X    }
  1257. X  if (image->signature != (char *) NULL)
  1258. X    {
  1259. X      /*
  1260. X        Allocate and copy the image signature.
  1261. X      */
  1262. X      copy_image->signature=(char *)
  1263. X        malloc(((strlen(image->signature)+1)*sizeof(char)));
  1264. X      if (copy_image->signature == (char *) NULL)
  1265. X        return((Image *) NULL);
  1266. X      (void) strcpy(copy_image->signature,image->signature);
  1267. X    }
  1268. X  /*
  1269. X    Allocate the image pixels.
  1270. X  */
  1271. X  if (!copy_pixels)
  1272. X    copy_image->packets=copy_image->columns*copy_image->rows;
  1273. X  copy_image->pixels=(RunlengthPacket *)
  1274. X    malloc((unsigned int) copy_image->packets*sizeof(RunlengthPacket));
  1275. X  if (copy_image->pixels == (RunlengthPacket *) NULL)
  1276. X    return((Image *) NULL);
  1277. X  if (copy_pixels)
  1278. X    {
  1279. X      register RunlengthPacket
  1280. X        *p,
  1281. X        *q;
  1282. X
  1283. X      if ((image->columns != columns) || (image->rows != rows))
  1284. X        return((Image *) NULL);
  1285. X      /*
  1286. X        Copy the image pixels.
  1287. X      */
  1288. X      p=image->pixels;
  1289. X      q=copy_image->pixels;
  1290. X      for (i=0; i < image->packets; i++)
  1291. X      {
  1292. X        *q=(*p);
  1293. X        p++;
  1294. X        q++;
  1295. X      }
  1296. X    }
  1297. X  if (!image->orphan)
  1298. X    {
  1299. X      /*
  1300. X        Link image into image list.
  1301. X      */
  1302. X      if (copy_image->previous != (Image *) NULL)
  1303. X        copy_image->previous->next=copy_image;
  1304. X      if (copy_image->next != (Image *) NULL)
  1305. X        copy_image->next->previous=copy_image;
  1306. X    }
  1307. X  return(copy_image);
  1308. }
  1309. X
  1310. /*
  1311. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1312. %                                                                             %
  1313. %                                                                             %
  1314. %                                                                             %
  1315. %   D e s t r o y I m a g e                                                   %
  1316. %                                                                             %
  1317. %                                                                             %
  1318. %                                                                             %
  1319. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1320. %
  1321. %  Function DestroyImage deallocates memory associated with an image.
  1322. %
  1323. %  The format of the DestroyImage routine is:
  1324. %
  1325. %      DestroyImage(image)
  1326. %
  1327. %  A description of each parameter follows:
  1328. %
  1329. %    o image: The address of a structure of type Image.
  1330. %
  1331. %
  1332. */
  1333. void DestroyImage(image)
  1334. Image
  1335. X  *image;
  1336. {
  1337. X  if (image->file != (FILE *) NULL)
  1338. X    if (image->file != stdin)
  1339. X      if (((int) strlen(image->filename) < 3) ||
  1340. X          ((strcmp(image->filename+strlen(image->filename)-2,".gz") != 0) &&
  1341. X           (strcmp(image->filename+strlen(image->filename)-2,".Z") != 0)))
  1342. X        (void) fclose(image->file);
  1343. X      else
  1344. X        (void) pclose(image->file);
  1345. X  /*
  1346. X    Deallocate the image comments.
  1347. X  */
  1348. X  if (image->comments != (char *) NULL)
  1349. X    (void) free((char *) image->comments);
  1350. X  /*
  1351. X    Deallocate the image label.
  1352. X  */
  1353. X  if (image->label != (char *) NULL)
  1354. X    (void) free((char *) image->label);
  1355. X  /*
  1356. X    Deallocate the image montage directory.
  1357. X  */
  1358. X  if (image->montage != (char *) NULL)
  1359. X    (void) free((char *) image->montage);
  1360. X  if (image->directory != (char *) NULL)
  1361. X    (void) free((char *) image->directory);
  1362. X  /*
  1363. X    Deallocate the image colormap.
  1364. X  */
  1365. X  if (image->colormap != (ColorPacket *) NULL)
  1366. X    (void) free((char *) image->colormap);
  1367. X  /*
  1368. X    Deallocate the image signature.
  1369. X  */
  1370. X  if (image->signature != (char *) NULL)
  1371. X    (void) free((char *) image->signature);
  1372. X  /*
  1373. X    Deallocate the image pixels.
  1374. X  */
  1375. X  if (image->pixels != (RunlengthPacket *) NULL)
  1376. X    (void) free((char *) image->pixels);
  1377. X  if (image->packed_pixels != (unsigned char *) NULL)
  1378. X    (void) free((char *) image->packed_pixels);
  1379. X  /*
  1380. X    Deallocate the image structure.
  1381. X  */
  1382. X  (void) free((char *) image);
  1383. X  image=(Image *) NULL;
  1384. }
  1385. X
  1386. /*
  1387. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1388. %                                                                             %
  1389. %                                                                             %
  1390. %                                                                             %
  1391. %   D e s t r o y I m a g e s                                                 %
  1392. %                                                                             %
  1393. %                                                                             %
  1394. %                                                                             %
  1395. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1396. %
  1397. %  Function DestroyImages deallocates memory associated with a linked list
  1398. %  of images.
  1399. %
  1400. %  The format of the DestroyImages routine is:
  1401. %
  1402. %      DestroyImages(image)
  1403. %
  1404. %  A description of each parameter follows:
  1405. %
  1406. %    o image: The address of a structure of type Image.
  1407. %
  1408. %
  1409. */
  1410. void DestroyImages(image)
  1411. Image
  1412. X  *image;
  1413. {
  1414. X  Image
  1415. X    *next_image;
  1416. X
  1417. X  /*
  1418. X    Proceed to the top of the image list.
  1419. X  */
  1420. X  while (image->previous != (Image *) NULL)
  1421. X    image=image->previous;
  1422. X  do
  1423. X  {
  1424. X    /*
  1425. X      Destroy this image.
  1426. X    */
  1427. X    next_image=image->next;
  1428. X    DestroyImage(image);
  1429. X    image=next_image;
  1430. X  } while (image != (Image *) NULL);
  1431. }
  1432. X
  1433. /*
  1434. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1435. %                                                                             %
  1436. %                                                                             %
  1437. %     E n h a n c e I m a g e                                                 %
  1438. %                                                                             %
  1439. %                                                                             %
  1440. %                                                                             %
  1441. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1442. %
  1443. %  Function EnhanceImage creates a new image that is a copy of an existing
  1444. %  one with the noise reduced.  It allocates the memory necessary for the new
  1445. %  Image structure and returns a pointer to the new image.
  1446. %
  1447. %  EnhanceImage does a weighted average of pixels in a 5x5 cell around each
  1448. %  target pixel.  Only pixels in the 5x5 cell that are within a RGB distance
  1449. %  threshold of the target pixel are averaged.
  1450. %
  1451. %  Weights assume that the importance of neighboring pixels is inversely
  1452. %  proportional to the square of their distance from the target pixel.
  1453. %
  1454. %  The scan only processes pixels that have a full set of neighbors.  Pixels
  1455. %  in the top, bottom, left, and right pairs of rows and columns are omitted
  1456. %  from the scan.
  1457. %
  1458. %  The format of the EnhanceImage routine is:
  1459. %
  1460. %      enhanced_image=EnhanceImage(image)
  1461. %
  1462. %  A description of each parameter follows:
  1463. %
  1464. %    o enhanced_image: Function EnhanceImage returns a pointer to the image
  1465. %      after it is enhanced.  A null image is returned if there is a memory
  1466. %      shortage.
  1467. %
  1468. %    o image: The address of a structure of type Image;  returned from
  1469. %      ReadImage.
  1470. %
  1471. %
  1472. */
  1473. Image *EnhanceImage(image)
  1474. Image
  1475. X  *image;
  1476. {
  1477. #define Esum(weight) \
  1478. X  red_distance=s->red-red; \
  1479. X  green_distance=s->green-green; \
  1480. X  blue_distance=s->blue-blue; \
  1481. X  distance=red_distance*red_distance+green_distance*green_distance+ \
  1482. X    blue_distance*blue_distance; \
  1483. X  if (distance < Threshold) \
  1484. X    { \
  1485. X      total_red+=weight*(s->red); \
  1486. X      total_green+=weight*(s->green); \
  1487. X      total_blue+=weight*(s->blue); \
  1488. X      total_weight+=weight; \
  1489. X    } \
  1490. X  s++;
  1491. #define Threshold  2500
  1492. X
  1493. X  Image
  1494. X    *enhanced_image;
  1495. X
  1496. X  int
  1497. X    blue_distance,
  1498. X    green_distance,
  1499. X    red_distance;
  1500. X
  1501. X  register RunlengthPacket
  1502. X    *p,
  1503. X    *q,
  1504. X    *s,
  1505. X    *s0,
  1506. X    *s1,
  1507. X    *s2,
  1508. X    *s3,
  1509. X    *s4;
  1510. X
  1511. X  register unsigned int
  1512. X    x;
  1513. X
  1514. X  RunlengthPacket
  1515. X    *scanline;
  1516. X
  1517. X  unsigned char
  1518. X    blue,
  1519. X    green,
  1520. X    red;
  1521. X
  1522. X  unsigned int
  1523. X    y;
  1524. X
  1525. X  unsigned long
  1526. X    distance,
  1527. X    total_blue,
  1528. X    total_green,
  1529. X    total_red,
  1530. X    total_weight;
  1531. X
  1532. X  if ((image->columns < 5) || (image->rows < 5))
  1533. X    {
  1534. X      Warning("unable to enhance image","image size must exceed 4x4");
  1535. X      return((Image *) NULL);
  1536. X    }
  1537. X  /*
  1538. X    Initialize enhanced image attributes.
  1539. X  */
  1540. X  enhanced_image=CopyImage(image,image->columns,image->rows,False);
  1541. X  if (enhanced_image == (Image *) NULL)
  1542. X    {
  1543. X      Warning("unable to enhance image","memory allocation failed");
  1544. X      return((Image *) NULL);
  1545. X    }
  1546. X  enhanced_image->class=DirectClass;
  1547. X  /*
  1548. X    Allocate scan line buffer for 5 rows of the image.
  1549. X  */
  1550. X  scanline=(RunlengthPacket *) malloc(5*image->columns*sizeof(RunlengthPacket));
  1551. X  if (scanline == (RunlengthPacket *) NULL)
  1552. X    {
  1553. X      Warning("unable to enhance image","memory allocation failed");
  1554. X      DestroyImage(enhanced_image);
  1555. X      return((Image *) NULL);
  1556. X    }
  1557. X  /*
  1558. X    Read the first 4 rows of the image.
  1559. X  */
  1560. X  p=image->pixels;
  1561. X  image->runlength=p->length+1;
  1562. X  s=scanline;
  1563. X  for (x=0; x < (image->columns*4); x++)
  1564. X  {
  1565. X    if (image->runlength != 0)
  1566. X      image->runlength--;
  1567. X    else
  1568. X      {
  1569. X        p++;
  1570. X        image->runlength=p->length;
  1571. X      }
  1572. X    *s=(*p);
  1573. X    s++;
  1574. X  }
  1575. X  /*
  1576. X    Dump first 2 scanlines of image.
  1577. X  */
  1578. X  q=enhanced_image->pixels;
  1579. X  s=scanline;
  1580. X  for (x=0; x < (2*image->columns); x++)
  1581. X  {
  1582. X    *q=(*s);
  1583. X    q->length=0;
  1584. X    q++;
  1585. X    s++;
  1586. X  }
  1587. X  /*
  1588. X    Enhance each row.
  1589. X  */
  1590. X  for (y=2; y < (image->rows-2); y++)
  1591. X  {
  1592. X    /*
  1593. X      Initialize sliding window pointers.
  1594. X    */
  1595. X    s0=scanline+image->columns*((y-2) % 5);
  1596. X    s1=scanline+image->columns*((y-1) % 5);
  1597. X    s2=scanline+image->columns*(y % 5);
  1598. X    s3=scanline+image->columns*((y+1) % 5);
  1599. X    s4=scanline+image->columns*((y+2) % 5);
  1600. X    /*
  1601. X      Read another scan line.
  1602. X    */
  1603. X    s=s4;
  1604. X    for (x=0; x < image->columns; x++)
  1605. X    {
  1606. X      if (image->runlength != 0)
  1607. X        image->runlength--;
  1608. X      else
  1609. X        {
  1610. X          p++;
  1611. X          image->runlength=p->length;
  1612. X        }
  1613. X      *s=(*p);
  1614. X      s++;
  1615. X    }
  1616. X    /*
  1617. X      Transfer first 2 pixels of the scanline.
  1618. X    */
  1619. X    s=s2;
  1620. X    for (x=0; x < 2; x++)
  1621. X    {
  1622. X      *q=(*s);
  1623. X      q->length=0;
  1624. X      q++;
  1625. X      s++;
  1626. X    }
  1627. X    for (x=2; x < (image->columns-2); x++)
  1628. X    {
  1629. X      /*
  1630. X        Compute weighted average of target pixel color components.
  1631. X      */
  1632. X      total_red=0;
  1633. X      total_green=0;
  1634. X      total_blue=0;
  1635. X      total_weight=0;
  1636. X      s=s2+2;
  1637. X      red=s->red;
  1638. X      green=s->green;
  1639. X      blue=s->blue;
  1640. X      s=s0;
  1641. X      Esum(5);  Esum(8);  Esum(10); Esum(8);  Esum(5);
  1642. X      s=s1;
  1643. X      Esum(8);  Esum(20); Esum(40); Esum(20); Esum(8);
  1644. X      s=s2;
  1645. X      Esum(10); Esum(40); Esum(80); Esum(40); Esum(10);
  1646. X      s=s3;
  1647. X      Esum(8);  Esum(20); Esum(40); Esum(20); Esum(8);
  1648. X      s=s4;
  1649. X      Esum(5);  Esum(8);  Esum(10); Esum(8);  Esum(5);
  1650. X      q->red=(unsigned char) ((total_red+(total_weight >> 1)-1)/total_weight);
  1651. X      q->green=
  1652. X        (unsigned char) ((total_green+(total_weight >> 1)-1)/total_weight);
  1653. X      q->blue=(unsigned char) ((total_blue+(total_weight >> 1)-1)/total_weight);
  1654. X      q->index=0;
  1655. X      q->length=0;
  1656. X      q++;
  1657. X      s0++;
  1658. X      s1++;
  1659. X      s2++;
  1660. X      s3++;
  1661. X      s4++;
  1662. X    }
  1663. X    /*
  1664. X      Transfer last 2 pixels of the scanline.
  1665. X    */
  1666. X    s=s2;
  1667. X    for (x=0; x < 2; x++)
  1668. X    {
  1669. X      *q=(*s);
  1670. X      q->length=0;
  1671. X      q++;
  1672. X      s++;
  1673. X    }
  1674. X  }
  1675. X  /*
  1676. X    Dump last 2 scanlines of pixels.
  1677. X  */
  1678. X  s=scanline+image->columns*(y % 3);
  1679. X  for (x=0; x < (2*image->columns); x++)
  1680. SHAR_EOF
  1681. true || echo 'restore of ImageMagick/image.c failed'
  1682. fi
  1683. echo 'End of ImageMagick part 27'
  1684. echo 'File ImageMagick/image.c is continued in part 28'
  1685. echo 28 > _shar_seq_.tmp
  1686. exit 0
  1687.  
  1688. exit 0 # Just in case...
  1689. -- 
  1690.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1691. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  1692.  "It's intuitively obvious to the |
  1693.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1694.