home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume34 / imagemagick / part08 < prev    next >
Encoding:
Text File  |  1992-12-14  |  57.0 KB  |  1,643 lines

  1. Newsgroups: comp.sources.misc
  2. From: cristy@eplrx7.es.duPont.com (John Cristy)
  3. Subject:  v34i036:  imagemagick - X11 image processing and display v2.2, Part08/26
  4. Message-ID: <1992Dec13.202750.9650@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4741345e10680ae21b1746a8b2adcdff
  6. Date: Sun, 13 Dec 1992 20:27:50 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: cristy@eplrx7.es.duPont.com (John Cristy)
  10. Posting-number: Volume 34, Issue 36
  11. Archive-name: imagemagick/part08
  12. Environment: UNIX, VMS, X11, SGI, DEC, Cray, Sun, Vax
  13.  
  14. #!/bin/sh
  15. # this is Part.08 (part 8 of a multipart archive)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file ImageMagick/import.c continued
  18. #
  19. if test ! -r _shar_seq_.tmp; then
  20.     echo 'Please unpack part 1 first!'
  21.     exit 1
  22. fi
  23. (read Scheck
  24.  if test "$Scheck" != 8; then
  25.     echo Please unpack part "$Scheck" next!
  26.     exit 1
  27.  else
  28.     exit 0
  29.  fi
  30. ) < _shar_seq_.tmp || exit 1
  31. if test ! -f _shar_wnt_.tmp; then
  32.     echo 'x - still skipping ImageMagick/import.c'
  33. else
  34. echo 'x - continuing file ImageMagick/import.c'
  35. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/import.c' &&
  36. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  37. %                                                                             %
  38. %                                                                             %
  39. %                                                                             %
  40. %                 IIIII  M   M  PPPP    OOO   RRRR    TTTTT                   %
  41. %                   I    MM MM  P   P  O   O  R   R     T                     %
  42. %                   I    M M M  PPPP   O   O  RRRR      T                     %
  43. %                   I    M   M  P      O   O  R R       T                     %
  44. %                 IIIII  M   M  P       OOO   R  R      T                     %
  45. %                                                                             %
  46. %                                                                             %
  47. %             Import X11 image to a machine independent format.               %
  48. %                                                                             %
  49. %                                                                             %
  50. %                                                                             %
  51. %                           Software Design                                   %
  52. %                             John Cristy                                     %
  53. %                              July 1992                                      %
  54. %                                                                             %
  55. %                                                                             %
  56. %  Copyright 1992 E. I. du Pont de Nemours & Company                          %
  57. %                                                                             %
  58. %  Permission to use, copy, modify, distribute, and sell this software and    %
  59. %  its documentation for any purpose is hereby granted without fee,           %
  60. %  provided that the above Copyright notice appear in all copies and that     %
  61. %  both that Copyright notice and this permission notice appear in            %
  62. %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
  63. %  & Company not be used in advertising or publicity pertaining to            %
  64. %  distribution of the software without specific, written prior               %
  65. %  permission.  E. I. du Pont de Nemours & Company makes no representations   %
  66. %  about the suitability of this software for any purpose.  It is provided    %
  67. %  "as is" without express or implied warranty.                               %
  68. %                                                                             %
  69. %  E. I. du Pont de Nemours & Company disclaims all warranties with regard    %
  70. %  to this software, including all implied warranties of merchantability      %
  71. %  and fitness, in no event shall E. I. du Pont de Nemours & Company be       %
  72. %  liable for any special, indirect or consequential damages or any           %
  73. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  74. %  in an action of contract, negligence or other tortious action, arising     %
  75. %  out of or in connection with the use or performance of this software.      %
  76. %                                                                             %
  77. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  78. %
  79. %  Import is an X Window System window dumping utility.  Import allows X
  80. %  users to store window images in a specially formatted dump file.  This
  81. %  file can then be read by the Display utility for redisplay, printing,
  82. %  editing, formatting, archiving, image processing, etc.  The target
  83. %  window can be specified by id or name or be selected by clicking the
  84. %  mouse in the desired window.  The keyboard bell is rung once at the
  85. %  beginning of the dump and twice when the dump is completed.
  86. %
  87. %  The import program command syntax is:
  88. %
  89. %  Usage: import [options ...] file
  90. %
  91. %  Where options include:
  92. %    -border          include image borders in the output image
  93. %    -compress type   RunlengthEncoded or QEncoded
  94. %    -delay seconds   pause before selecting target window
  95. %    -display server  X server to contact
  96. %    -frame           include window manager frame
  97. %    -monochrome      transform image to black and white
  98. %    -scene value     image scene number
  99. %    -screen          select image from root window
  100. %    -verbose         print detailed information about the image
  101. %    -window id       select window with this id or name
  102. %
  103. %  Change '-' to '+' in any option above to reverse its effect.
  104. %  For example, +frame means do not window manager frame.
  105. %
  106. %  By default, 'file' is written in the MIFF image format.  To specify
  107. %  a particular image format, precede the filename with an image format
  108. %  name and a colon (i.e. mtv:image) or specify the image type as the
  109. %  filename suffix (i.e. image.mtv).  Specify 'file' as '-' for standard
  110. %  input or output.
  111. %
  112. %
  113. */
  114. X
  115. /*
  116. X  Include declarations.
  117. */
  118. #include "display.h"
  119. #include "image.h"
  120. #include "alien.h"
  121. #include "X.h"
  122. X
  123. /*
  124. X  Global declarations.
  125. */
  126. char
  127. X  *application_name;
  128. X
  129. /*
  130. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  131. %                                                                             %
  132. %                                                                             %
  133. %                                                                             %
  134. %   E r r o r                                                                 %
  135. %                                                                             %
  136. %                                                                             %
  137. %                                                                             %
  138. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  139. %
  140. %  Function Error displays an error message and then terminates the program.
  141. %
  142. %  The format of the Error routine is:
  143. %
  144. %      Error(message,qualifier)
  145. %
  146. %  A description of each parameter follows:
  147. %
  148. %    o message: Specifies the message to display before terminating the
  149. %      program.
  150. %
  151. %    o qualifier: Specifies any qualifier to the message.
  152. %
  153. %
  154. */
  155. void Error(message,qualifier)
  156. char
  157. X  *message,
  158. X  *qualifier;
  159. {
  160. X  (void) fprintf(stderr,"%s: %s",application_name,message);
  161. X  if (qualifier != (char *) NULL)
  162. X    (void) fprintf(stderr," (%s)",qualifier);
  163. X  (void) fprintf(stderr,".\n");
  164. X  exit(1);
  165. }
  166. X
  167. /*
  168. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  169. %                                                                             %
  170. %                                                                             %
  171. %                                                                             %
  172. %   U s a g e                                                                 %
  173. %                                                                             %
  174. %                                                                             %
  175. %                                                                             %
  176. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  177. %
  178. %  Procedure Usage displays the program usage;
  179. %
  180. %  The format of the Usage routine is:
  181. %
  182. %      Usage()
  183. %
  184. %
  185. */
  186. static void Usage()
  187. {
  188. X  char
  189. X    **p;
  190. X
  191. X  static char
  192. X    *options[]=
  193. X    {
  194. X      "-border          include image borders in the output image",
  195. X      "-compress type   RunlengthEncoded or QEncoded",
  196. X      "-delay seconds   pause before selecting target window",
  197. X      "-display server  X server to contact",
  198. X      "-frame           include window manager frame",
  199. X      "-monochrome      transform image to black and white",
  200. X      "-scene value     image scene number",
  201. X      "-screen          select image from root window",
  202. X      "-verbose         print detailed information about the image",
  203. X      "-window id       select window with this id or name",
  204. X      (char *) NULL
  205. X    };
  206. X  (void) fprintf(stderr,"Usage: %s [options ...] file\n",application_name);
  207. X  (void) fprintf(stderr,"\nWhere options include:\n");
  208. X  for (p=options; *p != (char *) NULL; p++)
  209. X    (void) fprintf(stderr,"  %s\n",*p);
  210. X  (void) fprintf(stderr,
  211. X    "\nChange '-' to '+' in any option above to reverse its effect.\n");
  212. X  (void) fprintf(stderr,
  213. X    "For example, +frame means do not include window manager frame.\n");
  214. X  (void) fprintf(stderr,
  215. X  "\nBy default, 'file' is written in the MIFF image format.  To specify a\n");
  216. X  (void) fprintf(stderr,
  217. X    "particular image format, precede the filename with an image format\n");
  218. X  (void) fprintf(stderr,
  219. X    "name and a colon (i.e. mtv:image) or specify the image type as the\n");
  220. X  (void) fprintf(stderr,
  221. X    "filename suffix (i.e. image.mtv).  Specify 'file' as '-' for standard\n");
  222. X  (void) fprintf(stderr,"input or output.\n");
  223. X  exit(1);
  224. }
  225. X
  226. /*
  227. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  228. %                                                                             %
  229. %                                                                             %
  230. %                                                                             %
  231. %    M a i n                                                                  %
  232. %                                                                             %
  233. %                                                                             %
  234. %                                                                             %
  235. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  236. %
  237. %
  238. */
  239. int main(argc,argv)
  240. int
  241. X  argc;
  242. X
  243. char
  244. X  *argv[];
  245. {
  246. X  char
  247. X    *filename,
  248. X    *option,
  249. X    *resource_value,
  250. X    *server_name,
  251. X    *target_window;
  252. X
  253. X  Display
  254. X    *display;
  255. X
  256. X  Image
  257. X    *image;
  258. X
  259. X  int
  260. X    i,
  261. X    x;
  262. X
  263. X  time_t
  264. X    start_time;
  265. X
  266. X  unsigned int
  267. X    borders,
  268. X    compression,
  269. X    frame,
  270. X    scene,
  271. X    screen,
  272. X    verbose;
  273. X
  274. X  XResourceInfo
  275. X    resource_info;
  276. X
  277. X  XrmDatabase
  278. X    resource_database,
  279. X    server_database;
  280. X
  281. X  /*
  282. X    Display usage profile if there are no command line arguments.
  283. X  */
  284. X  application_name=(*argv);
  285. X  if (argc < 2)
  286. X    Usage();
  287. X  /*
  288. X    Connect to X server.
  289. X  */
  290. X  server_name=(char *) NULL;
  291. X  for (i=1; i < argc; i++)
  292. X  {
  293. X    /*
  294. X      Check command line for server name.
  295. X    */
  296. X    option=argv[i];
  297. X    if (((int) strlen(option) > 1) && ((*option == '-') || (*option == '+')))
  298. X      if (strncmp("dis",option+1,3) == 0)
  299. X        {
  300. X          /*
  301. X            User specified server name.
  302. X          */
  303. X          i++;
  304. X          if (i == argc)
  305. X            Error("missing server name on -display",(char *) NULL);
  306. X          server_name=argv[i];
  307. X          break;
  308. X        }
  309. X  }
  310. X  display=XOpenDisplay(server_name);
  311. X  if (display == (Display *) NULL)
  312. X    Error("unable to connect to X server",XDisplayName(server_name));
  313. X  /*
  314. X    Set our forgiving error handler.
  315. X  */
  316. X  XSetErrorHandler(XError);
  317. X  /*
  318. X    Initialize resource database.
  319. X  */
  320. X  XrmInitialize();
  321. X  resource_database=XrmGetDatabase(display);
  322. X  resource_value=XResourceManagerString(display);
  323. X  if (resource_value == (char *) NULL)
  324. X    resource_value="";
  325. X  server_database=XrmGetStringDatabase(resource_value);
  326. X  XrmMergeDatabases(server_database,&resource_database);
  327. X  /*
  328. X    Get user defaults from X resource database.
  329. X  */
  330. X  XGetResourceInfo(resource_database,application_name,&resource_info);
  331. X  resource_value=XGetResource(resource_database,application_name,"borders",
  332. X    (char *) NULL,"False");
  333. X  borders=IsTrue(resource_value);
  334. X  resource_value=XGetResource(resource_database,application_name,
  335. X    "compression",(char *) NULL,"Runlength");
  336. X  if (Latin1Compare("qencoded",resource_value) == 0)
  337. X    compression=QEncodedCompression;
  338. X  else
  339. X    compression=RunlengthEncodedCompression;
  340. X  resource_value=XGetResource(resource_database,application_name,"frame",
  341. X    (char *) NULL,"False");
  342. X  frame=IsTrue(resource_value);
  343. X  resource_value=XGetResource(resource_database,application_name,"scene",
  344. X    (char *) NULL,"0");
  345. X  scene=atoi(resource_value);
  346. X  resource_value=XGetResource(resource_database,application_name,"screen",
  347. X    (char *) NULL,"False");
  348. X  screen=IsTrue(resource_value);
  349. X  resource_value=XGetResource(resource_database,application_name,"verbose",
  350. X    (char *) NULL,"False");
  351. X  verbose=IsTrue(resource_value);
  352. X  /*
  353. X    Check command syntax.
  354. X  */
  355. X  filename=(char *) NULL;
  356. X  target_window=(char *) NULL;
  357. X  for (i=1; i < argc; i++)
  358. X  {
  359. X    option=argv[i];
  360. X    if (((int) strlen(option) < 2) || ((*option != '-') && (*option != '+')))
  361. X      filename=argv[i];
  362. X    else
  363. X      switch(*(option+1))
  364. X      {
  365. X        case 'b':
  366. X        {
  367. X          borders=(*option == '-');
  368. X          break;
  369. X        }
  370. X        case 'c':
  371. X        {
  372. X          compression=NoCompression;
  373. X          if (*option == '-')
  374. X            {
  375. X              i++;
  376. X              if (i == argc)
  377. X                Error("missing type on -compress",(char *) NULL);
  378. X              if ((*argv[i] == 'R') || (*argv[i] == 'r'))
  379. X                compression=RunlengthEncodedCompression;
  380. X              else
  381. X                if ((*argv[i] == 'Q') || (*argv[i] == 'q'))
  382. X                  compression=QEncodedCompression;
  383. X                else
  384. X                  Error("invalid compression type on -compress",(char *) NULL);
  385. X            }
  386. X          break;
  387. X        }
  388. X        case 'd':
  389. X        {
  390. X          if (strncmp("delay",option+1,2) == 0)
  391. X            {
  392. X              resource_info.delay=0;
  393. X              if (*option == '-')
  394. X                {
  395. X                  i++;
  396. X                  if ((i == argc) || !sscanf(argv[i],"%d",&x))
  397. X                    Error("missing seconds on -delay",(char *) NULL);
  398. X                  resource_info.delay=atoi(argv[i]);
  399. X                }
  400. X              break;
  401. X            }
  402. X          if (strncmp("display",option+1,3) == 0)
  403. X            {
  404. X              server_name=(char *) NULL;
  405. X              if (*option == '-')
  406. X                {
  407. X                  i++;
  408. X                  if (i == argc)
  409. X                    Error("missing server name on -display",(char *) NULL);
  410. X                  server_name=argv[i];
  411. X                }
  412. X              break;
  413. X            }
  414. X          Error("unrecognized option",option);
  415. X          break;
  416. X        }
  417. X        case 'h':
  418. X        {
  419. X          Usage();
  420. X          break;
  421. X        }
  422. X        case 'f':
  423. X        {
  424. X          frame=(*option == '-');
  425. X          break;
  426. X        }
  427. X        case 'm':
  428. X        {
  429. X          resource_info.monochrome=(*option == '-');
  430. X          break;
  431. X        }
  432. X        case 's':
  433. X        {
  434. X          if (strncmp("scene",option+1,4) == 0)
  435. X            {
  436. X              i++;
  437. X              if ((i == argc) || !sscanf(argv[i],"%d",&x))
  438. X                Error("missing scene on -scene",(char *) NULL);
  439. X              scene=atoi(argv[i]);
  440. X              break;
  441. X            }
  442. X          if (strncmp("screen",option+1,4) == 0)
  443. X            {
  444. X              screen=(*option == '-');
  445. X              break;
  446. X            }
  447. X          Error("unrecognized option",option);
  448. X          break;
  449. X        }
  450. X        case 'w':
  451. X        {
  452. X          i++;
  453. X          if (i == argc)
  454. X            Error("missing id, name, or 'root' on -window",(char *) NULL);
  455. X          target_window=argv[i];
  456. X          break;
  457. X        }
  458. X        case 'v':
  459. X        {
  460. X          verbose=(*option == '-');
  461. X          break;
  462. X        }
  463. X        default:
  464. X        {
  465. X          Error("unrecognized option",option);
  466. X          break;
  467. X        }
  468. X      }
  469. X  }
  470. X  if (filename == (char *) NULL)
  471. X    Error("missing an image file name",(char *) NULL);
  472. X  /*
  473. X    Read image from X server.
  474. X  */
  475. X  if (resource_info.delay > 0)
  476. X    (void) sleep(resource_info.delay);
  477. X  start_time=time((time_t *) 0);
  478. X  image=ReadXImage(target_window,server_name,frame,screen,borders);
  479. X  if (image == (Image *) NULL)
  480. X    exit(1);
  481. X  image->scene=scene;
  482. X  if (resource_info.monochrome)
  483. X    QuantizeImage(image,2,8,False,GRAYColorspace,True);
  484. X  if (compression != UndefinedCompression)
  485. X    image->compression=compression;
  486. X  (void) strcpy(image->filename,filename);
  487. X  (void) WriteAlienImage(image);
  488. X  if (verbose)
  489. X    {
  490. X      /*
  491. X        Display detailed info about the image.
  492. X      */
  493. X      if (image->class == DirectClass)
  494. X        image->colors=NumberColors(image);
  495. X      (void) fprintf(stderr,"[%u] %s %ux%u",image->scene,image->filename,
  496. X        image->columns,image->rows);
  497. X      if (image->class == DirectClass)
  498. X        (void) fprintf(stderr," DirectClass ");
  499. X      else
  500. X        (void) fprintf(stderr," PseudoClass ");
  501. X      (void) fprintf(stderr,"%dc %s %ds\n",image->colors,image->magick,
  502. X        time((time_t *) 0)-start_time+1);
  503. X    }
  504. X  DestroyImage(image);
  505. X  XCloseDisplay(display);
  506. X  return(False);
  507. }
  508. SHAR_EOF
  509. echo 'File ImageMagick/import.c is complete' &&
  510. chmod 0644 ImageMagick/import.c ||
  511. echo 'restore of ImageMagick/import.c failed'
  512. Wc_c="`wc -c < 'ImageMagick/import.c'`"
  513. test 16580 -eq "$Wc_c" ||
  514.     echo 'ImageMagick/import.c: original size 16580, current size' "$Wc_c"
  515. rm -f _shar_wnt_.tmp
  516. fi
  517. # ============= ImageMagick/import.man ==============
  518. if test -f 'ImageMagick/import.man' -a X"$1" != X"-c"; then
  519.     echo 'x - skipping ImageMagick/import.man (File already exists)'
  520.     rm -f _shar_wnt_.tmp
  521. else
  522. > _shar_wnt_.tmp
  523. echo 'x - extracting ImageMagick/import.man (Text)'
  524. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/import.man' &&
  525. .ad l
  526. .nh
  527. .TH IMPORT 1 "10 October 1992" "ImageMagick"
  528. .SH NAME
  529. import - capture some or all of an X server screen and save to file in the
  530. MIFF image format.
  531. .SH SYNOPSIS
  532. .B "import"
  533. [ \fIoptions\fP ... ] \fIfile\fP
  534. .SH DESCRIPTION
  535. .PP
  536. .I Import
  537. reads an image from any visible window on an X server and outputs it as
  538. an image file.  You can capture a single window, the entire screen, or any
  539. rectangular portion of the screen.  You can use \fIdisplay\fP (see
  540. \fBdisplay(1)\fP) utility for redisplay, printing, editing, formatting,
  541. archiving, image processing, etc. of the captured image.
  542. .PP
  543. The target window can be specified by id, name, or may be selected by
  544. clicking the mouse in the desired window.  If you press a button and
  545. then drag, a rectangle will form which expands and contracts as
  546. the mouse moves.  To save the portion of the screen  defined by the
  547. rectangle, just release the button.  The keyboard bell is rung once at
  548. the beginning of the screen capture and twice when it completes.
  549. .PP
  550. .SH EXAMPLES
  551. .PP
  552. To select an X window with the mouse and save it in the MIFF image
  553. format to a file on disk titled window.miff, use:
  554. .PP
  555. X     import window.miff
  556. .PP
  557. To select an X window and save it in the MIFF image format to a file on
  558. disk titled figure.miff to include in another document, use:
  559. .PP
  560. X     import -geometry +0+0 figure.miff
  561. .PP
  562. To capture the entire X server screen as the MIFF image format in a file on
  563. disk titled root.miff, use:
  564. .PP
  565. X     import -window root root.miff
  566. .SH OPTIONS
  567. \fIImport\fP options can appear on the command line or in your X resources
  568. file (see \fBX(1)\fP).  Options on the command line supersede values specified
  569. in your X resources file.
  570. .TP 5
  571. .B "-border"
  572. include image borders in the output image.
  573. .TP 5
  574. .B "-compress \fItype\fP"
  575. the type of image compression: \fIQEncoded\fP or \fIRunlengthEncoded\fP.
  576. See \fBMIFF(5)\fP for details.
  577. X
  578. Specify \fB\+compress\fP to store the binary image in an uncompressed format.
  579. The default is the compression type of the specified image file.
  580. .TP 5
  581. .B "-delay \fIseconds\fP"
  582. pause before selecting target window.
  583. X
  584. This option is useful when you need time to ready the target window before
  585. it is captured to a file.
  586. .TP 5
  587. .B "-display \fIhost:display[.screen]\fP"
  588. specifies the X server to contact; see \fBX(1)\fP.
  589. .TP 5
  590. .B "-frame"
  591. include window manager frame.
  592. .TP 5
  593. .B "-monochrome"
  594. transform image to black and white.
  595. .TP 5
  596. .B "-scene \fIvalue\fP"
  597. image scene number.
  598. .TP 5
  599. .B "-screen"
  600. This option indicates that the GetImage request used to obtain the image
  601. should be done on the root window, rather than directly on the specified
  602. window.  In this way, you can obtain pieces of other windows that overlap
  603. the specified window, and more importantly, you can capture menus or other
  604. popups that are independent windows but appear over the specified window.
  605. .TP 5
  606. .B -verbose
  607. print detailed information about the image.
  608. This information is printed: image scene number;  image name;  image size;  
  609. the image class (\fIDirectClass\fP or \fIPseudoClass\fP);  the total
  610. number of unique colors;  and the number of seconds to read and write the 
  611. image.
  612. .TP 5
  613. .B "-window \fIid\fP"
  614. select window with this id or name.
  615. X
  616. With this option you can specify the target window by id or name rather
  617. than using the mouse.  Specify 'root' to select X's root window as the
  618. target window.
  619. .PP
  620. Change \fI-\fP to \fI+\fP in any option above to reverse its effect.  For
  621. example \fB+frame\fP means do include window manager frame.
  622. .PP
  623. \fIfile\fP specifies the image filename.  By default, the image is
  624. written in the MIFF image format (see \fBMIFF(5)\fP).  To specify a
  625. particular image format, precede the filename with an image format name 
  626. and a colon (i.e.  mtv:image) or specify the image type as the filename
  627. suffix (i.e. image.mtv).  See \fBCONVERT(1)\fP for a list of valid
  628. image formats.  Specify \fIfile\fP as \fI-\fP for standard input or
  629. output.  If \fIfile\fP has the extension \fB.Z\fP, the file is encoded
  630. with \fIcompress\fP.
  631. .SH ENVIRONMENT
  632. .PP
  633. .TP 5
  634. .B DISPLAY
  635. To get the default host, display number, and screen.
  636. .SH SEE ALSO
  637. display(1), animate(1), mogrify(1), convert(1), Quantize(9), X(1)
  638. MIFF(5)
  639. .SH COPYRIGHT
  640. Copyright 1992 E. I. du Pont de Nemours & Company
  641. .PP
  642. Permission to use, copy, modify, distribute, and sell this software and
  643. its documentation for any purpose is hereby granted without fee,
  644. provided that the above copyright notice appear in all copies and that
  645. both that copyright notice and this permission notice appear in
  646. supporting documentation, and that the name of E. I. du Pont de Nemours
  647. & Company not be used in advertising or publicity pertaining to
  648. distribution of the software without specific, written prior
  649. permission.  E. I. du Pont de Nemours & Company makes no representations
  650. about the suitability of this software for any purpose.  It is provided
  651. "as is" without express or implied warranty.
  652. .PP
  653. E. I. du Pont de Nemours & Company disclaims all warranties with regard
  654. to this software, including all implied warranties of merchantability
  655. and fitness, in no event shall E. I. du Pont de Nemours & Company be
  656. liable for any special, indirect or consequential damages or any
  657. damages whatsoever resulting from loss of use, data or profits, whether
  658. in an action of contract, negligence or other tortious action, arising
  659. out of or in connection with the use or performance of this software.
  660. .SH AUTHORS
  661. John Cristy, E.I. du Pont De Nemours & Company Incorporated
  662. SHAR_EOF
  663. chmod 0644 ImageMagick/import.man ||
  664. echo 'restore of ImageMagick/import.man failed'
  665. Wc_c="`wc -c < 'ImageMagick/import.man'`"
  666. test 5476 -eq "$Wc_c" ||
  667.     echo 'ImageMagick/import.man: original size 5476, current size' "$Wc_c"
  668. rm -f _shar_wnt_.tmp
  669. fi
  670. # ============= ImageMagick/images/README ==============
  671. if test ! -d 'ImageMagick/images'; then
  672.     echo 'x - creating directory ImageMagick/images'
  673.     mkdir 'ImageMagick/images'
  674. fi
  675. if test -f 'ImageMagick/images/README' -a X"$1" != X"-c"; then
  676.     echo 'x - skipping ImageMagick/images/README (File already exists)'
  677.     rm -f _shar_wnt_.tmp
  678. else
  679. > _shar_wnt_.tmp
  680. echo 'x - extracting ImageMagick/images/README (Text)'
  681. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/images/README' &&
  682. The aquarium image was rendered with rayshade from a script written 
  683. by kilian@cray.com and Jerome A. Farm.
  684. X
  685. Image `montage.miff' was created with this command:
  686. X
  687. X  montage -colors 256 -gravity center -title "Image Montage"
  688. X    -geometry 128x128+5+5 dna.miff swan.miff aquarium.miff montage.miff
  689. SHAR_EOF
  690. chmod 0644 ImageMagick/images/README ||
  691. echo 'restore of ImageMagick/images/README failed'
  692. Wc_c="`wc -c < 'ImageMagick/images/README'`"
  693. test 295 -eq "$Wc_c" ||
  694.     echo 'ImageMagick/images/README: original size 295, current size' "$Wc_c"
  695. rm -f _shar_wnt_.tmp
  696. fi
  697. # ============= ImageMagick/quantize.c ==============
  698. if test -f 'ImageMagick/quantize.c' -a X"$1" != X"-c"; then
  699.     echo 'x - skipping ImageMagick/quantize.c (File already exists)'
  700.     rm -f _shar_wnt_.tmp
  701. else
  702. > _shar_wnt_.tmp
  703. echo 'x - extracting ImageMagick/quantize.c (Text)'
  704. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/quantize.c' &&
  705. /*
  706. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  707. %                                                                             %
  708. %                                                                             %
  709. %                                                                             %
  710. %           QQQ   U   U   AAA   N   N  TTTTT  IIIII   ZZZZZ  EEEEE            %
  711. %          Q   Q  U   U  A   A  NN  N    T      I        ZZ  E                %
  712. %          Q   Q  U   U  AAAAA  N N N    T      I      ZZZ   EEEEE            %
  713. %          Q  QQ  U   U  A   A  N  NN    T      I     ZZ     E                %
  714. %           QQQQ   UUU   A   A  N   N    T    IIIII   ZZZZZ  EEEEE            %
  715. %                                                                             %
  716. %                                                                             %
  717. %              Reduce the Number of Unique Colors in an Image                 %
  718. %                                                                             %
  719. %                                                                             %
  720. %                                                                             %
  721. %                           Software Design                                   %
  722. %                             John Cristy                                     %
  723. %                              July 1992                                      %
  724. %                                                                             %
  725. %  Copyright 1992 E. I. du Pont de Nemours & Company                          %
  726. %                                                                             %
  727. %  Permission to use, copy, modify, distribute, and sell this software and    %
  728. %  its documentation for any purpose is hereby granted without fee,           %
  729. %  provided that the above Copyright notice appear in all copies and that     %
  730. %  both that Copyright notice and this permission notice appear in            %
  731. %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
  732. %  & Company not be used in advertising or publicity pertaining to            %
  733. %  distribution of the software without specific, written prior               %
  734. %  permission.  E. I. du Pont de Nemours & Company makes no representations   %
  735. %  about the suitability of this software for any purpose.  It is provided    %
  736. %  "as is" without express or implied warranty.                               %
  737. %                                                                             %
  738. %  E. I. du Pont de Nemours & Company disclaims all warranties with regard    %
  739. %  to this software, including all implied warranties of merchantability      %
  740. %  and fitness, in no event shall E. I. du Pont de Nemours & Company be       %
  741. %  liable for any special, indirect or consequential damages or any           %
  742. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  743. %  in an action of contract, negligence or other tortious action, arising     %
  744. %  out of or in connection with the use or performance of this software.      %
  745. %                                                                             %
  746. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  747. %
  748. %  Realism in computer graphics typically requires using 24 bits/pixel to
  749. %  generate an image.  Yet many graphic display devices do not contain
  750. %  the amount of memory necessary to match the spatial and color
  751. %  resolution of the human eye.  The QUANTIZE program takes a 24 bit
  752. %  image and reduces the number of colors so it can be displayed on
  753. %  raster device with less bits per pixel.  In most instances, the
  754. %  quantized image closely resembles the original reference image.
  755. %
  756. %  A reduction of colors in an image is also desirable for image
  757. %  transmission and real-time animation.
  758. %
  759. %  Function Quantize takes a standard RGB or monochrome images and quantizes
  760. %  them down to some fixed number of colors.
  761. %
  762. %  For purposes of color allocation, an image is a set of n pixels, where
  763. %  each pixel is a point in RGB space.  RGB space is a 3-dimensional
  764. %  vector space, and each pixel, pi,  is defined by an ordered triple of
  765. %  red, green, and blue coordinates, (ri, gi, bi).
  766. %
  767. %  Each primary color component (red, green, or blue) represents an
  768. %  intensity which varies linearly from 0 to a maximum value, cmax, which
  769. %  corresponds to full saturation of that color.  Color allocation is
  770. %  defined over a domain consisting of the cube in RGB space with
  771. %  opposite vertices at (0,0,0) and (cmax,cmax,cmax).  QUANTIZE requires
  772. %  cmax = 255.
  773. %
  774. %  The algorithm maps this domain onto a tree in which each node
  775. %  represents a cube within that domain.  In the following discussion
  776. %  these cubes are defined by the coordinate of two opposite vertices:
  777. %  The vertex nearest the origin in RGB space and the vertex farthest
  778. %  from the origin.
  779. %
  780. %  The tree's root node represents the the entire domain, (0,0,0) through
  781. %  (cmax,cmax,cmax).  Each lower level in the tree is generated by
  782. %  subdividing one node's cube into eight smaller cubes of equal size.
  783. %  This corresponds to bisecting the parent cube with planes passing
  784. %  through the midpoints of each edge.
  785. %
  786. %  The basic algorithm operates in three phases: Classification,
  787. %  Reduction, and Assignment.  Classification builds a color
  788. %  description tree for the image.  Reduction collapses the tree until
  789. %  the number it represents, at most, the number of colors desired in the
  790. %  output image.  Assignment defines the output image's color map and
  791. %  sets each pixel's color by reclassification in the reduced tree.
  792. %
  793. %  Classification begins by initializing a color description tree of
  794. %  sufficient depth to represent each possible input color in a leaf.
  795. %  However, it is impractical to generate a fully-formed color
  796. %  description tree in the classification phase for realistic values of
  797. %  cmax.  If colors components in the input image are quantized to k-bit
  798. %  precision, so that cmax= 2k-1, the tree would need k levels below the
  799. %  root node to allow representing each possible input color in a leaf.
  800. %  This becomes prohibitive because the tree's total number of nodes is
  801. %  1 + sum(i=1,k,8k).
  802. %
  803. %  A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
  804. %  Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
  805. %  Initializes data structures for nodes only as they are needed;  (2)
  806. %  Chooses a maximum depth for the tree as a function of the desired
  807. %  number of colors in the output image (currently log2(colormap size)).
  808. %
  809. %  For each pixel in the input image, classification scans downward from
  810. %  the root of the color description tree.  At each level of the tree it
  811. %  identifies the single node which represents a cube in RGB space
  812. %  containing the pixel's color.  It updates the following data for each
  813. %  such node:
  814. %
  815. %    n1 : Number of pixels whose color is contained in the RGB cube
  816. %    which this node represents;
  817. %
  818. %    n2 : Number of pixels whose color is not represented in a node at
  819. %    lower depth in the tree;  initially,  n2 = 0 for all nodes except
  820. %    leaves of the tree.
  821. %
  822. %    Sr, Sg, Sb : Sums of the red, green, and blue component values for
  823. %    all pixels not classified at a lower depth. The combination of
  824. %    these sums and n2  will ultimately characterize the mean color of a
  825. %    set of pixels represented by this node.
  826. %
  827. %  Reduction repeatedly prunes the tree until the number of nodes with
  828. %  n2 > 0 is less than or equal to the maximum number of colors allowed
  829. %  in the output image.  On any given iteration over the tree, it selects
  830. %  those nodes whose n1  count is minimal for pruning and merges their
  831. %  color statistics upward. It uses a pruning threshold, ns, to govern
  832. %  node selection as follows:
  833. %
  834. %    ns = 0
  835. %    while number of nodes with (n2 > 0) > required maximum number of colors
  836. %      prune all nodes such that n1 <= ns
  837. %      Set ns to minimum n1 in remaining nodes
  838. %
  839. %  When a node to be pruned has offspring, the pruning procedure invokes
  840. %  itself recursively in order to prune the tree from the leaves upward.
  841. %  n2,  Sr, Sg,  and  Sb in a node being pruned are always added to the
  842. %  corresponding data in that node's parent.  This retains the pruned
  843. %  node's color characteristics for later averaging.
  844. %
  845. %  For each node, n2 pixels exist for which that node represents the
  846. %  smallest volume in RGB space containing those pixel's colors.  When n2
  847. %  > 0 the node will uniquely define a color in the output image. At the
  848. %  beginning of reduction,  n2 = 0  for all nodes except a the leaves of
  849. %  the tree which represent colors present in the input image.
  850. %
  851. %  The other pixel count, n1, indicates the total number of colors
  852. %  within the cubic volume which the node represents.  This includes n1 -
  853. %  n2  pixels whose colors should be defined by nodes at a lower level in
  854. %  the tree.
  855. %
  856. %  Assignment generates the output image from the pruned tree.  The
  857. %  output image consists of two parts: (1)  A color map, which is an
  858. %  array of color descriptions (RGB triples) for each color present in
  859. %  the output image;  (2)  A pixel array, which represents each pixel as
  860. %  an index into the color map array.
  861. %
  862. %  First, the assignment phase makes one pass over the pruned color
  863. %  description tree to establish the image's color map.  For each node
  864. %  with n2  > 0, it divides Sr, Sg, and Sb by n2 .  This produces the
  865. %  mean color of all pixels that classify no lower than this node.  Each
  866. %  of these colors becomes an entry in the color map.
  867. %
  868. %  Finally,  the assignment phase reclassifies each pixel in the pruned
  869. %  tree to identify the deepest node containing the pixel's color.  The
  870. %  pixel's value in the pixel array becomes the index of this node's mean
  871. %  color in the color map.
  872. %
  873. %  For efficiency, QUANTIZE requires that the reference image be in a
  874. %  run-length encoded format.
  875. %
  876. %  With the permission of USC Information Sciences Institute, 4676 Admiralty
  877. %  Way, Marina del Rey, California  90292, this code was adapted from module
  878. %  ALCOLS written by Paul Raveling.
  879. %
  880. %  The names of ISI and USC are not used in advertising or publicity
  881. %  pertaining to distribution of the software without prior specific
  882. %  written permission from ISI.
  883. %
  884. %
  885. */
  886. X
  887. /*
  888. X  Include declarations.
  889. */
  890. #include "display.h"
  891. #include "image.h"
  892. X
  893. /*
  894. X  Define declarations.
  895. */
  896. #define color_number  number_colors
  897. #define MaxNodes  266817
  898. #define MaxShift  8
  899. #define MaxTreeDepth  8  /* Log2(MaxRGB) */
  900. #define NodesInAList  2048
  901. X
  902. /*
  903. X  Structures.
  904. */
  905. typedef struct _Node
  906. {
  907. X  struct _Node
  908. X    *parent,
  909. X    *child[8];
  910. X
  911. X  unsigned char
  912. X    id,
  913. X    level,
  914. X    children,
  915. X    mid_red,
  916. X    mid_green,
  917. X    mid_blue;
  918. X
  919. X  unsigned long int
  920. X    number_colors,
  921. X    number_unique,
  922. X    total_red,
  923. X    total_green,
  924. X    total_blue;
  925. } Node;
  926. X
  927. typedef struct _Nodes
  928. {
  929. X  Node
  930. X    nodes[NodesInAList];
  931. X
  932. X  struct _Nodes
  933. X    *next;
  934. } Nodes;
  935. X
  936. typedef struct _Cube
  937. {
  938. X  Node
  939. X    *root;
  940. X
  941. X  ColorPacket
  942. X    color,
  943. X    *colormap;
  944. X
  945. X  unsigned int
  946. X    depth;
  947. X
  948. X  unsigned long int
  949. X    colors,
  950. X    pruning_threshold,
  951. X    next_pruning_threshold,
  952. X    distance,
  953. X    shift[MaxTreeDepth+1],
  954. X    squares[MaxRGB+MaxRGB+1];
  955. X
  956. X  unsigned int
  957. X    nodes,
  958. X    free_nodes,
  959. X    color_number;
  960. X
  961. X  Node
  962. X    *next_node;
  963. X
  964. X  Nodes
  965. X    *node_queue;
  966. } Cube;
  967. X
  968. /*
  969. X  Global variables.
  970. */
  971. static Cube
  972. X  cube;
  973. X
  974. /*
  975. X  External declarations.
  976. */
  977. extern char
  978. X  *application_name;
  979. X
  980. /*
  981. X  Forward declarations.
  982. */
  983. static Node
  984. X  *InitializeNode _Declare((unsigned int,unsigned int,Node *,unsigned int,
  985. X    unsigned int,unsigned int));
  986. X
  987. static unsigned int
  988. X  DitherImage _Declare((Image *));
  989. X
  990. static void
  991. X  ClosestColor _Declare((Node *)),
  992. X  Colormap _Declare((Node *)),
  993. X  PruneLevel _Declare((Node *));
  994. X
  995. /*
  996. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  997. %                                                                             %
  998. %                                                                             %
  999. %                                                                             %
  1000. %  A s s i g n m e n t                                                        %
  1001. %                                                                             %
  1002. %                                                                             %
  1003. %                                                                             %
  1004. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1005. %
  1006. %  Procedure Assignment generates the output image from the pruned tree.  The
  1007. %  output image consists of two parts: (1)  A color map, which is an
  1008. %  array of color descriptions (RGB triples) for each color present in
  1009. %  the output image;  (2)  A pixel array, which represents each pixel as
  1010. %  an index into the color map array.
  1011. %
  1012. %  First, the assignment phase makes one pass over the pruned color
  1013. %  description tree to establish the image's color map.  For each node
  1014. %  with n2  > 0, it divides Sr, Sg, and Sb by n2 .  This produces the
  1015. %  mean color of all pixels that classify no lower than this node.  Each
  1016. %  of these colors becomes an entry in the color map.
  1017. %
  1018. %  Finally,  the assignment phase reclassifies each pixel in the pruned
  1019. %  tree to identify the deepest node containing the pixel's color.  The
  1020. %  pixel's value in the pixel array becomes the index of this node's mean
  1021. %  color in the color map.
  1022. %
  1023. %  The format of the Assignment routine is:
  1024. %
  1025. %      Assignment(image,dither,optimal)
  1026. %
  1027. %  A description of each parameter follows.
  1028. %
  1029. %    o image: Specifies a pointer to an Image structure;  returned from
  1030. %      ReadImage.
  1031. %
  1032. %    o dither: Set this integer value to something other than zero to
  1033. %      dither the quantized image.  The basic strategy of dithering is to
  1034. %      trade intensity resolution for spatial resolution by averaging the
  1035. %      intensities of several neighboring pixels.  Images which suffer
  1036. %      from severe contouring when quantized can be improved with the
  1037. %      technique of dithering.  Severe contouring generally occurs when
  1038. %      quantizing to very few colors, or to a poorly-chosen colormap.
  1039. %      Note, dithering is a computationally expensive process and will
  1040. %      increase processing time significantly.
  1041. %
  1042. %    o optimal: An unsigned integer value greater than zero indicates that
  1043. %      the optimal representation of the reference image should be returned.
  1044. %
  1045. %
  1046. */
  1047. static void Assignment(image,dither,optimal)
  1048. Image
  1049. X  *image;
  1050. X
  1051. unsigned int
  1052. X  dither,
  1053. X  optimal;
  1054. {
  1055. X  register int
  1056. X    i;
  1057. X
  1058. X  register Node
  1059. X    *node;
  1060. X
  1061. X  register RunlengthPacket
  1062. X    *p;
  1063. X
  1064. X  register unsigned int
  1065. X    id;
  1066. X
  1067. X  /*
  1068. X    Allocate image colormap.
  1069. X  */
  1070. X  image->alpha=False;
  1071. X  image->class=PseudoClass;
  1072. X  if (image->colormap != (ColorPacket *) NULL)
  1073. X    (void) free((char *) image->colormap);
  1074. X  image->colormap=(ColorPacket *)
  1075. X    malloc((unsigned int) cube.colors*sizeof(ColorPacket));
  1076. X  if (image->colormap == (ColorPacket *) NULL)
  1077. X    {
  1078. X      Warning("unable to quantize image","memory allocation failed");
  1079. X      exit(1);
  1080. X    }
  1081. X  if (image->signature != (char *) NULL)
  1082. X    (void) free((char *) image->signature);
  1083. X  image->signature=(char *) NULL;
  1084. X  cube.colormap=image->colormap;
  1085. X  cube.colors=0;
  1086. X  Colormap(cube.root);
  1087. X  image->colors=(unsigned int) cube.colors;
  1088. X  /*
  1089. X    Create a reduced color image.  For the non-optimal case we trade
  1090. X    accuracy for speed improvements.
  1091. X  */
  1092. X  if (dither)
  1093. X    dither=!DitherImage(image);
  1094. X  p=image->pixels;
  1095. X  if (!dither)
  1096. X    if (!optimal)
  1097. X      for (i=0; i < image->packets; i++)
  1098. X      {
  1099. X        /*
  1100. X          Identify the deepest node containing the pixel's color.
  1101. X        */
  1102. X        node=cube.root;
  1103. X        do
  1104. X        {
  1105. X          id=(p->red > node->mid_red ? 1 : 0) |
  1106. X            (p->green > node->mid_green ? 1 : 0) << 1 |
  1107. X            (p->blue > node->mid_blue ? 1 : 0) << 2;
  1108. X          if ((node->children & (1 << id)) == 0)
  1109. X            break;
  1110. X          node=node->child[id];
  1111. X        } while (True);
  1112. X        p->index=(unsigned short) node->color_number;
  1113. X        p++;
  1114. X      }
  1115. X    else
  1116. X      for (i=0; i < image->packets; i++)
  1117. X      {
  1118. X        /*
  1119. X          Identify the deepest node containing the pixel's color.
  1120. X        */
  1121. X        node=cube.root;
  1122. X        do
  1123. X        {
  1124. X          id=(p->red > node->mid_red ? 1 : 0) |
  1125. X            (p->green > node->mid_green ? 1 : 0) << 1 |
  1126. X            (p->blue > node->mid_blue ? 1 : 0) << 2;
  1127. X          if ((node->children & (1 << id)) == 0)
  1128. X            break;
  1129. X          node=node->child[id];
  1130. X        }
  1131. X        while (True);
  1132. X        /*
  1133. X          Find closest color among siblings and their children.
  1134. X        */
  1135. X        cube.color.red=p->red;
  1136. X        cube.color.green=p->green;
  1137. X        cube.color.blue=p->blue;
  1138. X        cube.distance=(~0);
  1139. X        ClosestColor(node->parent);
  1140. X        p->index=cube.color_number;
  1141. X        p++;
  1142. X      }
  1143. }
  1144. X
  1145. /*
  1146. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1147. %                                                                             %
  1148. %                                                                             %
  1149. %                                                                             %
  1150. %  C l a s s i f i c a t i o n                                                %
  1151. %                                                                             %
  1152. %                                                                             %
  1153. %                                                                             %
  1154. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1155. %
  1156. %  Procedure Classification begins by initializing a color description tree
  1157. %  of sufficient depth to represent each possible input color in a leaf.
  1158. %  However, it is impractical to generate a fully-formed color
  1159. %  description tree in the classification phase for realistic values of
  1160. %  cmax.  If colors components in the input image are quantized to k-bit
  1161. %  precision, so that cmax= 2k-1, the tree would need k levels below the
  1162. %  root node to allow representing each possible input color in a leaf.
  1163. %  This becomes prohibitive because the tree's total number of nodes is
  1164. %  1 + sum(i=1,k,8k).
  1165. %
  1166. %  A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
  1167. %  Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
  1168. %  Initializes data structures for nodes only as they are needed;  (2)
  1169. %  Chooses a maximum depth for the tree as a function of the desired
  1170. %  number of colors in the output image (currently log2(colormap size)).
  1171. %
  1172. %  For each pixel in the input image, classification scans downward from
  1173. %  the root of the color description tree.  At each level of the tree it
  1174. %  identifies the single node which represents a cube in RGB space
  1175. %  containing It updates the following data for each such node:
  1176. %
  1177. %    n1 : Number of pixels whose color is contained in the RGB cube
  1178. %    which this node represents;
  1179. %
  1180. %    n2 : Number of pixels whose color is not represented in a node at
  1181. %    lower depth in the tree;  initially,  n2 = 0 for all nodes except
  1182. %    leaves of the tree.
  1183. %
  1184. %    Sr, Sg, Sb : Sums of the red, green, and blue component values for
  1185. %    all pixels not classified at a lower depth. The combination of
  1186. %    these sums and n2  will ultimately characterize the mean color of a
  1187. %    set of pixels represented by this node.
  1188. %
  1189. %  The format of the Classification routine is:
  1190. %
  1191. %      Classification(image)
  1192. %
  1193. %  A description of each parameter follows.
  1194. %
  1195. %    o image: Specifies a pointer to an Image structure;  returned from
  1196. %      ReadImage.
  1197. %
  1198. %
  1199. */
  1200. static void Classification(image)
  1201. Image
  1202. X  *image;
  1203. {
  1204. X  register int
  1205. X    i;
  1206. X
  1207. X  register Node
  1208. X    *node;
  1209. X
  1210. X  register RunlengthPacket
  1211. X    *p;
  1212. X
  1213. X  register unsigned int
  1214. X    bisect,
  1215. X    count,
  1216. X    id,
  1217. X    level;
  1218. X
  1219. X  p=image->pixels;
  1220. X  for (i=0; i < image->packets; i++)
  1221. X  {
  1222. X    if (cube.nodes > MaxNodes)
  1223. X      {
  1224. X        /*
  1225. X          Prune one level if the color tree is too large.
  1226. X        */
  1227. X        PruneLevel(cube.root);
  1228. X        cube.depth--;
  1229. X      }
  1230. X    /*
  1231. X      Start at the root and descend the color cube tree.
  1232. X    */
  1233. X    count=p->length+1;
  1234. X    node=cube.root;
  1235. X    for (level=1; level < cube.depth; level++)
  1236. X    {
  1237. X      id=(p->red > node->mid_red ? 1 : 0) |
  1238. X        (p->green > node->mid_green ? 1 : 0) << 1 |
  1239. X        (p->blue > node->mid_blue ? 1 : 0) << 2;
  1240. X      if (node->child[id] == (Node *) NULL)
  1241. X        {
  1242. X          /*
  1243. X            Set colors of new node to contain pixel.
  1244. X          */
  1245. X          node->children|=1 << id;
  1246. X          bisect=(unsigned int) (1 << (MaxTreeDepth-level)) >> 1;
  1247. X          node->child[id]=InitializeNode(id,level,node,
  1248. X            node->mid_red+(id & 1 ? bisect : -bisect),
  1249. X            node->mid_green+(id & 2 ? bisect : -bisect),
  1250. X            node->mid_blue+(id & 4 ? bisect : -bisect));
  1251. X          if (node->child[id] == (Node *) NULL)
  1252. X            {
  1253. X              Warning("unable to quantize image","memory allocation failed");
  1254. X              exit(1);
  1255. X            }
  1256. X          if (level == (cube.depth-1))
  1257. X            cube.colors++;
  1258. X        }
  1259. X      /*
  1260. X        Record the number of colors represented by this node.  Shift by level
  1261. X        in the color description tree.
  1262. X      */
  1263. X      node=node->child[id];
  1264. X      node->number_colors+=count << cube.shift[level];
  1265. X    }
  1266. X    /*
  1267. X      Increment unique color count and sum RGB values for this leaf for later
  1268. X      derivation of the mean cube color.
  1269. X    */
  1270. X    node->number_unique+=count;
  1271. X    node->total_red+=p->red*count;
  1272. X    node->total_green+=p->green*count;
  1273. X    node->total_blue+=p->blue*count;
  1274. X    p++;
  1275. X  }
  1276. }
  1277. X
  1278. /*
  1279. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1280. %                                                                             %
  1281. %                                                                             %
  1282. %                                                                             %
  1283. %  C l o s e s t C o l o r                                                    %
  1284. %                                                                             %
  1285. %                                                                             %
  1286. %                                                                             %
  1287. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1288. %
  1289. %  Procedure ClosestColor traverses the color cube tree at a particular node
  1290. %  and determines which colormap entry best represents the input color.
  1291. %
  1292. %  The format of the ClosestColor routine is:
  1293. %
  1294. %      ClosestColor(node)
  1295. %
  1296. %  A description of each parameter follows.
  1297. %
  1298. %    o node: The address of a structure of type Node which points to a
  1299. %      node in the color cube tree that is to be pruned.
  1300. %
  1301. %
  1302. */
  1303. static void ClosestColor(node)
  1304. register Node
  1305. X  *node;
  1306. {
  1307. X  register unsigned int
  1308. X    id;
  1309. X
  1310. X  /*
  1311. X    Traverse any children.
  1312. X  */
  1313. X  if (node->children > 0)
  1314. X    for (id=0; id < 8; id++)
  1315. X      if (node->children & (1 << id))
  1316. X        ClosestColor(node->child[id]);
  1317. X  if (node->number_unique > 0)
  1318. X    {
  1319. X      register ColorPacket
  1320. X        *color;
  1321. X
  1322. X      register unsigned int
  1323. X        blue_distance,
  1324. X        green_distance,
  1325. X        red_distance;
  1326. X
  1327. X      register unsigned long int
  1328. X        distance;
  1329. X
  1330. X      /*
  1331. X        Determine if this color is "closest".
  1332. X      */
  1333. X      color=cube.colormap+node->color_number;
  1334. X      red_distance=(int) color->red-(int) cube.color.red+MaxRGB;
  1335. X      green_distance=(int) color->green-(int) cube.color.green+MaxRGB;
  1336. X      blue_distance=(int) color->blue-(int) cube.color.blue+MaxRGB;
  1337. X      distance=cube.squares[red_distance]+cube.squares[green_distance]+
  1338. X        cube.squares[blue_distance];
  1339. X      if (distance < cube.distance)
  1340. X        {
  1341. X          cube.distance=distance;
  1342. X          cube.color_number=(unsigned short) node->color_number;
  1343. X        }
  1344. X    }
  1345. }
  1346. X
  1347. /*
  1348. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1349. %                                                                             %
  1350. %                                                                             %
  1351. %                                                                             %
  1352. %  C o l o r m a p                                                            %
  1353. %                                                                             %
  1354. %                                                                             %
  1355. %                                                                             %
  1356. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1357. %
  1358. %  Procedure Colormap traverses the color cube tree and notes each colormap
  1359. %  entry.  A colormap entry is any node in the color cube tree where the
  1360. %  number of unique colors is not zero.
  1361. %
  1362. %  The format of the Colormap routine is:
  1363. %
  1364. %      Colormap(node)
  1365. %
  1366. %  A description of each parameter follows.
  1367. %
  1368. %    o node: The address of a structure of type Node which points to a
  1369. %      node in the color cube tree that is to be pruned.
  1370. %
  1371. %
  1372. */
  1373. static void Colormap(node)
  1374. register Node
  1375. X  *node;
  1376. {
  1377. X  register unsigned int
  1378. X    id;
  1379. X
  1380. X  /*
  1381. X    Traverse any children.
  1382. X  */
  1383. X  if (node->children > 0)
  1384. X    for (id=0; id < 8; id++)
  1385. X      if (node->children & (1 << id))
  1386. X        Colormap(node->child[id]);
  1387. X  if (node->number_unique > 0)
  1388. X    {
  1389. X      /*
  1390. X        Colormap entry is defined by the mean color in this cube.        
  1391. X      */
  1392. X      cube.colormap[cube.colors].red=(unsigned char)
  1393. X        ((node->total_red+(node->number_unique >> 1))/node->number_unique);
  1394. X      cube.colormap[cube.colors].green=(unsigned char)
  1395. X        ((node->total_green+(node->number_unique >> 1))/node->number_unique);
  1396. X      cube.colormap[cube.colors].blue=(unsigned char)
  1397. X        ((node->total_blue+(node->number_unique >> 1))/node->number_unique);
  1398. X      node->color_number=cube.colors++;
  1399. X    }
  1400. }
  1401. X
  1402. /*
  1403. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1404. %                                                                             %
  1405. %                                                                             %
  1406. %                                                                             %
  1407. %  D i t h e r I m a g e                                                      %
  1408. %                                                                             %
  1409. %                                                                             %
  1410. %                                                                             %
  1411. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1412. %
  1413. %  Procedure DitherImage uses the Floyd-Steinberg algorithm to dither the
  1414. %  image.  Refer to "An Adaptive Algorithm for Spatial GreySscale", Robert W.
  1415. %  Floyd and Louis Steinberg, Proceedings of the S.I.D., Volume 17(2), 1976.
  1416. %
  1417. %  First find the closest representation to the reference pixel color in the
  1418. %  colormap, the node pixel is assigned this color.  Next, the colormap color
  1419. %  is subtracted from the reference pixels color, this represents the
  1420. %  quantization error.  Various amounts of this error are added to the pixels
  1421. %  ahead and below the node pixel to correct for this error.  The error
  1422. %  proportions are:
  1423. %
  1424. %            P     7/16
  1425. %      3/16  5/16  1/16
  1426. %
  1427. %  The error is distributed left-to-right for even scanlines and right-to-left
  1428. %  for odd scanlines.
  1429. %
  1430. %  The format of the DitherImage routine is:
  1431. %
  1432. %      DitherImage(image)
  1433. %
  1434. %  A description of each parameter follows.
  1435. %
  1436. %    o image: Specifies a pointer to an Image structure;  returned from
  1437. %      ReadImage.
  1438. %
  1439. %
  1440. */
  1441. static unsigned int DitherImage(image)
  1442. Image
  1443. X  *image;
  1444. {
  1445. X  typedef struct _ScaledColorPacket
  1446. X  {
  1447. X    int
  1448. X      red,
  1449. X      green,
  1450. X      blue;
  1451. X  } ScaledColorPacket;
  1452. X
  1453. X  Image
  1454. X    *dithered_image;
  1455. X
  1456. X  int
  1457. X    *cache,
  1458. X    odd_scanline;
  1459. X
  1460. X  register int
  1461. X    blue_error,
  1462. X    green_error,
  1463. X    red_error,
  1464. X    step;
  1465. X
  1466. X  register Node
  1467. X    *node;
  1468. X
  1469. X  register RunlengthPacket
  1470. X    *p,
  1471. X    *q;
  1472. X
  1473. X  register ScaledColorPacket
  1474. X    *cs,
  1475. X    *ns;
  1476. X
  1477. X  register unsigned int
  1478. X    id;
  1479. X
  1480. X  register unsigned short
  1481. X    index;
  1482. X
  1483. X  ScaledColorPacket
  1484. X    *scanline;
  1485. X
  1486. X  unsigned char
  1487. X    *range_limit,
  1488. X    *range_table;
  1489. X
  1490. X  unsigned int
  1491. X    i,
  1492. X    x,
  1493. X    y;
  1494. X
  1495. X  /*
  1496. X    Initialize dithered image attributes.
  1497. X  */
  1498. X  image->orphan=True;
  1499. X  dithered_image=CopyImage(image,image->columns,image->rows,False);
  1500. X  image->orphan=False;
  1501. X  if (dithered_image == (Image *) NULL)
  1502. X    {
  1503. X      Warning("unable to dither image","memory allocation failed");
  1504. X      return(True);
  1505. X    }
  1506. X  /*
  1507. X    Allocate the cache & scanline buffers to keep track of quantization error.
  1508. X  */
  1509. X  cache=(int *) malloc((1 << 18)*sizeof(int));
  1510. X  range_table=(unsigned char *) malloc(3*(MaxRGB+1)*sizeof(unsigned char));
  1511. X  scanline=(ScaledColorPacket *)
  1512. X    malloc(2*(image->columns+2)*sizeof(ScaledColorPacket));
  1513. X  if ((cache == (int *) NULL) || (range_table == (unsigned char *) NULL) ||
  1514. X      (scanline == (ScaledColorPacket *) NULL))
  1515. X    {
  1516. X      Warning("unable to dither image","memory allocation failed");
  1517. X      return(True);
  1518. X    }
  1519. X  /*
  1520. X    Initialize tables.
  1521. X  */
  1522. X  for (i=0; i < (1 << 18); i++)
  1523. X    cache[i]=(-1);
  1524. X  for (i=0; i <= MaxRGB; i++)
  1525. X  {
  1526. X    range_table[i]=0;
  1527. X    range_table[i+(MaxRGB+1)]=(unsigned char) i;
  1528. X    range_table[i+(MaxRGB+1)*2]=MaxRGB;
  1529. X  }
  1530. X  range_limit=range_table+(MaxRGB+1);
  1531. X  /*
  1532. X    Preload first scanline.
  1533. X  */
  1534. X  p=image->pixels;
  1535. X  image->runlength=p->length+1;
  1536. X  cs=scanline+1;
  1537. X  for (i=0; i < image->columns; i++)
  1538. X  {
  1539. X    if (image->runlength > 0)
  1540. X      image->runlength--;
  1541. X    else
  1542. X      {
  1543. X        p++;
  1544. X        image->runlength=p->length;
  1545. X      }
  1546. X    cs->red=p->red;
  1547. X    cs->green=p->green;
  1548. X    cs->blue=p->blue;
  1549. X    cs++;
  1550. X  }
  1551. X  odd_scanline=False;
  1552. X  for (y=0; y < image->rows; y++)
  1553. X  {
  1554. X    if (y < (image->rows-1))
  1555. X      {
  1556. X        /*
  1557. X          Read another scanline.
  1558. X        */
  1559. X        ns=scanline+1;
  1560. X        if (!odd_scanline)
  1561. X          ns+=(image->columns+2);
  1562. X        for (i=0; i < image->columns; i++)
  1563. X        {
  1564. X          if (image->runlength > 0)
  1565. X            image->runlength--;
  1566. X          else
  1567. X            {
  1568. X              p++;
  1569. X              image->runlength=p->length;
  1570. X            }
  1571. X          ns->red=p->red;
  1572. X          ns->green=p->green;
  1573. X          ns->blue=p->blue;
  1574. X          ns++;
  1575. X        }
  1576. X      }
  1577. X    if (!odd_scanline)
  1578. X      {
  1579. X        /*
  1580. X          Distribute error left-to-right for even scanlines.
  1581. X        */
  1582. X        q=dithered_image->pixels+image->columns*y;
  1583. X        cs=scanline+1;
  1584. X        ns=scanline+(image->columns+2)+1;
  1585. X        step=1;
  1586. X      }
  1587. X    else
  1588. X      {
  1589. X        /*
  1590. X          Distribute error right-to-left for odd scanlines.
  1591. X        */
  1592. X        q=dithered_image->pixels+image->columns*y+(image->columns-1);
  1593. X        cs=scanline+(image->columns+2)+(image->columns-1)+1;
  1594. X        ns=scanline+(image->columns-1)+1;
  1595. X        step=(-1);
  1596. X      }
  1597. X    for (x=0; x < image->columns; x++)
  1598. X    {
  1599. X      q->red=range_limit[cs->red];
  1600. X      q->green=range_limit[cs->green];
  1601. X      q->blue=range_limit[cs->blue];
  1602. X      i=(q->red >> 2) << 12 | (q->green >> 2) << 6 | q->blue >> 2;
  1603. X      if (cache[i] < 0)
  1604. X        {
  1605. X          /*
  1606. X            Identify the deepest node containing the pixel's color.
  1607. X          */
  1608. X          node=cube.root;
  1609. X          do
  1610. X          {
  1611. X            id=(q->red > node->mid_red ? 1 : 0) |
  1612. X              (q->green > node->mid_green ? 1 : 0) << 1 |
  1613. X              (q->blue > node->mid_blue ? 1 : 0) << 2;
  1614. X            if ((node->children & (1 << id)) == 0)
  1615. X              break;
  1616. X            node=node->child[id];
  1617. X          }
  1618. X          while (True);
  1619. X          /*
  1620. X            Find closest color among siblings and their children.
  1621. X          */
  1622. X          cube.color.red=q->red;
  1623. X          cube.color.green=q->green;
  1624. X          cube.color.blue=q->blue;
  1625. X          cube.distance=(~0);
  1626. X          ClosestColor(node->parent);
  1627. X          cache[i]=cube.color_number;
  1628. X        }
  1629. X      index=(unsigned short) cache[i];
  1630. X      red_error=(int) q->red-(int) cube.colormap[index].red;
  1631. X      green_error=(int) q->green-(int) cube.colormap[index].green;
  1632. X      blue_error=(int) q->blue-(int) cube.colormap[index].blue;
  1633. X      q->index=index;
  1634. SHAR_EOF
  1635. true || echo 'restore of ImageMagick/quantize.c failed'
  1636. fi
  1637. echo 'End of  part 8'
  1638. echo 'File ImageMagick/quantize.c is continued in part 9'
  1639. echo 9 > _shar_seq_.tmp
  1640. exit 0
  1641. exit 0 # Just in case...
  1642.