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

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: cristy@eplrx7.es.duPont.com (John Cristy)
  4. Subject:  v34i034:  imagemagick - X11 image processing and display v2.2, Part06/26
  5. Message-ID: <1992Dec13.202704.9309@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 2bbfaa12365a0e18fdc8373af0d29a49
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v34i028=imagemagick.141926@sparky.IMD.Sterling.COM>
  11. Date: Sun, 13 Dec 1992 20:27:04 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 2007
  14.  
  15. Submitted-by: cristy@eplrx7.es.duPont.com (John Cristy)
  16. Posting-number: Volume 34, Issue 34
  17. Archive-name: imagemagick/part06
  18. Environment: UNIX, VMS, X11, SGI, DEC, Cray, Sun, Vax
  19.  
  20. #!/bin/sh
  21. # this is Part.06 (part 6 of a multipart archive)
  22. # do not concatenate these parts, unpack them in order with /bin/sh
  23. # file ImageMagick/image.c continued
  24. #
  25. if test ! -r _shar_seq_.tmp; then
  26.     echo 'Please unpack part 1 first!'
  27.     exit 1
  28. fi
  29. (read Scheck
  30.  if test "$Scheck" != 6; then
  31.     echo Please unpack part "$Scheck" next!
  32.     exit 1
  33.  else
  34.     exit 0
  35.  fi
  36. ) < _shar_seq_.tmp || exit 1
  37. if test ! -f _shar_wnt_.tmp; then
  38.     echo 'x - still skipping ImageMagick/image.c'
  39. else
  40. echo 'x - continuing file ImageMagick/image.c'
  41. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/image.c' &&
  42. X      "  token pop /compression exch def pop",
  43. X      "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
  44. X      "  grestore",
  45. X      "  showpage",
  46. X      "} bind def",
  47. X      "",
  48. X      "DisplayImage",
  49. X      NULL
  50. X    };
  51. X
  52. X  char
  53. X    **q;
  54. X
  55. X  int
  56. X    x,
  57. X    y;
  58. X
  59. X  register RunlengthPacket
  60. X    *p;
  61. X
  62. X  register int
  63. X    i,
  64. X    j;
  65. X
  66. X  unsigned int
  67. X    height,
  68. X    width;
  69. X
  70. X  /*
  71. X    Open output image file.
  72. X  */
  73. X  OpenImage(image,"w");
  74. X  if (image->file == (FILE *) NULL)
  75. X    {
  76. X      Warning("unable to open file",image->filename);
  77. X      return(False);
  78. X    }
  79. X  if (geometry != (char *) NULL)
  80. X    {
  81. X      /*
  82. X        User specified Postscript page position.
  83. X      */
  84. X      x=0;
  85. X      y=0;
  86. X      width=image->columns;
  87. X      height=image->rows;
  88. X      (void) XParseGeometry(geometry,&x,&y,&width,&height);
  89. X    }
  90. X  else
  91. X    {
  92. X      int
  93. X        delta_x,
  94. X        delta_y;
  95. X
  96. X      unsigned long
  97. X        scale_factor;
  98. X
  99. X      /*
  100. X        Scale image to size of Postscript page.
  101. X      */
  102. X      scale_factor=UpShift(PageWidth-(2*PageSideMargin))/image->columns;
  103. X      if (scale_factor > (UpShift(PageHeight-(2*PageTopMargin))/image->rows))
  104. X        scale_factor=UpShift(PageHeight-(2*PageTopMargin))/image->rows;
  105. X      width=DownShift(image->columns*scale_factor);
  106. X      height=DownShift(image->rows*scale_factor);
  107. X      /*
  108. X        Center image on Postscript page.
  109. X      */
  110. X      delta_x=PageWidth-(width+(2*PageSideMargin));
  111. X      delta_y=PageHeight-(height+(2*PageTopMargin));
  112. X      if (delta_x >= 0)
  113. X        x=delta_x/2+PageSideMargin;
  114. X      else
  115. X        x=PageSideMargin;
  116. X      if (delta_y >= 0)
  117. X        y=delta_y/2+PageTopMargin;
  118. X      else
  119. X        y=PageTopMargin;
  120. X    }
  121. X  /*
  122. X    Output encapsulated Postscript header.
  123. X  */
  124. X  (void) fprintf(image->file,"%%!PS-Adobe-3.0 EPSF-2.0\n");
  125. X  (void) fprintf(image->file,"%%%%Title: %s\n",image->filename);
  126. X  (void) fprintf(image->file,"%%%%Creator: ImageMagick\n");
  127. X  (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",x,y,x+(int) width,
  128. X    y+(int) height);
  129. X  (void) fprintf(image->file,"%%%%EndComments\n");
  130. X  /*
  131. X    Output encapsulated Postscript commands.
  132. X  */
  133. X  for (q=Postscript; *q; q++)
  134. X    (void) fprintf(image->file,"%s\n",*q);
  135. X  /*
  136. X    Output image data.
  137. X  */
  138. X  if (image->compression == RunlengthEncodedCompression)
  139. X    CompressImage(image);
  140. X  p=image->pixels;
  141. X  switch (image->class)
  142. X  {
  143. X    case DirectClass:
  144. X    {
  145. X      (void) fprintf(image->file,"%d %d\n%u %u\n%u %u\n%d\n%d\n",x,y,width,
  146. X        height,image->columns,image->rows,(image->class == PseudoClass),
  147. X        image->compression == NoCompression);
  148. X      switch (image->compression)
  149. X      {
  150. X        case RunlengthEncodedCompression:
  151. X        default:
  152. X        {
  153. X          /*
  154. X            Dump runlength-encoded DirectColor packets.
  155. X          */
  156. X          x=0;
  157. X          for (i=0; i < image->packets; i++)
  158. X          {
  159. X            x++;
  160. X            (void) fprintf(image->file,"%02x%02x%02x%02x",p->red,p->green,
  161. X              p->blue,p->length);
  162. X            if (x == 9)
  163. X              {
  164. X                x=0;
  165. X                (void) fprintf(image->file,"\n");
  166. X              }
  167. X            p++;
  168. X          }
  169. X          break;
  170. X        }
  171. X        case NoCompression:
  172. X        {
  173. X          /*
  174. X            Dump uncompressed DirectColor packets.
  175. X          */
  176. X          x=0;
  177. X          for (i=0; i < image->packets; i++)
  178. X          {
  179. X            for (j=0; j <= ((int) p->length); j++)
  180. X            {
  181. X              x++;
  182. X              (void) fprintf(image->file,"%02x%02x%02x",p->red,p->green,
  183. X                p->blue);
  184. X              if (x == 12)
  185. X                {
  186. X                  x=0;
  187. X                  (void) fprintf(image->file,"\n");
  188. X                }
  189. X            }
  190. X            p++;
  191. X          }
  192. X          break;
  193. X        }
  194. X      }
  195. X      break;
  196. X    }
  197. X    case PseudoClass:
  198. X    {
  199. X      (void) fprintf(image->file,"%d %d\n%u %u\n%u %u\n%d\n%d\n",x,y,width,
  200. X        height,image->columns,image->rows,(image->class == PseudoClass),
  201. X        image->compression == NoCompression);
  202. X      /*
  203. X        Dump number of colors and colormap.
  204. X      */
  205. X      (void) fprintf(image->file,"%u\n",image->colors);
  206. X      for (i=0; i < image->colors; i++)
  207. X        (void) fprintf(image->file,"%02x%02x%02x\n",image->colormap[i].red,
  208. X          image->colormap[i].green,image->colormap[i].blue);
  209. X      switch (image->compression)
  210. X      {
  211. X        case RunlengthEncodedCompression:
  212. X        default:
  213. X        {
  214. X          /*
  215. X            Dump runlength-encoded PseudoColor packets.
  216. X          */
  217. X          x=0;
  218. X          for (i=0; i < image->packets; i++)
  219. X          {
  220. X            x++;
  221. X            (void) fprintf(image->file,"%02x%02x",p->index,p->length);
  222. X            if (x == 18)
  223. X              {
  224. X                x=0;
  225. X                (void) fprintf(image->file,"\n");
  226. X              }
  227. X            p++;
  228. X          }
  229. X          break;
  230. X        }
  231. X        case NoCompression:
  232. X        {
  233. X          /*
  234. X            Dump uncompressed PseudoColor packets.
  235. X          */
  236. X          x=0;
  237. X          for (i=0; i < image->packets; i++)
  238. X          {
  239. X            for (j=0; j <= ((int) p->length); j++)
  240. X            {
  241. X              x++;
  242. X              (void) fprintf(image->file,"%02x",p->index);
  243. X              if (x == 36)
  244. X                {
  245. X                  x=0;
  246. X                  (void) fprintf(image->file,"\n");
  247. X                }
  248. X            }
  249. X            p++;
  250. X          }
  251. X        }
  252. X        break;
  253. X      }
  254. X    }
  255. X  }
  256. X  (void) fprintf(image->file,"\n\n");
  257. X  (void) fprintf(image->file,"%%%%Trailer\n");
  258. X  CloseImage(image);
  259. X  return(True);
  260. }
  261. X
  262. /*
  263. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  264. %                                                                             %
  265. %                                                                             %
  266. %                                                                             %
  267. %  R e a d D a t a                                                            %
  268. %                                                                             %
  269. %                                                                             %
  270. %                                                                             %
  271. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  272. %
  273. %  Function ReadData reads data from the image file and returns it.  If it
  274. %  cannot read the requested number of items, False is returned indicating
  275. %  an error.
  276. %
  277. %  The format of the ReadData routine is:
  278. %
  279. %      status=ReadData(data,size,number_items,file)
  280. %
  281. %  A description of each parameter follows:
  282. %
  283. %    o status:  Function ReadData returns True if all the data requested
  284. %      is obtained without error, otherwise False.
  285. %
  286. %    o data:  Specifies an area to place the information reuested from
  287. %      the file.
  288. %
  289. %    o size:  Specifies an integer representing the length of an
  290. %      individual item to be read from the file.
  291. %
  292. %    o number_items:  Specifies an integer representing the number of items
  293. %      to read from the file.
  294. %
  295. %    o file:  Specifies a file to read the data.
  296. %
  297. %
  298. */
  299. unsigned int ReadData(data,size,number_items,file)
  300. char
  301. X  *data;
  302. X
  303. int
  304. X  size,
  305. X  number_items;
  306. X
  307. FILE
  308. X  *file;
  309. {
  310. X  size*=number_items;
  311. X  while (size > 0)
  312. X  {
  313. X    number_items=fread(data,1,size,file);
  314. X    if (number_items <= 0)
  315. X      return(False);
  316. X    size-=number_items;
  317. X    data+=number_items;
  318. X  }
  319. X  return(True);
  320. }
  321. X
  322. /*
  323. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  324. %                                                                             %
  325. %                                                                             %
  326. %                                                                             %
  327. %  R e a d D a t a B l o c k                                                  %
  328. %                                                                             %
  329. %                                                                             %
  330. %                                                                             %
  331. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  332. %
  333. %  Function ReadDataBlock reads data from the image file and returns it.  The
  334. %  amount of data is determined by first reading a count byte.  If
  335. %  ReadDataBlock cannot read the requested number of items, `-1' is returned
  336. %  indicating an error.
  337. %
  338. %  The format of the ReadData routine is:
  339. %
  340. %      status=ReadData(data,file)
  341. %
  342. %  A description of each parameter follows:
  343. %
  344. %    o status:  Function ReadData returns the number of characters read
  345. %      unless the is an error, otherwise `-1'.
  346. %
  347. %    o data:  Specifies an area to place the information reuested from
  348. %      the file.
  349. %
  350. %    o file:  Specifies a file to read the data.
  351. %
  352. %
  353. */
  354. int ReadDataBlock(data,file)
  355. char
  356. X  *data;
  357. X
  358. FILE
  359. X  *file;
  360. {
  361. X  unsigned char
  362. X    count;
  363. X
  364. X  unsigned int
  365. X    status;
  366. X
  367. X  status=ReadData((char *) &count,1,1,file);
  368. X  if (status == False)
  369. X    return(-1);
  370. X  if (count == 0)
  371. X    return(0);
  372. X  status=ReadData(data,1,(int) count,file);
  373. X  if (status == False)
  374. X    return(-1);
  375. X  return(count);
  376. }
  377. X
  378. /*
  379. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  380. %                                                                             %
  381. %                                                                             %
  382. %                                                                             %
  383. %   R e a d I m a g e                                                         %
  384. %                                                                             %
  385. %                                                                             %
  386. %                                                                             %
  387. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  388. %
  389. %  Function ReadImage reads an image file and returns it.  It allocates the
  390. %  memory necessary for the new Image structure and returns a pointer to the
  391. %  new image.
  392. %
  393. %  The format of the ReadImage routine is:
  394. %
  395. %      image=ReadImage(filename)
  396. %
  397. %  A description of each parameter follows:
  398. %
  399. %    o image: Function ReadImage returns a pointer to the image after reading.
  400. %      A null image is returned if there is a a memory shortage or if the
  401. %      image cannot be read.
  402. %
  403. %    o filename: Specifies the name of the image to read.
  404. %
  405. %
  406. */
  407. Image *ReadImage(filename)
  408. char
  409. X  *filename;
  410. {
  411. #define MaxKeywordLength  2048
  412. X
  413. X  char
  414. X    keyword[MaxKeywordLength],
  415. X    value[MaxKeywordLength];
  416. X
  417. X  Image
  418. X    *image;
  419. X
  420. X  register int
  421. X    c,
  422. X    i;
  423. X
  424. X  register unsigned char
  425. X    *p;
  426. X
  427. X  unsigned int
  428. X    max_characters,
  429. X    packet_size,
  430. X    status;
  431. X
  432. X  unsigned long int
  433. X    count,
  434. X    packets;
  435. X
  436. X  /*
  437. X    Allocate image structure.
  438. X  */
  439. X  image=AllocateImage("MIFF");
  440. X  if (image == (Image *) NULL)
  441. X    return((Image *) NULL);
  442. X  /*
  443. X    Open image file.
  444. X  */
  445. X  (void) strcpy(image->filename,filename);
  446. X  OpenImage(image,"r");
  447. X  if (image->file == (FILE *) NULL)
  448. X    {
  449. X      Warning("unable to open file",image->filename);
  450. X      DestroyImage(image);
  451. X      return((Image *) NULL);
  452. X    }
  453. X  /*
  454. X    Decode image header;  header terminates one character beyond a ':'.
  455. X  */
  456. X  c=fgetc(image->file);
  457. X  if (c == EOF)
  458. X    {
  459. X      DestroyImage(image);
  460. X      return((Image *) NULL);
  461. X    }
  462. X  do
  463. X  {
  464. X    /*
  465. X      Decode image header;  header terminates one character beyond a ':'.
  466. X    */
  467. X    image->compression=NoCompression;
  468. X    while (isgraph(c) && (c != ':'))
  469. X    {
  470. X      register char
  471. X        *p;
  472. X
  473. X      if (c == '{')
  474. X        {
  475. X          /*
  476. X            Comment.
  477. X          */
  478. X          max_characters=2048;
  479. X          image->comments=(char *) malloc(max_characters*sizeof(char));
  480. X          if (image->comments == (char *) NULL)
  481. X            {
  482. X              Warning("unable to read image","memory allocation failed");
  483. X              DestroyImages(image);
  484. X              return((Image *) NULL);
  485. X            }
  486. X          p=image->comments;
  487. X          *p='\0';
  488. X          c=fgetc(image->file);
  489. X          while ((isgraph(c) || isspace(c)) && (c != '}'))
  490. X          {
  491. X            if (p >= (image->comments+max_characters-1))
  492. X              {
  493. X                /*
  494. X                  Allocate more memory for the comment.
  495. X                */
  496. X                max_characters<<=1;
  497. X                image->comments=(char *)
  498. X                  realloc((char *) image->comments,max_characters);
  499. X                if (image->comments == (char *) NULL)
  500. X                  {
  501. X                    Warning("unable to read image","memory allocation failed");
  502. X                    DestroyImages(image);
  503. X                    return((Image *) NULL);
  504. X                  }
  505. X                p=image->comments+strlen(image->comments);
  506. X              }
  507. X            *p++=(unsigned char) c;
  508. X            c=fgetc(image->file);
  509. X          }
  510. X          *p='\0';
  511. X          c=fgetc(image->file);
  512. X        }
  513. X      else
  514. X        if (isalnum(c))
  515. X          {
  516. X            /*
  517. X              Determine a keyword and its value.
  518. X            */
  519. X            p=keyword;
  520. X            do
  521. X            {
  522. X              if ((p-keyword) < (MaxKeywordLength-1))
  523. X                *p++=(char) c;
  524. X              c=fgetc(image->file);
  525. X            } while (isalnum(c));
  526. X            *p='\0';
  527. X            while (isspace(c) || (c == '='))
  528. X              c=fgetc(image->file);
  529. X            p=value;
  530. X            while (!isspace(c))
  531. X            {
  532. X              if ((p-value) < (MaxKeywordLength-1))
  533. X                *p++=(char) c;
  534. X              c=fgetc(image->file);
  535. X            }
  536. X            *p='\0';
  537. X            /*
  538. X              Assign a value to the specified keyword.
  539. X            */
  540. X            if (strcmp(keyword,"alpha") == 0)
  541. X              if ((strcmp(value,"True") == 0) || (strcmp(value,"true") == 0))
  542. X                image->alpha=True;
  543. X              else
  544. X                image->class=False;
  545. X            if (strcmp(keyword,"class") == 0)
  546. X              if (strcmp(value,"PseudoClass") == 0)
  547. X                image->class=PseudoClass;
  548. X              else
  549. X                if (strcmp(value,"DirectClass") == 0)
  550. X                  image->class=DirectClass;
  551. X                else
  552. X                  image->class=UndefinedClass;
  553. X            if (strcmp(keyword,"colors") == 0)
  554. X              image->colors=(unsigned int) atoi(value);
  555. X            if (strcmp(keyword,"compression") == 0)
  556. X              if (strcmp(value,"QEncoded") == 0)
  557. X                image->compression=QEncodedCompression;
  558. X              else
  559. X                if (strcmp(value,"RunlengthEncoded") == 0)
  560. X                  image->compression=RunlengthEncodedCompression;
  561. X                else
  562. X                  image->compression=UndefinedCompression;
  563. X            if (strcmp(keyword,"columns") == 0)
  564. X              image->columns=(unsigned int) atoi(value);
  565. X            if (strcmp(keyword,"id") == 0)
  566. X              if (strcmp(value,"ImageMagick") == 0)
  567. X                image->id=ImageMagickId;
  568. X              else
  569. X                image->id=UndefinedId;
  570. X            if (strcmp(keyword,"montage") == 0)
  571. X              {
  572. X                image->montage=(char *) malloc(strlen(value)+1*sizeof(char));
  573. X                if (image->montage == (char *) NULL)
  574. X                  {
  575. X                    Warning("unable to read image","memory allocation failed");
  576. X                    DestroyImages(image);
  577. X                    return((Image *) NULL);
  578. X                  }
  579. X                (void) strcpy(image->montage,value);
  580. X              }
  581. X            if (strcmp(keyword,"packets") == 0)
  582. X              image->packets=(unsigned int) atoi(value);
  583. X            if (strcmp(keyword,"rows") == 0)
  584. X              image->rows=(unsigned int) atoi(value);
  585. X            if (strcmp(keyword,"scene") == 0)
  586. X              image->scene=(unsigned int) atoi(value);
  587. X            if (strcmp(keyword,"signature") == 0)
  588. X              {
  589. X                image->signature=(char *)
  590. X                  malloc((strlen(value)+1)*sizeof(char));
  591. X                if (image->signature == (char *) NULL)
  592. X                  {
  593. X                    Warning("unable to read image","memory allocation failed");
  594. X                    DestroyImages(image);
  595. X                    return((Image *) NULL);
  596. X                  }
  597. X                (void) strcpy(image->signature,value);
  598. X              }
  599. X          }
  600. X        else
  601. X          c=fgetc(image->file);
  602. X      while (isspace(c))
  603. X        c=fgetc(image->file);
  604. X    }
  605. X    (void) fgetc(image->file);
  606. X    /*
  607. X      Verify that required image information is defined.
  608. X    */
  609. X    if ((image->id == UndefinedId) || (image->class == UndefinedClass) ||
  610. X        (image->compression == UndefinedCompression) || (image->columns == 0) ||
  611. X        (image->rows == 0))
  612. X      {
  613. X        Warning("incorrect image header in file",image->filename);
  614. X        DestroyImages(image);
  615. X        return((Image *) NULL);
  616. X      }
  617. X    if ((image->columns*image->rows) > MaxImageSize)
  618. X      {
  619. X        Warning("unable to read image","image size too large");
  620. X        DestroyImages(image);
  621. X        return((Image *) NULL);
  622. X      }
  623. X    if (image->montage != (char *) NULL)
  624. X      {
  625. X        register char
  626. X          *p;
  627. X
  628. X        /*
  629. X          Tiling directory.
  630. X        */
  631. X        max_characters=2048;
  632. X        image->directory=(char *) malloc(max_characters*sizeof(char));
  633. X        if (image->directory == (char *) NULL)
  634. X          {
  635. X            Warning("unable to read image","memory allocation failed");
  636. X            DestroyImages(image);
  637. X            return((Image *) NULL);
  638. X          }
  639. X        p=image->directory;
  640. X        do
  641. X        {
  642. X          if (p >= (image->directory+max_characters-1))
  643. X            {
  644. X              /*
  645. X                Allocate more memory for the comment.
  646. X              */
  647. X              max_characters<<=1;
  648. X              image->directory=(char *)
  649. X                realloc((char *) image->directory,max_characters);
  650. X              if (image->directory == (char *) NULL)
  651. X                {
  652. X                  Warning("unable to read image","memory allocation failed");
  653. X                  DestroyImages(image);
  654. X                  return((Image *) NULL);
  655. X                }
  656. X              p=image->comments+strlen(image->comments);
  657. X            }
  658. X          c=fgetc(image->file);
  659. X          *p++=(unsigned char) c;
  660. X        } while (c != '\0');
  661. X      }
  662. X    if (image->class == PseudoClass)
  663. X      {
  664. X        unsigned int
  665. X          colors;
  666. X
  667. X        /*
  668. X          PseudoClass image cannot have alpha data or be QEncoded.
  669. X        */
  670. X        if (image->alpha)
  671. X          {
  672. X            Warning("unable to read image","alpha images must be DirectClass");
  673. X            DestroyImages(image);
  674. X            return((Image *) NULL);
  675. X          }
  676. X        if (image->compression == QEncodedCompression)
  677. X          {
  678. X            Warning("unable to read image",
  679. X              "QEncoded images must be DirectClass");
  680. X            DestroyImages(image);
  681. X            return((Image *) NULL);
  682. X          }
  683. X        /*
  684. X          Create image colormap.
  685. X        */
  686. X        colors=image->colors;
  687. X        if (colors == 0)
  688. X          colors=256;
  689. X        image->colormap=(ColorPacket *) malloc(colors*sizeof(ColorPacket));
  690. X        if (image->colormap == (ColorPacket *) NULL)
  691. X          {
  692. X            Warning("unable to read image","memory allocation failed");
  693. X            DestroyImages(image);
  694. X            return((Image *) NULL);
  695. X          }
  696. X        if (image->colors == 0)
  697. X          for (i=0; i < colors; i++)
  698. X          {
  699. X            image->colormap[i].red=(unsigned char) i;
  700. X            image->colormap[i].green=(unsigned char) i;
  701. X            image->colormap[i].blue=(unsigned char) i;
  702. X            image->colors++;
  703. X          }
  704. X        else
  705. X          {
  706. X            unsigned char
  707. X              *colormap;
  708. X
  709. X            /*
  710. X              Read image colormap from file.
  711. X            */
  712. X            colormap=(unsigned char *)
  713. X              malloc(3*image->colors*sizeof(unsigned char));
  714. X            if (colormap == (unsigned char *) NULL)
  715. X              {
  716. X                Warning("unable to read image","memory allocation failed");
  717. X                DestroyImages(image);
  718. X                return((Image *) NULL);
  719. X              }
  720. X            (void) ReadData((char *) colormap,1,(int) (3*image->colors),
  721. X              image->file);
  722. X            p=colormap;
  723. X            for (i=0; i < image->colors; i++)
  724. X            {
  725. X              image->colormap[i].red=(*p++);
  726. X              image->colormap[i].green=(*p++);
  727. X              image->colormap[i].blue=(*p++);
  728. X            }
  729. X            (void) free((char *) colormap);
  730. X          }
  731. X      }
  732. X    /*
  733. X      Determine packed packet size.
  734. X    */
  735. X    if (image->class == PseudoClass)
  736. X      {
  737. X        image->packet_size=1;
  738. X        if (image->colors > 256)
  739. X          image->packet_size++;
  740. X      }
  741. X    else
  742. X      {
  743. X        image->packet_size=3;
  744. X        if (image->alpha)
  745. X          image->packet_size++;
  746. X      }
  747. X    if (image->compression == RunlengthEncodedCompression)
  748. X      image->packet_size++;
  749. X    packet_size=image->packet_size;
  750. X    if (image->compression == QEncodedCompression)
  751. X      packet_size=1;
  752. X    /*
  753. X      Allocate image pixels.
  754. X    */
  755. X    if (image->compression == NoCompression)
  756. X      image->packets=image->columns*image->rows;
  757. X    packets=image->packets;
  758. X    if (image->packets == 0)
  759. X      packets=image->columns*image->rows;
  760. X    image->packed_pixels=(unsigned char *)
  761. X      malloc((unsigned int) packets*packet_size*sizeof(unsigned char));
  762. X    if (image->packed_pixels == (unsigned char *) NULL)
  763. X      {
  764. X        Warning("unable to read image","memory allocation failed");
  765. X        DestroyImages(image);
  766. X        return((Image *) NULL);
  767. X      }
  768. X    /*
  769. X      Read image pixels from file.
  770. X    */
  771. X    if ((image->compression != RunlengthEncodedCompression) ||
  772. X        (image->packets != 0))
  773. X      (void) ReadData((char *) image->packed_pixels,1,
  774. X        (int) (packets*packet_size),image->file);
  775. X    else
  776. X      {
  777. X        /*
  778. X          Number of runlength packets is unspecified.
  779. X        */
  780. X        count=0;
  781. X        p=image->packed_pixels;
  782. X        do
  783. X        {
  784. X          (void) ReadData((char *) p,1,(int) packet_size,image->file);
  785. X          image->packets++;
  786. X          p+=(packet_size-1);
  787. X          count+=(*p+1);
  788. X          p++;
  789. X        }
  790. X        while (count < (image->columns*image->rows));
  791. X      }
  792. X    if (image->compression ==  QEncodedCompression)
  793. X      {
  794. X        unsigned char
  795. X          *compressed_pixels;
  796. X
  797. X        /*
  798. X          Uncompress image pixels with Q encoding.
  799. X        */
  800. X        image->packets=image->columns*image->rows;
  801. X        compressed_pixels=image->packed_pixels;
  802. X        image->packed_pixels=(unsigned char *) malloc((unsigned int)
  803. X          image->packets*image->packet_size*sizeof(unsigned char));
  804. X        if (image->packed_pixels == (unsigned char *) NULL)
  805. X          {
  806. X            Warning("unable to write image","memory allocation failed");
  807. X            DestroyImage(image);
  808. X            return(False);
  809. X          }
  810. X        packets=QDecodeImage(compressed_pixels,image->packed_pixels,
  811. X          image->columns*(int) image->packet_size,image->rows);
  812. X        if (packets != (image->packets*image->packet_size))
  813. X          {
  814. X            Warning("Q encoding failed",image->filename);
  815. X            DestroyImages(image);
  816. X            return((Image *) NULL);
  817. X          }
  818. X        (void) free((char *) compressed_pixels);
  819. X      }
  820. X    /*
  821. X      Unpack the packed image pixels into runlength-encoded pixel packets.
  822. X    */
  823. X    status=UnpackImage(image);
  824. X    if (status == False)
  825. X      {
  826. X        DestroyImages(image);
  827. X        return((Image *) NULL);
  828. X      }
  829. X    /*
  830. X      Proceed to next image.
  831. X    */
  832. X    do
  833. X    {
  834. X      c=fgetc(image->file);
  835. X    } while (!isgraph(c) && (c != EOF));
  836. X    if (c != EOF)
  837. X      {
  838. X        /*
  839. X          Allocate image structure.
  840. X        */
  841. X        image->next=AllocateImage("MIFF");
  842. X        if (image->next == (Image *) NULL)
  843. X          {
  844. X            DestroyImages(image);
  845. X            return((Image *) NULL);
  846. X          }
  847. X        image->next->file=image->file;
  848. X        (void) sprintf(image->next->filename,"%s.%u\0",filename,image->scene+1);
  849. X        image->next->scene=image->scene+1;
  850. X        image->next->last=image;
  851. X        image=image->next;
  852. X      }
  853. X  } while (c != EOF);
  854. X  while (image->last != (Image *) NULL)
  855. X    image=image->last;
  856. X  CloseImage(image);
  857. X  return(image);
  858. }
  859. X
  860. /*
  861. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  862. %                                                                             %
  863. %                                                                             %
  864. %                                                                             %
  865. %   R e d u c e I m a g e                                                     %
  866. %                                                                             %
  867. %                                                                             %
  868. %                                                                             %
  869. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  870. %
  871. %  Function ReduceImage creates a new image that is a integral size less than
  872. %  an existing one.  It allocates the memory necessary for the new Image
  873. %  structure and returns a pointer to the new image.
  874. %
  875. %  ReduceImage scans the reference image to create a reduced image by computing
  876. %  the weighted average of a 4x4 cell centered at each reference pixel.  The
  877. %  target pixel requires two columns and two rows of the reference pixels.
  878. %  Therefore the reduced image columns and rows become:
  879. %
  880. %    number_columns/2
  881. %    number_rows/2
  882. %
  883. %  Weights assume that the importance of neighboring pixels is inversely
  884. %  proportional to the square of their distance from the target pixel.
  885. %
  886. %  The scan only processes pixels that have a full set of neighbors.  Pixels
  887. %  in the top, bottom, left, and right pairs of rows and columns are omitted
  888. %  from the scan.
  889. %
  890. %  The format of the ReduceImage routine is:
  891. %
  892. %      reduced_image=ReduceImage(image)
  893. %
  894. %  A description of each parameter follows:
  895. %
  896. %    o reduced_image: Function ReduceImage returns a pointer to the image
  897. %      after reducing.  A null image is returned if there is a a memory
  898. %      shortage or if the image size is less than IconSize*2.
  899. %
  900. %    o image: The address of a structure of type Image.
  901. %
  902. %
  903. */
  904. Image *ReduceImage(image)
  905. Image
  906. X  *image;
  907. {
  908. #define Rsum(weight) \
  909. X  total_red+=weight*(s->red); \
  910. X  total_green+=weight*(s->green); \
  911. X  total_blue+=weight*(s->blue); \
  912. X  total_alpha+=weight*(s->index); \
  913. X  s++;
  914. X
  915. X  ColorPacket
  916. X    *scanline;
  917. X
  918. X  Image
  919. X    *reduced_image;
  920. X
  921. X  register ColorPacket
  922. X    *s,
  923. X    *s0,
  924. X    *s1,
  925. X    *s2,
  926. X    *s3;
  927. X
  928. X  register RunlengthPacket
  929. X    *p,
  930. X    *q;
  931. X
  932. X  register unsigned int
  933. X    x;
  934. X
  935. X  unsigned int
  936. X    y;
  937. X
  938. X  unsigned long
  939. X    total_alpha,
  940. X    total_blue,
  941. X    total_green,
  942. X    total_red;
  943. X
  944. X  if ((image->columns < 4) || (image->rows < 4))
  945. X    {
  946. X      Warning("unable to reduce image","image size must exceed 3x3");
  947. X      return((Image *) NULL);
  948. X    }
  949. X  /*
  950. X    Initialize reduced image attributes.
  951. X  */
  952. X  reduced_image=CopyImage(image,image->columns >> 1,image->rows >> 1,False);
  953. X  if (reduced_image == (Image *) NULL)
  954. X    {
  955. X      Warning("unable to reduce image","memory allocation failed");
  956. X      return((Image *) NULL);
  957. X    }
  958. X  reduced_image->class=DirectClass;
  959. X  /*
  960. X    Allocate image buffer and scanline buffer for 4 rows of the image.
  961. X  */
  962. X  scanline=(ColorPacket *) malloc(4*image->columns*sizeof(ColorPacket));
  963. X  if (scanline == (ColorPacket *) NULL)
  964. X    {
  965. X      Warning("unable to reduce image","memory allocation failed");
  966. X      DestroyImage(reduced_image);
  967. X      return((Image *) NULL);
  968. X    }
  969. X  /*
  970. X    Preload the first 2 rows of the image.
  971. X  */
  972. X  p=image->pixels;
  973. X  image->runlength=p->length+1;
  974. X  s=scanline;
  975. X  for (x=0; x < (2*image->columns); x++)
  976. X  {
  977. X    if (image->runlength > 0)
  978. X      image->runlength--;
  979. X    else
  980. X      {
  981. X        p++;
  982. X        image->runlength=p->length;
  983. X      }
  984. X    s->red=p->red;
  985. X    s->green=p->green;
  986. X    s->blue=p->blue;
  987. X    s->index=p->index;
  988. X    s++;
  989. X  }
  990. X  /*
  991. X    Reduce each row.
  992. X  */
  993. X  p=image->pixels;
  994. X  image->runlength=p->length+1;
  995. X  q=reduced_image->pixels;
  996. X  for (y=0; y < (image->rows-1); y+=2)
  997. X  {
  998. X    /*
  999. X      Initialize sliding window pointers.
  1000. X    */
  1001. X    s0=scanline+image->columns*((y+0) % 4);
  1002. X    s1=scanline+image->columns*((y+1) % 4);
  1003. X    s2=scanline+image->columns*((y+2) % 4);
  1004. X    s3=scanline+image->columns*((y+3) % 4);
  1005. X    /*
  1006. X      Read another scan line.
  1007. X    */
  1008. X    s=s2;
  1009. X    for (x=0; x < image->columns; x++)
  1010. X    {
  1011. X      if (image->runlength > 0)
  1012. X        image->runlength--;
  1013. X      else
  1014. X        {
  1015. X          p++;
  1016. X          image->runlength=p->length;
  1017. X        }
  1018. X      s->red=p->red;
  1019. X      s->green=p->green;
  1020. X      s->blue=p->blue;
  1021. X      s->index=p->index;
  1022. X      s++;
  1023. X    }
  1024. X    /*
  1025. X      Read another scan line.
  1026. X    */
  1027. X    s=s3;
  1028. X    for (x=0; x < image->columns; x++)
  1029. X    {
  1030. X      if (image->runlength > 0)
  1031. X        image->runlength--;
  1032. X      else
  1033. X        {
  1034. X          p++;
  1035. X          image->runlength=p->length;
  1036. X        }
  1037. X      s->red=p->red;
  1038. X      s->green=p->green;
  1039. X      s->blue=p->blue;
  1040. X      s->index=p->index;
  1041. X      s++;
  1042. X    }
  1043. X    for (x=0; x < (image->columns-1); x+=2)
  1044. X    {
  1045. X      /*
  1046. X        Compute weighted average of target pixel color components.
  1047. X
  1048. X        These particular coefficients total to 128.  Use 128/2-1 or 63 to
  1049. X        insure correct round off.
  1050. X      */
  1051. X      total_red=0;
  1052. X      total_green=0;
  1053. X      total_blue=0;
  1054. X      total_alpha=0;
  1055. X      s=s0;
  1056. X      Rsum(3); Rsum(7);  Rsum(7);  Rsum(3);
  1057. X      s=s1;
  1058. X      Rsum(7); Rsum(15); Rsum(15); Rsum(7);
  1059. X      s=s2;
  1060. X      Rsum(7); Rsum(15); Rsum(15); Rsum(7);
  1061. X      s=s3;
  1062. X      Rsum(3); Rsum(7);  Rsum(7);  Rsum(3);
  1063. X      s0+=2;
  1064. X      s1+=2;
  1065. X      s2+=2;
  1066. X      s3+=2;
  1067. X      q->red=(unsigned char) ((total_red+63) >> 7);
  1068. X      q->green=(unsigned char) ((total_green+63) >> 7);
  1069. X      q->blue=(unsigned char) ((total_blue+63) >> 7);
  1070. X      q->index=(unsigned char) ((total_alpha+63) >> 7);
  1071. X      q->length=0;
  1072. X      q++;
  1073. X    }
  1074. X  }
  1075. X  (void) free((char *) scanline);
  1076. X  return(reduced_image);
  1077. }
  1078. X
  1079. /*
  1080. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1081. %                                                                             %
  1082. %                                                                             %
  1083. %                                                                             %
  1084. %   R e f l e c t I m a g e                                                   %
  1085. %                                                                             %
  1086. %                                                                             %
  1087. %                                                                             %
  1088. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1089. %
  1090. %  Function ReflectImage creates a new image that refelects each scanline of an
  1091. %  existing one.  It allocates the memory necessary for the new Image structure
  1092. %  and returns a pointer to the new image.
  1093. %
  1094. %  The format of the ReflectImage routine is:
  1095. %
  1096. %      reflected_image=ReflectImage(image)
  1097. %
  1098. %  A description of each parameter follows:
  1099. %
  1100. %    o reflected_image: Function ReflectImage returns a pointer to the image
  1101. %      after reflecting.  A null image is returned if there is a memory
  1102. %      shortage.
  1103. %
  1104. %    o image: The address of a structure of type Image.
  1105. %
  1106. %
  1107. */
  1108. Image *ReflectImage(image)
  1109. Image
  1110. X  *image;
  1111. {
  1112. X  ColorPacket
  1113. X    *scanline;
  1114. X
  1115. X  Image
  1116. X    *reflected_image;
  1117. X
  1118. X  register ColorPacket
  1119. X    *s;
  1120. X
  1121. X  register RunlengthPacket
  1122. X    *p,
  1123. X    *q;
  1124. X
  1125. X  register unsigned int
  1126. X    x,
  1127. X    y;
  1128. X
  1129. X  /*
  1130. X    Initialize reflected image attributes.
  1131. X  */
  1132. X  reflected_image=CopyImage(image,image->columns,image->rows,False);
  1133. X  if (reflected_image == (Image *) NULL)
  1134. X    {
  1135. X      Warning("unable to reflect image","memory allocation failed");
  1136. X      return((Image *) NULL);
  1137. X    }
  1138. X  /*
  1139. X    Allocate scan line buffer and column offset buffers.
  1140. X  */
  1141. X  scanline=(ColorPacket *) malloc(image->columns*sizeof(ColorPacket));
  1142. X  if (scanline == (ColorPacket *) NULL)
  1143. X    {
  1144. X      Warning("unable to reflect image","memory allocation failed");
  1145. X      DestroyImage(reflected_image);
  1146. X      return((Image *) NULL);
  1147. X    }
  1148. X  /*
  1149. X    Reflect each row.
  1150. X  */
  1151. X  p=image->pixels;
  1152. X  image->runlength=p->length+1;
  1153. X  q=reflected_image->pixels;
  1154. X  for (y=0; y < reflected_image->rows; y++)
  1155. X  {
  1156. X    /*
  1157. X      Read a scan line.
  1158. X    */
  1159. X    s=scanline;
  1160. X    for (x=0; x < image->columns; x++)
  1161. X    {
  1162. X      if (image->runlength > 0)
  1163. X        image->runlength--;
  1164. X      else
  1165. X        {
  1166. X          p++;
  1167. X          image->runlength=p->length;
  1168. X        }
  1169. X      s->red=p->red;
  1170. X      s->green=p->green;
  1171. X      s->blue=p->blue;
  1172. X      s->index=p->index;
  1173. X      s++;
  1174. X    }
  1175. X    /*
  1176. X      Reflect each column.
  1177. X    */
  1178. X    s=scanline+image->columns;
  1179. X    for (x=0; x < reflected_image->columns; x++)
  1180. X    {
  1181. X      s--;
  1182. X      q->red=s->red;
  1183. X      q->green=s->green;
  1184. X      q->blue=s->blue;
  1185. X      q->index=s->index;
  1186. X      q->length=0;
  1187. X      q++;
  1188. X    }
  1189. X  }
  1190. X  (void) free((char *) scanline);
  1191. X  return(reflected_image);
  1192. }
  1193. X
  1194. /*
  1195. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1196. %                                                                             %
  1197. %                                                                             %
  1198. %     R G B T r a n s f o r m I m a g e                                       %
  1199. %                                                                             %
  1200. %                                                                             %
  1201. %                                                                             %
  1202. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1203. %
  1204. %  Procedure RGBTransformImage converts the reference image from RGB to
  1205. %  an alternate colorspace.
  1206. %
  1207. %  The format of the RGBTransformImage routine is:
  1208. %
  1209. %      RGBTransformImage(image,colorspace)
  1210. %
  1211. %  A description of each parameter follows:
  1212. %
  1213. %    o image: The address of a structure of type Image;  returned from
  1214. %      ReadImage.
  1215. %
  1216. %    o colorspace: An unsigned integer value that indicates which colorspace
  1217. %      to transform the image.
  1218. %
  1219. %
  1220. */
  1221. void RGBTransformImage(image,colorspace)
  1222. Image
  1223. X  *image;
  1224. X
  1225. unsigned int
  1226. X  colorspace;
  1227. {
  1228. #define X 0
  1229. #define Y (MaxRGB+1)
  1230. #define Z (MaxRGB+1)*2
  1231. X
  1232. X  long int
  1233. X    tx,
  1234. X    ty,
  1235. X    tz,
  1236. X    *x,
  1237. X    *y,
  1238. X    *z;
  1239. X
  1240. X  register int
  1241. X    blue,
  1242. X    green,
  1243. X    i,
  1244. X    red;
  1245. X
  1246. X  register RunlengthPacket
  1247. X    *p;
  1248. X
  1249. X  register unsigned char
  1250. X    *range_limit;
  1251. X
  1252. X  unsigned char
  1253. X    *range_table;
  1254. X
  1255. X  if (colorspace == RGBColorspace)
  1256. X    return;
  1257. X  /*
  1258. X    Allocate the tables.
  1259. X  */
  1260. X  x=(long int *) malloc(3*(MaxRGB+1)*sizeof(long int));
  1261. X  y=(long int *) malloc(3*(MaxRGB+1)*sizeof(long int));
  1262. X  z=(long int *) malloc(3*(MaxRGB+1)*sizeof(long int));
  1263. X  range_table=(unsigned char *) malloc(3*(MaxRGB+1)*sizeof(unsigned char));
  1264. X  if ((x == (long int *) NULL) || (y == (long int *) NULL) ||
  1265. X      (z == (long int *) NULL) || (range_table == (unsigned char *) NULL))
  1266. X    {
  1267. X      Warning("unable to transform color space","memory allocation failed");
  1268. X      return;
  1269. X    }
  1270. X  /*
  1271. X    Pre-compute conversion tables.
  1272. X  */
  1273. X  for (i=0; i <= MaxRGB; i++)
  1274. X  {
  1275. X    range_table[i]=0;
  1276. X    range_table[i+(MaxRGB+1)]=(unsigned char) i;
  1277. X    range_table[i+(MaxRGB+1)*2]=MaxRGB;
  1278. X  }
  1279. X  range_limit=range_table+(MaxRGB+1);
  1280. X  tx=0;
  1281. X  ty=0;
  1282. X  tz=0;
  1283. X  switch (colorspace)
  1284. X  {
  1285. X    case GRAYColorspace:
  1286. X    {
  1287. X      /*
  1288. X        Initialize GRAY tables:
  1289. X
  1290. X          G = 0.29900*R+0.58700*G+0.11400*B
  1291. X      */
  1292. X      for (i=0; i <= MaxRGB; i++)
  1293. X      {
  1294. X        x[i+X]=UpShifted(0.29900)*i;
  1295. X        y[i+X]=UpShifted(0.58700)*i;
  1296. X        z[i+X]=UpShifted(0.11400)*i;
  1297. X        x[i+Y]=UpShifted(0.29900)*i;
  1298. X        y[i+Y]=UpShifted(0.58700)*i;
  1299. X        z[i+Y]=UpShifted(0.11400)*i;
  1300. X        x[i+Z]=UpShifted(0.29900)*i;
  1301. X        y[i+Z]=UpShifted(0.58700)*i;
  1302. X        z[i+Z]=UpShifted(0.11400)*i;
  1303. X      }
  1304. X      break;
  1305. X    }
  1306. X    case YIQColorspace:
  1307. X    {
  1308. X      /*
  1309. X        Initialize YIQ tables:
  1310. X
  1311. X          Y = 0.29900*R+0.58700*G+0.11400*B
  1312. X          I = 0.59600*R-0.27400*G-0.32200*B
  1313. X          Q = 0.21100*R-0.52300*G+0.31200*B
  1314. X      */
  1315. X      for (i=0; i <= MaxRGB; i++)
  1316. X      {
  1317. X        x[i+X]=UpShifted(0.29900)*i;
  1318. X        y[i+X]=UpShifted(0.58700)*i;
  1319. X        z[i+X]=UpShifted(0.11400)*i;
  1320. X        x[i+Y]=UpShifted(0.59600)*i;
  1321. X        y[i+Y]=(-UpShifted(0.27400))*i;
  1322. X        z[i+Y]=(-UpShifted(0.32200))*i;
  1323. X        x[i+Z]=UpShifted(0.21100)*i;
  1324. X        y[i+Z]=(-UpShifted(0.52300))*i;
  1325. X        z[i+Z]=UpShifted(0.31200)*i;
  1326. X      }
  1327. X      break;
  1328. X    }
  1329. X    case YUVColorspace:
  1330. X    default:
  1331. X    {
  1332. X      /*
  1333. X        Initialize YUV tables:
  1334. X
  1335. X          Y =  0.29900*R+0.58700*G+0.11400*B
  1336. X          U = -0.16874*R-0.33126*G+0.50000*B
  1337. X          V =  0.50000*R-0.41869*G-0.08131*B
  1338. X
  1339. X        U and V, normally -0.5 through 0.5, are normalized to the range 0
  1340. X        through MaxRGB.
  1341. X      */
  1342. X      ty=UpShifted((MaxRGB+1)/2);
  1343. X      tz=UpShifted((MaxRGB+1)/2);
  1344. X      for (i=0; i <= MaxRGB; i++)
  1345. X      {
  1346. X        x[i+X]=UpShifted(0.29900)*i;
  1347. X        y[i+X]=UpShifted(0.58700)*i;
  1348. X        z[i+X]=UpShifted(0.11400)*i;
  1349. X        x[i+Y]=(-UpShifted(0.16874))*i;
  1350. X        y[i+Y]=(-UpShifted(0.33126))*i;
  1351. X        z[i+Y]=UpShifted(0.50000)*i;
  1352. X        x[i+Z]=UpShifted(0.50000)*i;
  1353. X        y[i+Z]=(-UpShifted(0.41869))*i;
  1354. X        z[i+Z]=(-UpShifted(0.08131))*i;
  1355. X      }
  1356. X      break;
  1357. X    }
  1358. X    case XYZColorspace:
  1359. X    {
  1360. X      /*
  1361. X        Initialize XYZ tables:
  1362. X
  1363. X          X = 0.49000*R+0.31000*G+0.20000*B
  1364. X          Y = 0.17700*R+0.81300*G+0.01100*B
  1365. X          Z = 0.00000*R+0.01000*G+0.99000*B
  1366. X      */
  1367. X      for (i=0; i <= MaxRGB; i++)
  1368. X      {
  1369. X        x[i+X]=UpShifted(0.49000)*i;
  1370. X        y[i+X]=UpShifted(0.31000)*i;
  1371. X        z[i+X]=UpShifted(0.20000)*i;
  1372. X        x[i+Y]=UpShifted(0.17700)*i;
  1373. X        y[i+Y]=UpShifted(0.81300)*i;
  1374. X        z[i+Y]=UpShifted(0.01100)*i;
  1375. X        x[i+Z]=0;
  1376. X        y[i+Z]=UpShifted(0.01000)*i;
  1377. X        z[i+Z]=UpShifted(0.99000)*i;
  1378. X      }
  1379. X      break;
  1380. X    }
  1381. X  }
  1382. X  /*
  1383. X    Convert from RGB.
  1384. X  */
  1385. X  switch (image->class)
  1386. X  {
  1387. X    case DirectClass:
  1388. X    {
  1389. X      /*
  1390. X        Convert DirectClass image.
  1391. X      */
  1392. X      p=image->pixels;
  1393. X      for (i=0; i < image->packets; i++)
  1394. X      {
  1395. X        red=p->red;
  1396. X        green=p->green;
  1397. X        blue=p->blue;
  1398. X        p->red=range_limit[DownShift(x[red+X]+y[green+X]+z[blue+X]+tx)];
  1399. X        p->green=range_limit[DownShift(x[red+Y]+y[green+Y]+z[blue+Y]+ty)];
  1400. X        p->blue=range_limit[DownShift(x[red+Z]+y[green+Z]+z[blue+Z]+tz)];
  1401. X        p++;
  1402. X      }
  1403. X      break;
  1404. X    }
  1405. X    case PseudoClass:
  1406. X    {
  1407. X      register unsigned short
  1408. X        index;
  1409. X
  1410. X      /*
  1411. X        Convert PseudoClass image.
  1412. X      */
  1413. X      for (i=0; i < image->colors; i++)
  1414. X      {
  1415. X        red=image->colormap[i].red;
  1416. X        green=image->colormap[i].green;
  1417. X        blue=image->colormap[i].blue;
  1418. X        image->colormap[i].red=
  1419. X          range_limit[DownShift(x[red+X]+y[green+X]+z[blue+X]+tx)];
  1420. X        image->colormap[i].green=
  1421. X          range_limit[DownShift(x[red+Y]+y[green+Y]+z[blue+Y]+ty)];
  1422. X        image->colormap[i].blue=
  1423. X          range_limit[DownShift(x[red+Z]+y[green+Z]+z[blue+Z]+tz)];
  1424. X      }
  1425. X      p=image->pixels;
  1426. X      for (i=0; i < image->packets; i++)
  1427. X      {
  1428. X        index=p->index;
  1429. X        p->red=image->colormap[index].red;
  1430. X        p->green=image->colormap[index].green;
  1431. X        p->blue=image->colormap[index].blue;
  1432. X        p++;
  1433. X      }
  1434. X      break;
  1435. X    }
  1436. X  }
  1437. X  /*
  1438. X    Free allocated memory.
  1439. X  */
  1440. X  (void) free((char *) range_table);
  1441. X  (void) free((char *) z);
  1442. X  (void) free((char *) y);
  1443. X  (void) free((char *) x);
  1444. }
  1445. X
  1446. /*
  1447. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1448. %                                                                             %
  1449. %                                                                             %
  1450. %                                                                             %
  1451. %   S c a l e I m a g e                                                       %
  1452. %                                                                             %
  1453. %                                                                             %
  1454. %                                                                             %
  1455. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1456. %
  1457. %  Function ScaleImage creates a new image that is a scaled size of an
  1458. %  existing one using pixel replication.  It allocates the memory necessary
  1459. %  for the new Image structure and returns a pointer to the new image.
  1460. %
  1461. %  The format of the ScaleImage routine is:
  1462. %
  1463. %      scaled_image=ScaleImage(image,columns,rows)
  1464. %
  1465. %  A description of each parameter follows:
  1466. %
  1467. %    o scaled_image: Function ScaleImage returns a pointer to the image after
  1468. %      scaling.  A null image is returned if there is a memory shortage.
  1469. %
  1470. %    o image: The address of a structure of type Image.
  1471. %
  1472. %    o columns: An integer that specifies the number of columns in the scaled
  1473. %      image.
  1474. %
  1475. %    o rows: An integer that specifies the number of rows in the scaled
  1476. %      image.
  1477. %
  1478. %
  1479. */
  1480. Image *ScaleImage(image,columns,rows)
  1481. Image
  1482. X  *image;
  1483. X
  1484. unsigned int
  1485. X  columns,
  1486. X  rows;
  1487. {
  1488. X  ColorPacket
  1489. X    *scanline;
  1490. X
  1491. X  Image
  1492. X    *scaled_image;
  1493. X
  1494. X  register ColorPacket
  1495. X    *s;
  1496. X
  1497. X  register RunlengthPacket
  1498. X    *p,
  1499. X    *q;
  1500. X
  1501. X  register unsigned int
  1502. X    x;
  1503. X
  1504. X  unsigned int
  1505. X    *x_offset,
  1506. X    y,
  1507. X    *y_offset;
  1508. X
  1509. X  unsigned long
  1510. X    scale_factor;
  1511. X
  1512. X  if ((columns == 0) || (rows == 0))
  1513. X    {
  1514. X      Warning("unable to scale image","image dimensions are zero");
  1515. X      return((Image *) NULL);
  1516. X    }
  1517. X  if ((columns > MaxImageSize) || (rows > MaxImageSize))
  1518. X    {
  1519. X      Warning("unable to scale image","image too large");
  1520. X      return((Image *) NULL);
  1521. X    }
  1522. X  /*
  1523. X    Initialize scaled image attributes.
  1524. X  */
  1525. X  scaled_image=CopyImage(image,columns,rows,False);
  1526. X  if (scaled_image == (Image *) NULL)
  1527. X    {
  1528. X      Warning("unable to scale image","memory allocation failed");
  1529. X      return((Image *) NULL);
  1530. X    }
  1531. X  /*
  1532. X    Allocate scan line buffer and column offset buffers.
  1533. X  */
  1534. X  scanline=(ColorPacket *) malloc(image->columns*sizeof(ColorPacket));
  1535. X  x_offset=(unsigned int *) malloc(scaled_image->columns*sizeof(unsigned int));
  1536. X  y_offset=(unsigned int *) malloc(scaled_image->rows*sizeof(unsigned int));
  1537. X  if ((scanline == (ColorPacket *) NULL) ||
  1538. X      (x_offset == (unsigned int *) NULL) ||
  1539. X      (y_offset == (unsigned int *) NULL))
  1540. X    {
  1541. X      Warning("unable to scale image","memory allocation failed");
  1542. X      DestroyImage(scaled_image);
  1543. X      return((Image *) NULL);
  1544. X    }
  1545. X  /*
  1546. X    Initialize column pixel offsets.
  1547. X  */
  1548. X  scale_factor=UpShift(image->columns-1)/scaled_image->columns;
  1549. X  columns=0;
  1550. X  for (x=0; x < scaled_image->columns; x++)
  1551. X  {
  1552. X    x_offset[x]=DownShift((x+1)*scale_factor)-columns;
  1553. X    columns+=x_offset[x];
  1554. X  }
  1555. X  /*
  1556. X    Initialize row pixel offsets.
  1557. X  */
  1558. X  scale_factor=UpShift(image->rows-1)/scaled_image->rows;
  1559. X  rows=0;
  1560. X  for (y=0; y < scaled_image->rows; y++)
  1561. X  {
  1562. X    y_offset[y]=DownShift((y+1)*scale_factor)-rows;
  1563. X    rows+=y_offset[y];
  1564. X  }
  1565. X  /*
  1566. X    Preload first scanline.
  1567. X  */
  1568. X  p=image->pixels;
  1569. X  image->runlength=p->length+1;
  1570. X  s=scanline;
  1571. X  for (x=0; x < image->columns; x++)
  1572. X  {
  1573. X    if (image->runlength > 0)
  1574. X      image->runlength--;
  1575. X    else
  1576. X      {
  1577. X        p++;
  1578. X        image->runlength=p->length;
  1579. X      }
  1580. X    s->red=p->red;
  1581. X    s->green=p->green;
  1582. X    s->blue=p->blue;
  1583. X    s->index=p->index;
  1584. X    s++;
  1585. X  }
  1586. X  /*
  1587. X    Scale each row.
  1588. X  */
  1589. X  q=scaled_image->pixels;
  1590. X  for (y=0; y < scaled_image->rows; y++)
  1591. X  {
  1592. X    /*
  1593. X      Scale each column.
  1594. X    */
  1595. X    s=scanline;
  1596. X    for (x=0; x < scaled_image->columns; x++)
  1597. X    {
  1598. X      q->red=s->red;
  1599. X      q->green=s->green;
  1600. X      q->blue=s->blue;
  1601. X      q->index=s->index;
  1602. X      q->length=0;
  1603. X      q++;
  1604. X      s+=x_offset[x];
  1605. X    }
  1606. X    if (y_offset[y] > 0)
  1607. X      {
  1608. X        /*
  1609. X          Skip a scan line.
  1610. X        */
  1611. X        for (x=0; x < (image->columns*(y_offset[y]-1)); x++)
  1612. X          if (image->runlength > 0)
  1613. X            image->runlength--;
  1614. X          else
  1615. X            {
  1616. X              p++;
  1617. X              image->runlength=p->length;
  1618. X            }
  1619. X        /*
  1620. X          Read a scan line.
  1621. X        */
  1622. X        s=scanline;
  1623. X        for (x=0; x < image->columns; x++)
  1624. X        {
  1625. X          if (image->runlength > 0)
  1626. X            image->runlength--;
  1627. X          else
  1628. X            {
  1629. X              p++;
  1630. X              image->runlength=p->length;
  1631. X            }
  1632. X          s->red=p->red;
  1633. X          s->green=p->green;
  1634. X          s->blue=p->blue;
  1635. X          s->index=p->index;
  1636. X          s++;
  1637. X        }
  1638. X      }
  1639. X  }
  1640. X  (void) free((char *) scanline);
  1641. X  (void) free((char *) x_offset);
  1642. X  (void) free((char *) y_offset);
  1643. X  return(scaled_image);
  1644. }
  1645. X
  1646. /*
  1647. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1648. %                                                                             %
  1649. %                                                                             %
  1650. %                                                                             %
  1651. %   S o r t C o l o r m a p B y I n t e n t s i t y                           %
  1652. %                                                                             %
  1653. %                                                                             %
  1654. %                                                                             %
  1655. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1656. %
  1657. %  Function SortColormapByIntensity sorts the colormap of a PseudoClass image
  1658. %  by decreasing color intensity.
  1659. %
  1660. %  The format of the SortColormapByIntensity routine is:
  1661. %
  1662. %      SortColormapByIntensity(image)
  1663. %
  1664. %  A description of each parameter follows:
  1665. %
  1666. %    o image: A pointer to a Image structure.
  1667. %
  1668. %
  1669. */
  1670. static int IntensityCompare(x,y)
  1671. const void
  1672. X  *x,
  1673. X  *y;
  1674. {
  1675. X  ColorPacket
  1676. X    *color_1,
  1677. X    *color_2;
  1678. X
  1679. X  color_1=(ColorPacket *) x;
  1680. X  color_2=(ColorPacket *) y;
  1681. X  return((int) Intensity(*color_2)-(int) Intensity(*color_1));
  1682. }
  1683. X
  1684. void SortColormapByIntensity(image)
  1685. Image
  1686. X  *image;
  1687. {
  1688. X  register int
  1689. X    i;
  1690. X
  1691. X  register RunlengthPacket
  1692. X    *p;
  1693. X
  1694. X  register unsigned short
  1695. X    index;
  1696. X
  1697. X  unsigned short
  1698. X    *pixels;
  1699. X
  1700. X  if (image->class != PseudoClass)
  1701. X    return;
  1702. X  /*
  1703. X    Allocate memory for pixel indexes.
  1704. X  */
  1705. X  pixels=(unsigned short *) malloc(image->colors*sizeof(unsigned short));
  1706. X  if (pixels == (unsigned short *) NULL)
  1707. X    {
  1708. X      Warning("unable to sort colormap","memory allocation failed");
  1709. X      return;
  1710. X    }
  1711. X  /*
  1712. X    Assign index values to colormap entries.
  1713. X  */
  1714. X  for (i=0; i < image->colors; i++)
  1715. X    image->colormap[i].index=(unsigned short) i;
  1716. X  /*
  1717. X    Sort image colormap by decreasing color popularity.
  1718. X  */
  1719. X  (void) qsort((void *) image->colormap,(int) image->colors,sizeof(ColorPacket),
  1720. X    IntensityCompare);
  1721. X  /*
  1722. X    Update image colormap indexes to sorted colormap order.
  1723. X  */
  1724. X  for (i=0; i < image->colors; i++)
  1725. X    pixels[image->colormap[i].index]=(unsigned short) i;
  1726. X  p=image->pixels;
  1727. X  for (i=0; i < image->packets; i++)
  1728. X  {
  1729. X    index=pixels[p->index];
  1730. X    p->red=image->colormap[index].red;
  1731. X    p->green=image->colormap[index].green;
  1732. X    p->blue=image->colormap[index].blue;
  1733. X    p->index=index;
  1734. X    p++;
  1735. X  }
  1736. X  (void) free((char *) pixels);
  1737. }
  1738. X
  1739. /*
  1740. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1741. %                                                                             %
  1742. %                                                                             %
  1743. %                                                                             %
  1744. %   S t e r e o I m a g e                                                     %
  1745. %                                                                             %
  1746. %                                                                             %
  1747. %                                                                             %
  1748. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1749. %
  1750. %  Function StereoImage combines two images and produces a single image that
  1751. %  is the composite of a left and right image of a stereo pair.  The left
  1752. %  image is converted to grayscale and written to the red channel of the
  1753. %  stereo image.  The right image is converted to grayscale and written to the
  1754. %  blue channel of the stereo image.  View the composite image with red-blue
  1755. %  glasses to create a stereo effect.
  1756. %
  1757. %  The format of the StereoImage routine is:
  1758. %
  1759. %      stereo_image=StereoImage(left_image,right_image)
  1760. %
  1761. %  A description of each parameter follows:
  1762. %
  1763. %    o stereo_image: Function StereoImage returns a pointer to the stereo
  1764. %      image.  A null image is returned if there is a memory shortage.
  1765. %
  1766. %    o left_image: The address of a structure of type Image.
  1767. %
  1768. %    o right_image: The address of a structure of type Image.
  1769. %
  1770. %
  1771. */
  1772. Image *StereoImage(left_image,right_image)
  1773. Image
  1774. X  *left_image,
  1775. X  *right_image;
  1776. {
  1777. X  Image
  1778. X    *stereo_image;
  1779. X
  1780. X  register int
  1781. X    i;
  1782. X
  1783. X  register RunlengthPacket
  1784. X    *p,
  1785. X    *q,
  1786. X    *r;
  1787. X
  1788. X  if ((left_image->columns != right_image->columns) ||
  1789. X      (left_image->rows != right_image->rows))
  1790. X    {
  1791. X      Warning("unable to create stereo image",
  1792. X        "left and right image sizes differ");
  1793. X      return((Image *) NULL);
  1794. X    }
  1795. X  /*
  1796. X    Initialize stereo image attributes.
  1797. X  */
  1798. X  stereo_image=CopyImage(left_image,left_image->columns,left_image->rows,False);
  1799. X  if (stereo_image == (Image *) NULL)
  1800. X    {
  1801. X      Warning("unable to create stereo image","memory allocation failed");
  1802. X      return((Image *) NULL);
  1803. X    }
  1804. X  stereo_image->class=DirectClass;
  1805. X  /*
  1806. X    Copy left image to red channel and right image to blue channel.
  1807. X  */
  1808. X  QuantizeImage(left_image,256,8,False,GRAYColorspace,True);
  1809. X  p=left_image->pixels;
  1810. X  left_image->runlength=p->length+1;
  1811. X  QuantizeImage(right_image,256,8,False,GRAYColorspace,True);
  1812. X  q=right_image->pixels;
  1813. X  right_image->runlength=q->length+1;
  1814. X  r=stereo_image->pixels;
  1815. X  for (i=0; i < (stereo_image->columns*stereo_image->rows); i++)
  1816. X  {
  1817. X    if (left_image->runlength > 0)
  1818. X      left_image->runlength--;
  1819. X    else
  1820. X      {
  1821. X        p++;
  1822. X        left_image->runlength=p->length;
  1823. X      }
  1824. X    if (right_image->runlength > 0)
  1825. X      right_image->runlength--;
  1826. X    else
  1827. X      {
  1828. X        q++;
  1829. X        right_image->runlength=q->length;
  1830. X      }
  1831. X    r->red=(unsigned int) (p->red*12) >> 4;
  1832. X    r->green=0;
  1833. X    r->blue=q->blue;
  1834. X    r->index=0;
  1835. X    r->length=0;
  1836. X    r++;
  1837. X  }
  1838. X  return(stereo_image);
  1839. }
  1840. X
  1841. X
  1842. /*
  1843. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1844. %                                                                             %
  1845. %                                                                             %
  1846. %                                                                             %
  1847. %   T r a n s f o r m I m a g e                                               %
  1848. %                                                                             %
  1849. %                                                                             %
  1850. %                                                                             %
  1851. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1852. %
  1853. %  Function TransformImage creates a new image that is a transformed size of
  1854. %  of existing one as specified by the clip, image and scale geometries.  It
  1855. %  allocates the memory necessary for the new Image structure and returns a
  1856. %  pointer to the new image.
  1857. %
  1858. %  If a clip geometry is specified a subregion of the image is obtained.
  1859. %  If the specified image size, as defined by the image and scale geometries,
  1860. %  is smaller than the actual image size, the image is first reduced to an
  1861. %  integral of the specified image size with an antialias digital filter.  The
  1862. %  image is then scaled to the exact specified image size with pixel
  1863. %  replication.  If the specified image size is greater than the actual image
  1864. %  size, the image is first enlarged to an integral of the specified image
  1865. %  size with bilinear interpolation.  The image is then scaled to the exact
  1866. %  specified image size with pixel replication.
  1867. %
  1868. %  The format of the TransformImage routine is:
  1869. %
  1870. %      TransformImage(image,clip_geometry,image_geometry,scale_geometry)
  1871. %
  1872. %  A description of each parameter follows:
  1873. %
  1874. %    o image: The address of an address of a structure of type Image.  The
  1875. %      transformed image is returned as this parameter.
  1876. %
  1877. %    o clip_geometry: Specifies a pointer to a clip geometry string.
  1878. %      This geometry defined a subregion of the image.
  1879. %
  1880. %    o image_geometry: Specifies a pointer to a image geometry string.
  1881. %      The specified width and height of this geometry string are absolute.
  1882. %
  1883. %    o scale_geometry: Specifies a pointer to a scale geometry string.
  1884. %      The specified width and height of this geometry string are relative.
  1885. %
  1886. %
  1887. */
  1888. void TransformImage(image,clip_geometry,image_geometry,scale_geometry)
  1889. Image
  1890. X  **image;
  1891. X
  1892. char
  1893. X  *clip_geometry,
  1894. X  *image_geometry,
  1895. X  *scale_geometry;
  1896. {
  1897. X  Image
  1898. X    *transformed_image;
  1899. X
  1900. X  int
  1901. X    flags,
  1902. X    x,
  1903. X    y;
  1904. X
  1905. X  unsigned int
  1906. X    height,
  1907. X    width;
  1908. X
  1909. X  transformed_image=(*image);
  1910. X  if (clip_geometry != (char *) NULL)
  1911. X    {
  1912. X      Image
  1913. X        *clipped_image;
  1914. X
  1915. X      /*
  1916. X        Clip transformed_image to a user specified size.
  1917. X      */
  1918. X      x=0;
  1919. X      y=0;
  1920. X      flags=XParseGeometry(clip_geometry,&x,&y,&width,&height);
  1921. X      if ((flags & WidthValue) == 0)
  1922. X        width=(unsigned int) ((int) transformed_image->columns-x);
  1923. X      if ((flags & HeightValue) == 0)
  1924. X        height=(unsigned int) ((int) transformed_image->rows-y);
  1925. X      if ((flags & XNegative) != 0)
  1926. X        x+=transformed_image->columns-width;
  1927. X      if ((flags & YNegative) != 0)
  1928. X        y+=transformed_image->rows-height;
  1929. X      clipped_image=ClipImage(transformed_image,x,y,width,height);
  1930. X      if (clipped_image != (Image *) NULL)
  1931. X        {
  1932. X          DestroyImage(transformed_image);
  1933. X          transformed_image=clipped_image;
  1934. X        }
  1935. X    }
  1936. X  /*
  1937. X    Scale image to a user specified size.
  1938. X  */
  1939. X  width=transformed_image->columns;
  1940. X  height=transformed_image->rows;
  1941. X  if (scale_geometry != (char *) NULL)
  1942. X    {
  1943. X      float
  1944. X        scale_height,
  1945. X        scale_width;
  1946. X
  1947. X      scale_width=0.0;
  1948. X      scale_height=0.0;
  1949. X      (void) sscanf(scale_geometry,"%fx%f",&scale_width,&scale_height);
  1950. X      if (scale_height == 0.0)
  1951. X        scale_height=scale_width;
  1952. X      width=(unsigned int) (width*scale_width);
  1953. X      height=(unsigned int) (height*scale_height);
  1954. X    }
  1955. X  if (image_geometry != (char *) NULL)
  1956. X    (void) XParseGeometry(image_geometry,&x,&y,&width,&height);
  1957. X  while ((transformed_image->columns >= (width << 1)) &&
  1958. X         (transformed_image->rows >= (height << 1)))
  1959. X  {
  1960. X    Image
  1961. X      *reduced_image;
  1962. X
  1963. X    /*
  1964. X      Reduce image with a antialias digital filter.
  1965. X     */
  1966. X    reduced_image=ReduceImage(transformed_image);
  1967. X    if (reduced_image == (Image *) NULL)
  1968. X      break;
  1969. X    DestroyImage(transformed_image);
  1970. X    transformed_image=reduced_image;
  1971. X  }
  1972. X  while ((transformed_image->columns <= (width >> 1)) &&
  1973. X         (transformed_image->rows <= (height >> 1)))
  1974. X  {
  1975. X    Image
  1976. X      *zoomed_image;
  1977. X
  1978. X    /*
  1979. X      Zoom transformed_image with bilinear interpolation.
  1980. X    */
  1981. X    zoomed_image=ZoomImage(transformed_image);
  1982. X    if (zoomed_image == (Image *) NULL)
  1983. X      break;
  1984. X    DestroyImage(transformed_image);
  1985. X    transformed_image=zoomed_image;
  1986. X  }
  1987. X  if ((transformed_image->columns != width) ||
  1988. X      (transformed_image->rows != height))
  1989. X    {
  1990. X      Image
  1991. X        *scaled_image;
  1992. X
  1993. X      /*
  1994. X        Scale image with pixel replication.
  1995. X      */
  1996. X      scaled_image=ScaleImage(transformed_image,width,height);
  1997. X      if (scaled_image != (Image *) NULL)
  1998. X        {
  1999. X          DestroyImage(transformed_image);
  2000. X          transformed_image=scaled_image;
  2001. X        }
  2002. X    }
  2003. X  *image=transformed_image;
  2004. }
  2005. X
  2006. /*
  2007. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2008. %                                                                             %
  2009. %                                                                             %
  2010. %     T r a n s f o r m R G B I m a g e                                       %
  2011. %                                                                             %
  2012. %                                                                             %
  2013. %                                                                             %
  2014. SHAR_EOF
  2015. true || echo 'restore of ImageMagick/image.c failed'
  2016. fi
  2017. echo 'End of  part 6'
  2018. echo 'File ImageMagick/image.c is continued in part 7'
  2019. echo 7 > _shar_seq_.tmp
  2020. exit 0
  2021. exit 0 # Just in case...
  2022.