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

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