home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sources / misc / 4178 < prev    next >
Encoding:
Text File  |  1992-12-13  |  57.2 KB  |  1,649 lines

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