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

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: cristy@eplrx7.es.duPont.com (John Cristy)
  4. Subject:  v34i037:  imagemagick - X11 image processing and display v2.2, Part09/26
  5. Message-ID: <1992Dec13.202811.9789@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 90d00814723ce3528650c775e8603408
  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:28:11 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 1806
  14.  
  15. Submitted-by: cristy@eplrx7.es.duPont.com (John Cristy)
  16. Posting-number: Volume 34, Issue 37
  17. Archive-name: imagemagick/part09
  18. Environment: UNIX, VMS, X11, SGI, DEC, Cray, Sun, Vax
  19.  
  20. #!/bin/sh
  21. # this is Part.09 (part 9 of a multipart archive)
  22. # do not concatenate these parts, unpack them in order with /bin/sh
  23. # file ImageMagick/quantize.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" != 9; 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/quantize.c'
  39. else
  40. echo 'x - continuing file ImageMagick/quantize.c'
  41. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/quantize.c' &&
  42. X      q->length=0;
  43. X      q+=step;
  44. X      /*
  45. X        Propagate the error in these proportions:
  46. X                Q     7/16
  47. X          3/16  5/16  1/16
  48. X      */
  49. X      cs+=step;
  50. X      cs->red+=red_error-((red_error*9+8) >> 4);
  51. X      cs->green+=green_error-((green_error*9+8) >> 4);
  52. X      cs->blue+=blue_error-((blue_error*9+8) >> 4);
  53. X      ns-=step;
  54. X      ns->red+=(red_error*3+8) >> 4;
  55. X      ns->green+=(green_error*3+8) >> 4;
  56. X      ns->blue+=(blue_error*3+8) >> 4;
  57. X      ns+=step;
  58. X      ns->red+=(red_error*5+8) >> 4;
  59. X      ns->green+=(green_error*5+8) >> 4;
  60. X      ns->blue+=(blue_error*5+8) >> 4;
  61. X      ns+=step;
  62. X      ns->red+=(red_error+8) >> 4;
  63. X      ns->green+=(green_error+8) >> 4;
  64. X      ns->blue+=(blue_error+8) >> 4;
  65. X    }
  66. X    odd_scanline=!odd_scanline;
  67. X  }
  68. X  /*
  69. X    Free up memory.
  70. X  */
  71. X  (void) free((char *) scanline);
  72. X  (void) free((char *) range_table);
  73. X  (void) free((char *) cache);
  74. X  (void) free((char *) image->pixels);
  75. X  image->packets=dithered_image->packets;
  76. X  image->pixels=dithered_image->pixels;
  77. X  dithered_image->file=(FILE *) NULL;
  78. X  dithered_image->pixels=(RunlengthPacket *) NULL;
  79. X  DestroyImage(dithered_image);
  80. X  return(False);
  81. }
  82. X
  83. /*
  84. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  85. %                                                                             %
  86. %                                                                             %
  87. %                                                                             %
  88. %  I n i t i a l i z e C u b e                                                %
  89. %                                                                             %
  90. %                                                                             %
  91. %                                                                             %
  92. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  93. %
  94. %  Function InitializeCube initialize the Cube data structure.
  95. %
  96. %  The format of the InitializeCube routine is:
  97. %
  98. %      InitializeCube(number_colors,tree_depth,number_pixels,optimal)
  99. %
  100. %  A description of each parameter follows.
  101. %
  102. %    o number_colors: This integer value indicates the maximum number of
  103. %      colors in the quantized image or colormap.  Here we use this value
  104. %      to determine the depth of the color description tree.
  105. %
  106. %    o tree_depth: Normally, this integer value is zero or one.  A zero or
  107. %      one tells Quantize to choose a optimal tree depth of Log4(number_colors).
  108. %      A tree of this depth generally allows the best representation of the
  109. %      reference image with the least amount of memory and the fastest
  110. %      computational speed.  In some cases, such as an image with low color
  111. %      dispersion (a few number of colors), a value other than
  112. %      Log4(number_colors) is required.  To expand the color tree completely,
  113. %      use a value of 8.
  114. %
  115. %    o number_pixels: Specifies the number of individual pixels in the image.
  116. %
  117. %    o optimal: An unsigned integer value greater than zero indicates that
  118. %      the optimal representation of the reference image should be returned.
  119. %
  120. */
  121. static void InitializeCube(number_colors,tree_depth,number_pixels,optimal)
  122. unsigned int
  123. X  number_colors,
  124. X  tree_depth,
  125. X  number_pixels,
  126. X  optimal;
  127. {
  128. X  register int
  129. X    i;
  130. X
  131. X  static int
  132. X    log4[6] = {4, 16, 64, 256, 1024, ~0};
  133. X
  134. X  unsigned int
  135. X    level;
  136. X
  137. X  unsigned long int
  138. X    max_shift;
  139. X
  140. X  /*
  141. X    Initialize tree to describe color cube.  Depth is: Log4(colormap size)+2;
  142. X  */
  143. X  cube.node_queue=(Nodes *) NULL;
  144. X  cube.nodes=0;
  145. X  cube.free_nodes=0;
  146. X  if (tree_depth > 1)
  147. X    cube.depth=Min(tree_depth,8);
  148. X  else
  149. X    {
  150. X      for (i=0; i < 6; i++)
  151. X        if (number_colors <= log4[i])
  152. X          break;
  153. X      cube.depth=i+3;
  154. X      if (!optimal)
  155. X        cube.depth--;
  156. X    }
  157. X  /*
  158. X    Initialize the shift values.
  159. X  */
  160. X  for (max_shift=0; number_pixels > 0; max_shift++)
  161. X    number_pixels<<=1;
  162. X  for (level=0; level < cube.depth; level++)
  163. X  {
  164. X    cube.shift[level]=(cube.depth-level-1) << 1;
  165. X    if (cube.shift[level] > max_shift)
  166. X      cube.shift[level]=max_shift;
  167. X  }
  168. X  /*
  169. X    Initialize the square values.
  170. X  */
  171. X  for (i=(-MaxRGB); i <= MaxRGB; i++)
  172. X    cube.squares[i+MaxRGB]=i*i;
  173. X  /*
  174. X    Initialize root node.
  175. X  */
  176. X  cube.root=
  177. X    InitializeNode(0,0,(Node *) NULL,MaxRGB >> 1,MaxRGB >> 1,MaxRGB >> 1);
  178. X  if (cube.root == (Node *) NULL)
  179. X    {
  180. X      Warning("unable to quantize image","memory allocation failed");
  181. X      exit(1);
  182. X    }
  183. X  cube.root->parent=cube.root;
  184. X  cube.root->number_colors=(~0);
  185. X  cube.colors=0;
  186. }
  187. X
  188. /*
  189. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  190. %                                                                             %
  191. %                                                                             %
  192. %                                                                             %
  193. %  I n i t i a l i z e N o d e                                                %
  194. %                                                                             %
  195. %                                                                             %
  196. %                                                                             %
  197. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  198. %
  199. %  Function InitializeNode allocates memory for a new node in the color cube
  200. %  tree and presets all fields to zero.
  201. %
  202. %  The format of the InitializeNode routine is:
  203. %
  204. %      node=InitializeNode(node,id,level,mid_red,mid_green,mid_blue)
  205. %
  206. %  A description of each parameter follows.
  207. %
  208. %    o node: The InitializeNode routine returns this integer address.
  209. %
  210. %    o id: Specifies the child number of the node.
  211. %
  212. %    o level: Specifies the level in the classification the node resides.
  213. %
  214. %    o mid_red: Specifies the mid point of the red axis for this node.
  215. %
  216. %    o mid_green: Specifies the mid point of the green axis for this node.
  217. %
  218. %    o mid_blue: Specifies the mid point of the blue axis for this node.
  219. %
  220. %
  221. */
  222. static Node *InitializeNode(id,level,parent,mid_red,mid_green,mid_blue)
  223. unsigned int
  224. X  id,
  225. X  level;
  226. X
  227. Node
  228. X  *parent;
  229. X
  230. unsigned int
  231. X  mid_red,
  232. X  mid_green,
  233. X  mid_blue;
  234. {
  235. X  register int
  236. X    i;
  237. X
  238. X  register Node
  239. X    *node;
  240. X
  241. X  if (cube.free_nodes == 0)
  242. X    {
  243. X      register Nodes
  244. X        *nodes;
  245. X
  246. X      /*
  247. X        Allocate a new nodes of nodes.
  248. X      */
  249. X      nodes=(Nodes *) malloc(sizeof(Nodes));
  250. X      if (nodes == (Nodes *) NULL)
  251. X        return((Node *) NULL);
  252. X      nodes->next=cube.node_queue;
  253. X      cube.node_queue=nodes;
  254. X      cube.next_node=nodes->nodes;
  255. X      cube.free_nodes=NodesInAList;
  256. X    }
  257. X  cube.nodes++;
  258. X  cube.free_nodes--;
  259. X  node=cube.next_node++;
  260. X  node->parent=parent;
  261. X  for (i=0; i < 8; i++)
  262. X    node->child[i]=(Node *) NULL;
  263. X  node->id=id;
  264. X  node->level=level;
  265. X  node->children=0;
  266. X  node->mid_red=mid_red;
  267. X  node->mid_green=mid_green;
  268. X  node->mid_blue=mid_blue;
  269. X  node->number_colors=0;
  270. X  node->number_unique=0;
  271. X  node->total_red=0;
  272. X  node->total_green=0;
  273. X  node->total_blue=0;
  274. X  return(node);
  275. }
  276. X
  277. /*
  278. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  279. %                                                                             %
  280. %                                                                             %
  281. %                                                                             %
  282. %  P r u n e C h i l d                                                        %
  283. %                                                                             %
  284. %                                                                             %
  285. %                                                                             %
  286. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  287. %
  288. %  Function PruneChild deletes the given node and merges its statistics into
  289. %  its parent.
  290. %
  291. %  The format of the PruneSubtree routine is:
  292. %
  293. %      PruneChild(node)
  294. %
  295. %  A description of each parameter follows.
  296. %
  297. %    o node: pointer to node in color cube tree that is to be pruned.
  298. %
  299. %
  300. */
  301. static void PruneChild(node)
  302. register Node
  303. X  *node;
  304. {
  305. X  register Node
  306. X    *parent;
  307. X
  308. X  /*
  309. X    Merge color statistics into parent.
  310. X  */
  311. X  parent=node->parent;
  312. X  parent->children&=~(1 << node->id);
  313. X  parent->number_unique+=node->number_unique;
  314. X  parent->total_red+=node->total_red;
  315. X  parent->total_green+=node->total_green;
  316. X  parent->total_blue+=node->total_blue;
  317. X  cube.nodes--;
  318. }
  319. X
  320. /*
  321. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  322. %                                                                             %
  323. %                                                                             %
  324. %                                                                             %
  325. %  P r u n e L e v e l                                                        %
  326. %                                                                             %
  327. %                                                                             %
  328. %                                                                             %
  329. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  330. %
  331. %  Procedure PruneLevel deletes all nodes at the bottom level of the color
  332. %  tree merging their color statistics into their parent node.
  333. %
  334. %  The format of the PruneLevel routine is:
  335. %
  336. %      PruneLevel(node)
  337. %
  338. %  A description of each parameter follows.
  339. %
  340. %    o node: pointer to node in color cube tree that is to be pruned.
  341. %
  342. %
  343. */
  344. static void PruneLevel(node)
  345. register Node
  346. X  *node;
  347. {
  348. X  register int
  349. X    id;
  350. X
  351. X  /*
  352. X    Traverse any children.
  353. X  */
  354. X  if (node->children > 0)
  355. X    for (id=0; id < 8; id++)
  356. X      if (node->children & (1 << id))
  357. X        PruneLevel(node->child[id]);
  358. X  if (node->level == (cube.depth-1))
  359. X    PruneChild(node);
  360. }
  361. X
  362. /*
  363. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  364. %                                                                             %
  365. %                                                                             %
  366. %                                                                             %
  367. %  R e d u c e                                                                %
  368. %                                                                             %
  369. %                                                                             %
  370. %                                                                             %
  371. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  372. %
  373. %  Function Reduce traverses the color cube tree and prunes any node whose
  374. %  number of colors fall below a particular threshold.
  375. %
  376. %  The format of the Reduce routine is:
  377. %
  378. %      Reduce(node)
  379. %
  380. %  A description of each parameter follows.
  381. %
  382. %    o node: pointer to node in color cube tree that is to be pruned.
  383. %
  384. %
  385. */
  386. static void Reduce(node)
  387. register Node
  388. X  *node;
  389. {
  390. X  register unsigned int
  391. X    id;
  392. X
  393. X  /*
  394. X    Traverse any children.
  395. X  */
  396. X  if (node->children > 0)
  397. X    for (id=0; id < 8; id++)
  398. X      if (node->children & (1 << id))
  399. X        Reduce(node->child[id]);
  400. X  if (node->number_colors <= cube.pruning_threshold)
  401. X    {
  402. X      /*
  403. X        Node has a sub-threshold color count so prune it.  Node is an colormap
  404. X        entry if parent does not have any unique colors.
  405. X      */
  406. X      if (node->parent->number_unique == 0)
  407. X        cube.colors++;
  408. X      PruneChild(node);
  409. X      if (node->parent->number_colors < cube.next_pruning_threshold)
  410. X        cube.next_pruning_threshold=node->parent->number_colors;
  411. X    }
  412. X  else
  413. X    {
  414. X      /*
  415. X        Find minimum pruning threshold.  Node is a colormap entry if it has
  416. X        unique colors.
  417. X      */
  418. X      if (node->number_unique > 0)
  419. X        cube.colors++;
  420. X      if (node->number_colors < cube.next_pruning_threshold)
  421. X        cube.next_pruning_threshold=node->number_colors;
  422. X    }
  423. }
  424. X
  425. /*
  426. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  427. %                                                                             %
  428. %                                                                             %
  429. %                                                                             %
  430. %  R e d u c t i o n                                                          %
  431. %                                                                             %
  432. %                                                                             %
  433. %                                                                             %
  434. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  435. %
  436. %  Function Reduction repeatedly prunes the tree until the number of nodes
  437. %  with n2 > 0 is less than or equal to the maximum number of colors allowed
  438. %  in the output image.  On any given iteration over the tree, it selects
  439. %  those nodes whose n1  count is minimal for pruning and merges their
  440. %  color statistics upward. It uses a pruning threshold, ns, to govern
  441. %  node selection as follows:
  442. %
  443. %    ns = 0
  444. %    while number of nodes with (n2 > 0) > required maximum number of colors
  445. %      prune all nodes such that n1 <= ns
  446. %      Set ns to minimum n1 in remaining nodes
  447. %
  448. %  When a node to be pruned has offspring, the pruning procedure invokes
  449. %  itself recursively in order to prune the tree from the leaves upward.
  450. %  n2,  Sr, Sg,  and  Sb in a node being pruned are always added to the
  451. %  corresponding data in that node's parent.  This retains the pruned
  452. %  node's color characteristics for later averaging.
  453. %
  454. %  For each node, n2 pixels exist for which that node represents the
  455. %  smallest volume in RGB space containing those pixel's colors.  When n2
  456. %  > 0 the node will uniquely define a color in the output image. At the
  457. %  beginning of reduction,  n2 = 0  for all nodes except a the leaves of
  458. %  the tree which represent colors present in the input image.
  459. %
  460. %  The other pixel count, n1, indicates the total number of colors
  461. %  within the cubic volume which the node represents.  This includes n1 -
  462. %  n2  pixels whose colors should be defined by nodes at a lower level in
  463. %  the tree.
  464. %
  465. %  The format of the Reduction routine is:
  466. %
  467. %      Reduction(number_colors)
  468. %
  469. %  A description of each parameter follows.
  470. %
  471. %    o number_colors: This integer value indicates the maximum number of
  472. %      colors in the quantized image or colormap.  The actual number of
  473. %      colors allocated to the colormap may be less than this value, but
  474. %      never more.  Note, the number of colors is restricted to a value
  475. %      less than or equal to 65536 if the continuous_tone parameter has a
  476. %      value of zero.
  477. %
  478. %
  479. */
  480. static void Reduction(number_colors)
  481. register unsigned int
  482. X  number_colors;
  483. {
  484. X  cube.next_pruning_threshold=1;
  485. X  while (cube.colors > number_colors)
  486. X  {
  487. X    cube.pruning_threshold=cube.next_pruning_threshold;
  488. X    cube.next_pruning_threshold=cube.root->number_colors-1;
  489. X    cube.colors=0;
  490. X    Reduce(cube.root);
  491. X  }
  492. }
  493. X
  494. /*
  495. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  496. %                                                                             %
  497. %                                                                             %
  498. %                                                                             %
  499. %  Q u a n t i z a t i o n E r r o r                                          %
  500. %                                                                             %
  501. %                                                                             %
  502. %                                                                             %
  503. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  504. %
  505. %  Function QuantizationError measures the difference between the original
  506. %  and quantized images.  This difference is the total quantization error.
  507. %  The error is computed by summing over all pixels in an image the distance
  508. %  squared in RGB space between each reference pixel value and its quantized
  509. %  value.
  510. %
  511. %  The format of the QuantizationError routine is:
  512. %
  513. %      QuantizationError(image,mean_error_per_pixel,
  514. %        normalized_mean_square_error,normalized_maximum_square_error)
  515. %
  516. %  A description of each parameter follows.
  517. %
  518. %    o image: The address of a byte (8 bits) array of run-length
  519. %      encoded pixel data of your reference image.  The sum of the
  520. %      run-length counts in the reference image must be equal to or exceed
  521. %      the number of pixels.
  522. %
  523. %    o mean_error_per_pixel: The address of an integer value.  The value
  524. %      returned is the mean error for any single pixel in the image.
  525. %
  526. %    o normalized_mean_square_error: The address of a real value.  The value
  527. %      returned is the normalized mean quantization error for any single
  528. %      pixel in the image.  This distance measure is normalized to a
  529. %      range between 0 and 1.  It is independent of the range of red,
  530. %      green, and blue values in your image.
  531. %
  532. %    o normalized_maximum_square_error: The address of a real value.  The value
  533. %      returned is the normalized maximum quantization error for any
  534. %      single pixel in the image.  This distance measure is normalized to
  535. %      a range between 0 and 1.  It is independent of the range of red,
  536. %      green, and blue values in your image.
  537. %
  538. %
  539. */
  540. void QuantizationError(image,mean_error_per_pixel,normalized_mean_square_error,
  541. X  normalized_maximum_square_error)
  542. Image
  543. X  *image;
  544. X
  545. unsigned int
  546. X  *mean_error_per_pixel;
  547. X
  548. double
  549. X  *normalized_mean_square_error,
  550. X  *normalized_maximum_square_error;
  551. {
  552. X  register int
  553. X    i;
  554. X
  555. X  register RunlengthPacket
  556. X    *p;
  557. X
  558. X  register unsigned int
  559. X    blue_distance,
  560. X    green_distance,
  561. X    red_distance;
  562. X
  563. X  unsigned long int
  564. X    distance,
  565. X    maximum_error_per_pixel,
  566. X    total_error;
  567. X
  568. X  /*
  569. X    For each pixel, collect error statistics.
  570. X  */
  571. X  for (i=(-MaxRGB); i <= MaxRGB; i++)
  572. X    cube.squares[i+MaxRGB]=i*i;
  573. X  maximum_error_per_pixel=0;
  574. X  total_error=0;
  575. X  p=image->pixels;
  576. X  for (i=0; i < image->packets; i++)
  577. X  {
  578. X    red_distance=(int) p->red-(int) image->colormap[p->index].red+MaxRGB;
  579. X    green_distance=(int) p->green-(int) image->colormap[p->index].green+MaxRGB;
  580. X    blue_distance=(int) p->blue-(int) image->colormap[p->index].blue+MaxRGB;
  581. X    distance=cube.squares[red_distance]+cube.squares[green_distance]+
  582. X      cube.squares[blue_distance];
  583. X    total_error+=(distance*(p->length+1));
  584. X    if (distance > maximum_error_per_pixel)
  585. X      maximum_error_per_pixel=distance;
  586. X    p++;
  587. X  }
  588. X  /*
  589. X    Compute final error statistics.
  590. X  */
  591. X  *mean_error_per_pixel=(unsigned int) total_error/(image->columns*image->rows);
  592. X  *normalized_mean_square_error=((double) *mean_error_per_pixel)/
  593. X    (3.0*MaxRGB*MaxRGB);
  594. X  *normalized_maximum_square_error=((double) maximum_error_per_pixel)/
  595. X    (3.0*MaxRGB*MaxRGB);
  596. }
  597. X
  598. /*
  599. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  600. %                                                                             %
  601. %                                                                             %
  602. %                                                                             %
  603. %  Q u a n t i z e I m a g e                                                  %
  604. %                                                                             %
  605. %                                                                             %
  606. %                                                                             %
  607. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  608. %
  609. %  Function QuantizeImage analyzes the colors within a reference image and
  610. %  chooses a fixed number of colors to represent the image.  The goal of the
  611. %  algorithm is to minimize the difference between the input and output image
  612. %  while minimizing the processing time.
  613. %
  614. %  The format of the Quantize routine is:
  615. %
  616. %      colors=QuantizeImage(image,number_colors,tree_depth,dither,optimal)
  617. %
  618. %  A description of each parameter follows.
  619. %
  620. %    o colors: The QuantizeImage function returns this integer
  621. %      value.  It is the actual number of colors allocated in the
  622. %      colormap.  Note, the actual number of colors allocated may be less
  623. %      than the number of colors requested, but never more.
  624. %
  625. %    o image: Specifies a pointer to an Image structure;  returned from
  626. %      ReadImage.
  627. %
  628. %    o number_colors: This integer value indicates the maximum number of
  629. %      colors in the quantized image or colormap.  The actual number of
  630. %      colors allocated to the colormap may be less than this value, but
  631. %      never more.  Note, the number of colors is restricted to a value
  632. %      less than or equal to 65536 if the continuous_tone parameter has a
  633. %      value of zero.
  634. %
  635. %    o tree_depth: Normally, this integer value is zero or one.  A zero or
  636. %      one tells Quantize to choose a optimal tree depth of Log4(number_colors).
  637. %      A tree of this depth generally allows the best representation of the
  638. %      reference image with the least amount of memory and the fastest
  639. %      computational speed.  In some cases, such as an image with low color
  640. %      dispersion (a few number of colors), a value other than
  641. %      Log4(number_colors) is required.  To expand the color tree completely,
  642. %      use a value of 8.
  643. %
  644. %    o dither: Set this integer value to something other than zero to
  645. %      dither the quantized image.  The basic strategy of dithering is to
  646. %      trade intensity resolution for spatial resolution by averaging the
  647. %      intensities of several neighboring pixels.  Images which suffer
  648. %      from severe contouring when quantized can be improved with the
  649. %      technique of dithering.  Severe contouring generally occurs when
  650. %      quantizing to very few colors, or to a poorly-chosen colormap.
  651. %      Note, dithering is a computationally expensive process and will
  652. %      increase processing time significantly.
  653. %
  654. %    o colorspace: An unsigned integer value that indicates the colorspace.
  655. %      Empirical evidence suggests that distances in YUV or YIQ correspond to
  656. %      perceptual color differences more closely than do distances in RGB
  657. %      space.  The image is then returned to RGB colorspace after color
  658. %      reduction.
  659. %
  660. %    o optimal: An unsigned integer value greater than zero indicates that
  661. %      the optimal representation of the reference image should be returned.
  662. %
  663. %
  664. */
  665. void QuantizeImage(image,number_colors,tree_depth,dither,colorspace,optimal)
  666. Image
  667. X  *image;
  668. X
  669. unsigned int
  670. X  number_colors,
  671. X  tree_depth,
  672. X  dither,
  673. X  colorspace,
  674. X  optimal;
  675. {
  676. X  Nodes
  677. X    *nodes;
  678. X
  679. X  /*
  680. X    Reduce the number of colors in the continuous tone image.
  681. X  */
  682. X  if (number_colors > MaxColormapSize)
  683. X    number_colors=MaxColormapSize;
  684. X  InitializeCube(number_colors,tree_depth,image->columns*image->rows,optimal);
  685. X  if ((image->compression == RunlengthEncodedCompression) &&
  686. X      (image->packets == (image->columns*image->rows)))
  687. X    CompressImage(image);
  688. X  if (colorspace != RGBColorspace)
  689. X    RGBTransformImage(image,colorspace);
  690. X  Classification(image);
  691. X  if (!optimal)
  692. X    dither|=cube.colors > (1 << (cube.depth-1));
  693. X  Reduction(number_colors);
  694. X  Assignment(image,dither,optimal);
  695. X  if (colorspace != RGBColorspace)
  696. X    TransformRGBImage(image,colorspace);
  697. X  /*
  698. X    Release color cube tree storage.
  699. X  */
  700. X  do
  701. X  {
  702. X    nodes=cube.node_queue->next;
  703. X    (void) free((char *) cube.node_queue);
  704. X    cube.node_queue=nodes;
  705. X  }
  706. X  while (cube.node_queue != (Nodes *) NULL);
  707. }
  708. X
  709. /*
  710. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  711. %                                                                             %
  712. %                                                                             %
  713. %                                                                             %
  714. %   Q u a n t i z e I m a g e s                                               %
  715. %                                                                             %
  716. %                                                                             %
  717. %                                                                             %
  718. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  719. %
  720. %  QuantizeImages analyzes the colors within a set of reference images and
  721. %  chooses a fixed number of colors to represent the set.  The goal of the
  722. %  algorithm is to minimize the difference between the input and output images
  723. %  while minimizing the processing time.
  724. %
  725. %  The format of the QuantizeImages routine is:
  726. %
  727. %      QuantizeImages(images,number_images,number_colors,tree_depth,dither,
  728. %        optimal)
  729. %
  730. %  A description of each parameter follows:
  731. %
  732. %    o images: Specifies a pointer to a set of Image structures.
  733. %
  734. %    o number_images:  Specifies an unsigned integer representing the number
  735. %      images in the image set.
  736. %
  737. %    o colormap_image: Specifies a pointer to a Image structure.  Reduce
  738. %      images to a set of colors represented by this image.
  739. %
  740. %    o number_colors: This integer value indicates the maximum number of
  741. %      colors in the quantized image or colormap.  The actual number of colors
  742. %      allocated to the colormap may be less than this value, but never more.
  743. %      Note, the number of colors is restricted to a value less than or equal
  744. %      to 65536 if the quantized image is not DirectClass.
  745. %
  746. %    o tree_depth: Normally, this integer value is zero or one.  A zero or
  747. %      one tells QUANTIZE to choose a optimal tree depth.  An optimal depth
  748. %      generally allows the best representation of the reference image with the
  749. %      fastest computational speed and the least amount of memory.  However,
  750. %      the default depth is inappropriate for some images.  To assure the best
  751. %      representation, try values between 2 and 8 for this parameter.
  752. %
  753. %    o dither: Set this integer value to something other than zero to
  754. %      dither the quantized image.  The basic strategy of dithering is to
  755. %      trade intensity resolution for spatial resolution by averaging the
  756. %      intensities of several neighboring pixels.  Images which suffer
  757. %      from severe contouring when quantized can be improved with the
  758. %      technique of dithering.  Severe contouring generally occurs when
  759. %      quantizing to very few colors, or to a poorly-chosen colormap.
  760. %      Note, dithering is a computationally expensive process and will
  761. %      increase processing time significantly.
  762. %
  763. %    o colorspace: An unsigned integer value that indicates the colorspace.
  764. %      Empirical evidence suggests that distances in YUV or YIQ correspond to
  765. %      perceptual color differences more closely than do distances in RGB
  766. %      space.  The image is then returned to RGB colorspace after color
  767. %      reduction.
  768. %
  769. %    o optimal: An unsigned integer value greater than zero indicates that
  770. %      the optimal representation of the reference image should be returned.
  771. %
  772. %
  773. */
  774. void QuantizeImages(images,number_images,colormap_image,number_colors,
  775. X  tree_depth,dither,colorspace,optimal)
  776. Image
  777. X  **images;
  778. X
  779. unsigned int
  780. X  number_images;
  781. X
  782. Image
  783. X  *colormap_image;
  784. X
  785. unsigned int
  786. X  number_colors,
  787. X  tree_depth,
  788. X  dither,
  789. X  colorspace,
  790. X  optimal;
  791. {
  792. X  Nodes
  793. X    *nodes;
  794. X
  795. X  register unsigned int
  796. X    i;
  797. X
  798. X  /*
  799. X    Reduce the number of colors in the continuous tone image sequence.
  800. X  */
  801. X  InitializeCube(number_colors,tree_depth,~0,optimal);
  802. X  if (colormap_image != (Image *) NULL)
  803. X    {
  804. X      /*
  805. X        Reduce images to a set of colors represented by the colormap image.
  806. X      */
  807. X      if ((colormap_image->compression == RunlengthEncodedCompression) &&
  808. X          (colormap_image->packets ==
  809. X           (colormap_image->columns*colormap_image->rows)))
  810. X        CompressImage(colormap_image);
  811. X      if (colorspace != RGBColorspace)
  812. X        RGBTransformImage(colormap_image,colorspace);
  813. X      Classification(colormap_image);
  814. X      if (colorspace != RGBColorspace)
  815. X        TransformRGBImage(colormap_image,colorspace);
  816. X      optimal=True;
  817. X    }
  818. X  for (i=0; i < number_images; i++)
  819. X  {
  820. X    if ((images[i]->compression == RunlengthEncodedCompression) &&
  821. X        (images[i]->packets == (images[i]->columns*images[i]->rows)))
  822. X      CompressImage(images[i]);
  823. X    if (colorspace != RGBColorspace)
  824. X      RGBTransformImage(images[i],colorspace);
  825. X    if (colormap_image == (Image *) NULL)
  826. X      Classification(images[i]);
  827. X  }
  828. X  if (!optimal)
  829. X    dither|=cube.colors > (1 << (cube.depth-1));
  830. X  Reduction(number_colors);
  831. X  for (i=0; i < number_images; i++)
  832. X  {
  833. X    Assignment(images[i],dither,optimal);
  834. X    if (colorspace != RGBColorspace)
  835. X      TransformRGBImage(images[i],colorspace);
  836. X  }
  837. X  /*
  838. X    Release color cube tree storage.
  839. X  */
  840. X  do
  841. X  {
  842. X    nodes=cube.node_queue->next;
  843. X    (void) free((char *) cube.node_queue);
  844. X    cube.node_queue=nodes;
  845. X  }
  846. X  while (cube.node_queue != (Nodes *) NULL);
  847. }
  848. SHAR_EOF
  849. echo 'File ImageMagick/quantize.c is complete' &&
  850. chmod 0644 ImageMagick/quantize.c ||
  851. echo 'restore of ImageMagick/quantize.c failed'
  852. Wc_c="`wc -c < 'ImageMagick/quantize.c'`"
  853. test 60634 -eq "$Wc_c" ||
  854.     echo 'ImageMagick/quantize.c: original size 60634, current size' "$Wc_c"
  855. rm -f _shar_wnt_.tmp
  856. fi
  857. # ============= ImageMagick/rotate.c ==============
  858. if test -f 'ImageMagick/rotate.c' -a X"$1" != X"-c"; then
  859.     echo 'x - skipping ImageMagick/rotate.c (File already exists)'
  860.     rm -f _shar_wnt_.tmp
  861. else
  862. > _shar_wnt_.tmp
  863. echo 'x - extracting ImageMagick/rotate.c (Text)'
  864. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/rotate.c' &&
  865. /*
  866. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  867. %                                                                             %
  868. %                                                                             %
  869. %                                                                             %
  870. %                 RRRR    OOO   TTTTT   AAA   TTTTT   EEEEE                   %
  871. %                 R   R  O   O    T    A   A    T     E                       %
  872. %                 RRRR   O   O    T    AAAAA    T     EEE                     %
  873. %                 R R    O   O    T    A   A    T     E                       %
  874. %                 R  R    OOO     T    A   A    T     EEEEE                   %
  875. %                                                                             %
  876. %                                                                             %
  877. %                Rotate a raster image by an arbitrary angle.                 %
  878. %                                                                             %
  879. %                                                                             %
  880. %                                                                             %
  881. %                           Software Design                                   %
  882. %                             John Cristy                                     %
  883. %                              July 1992                                      %
  884. %                                                                             %
  885. %                                                                             %
  886. %  Copyright 1992 E. I. du Pont de Nemours & Company                          %
  887. %                                                                             %
  888. %  Permission to use, copy, modify, distribute, and sell this software and    %
  889. %  its documentation for any purpose is hereby granted without fee,           %
  890. %  provided that the above Copyright notice appear in all copies and that     %
  891. %  both that Copyright notice and this permission notice appear in            %
  892. %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
  893. %  & Company not be used in advertising or publicity pertaining to            %
  894. %  distribution of the software without specific, written prior               %
  895. %  permission.  E. I. du Pont de Nemours & Company makes no representations   %
  896. %  about the suitability of this software for any purpose.  It is provided    %
  897. %  "as is" without express or implied warranty.                               %
  898. %                                                                             %
  899. %  E. I. du Pont de Nemours & Company disclaims all warranties with regard    %
  900. %  to this software, including all implied warranties of merchantability      %
  901. %  and fitness, in no event shall E. I. du Pont de Nemours & Company be       %
  902. %  liable for any special, indirect or consequential damages or any           %
  903. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  904. %  in an action of contract, negligence or other tortious action, arising     %
  905. %  out of or in connection with the use or performance of this software.      %
  906. %                                                                             %
  907. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  908. %
  909. %  Function RotateImage is based on the paper "A Fast Algorithm for General
  910. %  Raster Rotatation" by Alan W. Paeth.  RotateImage is adapted from a similiar
  911. %  routine based on the Paeth paper written by Michael Halle of the Spatial
  912. %  Imaging Group, MIT Media Lab.
  913. %
  914. */
  915. X
  916. /*
  917. X  Include declarations.
  918. */
  919. #include "display.h"
  920. #include "image.h"
  921. X
  922. /*
  923. X  External declarations.
  924. */
  925. extern char
  926. X  *application_name;
  927. X
  928. /*
  929. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  930. %                                                                             %
  931. %                                                                             %
  932. %                                                                             %
  933. %   C o l u m n S h e a r                                                     %
  934. %                                                                             %
  935. %                                                                             %
  936. %                                                                             %
  937. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  938. %
  939. %  Procedure ColumnShear displaces a subcolumn of pixels a specified number of
  940. %  pixels.
  941. %
  942. %  The format of the ColumnShear routine is:
  943. %
  944. %      ColumnShear(source_image,source_columns,column,y,length,displacement,
  945. %        background)
  946. %
  947. %  A description of each parameter follows.
  948. %
  949. %    o source_image: A pointer to a ColorPacket structure which contains the
  950. %      source image.
  951. %
  952. %    o source_columns: Specifies the number of columns in the source image.
  953. %
  954. %    o column: Specifies which column in the image to move.
  955. %
  956. %    o y: Specifies the offset in the source image.
  957. %
  958. %    o length: Specifies the number of pixels to move.
  959. %
  960. %    o displacement: Specifies the number of pixels to displace the column of
  961. %      pixels.
  962. %
  963. %    o background: Specifies the background color.
  964. %
  965. %
  966. */
  967. static void ColumnShear(source_image,source_columns,column,y,length,
  968. X  displacement,background,range_limit)
  969. ColorPacket
  970. X  *source_image;
  971. X
  972. register unsigned int
  973. X  source_columns;
  974. X
  975. unsigned int
  976. X  column,
  977. X  y,
  978. X  length;
  979. X
  980. double
  981. X  displacement;
  982. X
  983. ColorPacket
  984. X  background;
  985. X
  986. register unsigned char
  987. X  *range_limit;
  988. {
  989. X  ColorPacket
  990. X    last_pixel;
  991. X
  992. X  enum {UP,DOWN}
  993. X    direction;
  994. X
  995. X  int
  996. X    blue,
  997. X    green,
  998. X    red,
  999. X    step;
  1000. X
  1001. X  long int
  1002. X    fractional_step;
  1003. X
  1004. X  register ColorPacket
  1005. X    *p,
  1006. X    *q;
  1007. X
  1008. X  register int
  1009. X    i;
  1010. X
  1011. X  if (displacement == 0.0)
  1012. X    return;
  1013. X  else
  1014. X    if (displacement > 0.0)
  1015. X      direction=DOWN;
  1016. X    else
  1017. X      {
  1018. X        displacement*=(-1.0);
  1019. X        direction=UP;
  1020. X      }
  1021. X  step=(int) floor(displacement);
  1022. X  fractional_step=UpShifted(displacement-(double) step);
  1023. X  if (fractional_step == 0)
  1024. X    {
  1025. X      /*
  1026. X        No fractional displacement-- just copy the pixels.
  1027. X      */
  1028. X      switch (direction)
  1029. X      {
  1030. X        case UP:
  1031. X        {
  1032. X          p=source_image+y*source_columns+column;
  1033. X          q=p-step*source_columns;
  1034. X          for (i=0; i < length; i++)
  1035. X          {
  1036. X            *q=(*p);
  1037. X            q+=source_columns;
  1038. X            p+=source_columns;
  1039. X          }
  1040. X          /*
  1041. X            Set old column to background color.
  1042. X          */
  1043. X          for (i=0; i < step; i++)
  1044. X          {
  1045. X            *q=background;
  1046. X            q+=source_columns;
  1047. X          }
  1048. X          break;
  1049. X        }
  1050. X        case DOWN:
  1051. X        {
  1052. X          p=source_image+(y+length)*source_columns+column;
  1053. X          q=p+step*source_columns;
  1054. X          for (i=0; i < length; i++)
  1055. X          {
  1056. X            q-=source_columns;
  1057. X            p-=source_columns;
  1058. X            *q=(*p);
  1059. X          }
  1060. X          /*
  1061. X            Set old column to background color.
  1062. X          */
  1063. X          for (i=0; i < step; i++)
  1064. X          {
  1065. X            q-=source_columns;
  1066. X            *q=background;
  1067. X          }
  1068. X          break;
  1069. X        }
  1070. X      }
  1071. X      return;
  1072. X    }
  1073. X  /*
  1074. X    Fractional displacment.
  1075. X  */
  1076. X  step++;
  1077. X  last_pixel=background;
  1078. X  switch (direction)
  1079. X  {
  1080. X    case UP:
  1081. X    {
  1082. X      p=source_image+y*source_columns+column;
  1083. X      q=p-step*source_columns;
  1084. X      for (i=0; i < length; i++)
  1085. X      {
  1086. X        red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+p->red*
  1087. X          fractional_step);
  1088. X        green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+p->green*
  1089. X          fractional_step);
  1090. X        blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+p->blue*
  1091. X          fractional_step);
  1092. X        last_pixel=(*p);
  1093. X        p+=source_columns;
  1094. X        q->red=range_limit[red];
  1095. X        q->green=range_limit[green];
  1096. X        q->blue=range_limit[blue];
  1097. X        q+=source_columns;
  1098. X      }
  1099. X      /*
  1100. X        Set old column to background color.
  1101. X      */
  1102. X      red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+
  1103. X        background.red*fractional_step);
  1104. X      green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+
  1105. X        background.green*fractional_step);
  1106. X      blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+
  1107. X        background.blue*fractional_step);
  1108. X      q->red=range_limit[red];
  1109. X      q->green=range_limit[green];
  1110. X      q->blue=range_limit[blue];
  1111. X      q+=source_columns;
  1112. X      for (i=0; i < step-1; i++)
  1113. X      {
  1114. X        *q=background;
  1115. X        q+=source_columns;
  1116. X      }
  1117. X      break;
  1118. X    }
  1119. X    case DOWN:
  1120. X    {
  1121. X      p=source_image+(y+length)*source_columns+column;
  1122. X      q=p+step*source_columns;
  1123. X      for (i=0; i < length; i++)
  1124. X      {
  1125. X        p-=source_columns;
  1126. X        red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+p->red*
  1127. X          fractional_step);
  1128. X        green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+p->green*
  1129. X          fractional_step);
  1130. X        blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+p->blue*
  1131. X          fractional_step);
  1132. X        last_pixel=(*p);
  1133. X        q-=source_columns;
  1134. X        q->red=range_limit[red];
  1135. X        q->green=range_limit[green];
  1136. X        q->blue=range_limit[blue];
  1137. X      }
  1138. X      /*
  1139. X        Set old column to background color.
  1140. X      */
  1141. X      red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+
  1142. X        background.red*fractional_step);
  1143. X      green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+
  1144. X        background.green*fractional_step);
  1145. X      blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+
  1146. X        background.blue*fractional_step);
  1147. X      q-=source_columns;
  1148. X      q->red=range_limit[red];
  1149. X      q->green=range_limit[green];
  1150. X      q->blue=range_limit[blue];
  1151. X      for (i=0; i < step-1; i++)
  1152. X      {
  1153. X        q-=source_columns;
  1154. X        *q=background;
  1155. X      }
  1156. X      break;
  1157. X    }
  1158. X  }
  1159. X  return;
  1160. }
  1161. X
  1162. /*
  1163. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1164. %                                                                             %
  1165. %                                                                             %
  1166. %                                                                             %
  1167. %   I n t e g r a l R o t a t i o n                                           %
  1168. %                                                                             %
  1169. %                                                                             %
  1170. %                                                                             %
  1171. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1172. %
  1173. %  Function IntegralRotation rotates the source image starting at location
  1174. %  (x,y) an integral of 90 degrees and copies the result to the rotated image
  1175. %  buffer.
  1176. %
  1177. %  The format of the IntegralRotation routine is:
  1178. %
  1179. %      IntegralRotation(image,source_columns,source_rows,rotated_image,
  1180. %        rotated_columns,x,y,rotations)
  1181. %
  1182. %  A description of each parameter follows.
  1183. %
  1184. %    o source_image: A pointer to a Image structure containing the source
  1185. %      image.
  1186. %
  1187. %    o source_columns: Specifies the number of columns of pixels in the
  1188. %      source image.
  1189. %
  1190. %    o source_rows: Specifies the number of rows of pixels in the source
  1191. %      image.
  1192. %
  1193. %    o rotated_image: A pointer to a ColorPacket structure containing the
  1194. %      rotated image.
  1195. %
  1196. %    o rotated_columns: Specifies the number of columns of pixels in the
  1197. %      rotated image.
  1198. %
  1199. %    o x: Specifies the x offset in the source image.
  1200. %
  1201. %    o y: Specifies the y offset in the source image.
  1202. %
  1203. %    o rotations: Specifies the number of 90 degree rotations.
  1204. %
  1205. %
  1206. */
  1207. static void IntegralRotation(image,source_columns,source_rows,rotated_image,
  1208. X  rotated_columns,x,y,rotations)
  1209. Image
  1210. X  *image;
  1211. X
  1212. unsigned int
  1213. X  source_columns,
  1214. X  source_rows;
  1215. X
  1216. ColorPacket
  1217. X  *rotated_image;
  1218. X
  1219. unsigned int
  1220. X  rotated_columns,
  1221. X  x,
  1222. X  y,
  1223. X  rotations;
  1224. {
  1225. X  ColorPacket
  1226. X    *q;
  1227. X
  1228. X  register RunlengthPacket
  1229. X    *p;
  1230. X
  1231. X  register int
  1232. X    i,
  1233. X    j;
  1234. X
  1235. X  /*
  1236. X    Expand runlength packets into a rectangular array of pixels.
  1237. X  */
  1238. X  p=image->pixels;
  1239. X  image->runlength=p->length+1;
  1240. X  switch (rotations)
  1241. X  {
  1242. X    case 0:
  1243. X    {
  1244. X      /*
  1245. X        Rotate 0 degrees.
  1246. X      */
  1247. X      for (j=0; j < source_rows; j++)
  1248. X      {
  1249. X        q=rotated_image+rotated_columns*(y+j)+x;
  1250. X        for (i=0; i < source_columns; i++)
  1251. X        {
  1252. X          if (image->runlength > 0)
  1253. X            image->runlength--;
  1254. X          else
  1255. X            {
  1256. X              p++;
  1257. X              image->runlength=p->length;
  1258. X            }
  1259. X          q->red=p->red;
  1260. X          q->green=p->green;
  1261. X          q->blue=p->blue;
  1262. X          q->index=p->index;
  1263. X          q++;
  1264. X        }
  1265. X      }
  1266. X      break;
  1267. X    }
  1268. X    case 1:
  1269. X    {
  1270. X      /*
  1271. X        Rotate 90 degrees.
  1272. X      */
  1273. X      for (j=source_columns-1; j >= 0; j--)
  1274. X      {
  1275. X        q=rotated_image+rotated_columns*y+x+j;
  1276. X        for (i=0; i < source_rows; i++)
  1277. X        {
  1278. X          if (image->runlength > 0)
  1279. X            image->runlength--;
  1280. X          else
  1281. X            {
  1282. X              p++;
  1283. X              image->runlength=p->length;
  1284. X            }
  1285. X          q->red=p->red;
  1286. X          q->green=p->green;
  1287. X          q->blue=p->blue;
  1288. X          q->index=p->index;
  1289. X          q+=rotated_columns;
  1290. X        }
  1291. X      }
  1292. X      break;
  1293. X    }
  1294. X    case 2:
  1295. X    {
  1296. X      /*
  1297. X        Rotate 180 degrees.
  1298. X      */
  1299. X      q=rotated_image;
  1300. X      for (j=source_rows-1; j >= 0; j--)
  1301. X      {
  1302. X        q=rotated_image+rotated_columns*(y+j)+x+source_columns;
  1303. X        for (i=0; i < source_columns; i++)
  1304. X        {
  1305. X          if (image->runlength > 0)
  1306. X            image->runlength--;
  1307. X          else
  1308. X            {
  1309. X              p++;
  1310. X              image->runlength=p->length;
  1311. X            }
  1312. X          q--;
  1313. X          q->red=p->red;
  1314. X          q->green=p->green;
  1315. X          q->blue=p->blue;
  1316. X          q->index=p->index;
  1317. X        }
  1318. X      }
  1319. X      break;
  1320. X    }
  1321. X    case 3:
  1322. X    {
  1323. X      /*
  1324. X        Rotate 270 degrees.
  1325. X      */
  1326. X      for (j=0; j < source_columns; j++)
  1327. X      {
  1328. X        q=rotated_image+rotated_columns*(y+source_rows)+x+j-rotated_columns;
  1329. X        for (i=0; i < source_rows; i++)
  1330. X        {
  1331. X          if (image->runlength > 0)
  1332. X            image->runlength--;
  1333. X          else
  1334. X            {
  1335. X              p++;
  1336. X              image->runlength=p->length;
  1337. X            }
  1338. X          q->red=p->red;
  1339. X          q->green=p->green;
  1340. X          q->blue=p->blue;
  1341. X          q->index=p->index;
  1342. X          q-=rotated_columns;
  1343. X        }
  1344. X      }
  1345. X      break;
  1346. X    }
  1347. X    default:
  1348. X      break;
  1349. X  }
  1350. }
  1351. X
  1352. /*
  1353. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1354. %                                                                             %
  1355. %                                                                             %
  1356. %                                                                             %
  1357. %   R o w S h e a r                                                           %
  1358. %                                                                             %
  1359. %                                                                             %
  1360. %                                                                             %
  1361. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1362. %
  1363. %  Procedure RowShear displaces a subrow of pixels a specified number of
  1364. %  pixels.
  1365. %
  1366. %  The format of the RowShear routine is:
  1367. %
  1368. %      RowShear(source_image,source_columns,row,y,length,displacement,
  1369. %        background)
  1370. %
  1371. %  A description of each parameter follows.
  1372. %
  1373. %    o source_image: A pointer to a ColorPacket structure.
  1374. %
  1375. %    o source_columns: Specifies the number of columns in the source image.
  1376. %
  1377. %    o row: Specifies which row in the image to move.
  1378. %
  1379. %    o y: Specifies the offset in the source image.
  1380. %
  1381. %    o length: Specifies the number of pixels to move.
  1382. %
  1383. %    o displacement: Specifies the number of pixels to displace the row of
  1384. %      pixels.
  1385. %
  1386. %    o background: Specifies the background color.
  1387. %
  1388. %
  1389. */
  1390. static void RowShear(source_image,source_columns,row,x,length,displacement,
  1391. X  background,range_limit)
  1392. ColorPacket
  1393. X  *source_image;
  1394. X
  1395. unsigned int
  1396. X  source_columns,
  1397. X  row,
  1398. X  x,
  1399. X  length;
  1400. X
  1401. double
  1402. X  displacement;
  1403. X
  1404. ColorPacket
  1405. X  background;
  1406. X
  1407. register unsigned char
  1408. X  *range_limit;
  1409. {
  1410. X  ColorPacket
  1411. X    last_pixel;
  1412. X
  1413. X  enum {LEFT,RIGHT}
  1414. X    direction;
  1415. X
  1416. X  int
  1417. X    blue,
  1418. X    green,
  1419. X    red,
  1420. X    step;
  1421. X
  1422. X  long int
  1423. X    fractional_step;
  1424. X
  1425. X  register ColorPacket
  1426. X    *p,
  1427. X    *q;
  1428. X
  1429. X  register int
  1430. X    i;
  1431. X
  1432. X  if (displacement == 0.0)
  1433. X    return;
  1434. X  else
  1435. X    if (displacement > 0.0)
  1436. X      direction=RIGHT;
  1437. X    else
  1438. X      {
  1439. X        displacement*=(-1.0);
  1440. X        direction=LEFT;
  1441. X      }
  1442. X  step=(int) floor(displacement);
  1443. X  fractional_step=UpShifted(displacement-(double) step);
  1444. X  if (fractional_step == 0)
  1445. X    {
  1446. X      /*
  1447. X        No fractional displacement-- just copy.
  1448. X      */
  1449. X      switch (direction)
  1450. X      {
  1451. X        case LEFT:
  1452. X        {
  1453. X          p=source_image+row*source_columns+x;
  1454. X          q=p-step;
  1455. X          for (i=0; i < length; i++)
  1456. X          {
  1457. X            *q=(*p);
  1458. X            q++;
  1459. X            p++;
  1460. X          }
  1461. X          /*
  1462. X            Set old row to background color.
  1463. X          */
  1464. X          for (i=0; i < step; i++)
  1465. X          {
  1466. X            *q=background;
  1467. X            q++;
  1468. X          }
  1469. X          break;
  1470. X        }
  1471. X        case RIGHT:
  1472. X        {
  1473. X          /*
  1474. X            Right is the same as left except data is transferred backwards
  1475. X            to prevent deleting data we need later.
  1476. X          */
  1477. X          p=source_image+row*source_columns+x+length;
  1478. X          q=p+step;
  1479. X          for (i=0; i < length; i++)
  1480. X          {
  1481. X            p--;
  1482. X            q--;
  1483. X            *q=(*p);
  1484. X          }
  1485. X          /*
  1486. X            Set old row to background color.
  1487. X          */
  1488. X          for (i=0; i < step; i++)
  1489. X          {
  1490. X            q--;
  1491. X            *q=background;
  1492. X          }
  1493. X          break;
  1494. X        }
  1495. X      }
  1496. X      return;
  1497. X    }
  1498. X  /*
  1499. X    Fractional displacement.
  1500. X  */
  1501. X  step++;
  1502. X  last_pixel=background;
  1503. X  switch (direction)
  1504. X  {
  1505. X    case LEFT:
  1506. X    {
  1507. X      p=source_image+row*source_columns+x;
  1508. X      q=p-step;
  1509. X      for (i=0; i < length; i++)
  1510. X      {
  1511. X        red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+p->red*
  1512. X          fractional_step);
  1513. X        green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+p->green*
  1514. X          fractional_step);
  1515. X        blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+p->blue*
  1516. X          fractional_step);
  1517. X        last_pixel=(*p);
  1518. X        p++;
  1519. X        q->red=range_limit[red];
  1520. X        q->green=range_limit[green];
  1521. X        q->blue=range_limit[blue];
  1522. X        q++;
  1523. X      }
  1524. X      /*
  1525. X        Set old row to background color.
  1526. X      */
  1527. X      red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+
  1528. X        background.red*fractional_step);
  1529. X      green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+
  1530. X        background.green*fractional_step);
  1531. X      blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+
  1532. X        background.blue*fractional_step);
  1533. X      q->red=range_limit[red];
  1534. X      q->green=range_limit[green];
  1535. X      q->blue=range_limit[blue];
  1536. X      q++;
  1537. X      for (i=0; i < step-1; i++)
  1538. X      {
  1539. X        *q=background;
  1540. X        q++;
  1541. X      }
  1542. X      break;
  1543. X    }
  1544. X    case RIGHT:
  1545. X    {
  1546. X      p=source_image+row*source_columns+x+length;
  1547. X      q=p+step;
  1548. X      for (i=0; i < length; i++)
  1549. X      {
  1550. X        p--;
  1551. X        red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+p->red*
  1552. X          fractional_step);
  1553. X        green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+p->green*
  1554. X          fractional_step);
  1555. X        blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+p->blue*
  1556. X          fractional_step);
  1557. X        last_pixel=(*p);
  1558. X        q--;
  1559. X        q->red=range_limit[red];
  1560. X        q->green=range_limit[green];
  1561. X        q->blue=range_limit[blue];
  1562. X      }
  1563. X      /*
  1564. X        Set old row to background color.
  1565. X      */
  1566. X      red=DownShift(last_pixel.red*(UpShift(1)-fractional_step)+
  1567. X        background.red*fractional_step);
  1568. X      green=DownShift(last_pixel.green*(UpShift(1)-fractional_step)+
  1569. X        background.green*fractional_step);
  1570. X      blue=DownShift(last_pixel.blue*(UpShift(1)-fractional_step)+
  1571. X        background.blue*fractional_step);
  1572. X      q--;
  1573. X      q->red=range_limit[red];
  1574. X      q->green=range_limit[green];
  1575. X      q->blue=range_limit[blue];
  1576. X      for (i=0; i < step-1; i++)
  1577. X      {
  1578. X        q--;
  1579. X        *q=background;
  1580. X      }
  1581. X      break;
  1582. X    }
  1583. X  }
  1584. X  return;
  1585. }
  1586. X
  1587. /*
  1588. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1589. %                                                                             %
  1590. %                                                                             %
  1591. %                                                                             %
  1592. %   R o t a t e I m a g e                                                     %
  1593. %                                                                             %
  1594. %                                                                             %
  1595. %                                                                             %
  1596. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1597. %
  1598. %  Function RotateImage creates a new image that is a rotated copy of an
  1599. %  existing one.  It allocates the memory necessary for the new Image structure %  and returns a pointer to the new image.
  1600. %
  1601. %  Function RotateImage is based on the paper "A Fast Algorithm for General
  1602. %  Raster Rotatation" by Alan W. Paeth.  RotateImage is adapted from a similiar
  1603. %  routine based on the Paeth paper written by Michael Halle of the Spatial
  1604. %  Imaging Group, MIT Media Lab.
  1605. %
  1606. %  The format of the RotateImage routine is:
  1607. %
  1608. %      RotateImage(image,degrees,clip)
  1609. %
  1610. %  A description of each parameter follows.
  1611. %
  1612. %    o status: Function RotateImage returns a pointer to the image after
  1613. %      rotating.  A null image is returned if there is a memory shortage.
  1614. %
  1615. %    o image: The address of a structure of type Image;  returned from
  1616. %      ReadImage.
  1617. %
  1618. %    o degrees: Specifies the number of degrees to rotate the image.
  1619. %
  1620. %    o clip: A value other than zero clips the corners of the rotated
  1621. %      image and retains the original image size.
  1622. %
  1623. %
  1624. */
  1625. Image *RotateImage(image,degrees,clip)
  1626. Image
  1627. X  *image;
  1628. X
  1629. double
  1630. X  degrees;
  1631. X
  1632. int
  1633. X  clip;
  1634. {
  1635. #define DegreesToRadians(x) ((x)*3.14159265358979323846/180.0)
  1636. X
  1637. X  ColorPacket
  1638. X    background,
  1639. X    *rotated_pixels;
  1640. X
  1641. X  double
  1642. X    x_shear,
  1643. X    y_shear;
  1644. X
  1645. X  Image
  1646. X    *rotated_image;
  1647. X
  1648. X  register ColorPacket
  1649. X    *p;
  1650. X
  1651. X  register int
  1652. X    i,
  1653. X    x,
  1654. X    y;
  1655. X
  1656. X  register RunlengthPacket
  1657. X    *q;
  1658. X
  1659. X  unsigned int
  1660. X    number_rows,
  1661. X    number_columns,
  1662. X    rotations,
  1663. X    x_offset,
  1664. X    y_offset,
  1665. X    y_width;
  1666. X
  1667. X  /*
  1668. X    Adjust rotation angle.
  1669. X  */
  1670. X  while (degrees < -45.0)
  1671. X    degrees+=360.0;
  1672. X  rotations=0;
  1673. X  while (degrees > 45.0)
  1674. X  {
  1675. X    degrees-=90.0;
  1676. X    rotations++;
  1677. X  }
  1678. X  rotations%=4;
  1679. X  /*
  1680. X    Calculate shear equations.
  1681. X  */
  1682. X  x_shear=(-tan(DegreesToRadians(degrees)/2.0));
  1683. X  y_shear=sin(DegreesToRadians(degrees));
  1684. X  if ((rotations == 1) || (rotations == 3))
  1685. X    {
  1686. X      /*
  1687. X        Invert image size.
  1688. X      */
  1689. X      y_width=image->rows+
  1690. X        (int) ceil(fabs(x_shear)*(double) (image->columns-1));
  1691. X      number_columns=image->rows+2*
  1692. X        (int) ceil(fabs(x_shear)*(double) (image->columns-1));
  1693. X      number_rows=image->columns+
  1694. X        (int) ceil(fabs(y_shear)*(double) (y_width-1));
  1695. X      rotated_image=CopyImage(image,number_columns,number_rows,False);
  1696. X      if (rotated_image == (Image *) NULL)
  1697. X        {
  1698. X          Warning("unable to rotate image","memory allocation failed");
  1699. X          return((Image *) NULL);
  1700. X        }
  1701. X      rotated_image->columns=image->rows;
  1702. X      rotated_image->rows=image->columns;
  1703. X    }
  1704. X  else
  1705. X    {
  1706. X      y_width=image->columns+
  1707. X        (int) ceil(fabs(x_shear)*(double) (image->rows-1));
  1708. X      number_columns=image->columns+2*
  1709. X        (int) ceil(fabs(x_shear)*(double) (image->rows-1));
  1710. X      number_rows=image->rows+
  1711. X        (int) ceil(fabs(y_shear)*(double) (y_width-1));
  1712. X      rotated_image=CopyImage(image,number_columns,number_rows,False);
  1713. X      if (rotated_image == (Image *) NULL)
  1714. X        {
  1715. X          Warning("unable to rotate image","memory allocation failed");
  1716. X          return((Image *) NULL);
  1717. X        }
  1718. X      rotated_image->columns=image->columns;
  1719. X      rotated_image->rows=image->rows;
  1720. X    }
  1721. X  /*
  1722. X    Initialize rotated image attributes.
  1723. X  */
  1724. X  rotated_pixels=(ColorPacket *)
  1725. X    malloc(number_columns*(number_rows+2)*sizeof(ColorPacket));
  1726. X  if (rotated_pixels == (ColorPacket *) NULL)
  1727. X    {
  1728. X      Warning("unable to rotate image","memory allocation failed");
  1729. X      return((Image *) NULL);
  1730. X    }
  1731. X  if ((x_shear == 0.0) || (y_shear == 0.0))
  1732. X    {
  1733. X      /*
  1734. X        No shearing required; do integral rotation.
  1735. X      */
  1736. X      x_offset=0;
  1737. X      y_offset=0;
  1738. X      IntegralRotation(image,rotated_image->columns,rotated_image->rows,
  1739. X        rotated_pixels+number_columns,number_columns,x_offset,y_offset,
  1740. X        rotations);
  1741. X    }
  1742. X  else
  1743. X    {
  1744. X      typedef struct Point
  1745. X      {
  1746. X        double
  1747. X          x,
  1748. X          y;
  1749. X      } Point;
  1750. X
  1751. X      double
  1752. X        x_max,
  1753. X        x_min,
  1754. X        y_max,
  1755. X        y_min;
  1756. X
  1757. X      Point
  1758. X        corners[4];
  1759. X
  1760. X      unsigned char
  1761. X        *range_limit,
  1762. X        *range_table;
  1763. X
  1764. X      unsigned int
  1765. X        column,
  1766. X        row;
  1767. X
  1768. X      /*
  1769. X        Initialize rotated image buffer to background color.
  1770. X      */
  1771. X      rotated_image->class=DirectClass;
  1772. X      background.red=image->pixels[0].red;
  1773. X      background.green=image->pixels[0].green;
  1774. X      background.blue=image->pixels[0].blue;
  1775. X      p=rotated_pixels;
  1776. X      for (i=0; i < (number_columns*(number_rows+2)); i++)
  1777. X      {
  1778. X        *p=background;
  1779. X        p++;
  1780. X      }
  1781. X      /*
  1782. X        Perform an initial integral 90 degree rotation.
  1783. X      */
  1784. X      x_offset=(number_columns-rotated_image->columns)/2;
  1785. X      y_offset=(number_rows-rotated_image->rows)/2;
  1786. X      IntegralRotation(image,rotated_image->columns,rotated_image->rows,
  1787. X        rotated_pixels+number_columns,number_columns,x_offset,y_offset,
  1788. X        rotations);
  1789. X      /*
  1790. X        Initialize range table.
  1791. X      */
  1792. X      range_table=(unsigned char *) malloc(3*(MaxRGB+1)*sizeof(unsigned char));
  1793. X      if (range_table == (unsigned char *) NULL)
  1794. X        {
  1795. X          DestroyImage(rotated_image);
  1796. X          Warning("unable to rotate image","memory allocation failed");
  1797. X          return((Image *) NULL);
  1798. X        }
  1799. X      for (i=0; i <= MaxRGB; i++)
  1800. X      {
  1801. X        range_table[i]=0;
  1802. X        range_table[i+(MaxRGB+1)]=(unsigned char) i;
  1803. X        range_table[i+(MaxRGB+1)*2]=MaxRGB;
  1804. X      }
  1805. X      range_limit=range_table+(MaxRGB+1);
  1806. X      /*
  1807. X        Perform a fractional rotation.  First, shear the image rows.
  1808. X      */
  1809. X      row=(number_rows-rotated_image->rows)/2;
  1810. X      for (i=0; i < rotated_image->rows; i++)
  1811. X      {
  1812. X        RowShear(rotated_pixels+number_columns,number_columns,row,x_offset,
  1813. SHAR_EOF
  1814. true || echo 'restore of ImageMagick/rotate.c failed'
  1815. fi
  1816. echo 'End of  part 9'
  1817. echo 'File ImageMagick/rotate.c is continued in part 10'
  1818. echo 10 > _shar_seq_.tmp
  1819. exit 0
  1820. exit 0 # Just in case...
  1821.