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

  1. Newsgroups: comp.sources.x
  2. From: cristy@eplrx7.es.duPont.com (Cristy)
  3. Subject: v20i060:  imagemagic - X11 image processing and display, Part04/38
  4. Message-ID: <1993Jul14.175318.781@sparky.sterling.com>
  5. X-Md4-Signature: bd4d7ab9a920fc55b6a0e5848adef5ef
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Wed, 14 Jul 1993 17:53:18 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: cristy@eplrx7.es.duPont.com (Cristy)
  12. Posting-number: Volume 20, Issue 60
  13. Archive-name: imagemagic/part04
  14. Environment: X11
  15. Supersedes: imagemagic: Volume 13, Issue 17-37
  16.  
  17. #!/bin/sh
  18. # this is magick.04 (part 4 of ImageMagick)
  19. # do not concatenate these parts, unpack them in order with /bin/sh
  20. # file ImageMagick/utilities/segment.c continued
  21. #
  22. if test ! -r _shar_seq_.tmp; then
  23.     echo 'Please unpack part 1 first!'
  24.     exit 1
  25. fi
  26. (read Scheck
  27.  if test "$Scheck" != 4; then
  28.     echo Please unpack part "$Scheck" next!
  29.     exit 1
  30.  else
  31.     exit 0
  32.  fi
  33. ) < _shar_seq_.tmp || exit 1
  34. if test ! -f _shar_wnt_.tmp; then
  35.     echo 'x - still skipping ImageMagick/utilities/segment.c'
  36. else
  37. echo 'x - continuing file ImageMagick/utilities/segment.c'
  38. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/utilities/segment.c' &&
  39. %    -display server     obtain image or font from this X server
  40. %    -font name          X11 font for displaying text
  41. %    -geometry geometry  width and height of the image
  42. %    -interlace type     NONE, LINE, or PLANE
  43. %    -page geometry      size and location of the Postscript page
  44. %    -quality value      JPEG quality setting
  45. %    -scene value        image scene number
  46. %    -treedepth value    depth of the color classification tree
  47. %    -verbose            print detailed information about the image
  48. %
  49. %  Change '-' to '+' in any option above to reverse its effect.  For
  50. %  example,  specify +alpha to store the image without its alpha channel.
  51. %
  52. %  By default, the image format of `file' is determined by its magic
  53. %  number.  To specify a particular image format, precede the filename
  54. %  with an image format name and a colon (i.e. ps:image) or specify the
  55. %  image type as the filename suffix (i.e. image.ps).  Specify 'file' as
  56. %  '-' for standard input or output.
  57. %
  58. %
  59. */
  60. X
  61. #include "display.h"
  62. #include "image.h"
  63. #include "X.h"
  64. X
  65. /*
  66. X  Define declarations.
  67. */
  68. #define Blue  2
  69. #define Dimension  3
  70. #define Green  1
  71. #define Red  0
  72. #define SafeMargin  3
  73. X
  74. /*
  75. X  Typedef declarations.
  76. */
  77. typedef struct _ExtentPacket
  78. {
  79. X  short
  80. X    index,
  81. X    left,
  82. X    right;
  83. X
  84. X  long
  85. X    center;
  86. } ExtentPacket;
  87. X
  88. typedef struct _IntervalTree
  89. {
  90. X  float
  91. X    tau;
  92. X
  93. X  short
  94. X    left,
  95. X    right;
  96. X
  97. X  float
  98. X    mean_stability,
  99. X    stability;
  100. X
  101. X  struct _IntervalTree
  102. X    *sibling,
  103. X    *child;
  104. } IntervalTree;
  105. X
  106. typedef struct _ZeroCrossing
  107. {
  108. X  float
  109. X    tau,
  110. X    histogram[MaxRGB+1];
  111. X
  112. X  short
  113. X    crossings[MaxRGB+1];
  114. } ZeroCrossing;
  115. X
  116. /*
  117. X  Forward declarations.
  118. */
  119. static int
  120. X  DefineRegion _Declare((short *,ExtentPacket *));
  121. X
  122. static void
  123. X  ScaleSpace _Declare((long *,double,float *)),
  124. X  ZeroCrossHistogram _Declare((float *,double,short *));
  125. X
  126. void
  127. X  Error _Declare((char *,char *));
  128. X
  129. /*
  130. X  Global declarations.
  131. */
  132. char
  133. X  *client_name;
  134. X
  135. int
  136. X  number_nodes;
  137. X
  138. IntervalTree
  139. X  *list[600];
  140. X
  141. /*
  142. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  143. %                                                                             %
  144. %                                                                             %
  145. %                                                                             %
  146. %   C l a s s i f y                                                           %
  147. %                                                                             %
  148. %                                                                             %
  149. %                                                                             %
  150. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  151. %
  152. %
  153. %  Function Classify defines on ore more classes.  Each pixel is thresholded
  154. %  to determine which class it belongs to.  If not class is identified it
  155. %  is assigned to the closest class based on the fuzzy c-Means technique.
  156. %
  157. %  The format of the Classify routine is:
  158. %
  159. %      Classify(image,extrema,cluster_threshold,weighting_exponent,verbose)
  160. %
  161. %  A description of each parameter follows.
  162. %
  163. %    o image: Specifies a pointer to an Image structure;  returned from
  164. %      ReadImage.
  165. %
  166. %    o extrema:  Specifies a pointer to an array of shortegers.  They
  167. %      represent the peaks and valleys of the histogram for each color
  168. %      component.
  169. %
  170. %    o cluster_threshold:  This float represents the minimum number of pixels
  171. %      contained in a hexahedra before it can be considered valid (expressed
  172. %      as a percentage).
  173. %
  174. %    o weighting_exponent: Specifies the membership weighting exponent.
  175. %
  176. %    o verbose:  A value greater than zero prints detailed information about
  177. %      the identified classes.
  178. %
  179. %
  180. */
  181. static void Classify(image,extrema,cluster_threshold,weighting_exponent,verbose)
  182. Image
  183. X  *image;
  184. X
  185. short
  186. X  **extrema;
  187. X
  188. float
  189. X  cluster_threshold,
  190. X  weighting_exponent;
  191. X
  192. unsigned int
  193. X  verbose;
  194. {
  195. X  typedef struct _Cluster
  196. X  {
  197. X    short
  198. X      id;
  199. X
  200. X    ExtentPacket
  201. X      red,
  202. X      green,
  203. X      blue;
  204. X
  205. X    long
  206. X      count;
  207. X
  208. X    struct _Cluster
  209. X      *next;
  210. X  } Cluster;
  211. X
  212. X  Cluster
  213. X    *cluster,
  214. X    *head,
  215. X    *last_cluster,
  216. X    *next_cluster;
  217. X
  218. X  double
  219. X    distance,
  220. X    local_minima,
  221. X    numerator,
  222. X    ratio,
  223. X    sum;
  224. X
  225. X  ExtentPacket
  226. X    blue,
  227. X    green,
  228. X    red;
  229. X
  230. X  int
  231. X    blue_distance,
  232. X    count,
  233. X    green_distance,
  234. X    red_distance;
  235. X
  236. X  register int
  237. X    i,
  238. X    j,
  239. X    k;
  240. X
  241. X  register RunlengthPacket
  242. X    *p,
  243. X    *q;
  244. X
  245. X  unsigned int
  246. X    number_clusters;
  247. X
  248. X  /*
  249. X    Form clusters.
  250. X  */
  251. X  cluster=(Cluster *) NULL;
  252. X  head=(Cluster *) NULL;
  253. X  red.index=0;
  254. X  while (DefineRegion(extrema[Red],&red))
  255. X  {
  256. X    green.index=0;
  257. X    while (DefineRegion(extrema[Green],&green))
  258. X    {
  259. X      blue.index=0;
  260. X      while (DefineRegion(extrema[Blue],&blue))
  261. X      {
  262. X        /*
  263. X          Allocate a new class.
  264. X        */
  265. X        if (head != (Cluster *) NULL)
  266. X          {
  267. X            cluster->next=(Cluster *) malloc(sizeof(Cluster));
  268. X            cluster=cluster->next;
  269. X          }
  270. X        else
  271. X          {
  272. X            cluster=(Cluster *) malloc(sizeof(Cluster));
  273. X            head=cluster;
  274. X          }
  275. X        if (cluster == (Cluster *) NULL)
  276. X          {
  277. X            (void) fprintf(stderr,"duCMeans: unable to allocate memory\n");
  278. X            exit(1);
  279. X          }
  280. X        /*
  281. X          Initialize a new class.
  282. X        */
  283. X        cluster->count=0;
  284. X        cluster->red=red;
  285. X        cluster->green=green;
  286. X        cluster->blue=blue;
  287. X        cluster->next=(Cluster *) NULL;
  288. X      }
  289. X    }
  290. X  }
  291. X  if (head == (Cluster *) NULL)
  292. X    {
  293. X      /*
  294. X        No classes were identified-- create one.
  295. X      */
  296. X      cluster=(Cluster *) malloc(sizeof(Cluster));
  297. X      if (cluster == (Cluster *) NULL)
  298. X        Error("unable to allocate memory",(char *) NULL);
  299. X      /*
  300. X        Initialize a new class.
  301. X      */
  302. X      cluster->count=0;
  303. X      cluster->red=red;
  304. X      cluster->green=green;
  305. X      cluster->blue=blue;
  306. X      cluster->next=(Cluster *) NULL;
  307. X      head=cluster;
  308. X    }
  309. X  /*
  310. X    Count the pixels for each cluster.
  311. X  */
  312. X  count=0;
  313. X  p=image->pixels;
  314. X  for (i=0; i < image->packets; i++)
  315. X  {
  316. X    for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
  317. X      if (((int) p->red >= (cluster->red.left-SafeMargin)) &&
  318. X          ((int) p->red <= (cluster->red.right+SafeMargin)) &&
  319. X          ((int) p->green >= (cluster->green.left-SafeMargin)) &&
  320. X          ((int) p->green <= (cluster->green.right+SafeMargin)) &&
  321. X          ((int) p->blue >= (cluster->blue.left-SafeMargin)) &&
  322. X          ((int) p->blue <= (cluster->blue.right+SafeMargin)))
  323. X        {
  324. X          /*
  325. X            Count this pixel.
  326. X          */
  327. X          count+=(p->length+1);
  328. X          cluster->count+=(p->length+1);
  329. X          cluster->red.center+=(p->red*(p->length+1));
  330. X          cluster->green.center+=(p->green*(p->length+1));
  331. X          cluster->blue.center+=(p->blue*(p->length+1));
  332. X          break;
  333. X        }
  334. X    p++;
  335. X  }
  336. X  /*
  337. X    Remove clusters that do not meet minimum cluster threshold.
  338. X  */
  339. X  cluster_threshold*=(float) count*0.01;
  340. X  count=0;
  341. X  last_cluster=head;
  342. X  for (cluster=head; cluster != (Cluster *) NULL; cluster=next_cluster)
  343. X  {
  344. X    next_cluster=cluster->next;
  345. X    if (cluster->count >= cluster_threshold)
  346. X      {
  347. X        /*
  348. X          Initialize cluster.
  349. X        */
  350. X        cluster->id=count;
  351. X        cluster->red.center=(cluster->red.center+(cluster->count >> 1))/
  352. X          cluster->count;
  353. X        cluster->green.center=(cluster->green.center+(cluster->count >> 1))/
  354. X          cluster->count;
  355. X        cluster->blue.center=(cluster->blue.center+(cluster->count >> 1))/
  356. X          cluster->count;
  357. X        count++;
  358. X        last_cluster=cluster;
  359. X      }
  360. X    else
  361. X      {
  362. X        /*
  363. X          Delete cluster.
  364. X        */
  365. X        if (cluster == head)
  366. X          head=next_cluster;
  367. X        (void) free((char *) cluster);
  368. X        last_cluster->next=next_cluster;
  369. X      }
  370. X  }
  371. X  number_clusters=count;
  372. X  if (verbose)
  373. X    {
  374. X      /*
  375. X        Print cluster statistics.
  376. X      */
  377. X      (void) fprintf(stderr,"Fuzzy c-Means Statistics\n");
  378. X      (void) fprintf(stderr,"===================\n\n");
  379. X      (void) fprintf(stderr,"\tTotal Number of Clusters = %d\n\n",
  380. X        number_clusters);
  381. X      /*
  382. X        Print the total number of points per cluster.
  383. X      */
  384. X      (void) fprintf(stderr,"\n\nNumber of Vectors Per Cluster\n");
  385. X      (void) fprintf(stderr,"=============================\n\n");
  386. X      for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
  387. X        (void) fprintf(stderr,"Cluster #%d = %ld\n",cluster->id,cluster->count);
  388. X      /*
  389. X        Print the cluster extents.
  390. X      */
  391. X      (void) fprintf(stderr,
  392. X        "\n\n\nCluster Extents:        (Vector Size: %d)\n",Dimension);
  393. X      (void) fprintf(stderr, "================");
  394. X      for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
  395. X      {
  396. X        (void) fprintf(stderr,"\n\nCluster #%d\n\n",cluster->id);
  397. X        (void) fprintf(stderr,"%d-%d  %d-%d  %d-%d\n",
  398. X          cluster->red.left,cluster->red.right,
  399. X          cluster->green.left,cluster->green.right,
  400. X          cluster->blue.left,cluster->blue.right);
  401. X      }
  402. X      /*
  403. X        Print the cluster center values.
  404. X      */
  405. X      (void) fprintf(stderr,
  406. X        "\n\n\nCluster Center Values:        (Vector Size: %d)\n",Dimension);
  407. X      (void) fprintf(stderr, "=====================");
  408. X      for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
  409. X      {
  410. X        (void) fprintf(stderr,"\n\nCluster #%d\n\n",cluster->id);
  411. X        (void) fprintf(stderr,"%ld  %ld  %ld\n",cluster->red.center,
  412. X          cluster->green.center,cluster->blue.center);
  413. X      }
  414. X      (void) fprintf(stderr,"\n");
  415. X    }
  416. X  /*
  417. X    Allocate image colormap.
  418. X  */
  419. X  image->alpha=False;
  420. X  image->class=PseudoClass;
  421. X  if (image->colormap != (ColorPacket *) NULL)
  422. X    (void) free((char *) image->colormap);
  423. X  image->colormap=(ColorPacket *)
  424. X    malloc((unsigned int) number_clusters*sizeof(ColorPacket));
  425. X  if (image->colormap == (ColorPacket *) NULL)
  426. X    Error("unable to allocate memory",(char *) NULL);
  427. X  if (image->signature != (char *) NULL)
  428. X    (void) free((char *) image->signature);
  429. X  image->signature=(char *) NULL;
  430. X  image->colors=number_clusters;
  431. X  i=0;
  432. X  for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
  433. X  {
  434. X    image->colormap[i].red=(unsigned char) cluster->red.center;
  435. X    image->colormap[i].green=(unsigned char) cluster->green.center;
  436. X    image->colormap[i].blue=(unsigned char) cluster->blue.center;
  437. X    i++;
  438. X  }
  439. X  /*
  440. X    Do course grain classification.
  441. X  */
  442. X  q=image->pixels;
  443. X  for (i=0; i < image->packets; i++)
  444. X  {
  445. X    for (cluster=head; cluster != (Cluster *) NULL; cluster=cluster->next)
  446. X      if (((int) q->red >= (cluster->red.left-SafeMargin)) &&
  447. X          ((int) q->red <= (cluster->red.right+SafeMargin)) &&
  448. X          ((int) q->green >= (cluster->green.left-SafeMargin)) &&
  449. X          ((int) q->green <= (cluster->green.right+SafeMargin)) &&
  450. X          ((int) q->blue >= (cluster->blue.left-SafeMargin)) &&
  451. X          ((int) q->blue <= (cluster->blue.right+SafeMargin)))
  452. X        {
  453. X          /*
  454. X            Classify this pixel.
  455. X          */
  456. X          q->index=cluster->id;
  457. X          break;
  458. X        }
  459. X    if (cluster == (Cluster *) NULL)
  460. X      {
  461. X        /*
  462. X          Compute fuzzy membership.
  463. X        */
  464. X        local_minima=0.0;
  465. X        for (j=0; j < image->colors; j++)
  466. X        {
  467. X          sum=0.0;
  468. X          red_distance=image->colormap[j].red-(int) q->red;
  469. X          green_distance=image->colormap[j].green-(int) q->green;
  470. X          blue_distance=image->colormap[j].blue-(int) q->blue;
  471. X          distance=red_distance*red_distance+green_distance*green_distance+
  472. X            blue_distance*blue_distance;
  473. X          numerator=sqrt(distance);
  474. X          for (k=0; k < image->colors; k++)
  475. X          {
  476. X            red_distance=image->colormap[k].red-(int) q->red;
  477. X            green_distance=image->colormap[k].green-(int) q->green;
  478. X            blue_distance=image->colormap[k].blue-(int) q->blue;
  479. X            distance=red_distance*red_distance+green_distance*green_distance+
  480. X            blue_distance*blue_distance;
  481. X            ratio=numerator/sqrt(distance);
  482. X            sum+=pow(ratio,(double) (2.0/(weighting_exponent-1.0)));
  483. X          }
  484. X          if ((1.0/sum) > local_minima)
  485. X            {
  486. X              /*
  487. X                Classify this pixel.
  488. X              */
  489. X              local_minima=1.0/sum;
  490. X              q->index=j;
  491. X            }
  492. X        }
  493. X      }
  494. X    q++;
  495. X  }
  496. X  /*
  497. X    Free memory.
  498. X  */
  499. X  for (cluster=head; cluster != (Cluster *) NULL; cluster=next_cluster)
  500. X  {
  501. X    next_cluster=cluster->next;
  502. X    (void) free((char *) cluster);
  503. X  }
  504. }
  505. X
  506. /*
  507. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  508. %                                                                             %
  509. %                                                                             %
  510. %                                                                             %
  511. %   C o n s o l i d a t e C r o s s i n g s                                   %
  512. %                                                                             %
  513. %                                                                             %
  514. %                                                                             %
  515. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  516. %
  517. %
  518. %  Function ConsolidateCrossings guarentees that an even number of zero
  519. %  crossings always lie between two crossings.
  520. %
  521. %  The format of the ConsolidateCrossings routine is:
  522. %
  523. %      ConsolidateCrossings(zero_crossing,number_crossings)
  524. %
  525. %  A description of each parameter follows.
  526. %
  527. %    o zero_crossing: Specifies an array of structures of type ZeroCrossing.
  528. %
  529. %    o number_crossings: This unsigned int specifies the number of elements
  530. %      in the zero_crossing array.
  531. %
  532. %
  533. */
  534. static void ConsolidateCrossings(zero_crossing,number_crossings)
  535. ZeroCrossing
  536. X  *zero_crossing;
  537. X
  538. unsigned int
  539. X  number_crossings;
  540. {
  541. X  int
  542. X    center,
  543. X    correct,
  544. X    count,
  545. X    left,
  546. X    right;
  547. X
  548. X  register int
  549. X    i,
  550. X    j,
  551. X    k,
  552. X    l;
  553. X
  554. X  /*
  555. X    Consolidate zero crossings.
  556. X  */
  557. X  for (i=number_crossings-1; i >= 0; i--)
  558. X    for (j=0; j <= MaxRGB; j++)
  559. X      if (zero_crossing[i].crossings[j] != 0)
  560. X        {
  561. X          /*
  562. X            Find the entry that is closest to j and still preserves the
  563. X            property that there are an even number of crossings between
  564. X            intervals.
  565. X          */
  566. X          for (k=j-1; k > 0; k--)
  567. X            if (zero_crossing[i+1].crossings[k] != 0)
  568. X              break;
  569. X          left=Max(k,0);
  570. X          center=j;
  571. X          for (k=j+1; k < MaxRGB; k++)
  572. X            if (zero_crossing[i+1].crossings[k] != 0)
  573. X              break;
  574. X          right=Min(k,MaxRGB);
  575. X          /*
  576. X            K is the zero crossing just left of j.
  577. X          */
  578. X          for (k=j-1; k > 0; k--)
  579. X            if (zero_crossing[i].crossings[k] != 0)
  580. X              break;
  581. X          if (k < 0)
  582. X            k=0;
  583. X          /*
  584. X            Check center for an even number of crossings between k and j.
  585. X          */
  586. X          correct=(-1);
  587. X          if (zero_crossing[i+1].crossings[j] != 0)
  588. X            {
  589. X              count=0;
  590. X              for (l=k+1; l < center; l++)
  591. X                if (zero_crossing[i+1].crossings[l] != 0)
  592. X                  count++;
  593. X              if ((count % 2) == 0)
  594. X                if (center != k)
  595. X                  correct=center;
  596. X            }
  597. X          /*
  598. X            Check left for an even number of crossings between k and j.
  599. X          */
  600. X          if (correct == -1)
  601. X            {
  602. X              count=0;
  603. X              for (l=k+1; l < left; l++)
  604. X                if (zero_crossing[i+1].crossings[l] != 0)
  605. X                  count++;
  606. X              if ((count % 2) == 0)
  607. X                if (left != k)
  608. X                  correct=left;
  609. X            }
  610. X          /*
  611. X            Check right for an even number of crossings between k and j.
  612. X          */
  613. X          if (correct == -1)
  614. X            {
  615. X              count=0;
  616. X              for (l=k+1; l < right; l++)
  617. X                if (zero_crossing[i+1].crossings[l] != 0)
  618. X                  count++;
  619. X              if ((count % 2) == 0)
  620. X                if (right != k)
  621. X                  correct=right;
  622. X            }
  623. X          l=zero_crossing[i].crossings[j];
  624. X          zero_crossing[i].crossings[j]=0;
  625. X          if (correct != -1)
  626. X            zero_crossing[i].crossings[correct]=l;
  627. X        }
  628. }
  629. X
  630. /*
  631. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  632. %                                                                             %
  633. %                                                                             %
  634. %                                                                             %
  635. %   D e f i n e R e g i o n                                                   %
  636. %                                                                             %
  637. %                                                                             %
  638. %                                                                             %
  639. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  640. %
  641. %
  642. %  Function DefineRegion defines the left and right boundaries of a peak
  643. %  region.
  644. %
  645. %  The format of the DefineRegion routine is:
  646. %
  647. %      status=DefineRegion(extrema,extents)
  648. %
  649. %  A description of each parameter follows.
  650. %
  651. %    o extrema:  Specifies a pointer to an array of shortegers.  They
  652. %      represent the peaks and valleys of the histogram for each color
  653. %      component.
  654. %
  655. %    o extents:  This pointer to an ExtentPacket represent the extends
  656. %      of a particular peak or valley of a color component.
  657. %
  658. %
  659. */
  660. static int DefineRegion(extrema,extents)
  661. short
  662. X  *extrema;
  663. X
  664. ExtentPacket
  665. X  *extents;
  666. {
  667. X  /*
  668. X    Initialize to default values.
  669. X  */
  670. X  extents->left=0;
  671. X  extents->center=0;
  672. X  extents->right=MaxRGB;
  673. X  /*
  674. X    Find the left side (maxima).
  675. X  */
  676. X  for ( ; extents->index <= MaxRGB; extents->index++)
  677. X    if (extrema[extents->index] > 0)
  678. X      break;
  679. X  if (extents->index > MaxRGB)
  680. X    return(False);  /* no left side - no region exists */
  681. X  extents->left=extents->index;
  682. X  /*
  683. X    Find the right side (minima).
  684. X  */
  685. X  for ( ; extents->index <= MaxRGB; extents->index++)
  686. X    if (extrema[extents->index] < 0)
  687. X      break;
  688. X  extents->right=extents->index-1;
  689. X  return(True);
  690. }
  691. X
  692. /*
  693. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  694. %                                                                             %
  695. %                                                                             %
  696. %                                                                             %
  697. %   D e r i v a t i v e H i s t o g r a m                                     %
  698. %                                                                             %
  699. %                                                                             %
  700. %                                                                             %
  701. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  702. %
  703. %
  704. %  Function DerivativeHistogram determines the derivative of the histogram
  705. %  using central differencing.
  706. %
  707. %  The format of the DerivativeHistogram routine is:
  708. %
  709. %      DerivativeHistogram(histogram,derivative)
  710. %
  711. %  A description of each parameter follows.
  712. %
  713. %    o histogram: Specifies an array of floats representing the number of
  714. %      pixels for each intensity of a paritcular color component.
  715. %
  716. %    o derivative: This array of floats is initialized by DerivativeHistogram
  717. %      to the derivative of the histogram using centeral differencing.
  718. %
  719. %
  720. */
  721. static void DerivativeHistogram(histogram,derivative)
  722. float
  723. X  *histogram,
  724. X  *derivative;
  725. {
  726. X  register int
  727. X    i,
  728. X    n;
  729. X
  730. X  /*
  731. X    Compute endpoints using second order polynomial interpolation.
  732. X  */
  733. X  n=MaxRGB;
  734. X  derivative[0]=(-1.5*histogram[0]+2.0*histogram[1]-0.5*histogram[2]);
  735. X  derivative[n]=(0.5*histogram[n-2]-2.0*histogram[n-1]+1.5*histogram[n]);
  736. X  /*
  737. X    Compute derivative using central differencing.
  738. X  */
  739. X  for (i=1; i < n; i++)
  740. X    derivative[i]=(histogram[i+1]-histogram[i-1])/2;
  741. X  return;
  742. }
  743. X
  744. /*
  745. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  746. %                                                                             %
  747. %                                                                             %
  748. %                                                                             %
  749. %   E r r o r                                                                 %
  750. %                                                                             %
  751. %                                                                             %
  752. %                                                                             %
  753. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  754. %
  755. %  Function Error displays an error message and then terminates the program.
  756. %
  757. %  The format of the Error routine is:
  758. %
  759. %      Error(message,qualifier)
  760. %
  761. %  A description of each parameter follows:
  762. %
  763. %    o message: Specifies the message to display before terminating the
  764. %      program.
  765. %
  766. %    o qualifier: Specifies any qualifier to the message.
  767. %
  768. %
  769. */
  770. void Error(message,qualifier)
  771. char
  772. X  *message,
  773. X  *qualifier;
  774. {
  775. X  (void) fprintf(stderr,"%s: %s",client_name,message);
  776. X  if (qualifier != (char *) NULL)
  777. X    (void) fprintf(stderr," (%s)",qualifier);
  778. X  (void) fprintf(stderr,".\n");
  779. X  exit(1);
  780. }
  781. X
  782. /*
  783. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  784. %                                                                             %
  785. %                                                                             %
  786. %                                                                             %
  787. %  I n i t i a l i z e H i s t o g r a m                                      %
  788. %                                                                             %
  789. %                                                                             %
  790. %                                                                             %
  791. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  792. %
  793. %  Function InitializeHistogram computes the histogram for an image.
  794. %
  795. %  The format of the InitializeHistogram routine is:
  796. %
  797. %      InitializeHistogram(image,histogram)
  798. %
  799. %  A description of each parameter follows.
  800. %
  801. %    o image: Specifies a pointer to an Image structure;  returned from
  802. %      ReadImage.
  803. %
  804. %    o histogram: Specifies an array of longegers representing the number
  805. %      of pixels for each intensity of a paritcular color component.
  806. %
  807. %
  808. */
  809. static void InitializeHistogram(image,histogram)
  810. Image
  811. X  *image;
  812. X
  813. long
  814. X  **histogram;
  815. {
  816. X  register int
  817. X    i;
  818. X
  819. X  register RunlengthPacket
  820. X    *p;
  821. X
  822. X  /*
  823. X    Initialize histogram.
  824. X  */
  825. X  for (i=0; i <= MaxRGB; i++)
  826. X  {
  827. X    histogram[Red][i]=0;
  828. X    histogram[Green][i]=0;
  829. X    histogram[Blue][i]=0;
  830. X  }
  831. X  p=image->pixels;
  832. X  for (i=0; i < image->packets; i++)
  833. X  {
  834. X    histogram[Red][p->red]+=(p->length+1);
  835. X    histogram[Green][p->green]+=(p->length+1);
  836. X    histogram[Blue][p->blue]+=(p->length+1);
  837. X    p++;
  838. X  }
  839. }
  840. X
  841. /*
  842. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  843. %                                                                             %
  844. %                                                                             %
  845. %                                                                             %
  846. %   I n i t i a l i z e I n t e r v a l T r e e                               %
  847. %                                                                             %
  848. %                                                                             %
  849. %                                                                             %
  850. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  851. %
  852. %
  853. %  Function InitializeIntervalTree initializes an interval tree from the
  854. %  lists of zero crossings.
  855. %
  856. %  The format of the InitializeIntervalTree routine is:
  857. %
  858. %      InitializeIntervalTree(zero_crossing,number_crossings)
  859. %
  860. %  A description of each parameter follows.
  861. %
  862. %    o zero_crossing: Specifies an array of structures of type ZeroCrossing.
  863. %
  864. %    o number_crossings: This unsigned int specifies the number of elements
  865. %      in the zero_crossing array.
  866. %
  867. %
  868. */
  869. static void InitializeList(node)
  870. IntervalTree
  871. X  *node;
  872. {
  873. X  if (node == (IntervalTree *) NULL)
  874. X    return;
  875. X  if (node->child == (IntervalTree *) NULL)
  876. X    list[number_nodes++]=node;
  877. X  InitializeList(node->sibling);
  878. X  InitializeList(node->child);
  879. }
  880. X
  881. static void MeanStability(node)
  882. IntervalTree
  883. X  *node;
  884. {
  885. X  register IntervalTree
  886. X    *child;
  887. X
  888. X  if (node == (IntervalTree *) NULL)
  889. X    return;
  890. X  node->mean_stability=0.0;
  891. X  child=node->child;
  892. X  if (child != (IntervalTree *) NULL)
  893. X    {
  894. X      register double
  895. X        sum;
  896. X
  897. X      register int
  898. X        count;
  899. X
  900. X      sum=0.0;
  901. X      count=0;
  902. X      for ( ; child != (IntervalTree *) NULL; child=child->sibling)
  903. X      {
  904. X        sum+=child->stability;
  905. X        count++;
  906. X      }
  907. X      node->mean_stability=sum/(double) count;
  908. X    }
  909. X  MeanStability(node->sibling);
  910. X  MeanStability(node->child);
  911. }
  912. X
  913. static void Stability(node)
  914. IntervalTree
  915. X  *node;
  916. {
  917. X  if (node == (IntervalTree *) NULL)
  918. X    return;
  919. X  if (node->child == (IntervalTree *) NULL)
  920. X    node->stability=0.0;
  921. X  else
  922. X    node->stability=node->tau-(node->child)->tau;
  923. X  Stability(node->sibling);
  924. X  Stability(node->child);
  925. }
  926. X
  927. static IntervalTree *InitializeIntervalTree(zero_crossing,number_crossings)
  928. ZeroCrossing
  929. X  *zero_crossing;
  930. X
  931. unsigned int
  932. X  number_crossings;
  933. {
  934. X  int
  935. X    left;
  936. X
  937. X  IntervalTree
  938. X    *head,
  939. X    *node,
  940. X    *root;
  941. X
  942. X  register int
  943. X    i,
  944. X    j,
  945. X    k;
  946. X
  947. X  /*
  948. X    The root is the entire histogram.
  949. X  */
  950. X  root=(IntervalTree *) malloc(sizeof(IntervalTree));
  951. X  root->child=(IntervalTree *) NULL;
  952. X  root->sibling=(IntervalTree *) NULL;
  953. X  root->tau=0.0;
  954. X  root->left=0;
  955. X  root->right=MaxRGB;
  956. X  for (i=(-1); i < (int) number_crossings; i++)
  957. X  {
  958. X    /*
  959. X      Initialize list with all nodes with no children.
  960. X    */
  961. X    for (j=0; j < 600; j++)
  962. X      list[j]=(IntervalTree *) NULL;
  963. X    number_nodes=0;
  964. X    InitializeList(root);
  965. X    /*
  966. X      Split list.
  967. X    */
  968. X    for (j=0; j < number_nodes; j++)
  969. X    {
  970. X      head=list[j];
  971. X      left=head->left;
  972. X      node=head;
  973. X      for (k=head->left+1; k < head->right; k++)
  974. X      {
  975. X        if (zero_crossing[i+1].crossings[k] != 0)
  976. X          {
  977. X            if (node == head)
  978. X              {
  979. X                node->child=(IntervalTree *) malloc(sizeof(IntervalTree));
  980. X                node=node->child;
  981. X              }
  982. X            else
  983. X              {
  984. X                node->sibling=(IntervalTree *) malloc(sizeof(IntervalTree));
  985. X                node=node->sibling;
  986. X              }
  987. X            node->tau=zero_crossing[i+1].tau;
  988. X            node->child=(IntervalTree *) NULL;
  989. X            node->sibling=(IntervalTree *) NULL;
  990. X            node->left=left;
  991. X            node->right=k;
  992. X            left=k;
  993. X          }
  994. X        }
  995. X        if (left != head->left)
  996. X          {
  997. X            node->sibling=(IntervalTree *) malloc(sizeof(IntervalTree));
  998. X            node=node->sibling;
  999. X            node->tau=zero_crossing[i+1].tau;
  1000. X            node->child=(IntervalTree *) NULL;
  1001. X            node->sibling=(IntervalTree *) NULL;
  1002. X            node->left=left;
  1003. X            node->right=head->right;
  1004. X          }
  1005. X      }
  1006. X    }
  1007. X  /*
  1008. X    Determine the stability: difference between a nodes tau and its child.
  1009. X  */
  1010. X  Stability(root->child);
  1011. X  MeanStability(root->child);
  1012. X  return(root);
  1013. }
  1014. X
  1015. /*
  1016. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1017. %                                                                             %
  1018. %                                                                             %
  1019. %                                                                             %
  1020. %   O p t i m a l T a u                                                       %
  1021. %                                                                             %
  1022. %                                                                             %
  1023. %                                                                             %
  1024. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1025. %
  1026. %
  1027. %  Function OptimalTau finds the optimal tau for each band of the histogram.
  1028. %
  1029. %  The format of the OptimalTau routine is:
  1030. %
  1031. %      OptimalTau(histogram,max_tau,min_tau,delta_tau,smoothing_threshold,
  1032. %        extrema)
  1033. %
  1034. %  A description of each parameter follows.
  1035. %
  1036. %    o histogram: Specifies an array of longegers representing the number
  1037. %      of pixels for each intensity of a paritcular color component.
  1038. %
  1039. %    o extrema:  Specifies a pointer to an array of shortegers.  They
  1040. %      represent the peaks and valleys of the histogram for each color
  1041. %      component.
  1042. %
  1043. %
  1044. */
  1045. static void ActiveNodes(node)
  1046. IntervalTree
  1047. X  *node;
  1048. {
  1049. X  if (node == (IntervalTree *) NULL)
  1050. X    return;
  1051. X  if (node->stability >= node->mean_stability)
  1052. X    {
  1053. X      list[number_nodes++]=node;
  1054. X      ActiveNodes(node->sibling);
  1055. X    }
  1056. X  else
  1057. X    {
  1058. X      ActiveNodes(node->sibling);
  1059. X      ActiveNodes(node->child);
  1060. X    }
  1061. }
  1062. X
  1063. static void FreeNodes(node)
  1064. IntervalTree
  1065. X  *node;
  1066. {
  1067. X  if (node == (IntervalTree *) NULL)
  1068. X    return;
  1069. X  FreeNodes(node->sibling);
  1070. X  FreeNodes(node->child);
  1071. X  (void) free((char *) node);
  1072. }
  1073. X
  1074. static float OptimalTau(histogram,max_tau,min_tau,delta_tau,smoothing_threshold,
  1075. X  extrema)
  1076. long
  1077. X  *histogram;
  1078. X
  1079. float
  1080. X  max_tau,
  1081. X  min_tau,
  1082. X  delta_tau,
  1083. X  smoothing_threshold;
  1084. X
  1085. short
  1086. X  *extrema;
  1087. {
  1088. X  float
  1089. X    average_tau,
  1090. X    derivative[MaxRGB+1],
  1091. X    second_derivative[MaxRGB+1],
  1092. X    tau,
  1093. X    value;
  1094. X
  1095. X  int
  1096. X    index,
  1097. X    peak,
  1098. X    x;
  1099. X
  1100. X  IntervalTree
  1101. X    *node,
  1102. X    *root;
  1103. X
  1104. X  register int
  1105. X    i,
  1106. X    j,
  1107. X    k;
  1108. X
  1109. X  ZeroCrossing
  1110. X    *zero_crossing;
  1111. X
  1112. X  unsigned int
  1113. X    count,
  1114. X    number_crossings;
  1115. X
  1116. X  /*
  1117. X    Allocate zero crossing list.
  1118. X  */
  1119. X  count=((max_tau-min_tau)/delta_tau)+2;
  1120. X  zero_crossing=(ZeroCrossing *) malloc(count*sizeof(ZeroCrossing));
  1121. X  if (zero_crossing == (ZeroCrossing *) NULL)
  1122. X    {
  1123. X      (void) fprintf(stderr,"duCMeans: unable to allocate memory\n");
  1124. X      exit(1);
  1125. X    }
  1126. X  for (i=0; i < count; i++)
  1127. X    zero_crossing[i].tau=(-1);
  1128. X  /*
  1129. X    Initialize zero crossing list.
  1130. X  */
  1131. X  i=0;
  1132. X  for (tau=max_tau; tau >= min_tau; tau-=delta_tau)
  1133. X  {
  1134. X    zero_crossing[i].tau=tau;
  1135. X    ScaleSpace(histogram,tau,zero_crossing[i].histogram);
  1136. X    DerivativeHistogram(zero_crossing[i].histogram,derivative);
  1137. X    DerivativeHistogram(derivative,second_derivative);
  1138. X    ZeroCrossHistogram(second_derivative,smoothing_threshold,
  1139. X      zero_crossing[i].crossings);
  1140. X    i++;
  1141. X  }
  1142. X  /*
  1143. X    Add an entry for the original histogram.
  1144. X  */
  1145. X  zero_crossing[i].tau=0.0;
  1146. X  for (j=0; j <= MaxRGB; j++)
  1147. X    zero_crossing[i].histogram[j]=histogram[j];
  1148. X  DerivativeHistogram(zero_crossing[i].histogram,derivative);
  1149. X  DerivativeHistogram(derivative,second_derivative);
  1150. X  ZeroCrossHistogram(second_derivative,smoothing_threshold,
  1151. X    zero_crossing[i].crossings);
  1152. X  number_crossings=i;
  1153. X  /*
  1154. X    Ensure the scale-space fingerprints form lines in scale-space, not loops.
  1155. X  */
  1156. X  ConsolidateCrossings(zero_crossing,number_crossings);
  1157. X  /*
  1158. X    Force endpoints to be included in the interval.
  1159. X  */
  1160. X  for (i=0; i <= number_crossings; i++)
  1161. X  {
  1162. X    for (j=0; j < MaxRGB; j++)
  1163. X      if (zero_crossing[i].crossings[j] != 0)
  1164. X        break;
  1165. X    zero_crossing[i].crossings[0]=(-zero_crossing[i].crossings[j]);
  1166. X    for (j=MaxRGB; j > 0; j--)
  1167. X      if (zero_crossing[i].crossings[j] != 0)
  1168. X        break;
  1169. X    zero_crossing[i].crossings[MaxRGB]=(-zero_crossing[i].crossings[j]);
  1170. X  }
  1171. X  /*
  1172. X    Initialize interval tree.
  1173. X  */
  1174. X  root=InitializeIntervalTree(zero_crossing,number_crossings);
  1175. X  /*
  1176. X    Find active nodes:  stabilty is greater (or equal) to the mean stability of
  1177. X    its children.
  1178. X  */
  1179. X  for (i = 0; i < 600; i++)
  1180. X    list[i]=(IntervalTree *) NULL;
  1181. X  number_nodes=0;
  1182. X  ActiveNodes(root->child);
  1183. X  /*
  1184. X    Initialize extrema.
  1185. X  */
  1186. X  for (i=0; i <= MaxRGB; i++)
  1187. X    extrema[i]=0;
  1188. X  for (i=0; i < number_nodes; i++)
  1189. X  {
  1190. X    /*
  1191. X      Find this tau in zero crossings list.
  1192. X    */
  1193. X    k=0;
  1194. X    node=list[i];
  1195. X    for (j=0; j <= number_crossings; j++)
  1196. X      if (zero_crossing[j].tau == node->tau)
  1197. X        k=j;
  1198. X    /*
  1199. X      Find the value of the peak.
  1200. X    */
  1201. X    peak=zero_crossing[k].crossings[node->right] == -1;
  1202. X    index=node->left;
  1203. X    value=zero_crossing[k].histogram[index];
  1204. X    for (x=node->left; x <= node->right; x++)
  1205. X    {
  1206. X      if (peak)
  1207. X        {
  1208. X          if (zero_crossing[k].histogram[x] > value)
  1209. X            {
  1210. X              value=zero_crossing[k].histogram[x];
  1211. X              index=x;
  1212. X            }
  1213. X        }
  1214. X      else
  1215. X        if (zero_crossing[k].histogram[x] < value)
  1216. X          {
  1217. X            value=zero_crossing[k].histogram[x];
  1218. X            index=x;
  1219. X          }
  1220. X    }
  1221. X    for (x=node->left; x <= node->right; x++)
  1222. X    {
  1223. X      if (index == 0)
  1224. X        index=MaxRGB+1;
  1225. X      if (peak)
  1226. X        extrema[x]=index;
  1227. X      else
  1228. X        extrema[x]=(-index);
  1229. X    }
  1230. X  }
  1231. X  /*
  1232. X    Free memory.
  1233. X  */
  1234. X  FreeNodes(root);
  1235. X  (void) free((char *) zero_crossing);
  1236. X  /*
  1237. X    Determine the average tau.
  1238. X  */
  1239. X  average_tau=0.0;
  1240. X  for (i=0; i < number_nodes; i++)
  1241. X    average_tau+=list[i]->tau;
  1242. X  average_tau/=(float) number_nodes;
  1243. X  return(average_tau);
  1244. }
  1245. X
  1246. /*
  1247. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1248. %                                                                             %
  1249. %                                                                             %
  1250. %                                                                             %
  1251. %   S c a l e S p a c e                                                       %
  1252. %                                                                             %
  1253. %                                                                             %
  1254. %                                                                             %
  1255. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1256. %
  1257. %
  1258. %  Function ScaleSpace performs a scale-space filter on the 1D histogram.
  1259. %
  1260. %  The format of the ScaleSpace routine is:
  1261. %
  1262. %      ScaleSpace(histogram,tau,scaled_histogram)
  1263. %
  1264. %  A description of each parameter follows.
  1265. %
  1266. %    o histogram: Specifies an array of floats representing the number of
  1267. %      pixels for each intensity of a paritcular color component.
  1268. %
  1269. %
  1270. */
  1271. static void ScaleSpace(histogram,tau,scaled_histogram)
  1272. long
  1273. X  *histogram;
  1274. X
  1275. double
  1276. X  tau;
  1277. X
  1278. float
  1279. X  *scaled_histogram;
  1280. {
  1281. #define PI 3.14159265358979323846
  1282. X
  1283. X  float
  1284. X    alpha,
  1285. X    beta;
  1286. X
  1287. X  double
  1288. X    sum;
  1289. X
  1290. X  register int
  1291. X    u,
  1292. X    x;
  1293. X
  1294. X  alpha=1.0/(tau*sqrt((double) (2.0*PI)));
  1295. X  beta=(-1.0/(2.0*tau*tau));
  1296. X  for (x=0; x <= MaxRGB; x++)
  1297. X  {
  1298. X    sum=0.0;
  1299. X    for (u=0; u <= MaxRGB; u++)
  1300. X      sum+=histogram[u]*exp((double) (beta*(x-u)*(x-u)));
  1301. X    scaled_histogram[x]=alpha*sum;
  1302. X  }
  1303. }
  1304. X
  1305. /*
  1306. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1307. %                                                                             %
  1308. %                                                                             %
  1309. %                                                                             %
  1310. %   U s a g e                                                                 %
  1311. %                                                                             %
  1312. %                                                                             %
  1313. %                                                                             %
  1314. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1315. %
  1316. %  Procedure Usage displays the program usage;
  1317. %
  1318. %  The format of the Usage routine is:
  1319. %
  1320. %      Usage()
  1321. %
  1322. %
  1323. */
  1324. static void Usage()
  1325. {
  1326. X  char
  1327. X    **p;
  1328. X
  1329. X  static char
  1330. X    *options[]=
  1331. X    {
  1332. X      "-alpha              store alpha channel if the image has one",
  1333. X      "-colorspace type    GRAY, RGB, XYZ, YCbCr, YIQ, or YUV",
  1334. X      "-compress type      RunlengthEncoded or QEncoded",
  1335. X      "-density geometry   vertical and horizonal density of the image",
  1336. X      "-display server     obtain image or font from this X server",
  1337. X      "-font name          X11 font for displaying text",
  1338. X      "-geometry geometry  width and height of the image",
  1339. X      "-interlace type     NONE, LINE, or PLANE",
  1340. X      "-page geometry      size and location of the Postscript page",
  1341. X      "-quality value      JPEG quality setting",
  1342. X      "-scene value        image scene number",
  1343. X      "-treedepth value    depth of the color classification tree",
  1344. X      "-verbose            print detailed information about the image",
  1345. X      (char *) NULL
  1346. X    };
  1347. X  (void) fprintf(stderr,"Usage: %s [options ...] input_file output_file\n",
  1348. X    client_name);
  1349. X  (void) fprintf(stderr,"\nWhere options include:\n");
  1350. X  for (p=options; *p != (char *) NULL; p++)
  1351. X    (void) fprintf(stderr,"  %s\n",*p);
  1352. X  (void) fprintf(stderr,
  1353. X    "\nChange '-' to '+' in any option above to reverse its effect.  For\n");
  1354. X  (void) fprintf(stderr,
  1355. X    "example,  specify +alpha to store the image without an alpha channel.\n");
  1356. X  (void) fprintf(stderr,
  1357. X    "\nBy default, the image format of `file' is determined by its magic\n");
  1358. X  (void) fprintf(stderr,
  1359. X    "number.  To specify a particular image format, precede the filename\n");
  1360. X  (void) fprintf(stderr,
  1361. X    "with an image format name and a colon (i.e. ps:image) or specify the\n");
  1362. X  (void) fprintf(stderr,
  1363. X    "image type as the filename suffix (i.e. image.ps).  Specify 'file' as\n");
  1364. X  (void) fprintf(stderr,"'-' for standard input or output.\n");
  1365. X  exit(1);
  1366. }
  1367. X
  1368. /*
  1369. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1370. %                                                                             %
  1371. %                                                                             %
  1372. %                                                                             %
  1373. %   Z e r o C r o s s H i s t o g r a m                                       %
  1374. %                                                                             %
  1375. %                                                                             %
  1376. %                                                                             %
  1377. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1378. %
  1379. %
  1380. %  Function ZeroCrossHistogram find the zero crossings in a histogram and
  1381. %  marks directions as:  1 is negative to positive; 0 is zero crossing; and
  1382. %  -1 is positive to negative.
  1383. %
  1384. %  The format of the ZeroCrossHistogram routine is:
  1385. %
  1386. %      ZeroCrossHistogram(second_derivative,smoothing_threshold,crossings)
  1387. %
  1388. %  A description of each parameter follows.
  1389. %
  1390. %    o second_derivative: Specifies an array of floats representing the
  1391. %      second derivative of the histogram of a particular color component.
  1392. %
  1393. %    o crossings:  This array of shortegers is initialized with
  1394. %      -1, 0, or 1 representing the slope of the first derivative of the
  1395. %      of a particular color component.
  1396. %
  1397. %
  1398. */
  1399. static void ZeroCrossHistogram(second_derivative,smoothing_threshold,crossings)
  1400. float
  1401. X  *second_derivative;
  1402. X
  1403. double
  1404. X  smoothing_threshold;
  1405. X
  1406. short
  1407. X  *crossings;
  1408. {
  1409. X  int
  1410. X    parity;
  1411. X
  1412. X  register int
  1413. X    i;
  1414. X
  1415. X  /*
  1416. X    Merge low numbers to zero to help prevent noise.
  1417. X  */
  1418. X  for (i=0; i <= MaxRGB; i++)
  1419. X    if ((second_derivative[i] < smoothing_threshold) &&
  1420. X        (second_derivative[i] > -smoothing_threshold))
  1421. X      second_derivative[i]=0.0;
  1422. X  /*
  1423. X    Mark zero crossings.
  1424. X  */
  1425. X  parity=0;
  1426. X  for (i=0; i <= MaxRGB; i++)
  1427. X  {
  1428. X    crossings[i]=0;
  1429. X    if (second_derivative[i] < 0.0)
  1430. X      {
  1431. X        if (parity > 0)
  1432. X          crossings[i]=(-1);
  1433. X        parity=1;
  1434. X      }
  1435. X    else
  1436. X      if (second_derivative[i] > 0.0)
  1437. X        {
  1438. X          if (parity < 0)
  1439. X            crossings[i]=1;
  1440. X          parity=(-1);
  1441. X        }
  1442. X  }
  1443. }
  1444. X
  1445. /*
  1446. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1447. %                                                                             %
  1448. %                                                                             %
  1449. %                                                                             %
  1450. %  S e g m e n t I m a g e                                                    %
  1451. %                                                                             %
  1452. %                                                                             %
  1453. %                                                                             %
  1454. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1455. %
  1456. %  Function SegmentImage analyzes the colors within a reference image and
  1457. %
  1458. %  The format of the SegmentImage routine is:
  1459. %
  1460. %      colors=SegmentImage(image,colorspace,verbose)
  1461. %
  1462. %  A description of each parameter follows.
  1463. %
  1464. %    o colors: The SegmentImage function returns this integer
  1465. %      value.  It is the actual number of colors allocated in the
  1466. %      colormap.
  1467. %
  1468. %    o image: Specifies a pointer to an Image structure;  returned from
  1469. %      ReadImage.
  1470. %
  1471. %    o colorspace: An unsigned integer value that indicates the colorspace.
  1472. %      Empirical evidence suggests that distances in YUV or YIQ correspond to
  1473. %      perceptual color differences more closely than do distances in RGB
  1474. %      space.  The image is then returned to RGB colorspace after color
  1475. %      reduction.
  1476. %
  1477. %    o verbose:  A value greater than zero prints detailed information about
  1478. %      the identified classes.
  1479. %
  1480. %
  1481. */
  1482. static void SegmentImage(image,colorspace,verbose)
  1483. Image
  1484. X  *image;
  1485. X
  1486. unsigned int
  1487. X  colorspace,
  1488. X  verbose;
  1489. {
  1490. #define ClusterThreshold  1.0
  1491. #define DeltaTau  0.5
  1492. #define SmoothingThreshold  5.0
  1493. #define Tau  5.2
  1494. #define WeightingExponent  2.0
  1495. X
  1496. X  long
  1497. X    *histogram[Dimension];
  1498. X
  1499. X  register int
  1500. X    i;
  1501. X
  1502. X  short
  1503. X    *extrema[Dimension];
  1504. X
  1505. X  /*
  1506. X    Allocate histogram and extrema.
  1507. X  */
  1508. X  for (i=0; i < Dimension; i++)
  1509. X  {
  1510. X    histogram[i]=(long *) malloc((MaxRGB+1)*sizeof(long));
  1511. X    extrema[i]=(short *) malloc((MaxRGB+1)*sizeof(short));
  1512. X    if ((histogram[i] == (long *) NULL) ||
  1513. X        (extrema[i] == (short *) NULL))
  1514. X      Error("unable to allocate memory",(char *) NULL);
  1515. X  }
  1516. X  if (colorspace != RGBColorspace)
  1517. X    RGBTransformImage(image,colorspace);
  1518. X  /*
  1519. X    Initialize histogram.
  1520. X  */
  1521. X  InitializeHistogram(image,histogram);
  1522. X  (void) OptimalTau(histogram[Red],Tau,0.2,DeltaTau,SmoothingThreshold,
  1523. X    extrema[Red]);
  1524. X  (void) OptimalTau(histogram[Green],Tau,0.2,DeltaTau,SmoothingThreshold,
  1525. X    extrema[Green]);
  1526. X  (void) OptimalTau(histogram[Blue],Tau,0.2,DeltaTau,SmoothingThreshold,
  1527. X    extrema[Blue]);
  1528. X  /*
  1529. X    Classify using the fuzzy c-Means technique.
  1530. X  */
  1531. X  Classify(image,extrema,ClusterThreshold,WeightingExponent,verbose);
  1532. X  if (colorspace != RGBColorspace)
  1533. X    TransformRGBImage(image,colorspace);
  1534. X  /*
  1535. X    Free memory.
  1536. X  */
  1537. X  for (i=0; i < Dimension; i++)
  1538. X  {
  1539. X    (void) free((char *) extrema[i]);
  1540. X    (void) free((char *) histogram[i]);
  1541. X  }
  1542. }
  1543. X
  1544. /*
  1545. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1546. %                                                                             %
  1547. %                                                                             %
  1548. %                                                                             %
  1549. %  M a i n                                                                    %
  1550. %                                                                             %
  1551. %                                                                             %
  1552. %                                                                             %
  1553. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1554. %
  1555. %
  1556. */
  1557. int main(argc,argv)
  1558. int
  1559. X  argc;
  1560. X
  1561. char
  1562. X  *argv[];
  1563. {
  1564. #define NotInitialized  (unsigned int) (~0)
  1565. X
  1566. X  char
  1567. X    *border_color,
  1568. X    *density,
  1569. X    *filename,
  1570. X    *font,
  1571. X    *image_geometry,
  1572. X    *option,
  1573. X    *page_geometry,
  1574. X    *server_name;
  1575. X
  1576. X  double
  1577. X    normalized_maximum_error,
  1578. X    normalized_mean_error;
  1579. X
  1580. X  Image
  1581. X    *image,
  1582. X    *next_image;
  1583. X
  1584. X  ImageInfo
  1585. X    image_info;
  1586. X
  1587. X  int
  1588. X    i,
  1589. X    status,
  1590. X    x;
  1591. X
  1592. X  time_t
  1593. X    start_time;
  1594. X
  1595. X  unsigned int
  1596. X    alpha,
  1597. X    colorspace,
  1598. X    compression,
  1599. X    interlace,
  1600. X    mean_error_per_pixel,
  1601. X    quality,
  1602. X    scene,
  1603. X    verbose;
  1604. X
  1605. X  unsigned long
  1606. X    total_colors;
  1607. X
  1608. X  /*
  1609. X    Initialize program variables.
  1610. X  */
  1611. X  client_name=argv[0];
  1612. X  if (argc < 3)
  1613. X    Usage();
  1614. X  /*
  1615. X    Read image and convert to MIFF format.
  1616. X  */
  1617. X  alpha=NotInitialized;
  1618. X  border_color=(char *) NULL;
  1619. X  colorspace=RGBColorspace;
  1620. X  compression=UndefinedCompression;
  1621. X  density=(char *) NULL;
  1622. X  font=(char *) NULL;
  1623. X  image=(Image *) NULL;
  1624. X  image_geometry=(char *) NULL;
  1625. X  interlace=NoneInterlace;
  1626. X  page_geometry=(char *) NULL;
  1627. X  quality=75;
  1628. X  scene=0;
  1629. X  server_name=(char *) NULL;
  1630. X  start_time=time((time_t *) NULL);
  1631. X  verbose=False;
  1632. X  /*
  1633. X    Check command syntax.
  1634. X  */
  1635. X  filename=(char *) NULL;
  1636. X  for (i=1; i < (argc-1); i++)
  1637. X  {
  1638. X    option=argv[i];
  1639. X    if (((int) strlen(option) < 2) || ((*option != '-') && (*option != '+')))
  1640. X      {
  1641. X        /*
  1642. X          Read input image.
  1643. X        */
  1644. X        filename=option;
  1645. X        GetImageInfo(&image_info);
  1646. X        (void) strcpy(image_info.filename,filename);
  1647. X        image_info.server_name=server_name;
  1648. X        image_info.font=font;
  1649. X        image_info.geometry=image_geometry;
  1650. X        image_info.page=page_geometry;
  1651. X        image_info.density=density;
  1652. X        image_info.border_color=border_color;
  1653. X        image_info.interlace=interlace;
  1654. X        image_info.quality=quality;
  1655. X        image_info.verbose=verbose;
  1656. X        if (image != (Image *) NULL)
  1657. X          Error("input image already specified",filename);
  1658. X        image=ReadImage(&image_info);
  1659. X        if (image == (Image *) NULL)
  1660. X          exit(1);
  1661. X      }
  1662. X    else
  1663. X      switch(*(option+1))
  1664. X      {
  1665. X        case 'a':
  1666. X        {
  1667. X          alpha=(*option == '-');
  1668. X          break;
  1669. X        }
  1670. X        case 'b':
  1671. X        {
  1672. X          if (strncmp("bordercolor",option+1,7) == 0)
  1673. X            {
  1674. X              border_color=(char *) NULL;
  1675. X              if (*option == '-')
  1676. X                {
  1677. X                  i++;
  1678. X                  if (i == argc)
  1679. X                    Error("missing color on -bordercolor",(char *) NULL);
  1680. X                  border_color=argv[i];
  1681. X                }
  1682. X              break;
  1683. X            }
  1684. X          break;
  1685. X        }
  1686. X        case 'c':
  1687. X        {
  1688. X          if (strncmp("colorspace",option+1,7) == 0)
  1689. X            {
  1690. X              colorspace=RGBColorspace;
  1691. X              if (*option == '-')
  1692. X                {
  1693. X                  i++;
  1694. X                  if (i == argc)
  1695. X                    Error("missing type on -colorspace",(char *) NULL);
  1696. X                  option=argv[i];
  1697. X                  colorspace=UndefinedColorspace;
  1698. X                  if (Latin1Compare("gray",option) == 0)
  1699. X                    colorspace=GRAYColorspace;
  1700. X                  if (Latin1Compare("rgb",option) == 0)
  1701. X                    colorspace=RGBColorspace;
  1702. X                  if (Latin1Compare("xyz",option) == 0)
  1703. X                    colorspace=XYZColorspace;
  1704. X                  if (Latin1Compare("ycbcr",option) == 0)
  1705. X                    colorspace=YCbCrColorspace;
  1706. X                  if (Latin1Compare("yiq",option) == 0)
  1707. X                    colorspace=YIQColorspace;
  1708. X                  if (Latin1Compare("yuv",option) == 0)
  1709. X                    colorspace=YUVColorspace;
  1710. X                  if (colorspace == UndefinedColorspace)
  1711. X                    Error("invalid colorspace type on -colorspace",option);
  1712. X                }
  1713. X              break;
  1714. X            }
  1715. X          if (strncmp("compress",option+1,3) == 0)
  1716. X            {
  1717. X              compression=NoCompression;
  1718. X              if (*option == '-')
  1719. X                {
  1720. X                  i++;
  1721. X                  if (i == argc)
  1722. X                    Error("missing type on -compress",(char *) NULL);
  1723. X                  option=argv[i];
  1724. X                  if (Latin1Compare("runlengthencoded",option) == 0)
  1725. X                    compression=RunlengthEncodedCompression;
  1726. X                  else
  1727. X                    if (Latin1Compare("qencoded",option) == 0)
  1728. X                      compression=QEncodedCompression;
  1729. X                    else
  1730. X                      Error("invalid compression type on -compress",option);
  1731. X                }
  1732. X              break;
  1733. X            }
  1734. X          Error("unrecognized option",option);
  1735. X          break;
  1736. X        }
  1737. X        case 'd':
  1738. X        {
  1739. X          if (strncmp("density",option+1,3) == 0)
  1740. X            {
  1741. X              density=(char *) NULL;
  1742. X              if (*option == '-')
  1743. X                {
  1744. X                  i++;
  1745. X                  if (i == argc)
  1746. X                    Error("missing geometry on -density",(char *) NULL);
  1747. X                  density=argv[i];
  1748. X                }
  1749. X              break;
  1750. X            }
  1751. X          if (strncmp("display",option+1,3) == 0)
  1752. X            {
  1753. X              server_name=(char *) NULL;
  1754. X              if (*option == '-')
  1755. X                {
  1756. X                  i++;
  1757. X                  if (i == argc)
  1758. X                    Error("missing server name on -display",(char *) NULL);
  1759. X                  server_name=argv[i];
  1760. X                }
  1761. X              break;
  1762. X            }
  1763. SHAR_EOF
  1764. true || echo 'restore of ImageMagick/utilities/segment.c failed'
  1765. fi
  1766. echo 'End of ImageMagick part 4'
  1767. echo 'File ImageMagick/utilities/segment.c is continued in part 5'
  1768. echo 5 > _shar_seq_.tmp
  1769. exit 0
  1770.  
  1771. exit 0 # Just in case...
  1772. -- 
  1773.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1774. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  1775.  "It's intuitively obvious to the |
  1776.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1777.