~ubuntu-branches/ubuntu/intrepid/graphicsmagick/intrepid

« back to all changes in this revision

Viewing changes to coders/preview.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2006-05-06 16:28:08 UTC
  • Revision ID: james.westby@ubuntu.com-20060506162808-vt2ni3r5nytcszms
Tags: upstream-1.1.7
ImportĀ upstreamĀ versionĀ 1.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
% Copyright (C) 2003 GraphicsMagick Group
 
3
% Copyright (C) 2002 ImageMagick Studio
 
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
 
5
%
 
6
% This program is covered by multiple licenses, which are described in
 
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
 
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
 
9
%
 
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
11
%                                                                             %
 
12
%                                                                             %
 
13
%                                                                             %
 
14
%              PPPP   RRRR   EEEEE  V   V  IIIII  EEEEE  W   W                %
 
15
%              P   P  R   R  E      V   V    I    E      W   W                %
 
16
%              PPPP   RRRR   EEE    V   V    I    EEE    W   W                %
 
17
%              P      R R    E       V V     I    E      W W W                %
 
18
%              P      R  R   EEEEE    V    IIIII  EEEEE   W W                 %
 
19
%                                                                             %
 
20
%                                                                             %
 
21
%                           Write A Preview Image.                            %
 
22
%                                                                             %
 
23
%                                                                             %
 
24
%                              Software Design                                %
 
25
%                                John Cristy                                  %
 
26
%                                 July 1992                                   %
 
27
%                                                                             %
 
28
%                                                                             %
 
29
%                                                                             %
 
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
31
%
 
32
%
 
33
*/
 
34
 
 
35
/*
 
36
  Include declarations.
 
37
*/
 
38
#include "magick/studio.h"
 
39
#include "magick/attribute.h"
 
40
#include "magick/blob.h"
 
41
#include "magick/color.h"
 
42
#include "magick/constitute.h"
 
43
#include "magick/decorate.h"
 
44
#include "magick/effect.h"
 
45
#include "magick/enhance.h"
 
46
#include "magick/fx.h"
 
47
#include "magick/magick.h"
 
48
#include "magick/monitor.h"
 
49
#include "magick/montage.h"
 
50
#include "magick/quantize.h"
 
51
#include "magick/resize.h"
 
52
#include "magick/shear.h"
 
53
#include "magick/tempfile.h"
 
54
#include "magick/transform.h"
 
55
#include "magick/utility.h"
 
56
 
 
57
/*
 
58
  Constant declarations.
 
59
*/
 
60
static const char
 
61
  *DefaultPreviewGeometry = "204x204+10+10";
 
62
 
 
63
/*
 
64
  Forward declarations.
 
65
*/
 
66
static unsigned int
 
67
  WritePreviewImage(const ImageInfo *,Image *);
 
68
 
 
69
/*
 
70
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
71
%                                                                             %
 
72
%                                                                             %
 
73
%                                                                             %
 
74
%   R e g i s t e r P R E V I E W I m a g e                                   %
 
75
%                                                                             %
 
76
%                                                                             %
 
77
%                                                                             %
 
78
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
79
%
 
80
%  Method RegisterPREVIEWImage adds attributes for the Preview image format to
 
81
%  the list of supported formats.  The attributes include the image format
 
82
%  tag, a method to read and/or write the format, whether the format
 
83
%  supports the saving of more than one frame to the same file or blob,
 
84
%  whether the format supports native in-memory I/O, and a brief
 
85
%  description of the format.
 
86
%
 
87
%  The format of the RegisterPREVIEWImage method is:
 
88
%
 
89
%      RegisterPREVIEWImage(void)
 
90
%
 
91
*/
 
92
ModuleExport void RegisterPREVIEWImage(void)
 
93
{
 
94
  MagickInfo
 
95
    *entry;
 
96
 
 
97
  entry=SetMagickInfo("PREVIEW");
 
98
  entry->encoder=(EncoderHandler) WritePreviewImage;
 
99
  entry->adjoin=False;
 
100
  entry->description=
 
101
    AcquireString("Show a preview an image enhancement, effect, or f/x");
 
102
  entry->module=AcquireString("PREVIEW");
 
103
  (void) RegisterMagickInfo(entry);
 
104
}
 
105
 
 
106
/*
 
107
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
108
%                                                                             %
 
109
%                                                                             %
 
110
%                                                                             %
 
111
%   U n r e g i s t e r P R E V I E W I m a g e                               %
 
112
%                                                                             %
 
113
%                                                                             %
 
114
%                                                                             %
 
115
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
116
%
 
117
%  Method UnregisterPREVIEWImage removes format registrations made by the
 
118
%  PREVIEW module from the list of supported formats.
 
119
%
 
120
%  The format of the UnregisterPREVIEWImage method is:
 
121
%
 
122
%      UnregisterPREVIEWImage(void)
 
123
%
 
124
*/
 
125
ModuleExport void UnregisterPREVIEWImage(void)
 
126
{
 
127
  (void) UnregisterMagickInfo("PREVIEW");
 
128
}
 
129
 
 
130
/*
 
131
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
132
%                                                                             %
 
133
%                                                                             %
 
134
%                                                                             %
 
135
%   W r i t e P R E V I E W I m a g e                                         %
 
136
%                                                                             %
 
137
%                                                                             %
 
138
%                                                                             %
 
139
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
140
%
 
141
%  Method WritePreviewImage creates several tiles each with a varying
 
142
%  stength of an image enhancement function (e.g. gamma).  The image is written
 
143
%  in the MIFF format.
 
144
%
 
145
%  The format of the WritePreviewImage method is:
 
146
%
 
147
%      unsigned int WritePreviewImage(const ImageInfo *image_info,Image *image)
 
148
%
 
149
%  A description of each parameter follows.
 
150
%
 
151
%    o status: Method WritePreviewImage return True if the image is written.
 
152
%      False is returned is there is a memory shortage or if the image file
 
153
%      fails to write.
 
154
%
 
155
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
156
%
 
157
%    o image:  A pointer to an Image structure.
 
158
%
 
159
%
 
160
*/
 
161
#define ReplaceImage(oldimage,func) \
 
162
{ \
 
163
  Image \
 
164
    *temporary_image; \
 
165
\
 
166
  temporary_image=func; \
 
167
  if (temporary_image) \
 
168
  { \
 
169
    DestroyImage(oldimage); \
 
170
    oldimage=temporary_image; \
 
171
  } \
 
172
}
 
173
static unsigned int WritePreviewImage(const ImageInfo *image_info,Image *image)
 
174
{
 
175
#define NumberTiles  9
 
176
#define PreviewImageText  "  Creating image preview...  "
 
177
 
 
178
  char
 
179
    factor[MaxTextExtent],
 
180
    label[MaxTextExtent];
 
181
 
 
182
  float
 
183
    degrees,
 
184
    gamma,
 
185
    percentage,
 
186
    radius,
 
187
    sigma,
 
188
    threshold;
 
189
 
 
190
  Image
 
191
    *images,
 
192
    *montage_image,
 
193
    *preview_image,
 
194
    *master_image;
 
195
 
 
196
  ImageInfo
 
197
    *clone_info;
 
198
 
 
199
  long
 
200
    y;
 
201
 
 
202
  MonitorHandler
 
203
    handler;
 
204
 
 
205
  MontageInfo
 
206
    *montage_info;
 
207
 
 
208
  RectangleInfo
 
209
    geometry;
 
210
 
 
211
  register long
 
212
    i,
 
213
    x;
 
214
 
 
215
  unsigned int
 
216
    status;
 
217
 
 
218
  unsigned long
 
219
    colors;
 
220
 
 
221
  /*
 
222
    Open output image file.
 
223
  */
 
224
  assert(image_info != (const ImageInfo *) NULL);
 
225
  assert(image_info->signature == MagickSignature);
 
226
  assert(image != (Image *) NULL);
 
227
  assert(image->signature == MagickSignature);
 
228
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
 
229
  if (status == False)
 
230
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
231
  CloseBlob(image);
 
232
  TransformColorspace(image,RGBColorspace);
 
233
  clone_info=CloneImageInfo(image_info);
 
234
  clone_info->quality=0;
 
235
  colors=2;
 
236
  degrees=0;
 
237
  gamma=(-0.2f);
 
238
  SetGeometry(image,&geometry);
 
239
  (void) GetMagickGeometry(DefaultPreviewGeometry,&geometry.x,&geometry.y,
 
240
    &geometry.width,&geometry.height);
 
241
  images=NewImageList();
 
242
  percentage=12.5;
 
243
  radius=0.0;
 
244
  sigma=1.0;
 
245
  threshold=0.0;
 
246
  x=0;
 
247
  y=0;
 
248
  master_image=ResizeImage(image,geometry.width,geometry.height,
 
249
                           TriangleFilter,1.0,&image->exception);
 
250
  if (master_image == (Image *) NULL)
 
251
    return False;
 
252
  for (i=0; i < NumberTiles; i++)
 
253
  {
 
254
    preview_image=CloneImage(master_image,0,0,True,&image->exception);
 
255
    if (preview_image == (Image *) NULL)
 
256
      break;
 
257
    (void) SetImageAttribute(preview_image,"label",DefaultTileLabel);
 
258
    if (i == (NumberTiles >> 1))
 
259
      {
 
260
        (void) QueryColorDatabase("#dfdfdf",&preview_image->matte_color,
 
261
          &image->exception);
 
262
        AppendImageToList(&images,preview_image);
 
263
        continue;
 
264
      }
 
265
    handler=SetMonitorHandler((MonitorHandler) NULL);
 
266
    switch (image_info->preview_type)
 
267
    {
 
268
      case RotatePreview:
 
269
      {
 
270
        FormatString(factor,"%.1f",degrees+=45.0);
 
271
        FormatString(label,"rotate %.1024s",factor);
 
272
        ReplaceImage(preview_image,RotateImage(preview_image,degrees,
 
273
          &image->exception));
 
274
        break;
 
275
      }
 
276
      case ShearPreview:
 
277
      {
 
278
        degrees+=10.0;
 
279
        FormatString(factor,"%.1fx%.1f",degrees,2.0*degrees);
 
280
        FormatString(label,"shear %.1024s",factor);
 
281
        ReplaceImage(preview_image,ShearImage(preview_image,degrees,
 
282
          2.0*degrees,&image->exception));
 
283
        break;
 
284
      }
 
285
      case RollPreview:
 
286
      {
 
287
        x=(long) ((i+1)*preview_image->columns)/NumberTiles;
 
288
        y=(long) ((i+1)*preview_image->rows)/NumberTiles;
 
289
        FormatString(factor,"%+ld%+ld",x,y);
 
290
        FormatString(label,"roll %.1024s",factor);
 
291
        ReplaceImage(preview_image,RollImage(preview_image,x,y,
 
292
          &image->exception));
 
293
        break;
 
294
      }
 
295
      case HuePreview:
 
296
      {
 
297
        FormatString(factor,"100/100/%g",2.0*percentage);
 
298
        FormatString(label,"modulate %.1024s",factor);
 
299
        (void) ModulateImage(preview_image,factor);
 
300
        break;
 
301
      }
 
302
      case SaturationPreview:
 
303
      {
 
304
        FormatString(factor,"100/%g",2.0*percentage);
 
305
        FormatString(label,"modulate %.1024s",factor);
 
306
        (void) ModulateImage(preview_image,factor);
 
307
        break;
 
308
      }
 
309
      case BrightnessPreview:
 
310
      {
 
311
        FormatString(factor,"%g",2.0*percentage);
 
312
        FormatString(label,"modulate %.1024s",factor);
 
313
        (void) ModulateImage(preview_image,factor);
 
314
        break;
 
315
      }
 
316
      case GammaPreview:
 
317
      default:
 
318
      {
 
319
        FormatString(factor,"%g",gamma+=0.4f);
 
320
        FormatString(label,"gamma %.1024s",factor);
 
321
        (void) GammaImage(preview_image,factor);
 
322
        break;
 
323
      }
 
324
      case SpiffPreview:
 
325
      {
 
326
        for (x=0; x < i; x++)
 
327
          (void) ContrastImage(preview_image,True);
 
328
        FormatString(label,"-contrast %ld",i+1);
 
329
        break;
 
330
      }
 
331
      case DullPreview:
 
332
      {
 
333
        for (x=0; x < i; x++)
 
334
          (void) ContrastImage(preview_image,False);
 
335
        FormatString(label,"+contrast %ld",i+1);
 
336
        break;
 
337
      }
 
338
      case GrayscalePreview:
 
339
      {
 
340
        QuantizeInfo
 
341
          quantize_info;
 
342
 
 
343
        GetQuantizeInfo(&quantize_info);
 
344
        FormatString(factor,"%lu",colors);
 
345
        FormatString(label,"colors %.1024s",factor);
 
346
        TransformColorspace(preview_image,GRAYColorspace);
 
347
        quantize_info.number_colors=colors;
 
348
        quantize_info.colorspace=GRAYColorspace;
 
349
        quantize_info.dither=image_info->dither;
 
350
        quantize_info.tree_depth=8;
 
351
        (void) QuantizeImage(&quantize_info,preview_image);
 
352
        colors<<=1;
 
353
        break;
 
354
      }
 
355
      case QuantizePreview:
 
356
      {
 
357
        QuantizeInfo
 
358
          quantize_info;
 
359
 
 
360
        GetQuantizeInfo(&quantize_info);
 
361
        FormatString(factor,"%lu",colors);
 
362
        FormatString(label,"colors %.1024s",factor);
 
363
        quantize_info.number_colors=colors;
 
364
        quantize_info.colorspace=preview_image->colorspace;
 
365
        quantize_info.dither=image_info->dither;
 
366
        quantize_info.tree_depth=8;
 
367
        (void) QuantizeImage(&quantize_info,preview_image);
 
368
        colors<<=1;
 
369
        break;
 
370
      }
 
371
      case DespecklePreview:
 
372
      {
 
373
        for (x=0; x < i; x++)
 
374
          {
 
375
            ReplaceImage(preview_image,DespeckleImage(preview_image,
 
376
              &image->exception));
 
377
          }
 
378
        FormatString(label,"despeckle %ld",i+1);
 
379
        break;
 
380
      }
 
381
      case ReduceNoisePreview:
 
382
      {
 
383
        FormatString(factor,"%gx%g",radius,sigma);
 
384
        FormatString(label,"noise %.1024s",factor);
 
385
        ReplaceImage(preview_image,ReduceNoiseImage(preview_image,radius,
 
386
          &image->exception));
 
387
        break;
 
388
      }
 
389
      case AddNoisePreview:
 
390
      {
 
391
        NoiseType
 
392
          noise;
 
393
 
 
394
        switch ((int) x)
 
395
        {
 
396
          case 0:
 
397
            (void) strcpy(factor,"uniform");
 
398
            noise=UniformNoise;
 
399
            break;
 
400
          case 1:
 
401
            (void) strcpy(factor,"Gaussian");
 
402
            noise=GaussianNoise;
 
403
            break;
 
404
          case 2:
 
405
            (void) strcpy(factor,"multiplicative");
 
406
            noise=MultiplicativeGaussianNoise;
 
407
            break;
 
408
          case 3:
 
409
            (void) strcpy(factor,"impulse");
 
410
            noise=ImpulseNoise;
 
411
            break;
 
412
          case 4:
 
413
            (void) strcpy(factor,"laplacian");
 
414
            noise=LaplacianNoise;
 
415
            break;
 
416
          case 5:
 
417
            (void) strcpy(factor,"Poisson");
 
418
            noise=PoissonNoise;
 
419
            break;
 
420
          default:
 
421
            (void) strcpy(preview_image->magick,"NULL");
 
422
            noise=UniformNoise;
 
423
            break;
 
424
        }
 
425
        x++;
 
426
        FormatString(label,"+noise %.1024s",factor);
 
427
        ReplaceImage(preview_image,AddNoiseImage(preview_image,noise,
 
428
          &image->exception));
 
429
        break;
 
430
      }
 
431
      case SharpenPreview:
 
432
      {
 
433
        FormatString(factor,"%gx%g",radius,sigma);
 
434
        FormatString(label,"sharpen %.1024s",factor);
 
435
        ReplaceImage(preview_image,SharpenImage(preview_image,radius,sigma,
 
436
          &image->exception));
 
437
        break;
 
438
      }
 
439
      case BlurPreview:
 
440
      {
 
441
        FormatString(factor,"%gx%g",radius,sigma);
 
442
        FormatString(label,"-blur %.1024s",factor);
 
443
        ReplaceImage(preview_image,BlurImage(preview_image,radius,sigma,
 
444
          &image->exception));
 
445
        break;
 
446
      }
 
447
      case ThresholdPreview:
 
448
      {
 
449
        FormatString(factor,"%lu",(unsigned long)
 
450
          ((percentage*((double) MaxRGB+1.0))/100));
 
451
        FormatString(label,"threshold %.1024s",factor);
 
452
        (void ) ThresholdImage(preview_image,
 
453
          (percentage*((double) MaxRGB+1.0))/100);
 
454
        break;
 
455
      }
 
456
      case EdgeDetectPreview:
 
457
      {
 
458
        FormatString(factor,"%gx%g",radius,sigma);
 
459
        FormatString(label,"edge %.1024s",factor);
 
460
        ReplaceImage(preview_image,EdgeImage(preview_image,radius,
 
461
          &image->exception));
 
462
        break;
 
463
      }
 
464
      case SpreadPreview:
 
465
      {
 
466
        FormatString(factor,"%ld",i+1);
 
467
        FormatString(label,"spread %.1024s",factor);
 
468
        ReplaceImage(preview_image,SpreadImage(preview_image,i+1,
 
469
          &image->exception));
 
470
        break;
 
471
      }
 
472
      case SolarizePreview:
 
473
      {
 
474
        FormatString(factor,"%g",percentage);
 
475
        FormatString(label,"solarize %.1024s",factor);
 
476
        SolarizeImage(preview_image,percentage);
 
477
        break;
 
478
      }
 
479
      case ShadePreview:
 
480
      {
 
481
        if (i == 0)
 
482
          {
 
483
            FormatString(factor,"30x30");
 
484
            FormatString(label,"+shade %.1024s",factor);
 
485
            ReplaceImage(preview_image,ShadeImage(preview_image,False,30,30,
 
486
              &image->exception));
 
487
            break;
 
488
          }
 
489
        degrees+=10.0;
 
490
        FormatString(factor,"%gx%g",degrees,degrees);
 
491
        FormatString(label,"shade %.1024s",factor);
 
492
        ReplaceImage(preview_image,ShadeImage(preview_image,True,degrees,
 
493
          degrees,&image->exception));
 
494
        break;
 
495
      }
 
496
      case RaisePreview:
 
497
      {
 
498
        RectangleInfo
 
499
          raise_info;
 
500
 
 
501
        raise_info.width=2*i+2;
 
502
        raise_info.height=2*i+2;
 
503
        raise_info.x=0;
 
504
        raise_info.y=0;
 
505
        FormatString(factor,"%ldx%ld",2*i+2,2*i+2);
 
506
        FormatString(label,"raise %.1024s",factor);
 
507
        RaiseImage(preview_image,&raise_info,True);
 
508
        break;
 
509
      }
 
510
      case SegmentPreview:
 
511
      {
 
512
        threshold+=0.4f;
 
513
        FormatString(factor,"%.1fx%.1f",threshold,threshold);
 
514
        FormatString(label,"segment %.1024s",factor);
 
515
        (void) SegmentImage(preview_image,preview_image->colorspace,False,
 
516
                            threshold,threshold);
 
517
        break;
 
518
      }
 
519
      case SwirlPreview:
 
520
      {
 
521
        FormatString(factor,"%.1f",degrees);
 
522
        FormatString(label,"swirl %.1024s",factor);
 
523
        ReplaceImage(preview_image,SwirlImage(preview_image,degrees,
 
524
          &image->exception));
 
525
        degrees+=45.0;
 
526
        break;
 
527
      }
 
528
      case ImplodePreview:
 
529
      {
 
530
        FormatString(factor,"%.1f",percentage/100.0);
 
531
        FormatString(label,"implode %.1024s",factor);
 
532
        ReplaceImage(preview_image,ImplodeImage(preview_image,
 
533
          percentage/100.0,&image->exception));
 
534
        break;
 
535
      }
 
536
      case WavePreview:
 
537
      {
 
538
        degrees+=5.0;
 
539
        FormatString(factor,"%.1fx%.1f",0.5*degrees,2.0*degrees);
 
540
        FormatString(label,"wave %.1024s",factor);
 
541
        ReplaceImage(preview_image,WaveImage(preview_image,0.5*degrees,
 
542
          2.0*degrees,&image->exception));
 
543
        break;
 
544
      }
 
545
      case OilPaintPreview:
 
546
      {
 
547
        FormatString(factor,"%g",0.5*(i+1));
 
548
        FormatString(label,"paint %.1024s",factor);
 
549
        ReplaceImage(preview_image,OilPaintImage(preview_image,0.5*(i+1),
 
550
          &image->exception));
 
551
        break;
 
552
      }
 
553
      case CharcoalDrawingPreview:
 
554
      {
 
555
        FormatString(factor,"%gx%g",radius,sigma);
 
556
        FormatString(label,"charcoal %.1024s",factor);
 
557
        ReplaceImage(preview_image,CharcoalImage(preview_image,radius,sigma,
 
558
          &image->exception));
 
559
        break;
 
560
      }
 
561
      case JPEGPreview:
 
562
      {
 
563
        char
 
564
          filename[MaxTextExtent];
 
565
 
 
566
        clone_info->quality=(unsigned int) (percentage+13.0);
 
567
        FormatString(factor,"%lu",clone_info->quality);
 
568
        if(!AcquireTemporaryFileName(filename))
 
569
          {
 
570
            DestroyImage(master_image);
 
571
            DestroyImageInfo(clone_info);
 
572
            ThrowWriterTemporaryFileException(filename);
 
573
          }
 
574
        FormatString(preview_image->filename,"jpeg:%.1024s",filename);
 
575
        status=WriteImage(clone_info,preview_image);
 
576
        if (status != False)
 
577
          {
 
578
            Image
 
579
              *quality_image;
 
580
 
 
581
            (void) strncpy(clone_info->filename,preview_image->filename,
 
582
              MaxTextExtent-1);
 
583
            quality_image=ReadImage(clone_info,&image->exception);
 
584
            if (quality_image != (Image *) NULL)
 
585
              {
 
586
                DestroyImage(preview_image);
 
587
                preview_image=quality_image;
 
588
              }
 
589
          }
 
590
        LiberateTemporaryFile(filename);
 
591
        if ((GetBlobSize(preview_image)/1024) >= 1024)
 
592
          FormatString(label,"quality %.1024s\n%gmb ",factor,
 
593
            (double) GetBlobSize(preview_image)/1024.0/1024.0);
 
594
        else
 
595
          if (GetBlobSize(preview_image) >= 1024)
 
596
            FormatString(label,"quality %.1024s\n%gkb ",factor,
 
597
              (double) GetBlobSize(preview_image)/1024.0);
 
598
          else
 
599
            FormatString(label,"quality %.1024s\n%lub ",factor,
 
600
              (unsigned long) GetBlobSize(preview_image));
 
601
        break;
 
602
      }
 
603
    }
 
604
    percentage+=12.5;
 
605
    radius+=0.5;
 
606
    sigma+=0.25;
 
607
    (void) SetImageAttribute(preview_image,"label",(char *) NULL);
 
608
    (void) SetImageAttribute(preview_image,"label",label);
 
609
    (void) SetMonitorHandler(handler);
 
610
    AppendImageToList(&images,preview_image);
 
611
    if (!MagickMonitor(PreviewImageText,i,NumberTiles,&image->exception))
 
612
      break;
 
613
  }
 
614
  DestroyImage(master_image);
 
615
  DestroyImageInfo(clone_info);
 
616
  if (images == (Image *) NULL)
 
617
    return(False);
 
618
  /*
 
619
    Create the montage.
 
620
  */
 
621
  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
 
622
  (void) strncpy(montage_info->filename,image->filename,MaxTextExtent-1);
 
623
  montage_info->shadow=True;
 
624
  (void) CloneString(&montage_info->tile,"3x3");
 
625
  (void) CloneString(&montage_info->geometry,DefaultPreviewGeometry);
 
626
  (void) CloneString(&montage_info->frame,DefaultTileFrame);
 
627
  montage_image=MontageImages(images,montage_info,&image->exception);
 
628
  DestroyMontageInfo(montage_info);
 
629
  DestroyImageList(images);
 
630
  if (montage_image == (Image *) NULL)
 
631
    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
 
632
  if (montage_image->montage != (char *) NULL)
 
633
    {
 
634
      /*
 
635
        Free image directory.
 
636
      */
 
637
      MagickFreeMemory(montage_image->montage);
 
638
      montage_image->montage=(char *) NULL;
 
639
      if (image->directory != (char *) NULL)
 
640
        {
 
641
          MagickFreeMemory(montage_image->directory);
 
642
          montage_image->directory=(char *) NULL;
 
643
        }
 
644
    }
 
645
  FormatString(montage_image->filename,"miff:%.1024s",image_info->filename);
 
646
  status=WriteImage(image_info,montage_image);
 
647
  DestroyImage(montage_image);
 
648
  return(status);
 
649
}