00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "magick/studio.h"
00044 #include "magick/annotate.h"
00045 #include "magick/client.h"
00046 #include "magick/color.h"
00047 #include "magick/composite.h"
00048 #include "magick/constitute.h"
00049 #include "magick/decorate.h"
00050 #include "magick/draw.h"
00051 #include "magick/effect.h"
00052 #include "magick/enhance.h"
00053 #include "magick/exception.h"
00054 #include "magick/exception-private.h"
00055 #include "magick/fx.h"
00056 #include "magick/gem.h"
00057 #include "magick/geometry.h"
00058 #include "magick/image.h"
00059 #include "magick/image-private.h"
00060 #include "magick/list.h"
00061 #include "magick/memory_.h"
00062 #include "magick/monitor.h"
00063 #include "magick/monitor-private.h"
00064 #include "magick/montage.h"
00065 #include "magick/option.h"
00066 #include "magick/quantize.h"
00067 #include "magick/property.h"
00068 #include "magick/resize.h"
00069 #include "magick/resource_.h"
00070 #include "magick/string_.h"
00071 #include "magick/utility.h"
00072 #include "magick/version.h"
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 MagickExport MontageInfo *CloneMontageInfo(const ImageInfo *image_info,
00102 const MontageInfo *montage_info)
00103 {
00104 MontageInfo
00105 *clone_info;
00106
00107 clone_info=(MontageInfo *) AcquireMagickMemory(sizeof(*clone_info));
00108 if (clone_info == (MontageInfo *) NULL)
00109 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00110 GetMontageInfo(image_info,clone_info);
00111 if (montage_info == (MontageInfo *) NULL)
00112 return(clone_info);
00113 if (montage_info->geometry != (char *) NULL)
00114 clone_info->geometry=AcquireString(montage_info->geometry);
00115 if (montage_info->tile != (char *) NULL)
00116 clone_info->tile=AcquireString(montage_info->tile);
00117 if (montage_info->title != (char *) NULL)
00118 clone_info->title=AcquireString(montage_info->title);
00119 if (montage_info->frame != (char *) NULL)
00120 clone_info->frame=AcquireString(montage_info->frame);
00121 if (montage_info->texture != (char *) NULL)
00122 clone_info->texture=AcquireString(montage_info->texture);
00123 if (montage_info->font != (char *) NULL)
00124 clone_info->font=AcquireString(montage_info->font);
00125 clone_info->pointsize=montage_info->pointsize;
00126 clone_info->border_width=montage_info->border_width;
00127 clone_info->shadow=montage_info->shadow;
00128 clone_info->fill=montage_info->fill;
00129 clone_info->stroke=montage_info->stroke;
00130 clone_info->background_color=montage_info->background_color;
00131 clone_info->border_color=montage_info->border_color;
00132 clone_info->matte_color=montage_info->matte_color;
00133 clone_info->gravity=montage_info->gravity;
00134 (void) CopyMagickString(clone_info->filename,montage_info->filename,
00135 MaxTextExtent);
00136 clone_info->debug=IsEventLogging();
00137 return(clone_info);
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 MagickExport MontageInfo *DestroyMontageInfo(MontageInfo *montage_info)
00164 {
00165 if (montage_info->debug != MagickFalse)
00166 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00167 assert(montage_info != (MontageInfo *) NULL);
00168 assert(montage_info->signature == MagickSignature);
00169 if (montage_info->geometry != (char *) NULL)
00170 montage_info->geometry=(char *)
00171 RelinquishMagickMemory(montage_info->geometry);
00172 if (montage_info->tile != (char *) NULL)
00173 montage_info->tile=DestroyString(montage_info->tile);
00174 if (montage_info->title != (char *) NULL)
00175 montage_info->title=DestroyString(montage_info->title);
00176 if (montage_info->frame != (char *) NULL)
00177 montage_info->frame=DestroyString(montage_info->frame);
00178 if (montage_info->texture != (char *) NULL)
00179 montage_info->texture=(char *) RelinquishMagickMemory(
00180 montage_info->texture);
00181 if (montage_info->font != (char *) NULL)
00182 montage_info->font=DestroyString(montage_info->font);
00183 montage_info->signature=(~MagickSignature);
00184 montage_info=(MontageInfo *) RelinquishMagickMemory(montage_info);
00185 return(montage_info);
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 MagickExport void GetMontageInfo(const ImageInfo *image_info,
00214 MontageInfo *montage_info)
00215 {
00216 assert(image_info != (const ImageInfo *) NULL);
00217 assert(image_info->signature == MagickSignature);
00218 if (image_info->debug != MagickFalse)
00219 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00220 image_info->filename);
00221 assert(montage_info != (MontageInfo *) NULL);
00222 (void) ResetMagickMemory(montage_info,0,sizeof(*montage_info));
00223 (void) CopyMagickString(montage_info->filename,image_info->filename,
00224 MaxTextExtent);
00225 montage_info->geometry=AcquireString(DefaultTileGeometry);
00226 if (image_info->font != (char *) NULL)
00227 montage_info->font=AcquireString(image_info->font);
00228 montage_info->gravity=CenterGravity;
00229 montage_info->pointsize=image_info->pointsize;
00230 montage_info->fill.opacity=OpaqueOpacity;
00231 montage_info->stroke.opacity=(Quantum) TransparentOpacity;
00232 montage_info->background_color=image_info->background_color;
00233 montage_info->border_color=image_info->border_color;
00234 montage_info->matte_color=image_info->matte_color;
00235 montage_info->debug=IsEventLogging();
00236 montage_info->signature=MagickSignature;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 static void GetMontageGeometry(char *geometry,const unsigned long number_images,
00272 long *x_offset,long *y_offset,unsigned long *tiles_per_column,
00273 unsigned long *tiles_per_row)
00274 {
00275 *tiles_per_column=0;
00276 *tiles_per_row=0;
00277 (void) GetGeometry(geometry,x_offset,y_offset,tiles_per_row,tiles_per_column);
00278 if ((*tiles_per_column == 0) && (*tiles_per_row == 0))
00279 *tiles_per_column=(unsigned long) sqrt((double) number_images);
00280 if (*tiles_per_column == 0)
00281 *tiles_per_column=(unsigned long)
00282 ceil((double) number_images/(*tiles_per_row));
00283 if (*tiles_per_row == 0)
00284 *tiles_per_row=(unsigned long)
00285 ceil((double) number_images/(*tiles_per_column));
00286 }
00287
00288 static inline long MagickMax(const long x,const long y)
00289 {
00290 if (x > y)
00291 return(x);
00292 return(y);
00293 }
00294
00295 static inline long MagickMin(const long x,const long y)
00296 {
00297 if (x < y)
00298 return(x);
00299 return(y);
00300 }
00301
00302 #if defined(__cplusplus) || defined(c_plusplus)
00303 extern "C" {
00304 #endif
00305
00306 static int SceneCompare(const void *x,const void *y)
00307 {
00308 Image
00309 **image_1,
00310 **image_2;
00311
00312 image_1=(Image **) x;
00313 image_2=(Image **) y;
00314 return((int) ((*image_1)->scene-(*image_2)->scene));
00315 }
00316
00317 #if defined(__cplusplus) || defined(c_plusplus)
00318 }
00319 #endif
00320
00321 MagickExport Image *MontageImages(const Image *images,
00322 const MontageInfo *montage_info,ExceptionInfo *exception)
00323 {
00324 Image
00325 *montage_image;
00326
00327 ImageInfo
00328 *image_info;
00329
00330 image_info=AcquireImageInfo();
00331 montage_image=MontageImageList(image_info,montage_info,images,exception);
00332 image_info=DestroyImageInfo(image_info);
00333 return(montage_image);
00334 }
00335
00336 MagickExport Image *MontageImageList(const ImageInfo *image_info,
00337 const MontageInfo *montage_info,const Image *images,ExceptionInfo *exception)
00338 {
00339 #define MontageImageTag "Montage/Image"
00340 #define TileImageTag "Tile/Image"
00341
00342 char
00343 tile_geometry[MaxTextExtent],
00344 *title;
00345
00346 const char
00347 *value;
00348
00349 DrawInfo
00350 *draw_info;
00351
00352 FrameInfo
00353 frame_info;
00354
00355 Image
00356 *image,
00357 **image_list,
00358 **master_list,
00359 *montage,
00360 *texture,
00361 *tile_image,
00362 *thumbnail;
00363
00364 ImageInfo
00365 *clone_info;
00366
00367 long
00368 tile,
00369 x,
00370 x_offset,
00371 y,
00372 y_offset;
00373
00374 MagickBooleanType
00375 concatenate,
00376 proceed,
00377 status;
00378
00379 MagickOffsetType
00380 tiles;
00381
00382 MagickStatusType
00383 flags;
00384
00385 MagickProgressMonitor
00386 progress_monitor;
00387
00388 register long
00389 i;
00390
00391 RectangleInfo
00392 bounds,
00393 geometry,
00394 extract_info;
00395
00396 size_t
00397 extent;
00398
00399 TypeMetric
00400 metrics;
00401
00402 unsigned long
00403 bevel_width,
00404 border_width,
00405 height,
00406 images_per_page,
00407 max_height,
00408 number_images,
00409 number_lines,
00410 sans,
00411 tiles_per_column,
00412 tiles_per_page,
00413 tiles_per_row,
00414 title_offset,
00415 total_tiles,
00416 width;
00417
00418
00419
00420
00421 assert(images != (Image *) NULL);
00422 assert(images->signature == MagickSignature);
00423 if (images->debug != MagickFalse)
00424 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
00425 assert(montage_info != (MontageInfo *) NULL);
00426 assert(montage_info->signature == MagickSignature);
00427 assert(exception != (ExceptionInfo *) NULL);
00428 assert(exception->signature == MagickSignature);
00429 number_images=GetImageListLength(images);
00430 master_list=ImageListToArray(images,exception);
00431 image_list=master_list;
00432 image=image_list[0];
00433 if (master_list == (Image **) NULL)
00434 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
00435 thumbnail=NewImageList();
00436 for (i=0; i < (long) number_images; i++)
00437 {
00438 image=CloneImage(image_list[i],0,0,MagickTrue,exception);
00439 if (image == (Image *) NULL)
00440 break;
00441 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
00442 progress_monitor=SetImageProgressMonitor(image,(MagickProgressMonitor) NULL,
00443 image->client_data);
00444 flags=ParseRegionGeometry(image,montage_info->geometry,&geometry,exception);
00445 thumbnail=ThumbnailImage(image,geometry.width,geometry.height,exception);
00446 if (thumbnail == (Image *) NULL)
00447 break;
00448 image_list[i]=thumbnail;
00449 (void) SetImageProgressMonitor(image,progress_monitor,image->client_data);
00450 proceed=SetImageProgress(image,TileImageTag,i,number_images);
00451 if (proceed == MagickFalse)
00452 break;
00453 image=DestroyImage(image);
00454 }
00455 if (i < (long) number_images)
00456 {
00457 if (thumbnail == (Image *) NULL)
00458 i--;
00459 for (tile=0; (long) tile <= i; tile++)
00460 if (image_list[tile] != (Image *) NULL)
00461 image_list[tile]=DestroyImage(image_list[tile]);
00462 master_list=(Image **) RelinquishMagickMemory(master_list);
00463 return((Image *) NULL);
00464 }
00465
00466
00467
00468 for (i=0; i < (long) number_images; i++)
00469 if (image_list[i]->scene == 0)
00470 break;
00471 if (i == (long) number_images)
00472 qsort((void *) image_list,(size_t) number_images,sizeof(*image_list),
00473 SceneCompare);
00474
00475
00476
00477 tiles_per_column=(unsigned long) sqrt((double) number_images);
00478 tiles_per_row=(unsigned long) ceil((double) number_images/tiles_per_column);
00479 x_offset=0;
00480 y_offset=0;
00481 if (montage_info->tile != (char *) NULL)
00482 GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
00483 &tiles_per_column,&tiles_per_row);
00484
00485
00486
00487 concatenate=MagickFalse;
00488 SetGeometry(image_list[0],&extract_info);
00489 extract_info.x=(long) montage_info->border_width;
00490 extract_info.y=(long) montage_info->border_width;
00491 if (montage_info->geometry != (char *) NULL)
00492 {
00493
00494
00495
00496 flags=GetGeometry(montage_info->geometry,&extract_info.x,&extract_info.y,
00497 &extract_info.width,&extract_info.height);
00498 if ((extract_info.x == 0) && (extract_info.y == 0))
00499 concatenate=((flags & RhoValue) == 0) && ((flags & SigmaValue) == 0) ?
00500 MagickTrue : MagickFalse;
00501 }
00502 border_width=montage_info->border_width;
00503 bevel_width=0;
00504 if (montage_info->frame != (char *) NULL)
00505 {
00506 char
00507 absolute_geometry[MaxTextExtent];
00508
00509 (void) ResetMagickMemory(&frame_info,0,sizeof(frame_info));
00510 frame_info.width=extract_info.width;
00511 frame_info.height=extract_info.height;
00512 (void) FormatMagickString(absolute_geometry,MaxTextExtent,"%s!",
00513 montage_info->frame);
00514 flags=ParseMetaGeometry(absolute_geometry,&frame_info.outer_bevel,
00515 &frame_info.inner_bevel,&frame_info.width,&frame_info.height);
00516 if ((flags & HeightValue) == 0)
00517 frame_info.height=frame_info.width;
00518 if ((flags & XiValue) == 0)
00519 frame_info.outer_bevel=(long) frame_info.width/2;
00520 if ((flags & PsiValue) == 0)
00521 frame_info.inner_bevel=frame_info.outer_bevel;
00522 frame_info.x=(long) frame_info.width;
00523 frame_info.y=(long) frame_info.height;
00524 bevel_width=(unsigned long) MagickMax(frame_info.inner_bevel,
00525 frame_info.outer_bevel);
00526 border_width=(unsigned long) MagickMax((long) frame_info.width,
00527 (long) frame_info.height);
00528 }
00529 for (i=0; i < (long) number_images; i++)
00530 {
00531 if (image_list[i]->columns > extract_info.width)
00532 extract_info.width=image_list[i]->columns;
00533 if (image_list[i]->rows > extract_info.height)
00534 extract_info.height=image_list[i]->rows;
00535 }
00536
00537
00538
00539 clone_info=CloneImageInfo(image_info);
00540 clone_info->background_color=montage_info->background_color;
00541 clone_info->border_color=montage_info->border_color;
00542 draw_info=CloneDrawInfo(clone_info,(DrawInfo *) NULL);
00543 if (montage_info->font != (char *) NULL)
00544 (void) CloneString(&draw_info->font,montage_info->font);
00545 if (montage_info->pointsize != 0.0)
00546 draw_info->pointsize=montage_info->pointsize;
00547 draw_info->gravity=CenterGravity;
00548 draw_info->stroke=montage_info->stroke;
00549 draw_info->fill=montage_info->fill;
00550 draw_info->text=AcquireString("");
00551 (void) GetTypeMetrics(image_list[0],draw_info,&metrics);
00552 texture=NewImageList();
00553 if (montage_info->texture != (char *) NULL)
00554 {
00555 (void) CopyMagickString(clone_info->filename,montage_info->texture,
00556 MaxTextExtent);
00557 texture=ReadImage(clone_info,exception);
00558 }
00559
00560
00561
00562 title=InterpretImageProperties(clone_info,image_list[0],montage_info->title);
00563 title_offset=0;
00564 if (montage_info->title != (char *) NULL)
00565 title_offset=(unsigned long) (2*(metrics.ascent-metrics.descent)*
00566 MultilineCensus(title)+2*extract_info.y);
00567 number_lines=0;
00568 for (i=0; i < (long) number_images; i++)
00569 {
00570 value=GetImageProperty(image_list[i],"label");
00571 if (value == (const char *) NULL)
00572 continue;
00573 if (MultilineCensus(value) > number_lines)
00574 number_lines=MultilineCensus(value);
00575 }
00576
00577
00578
00579 tile_image=AcquireImage(NULL);
00580 montage=AcquireImage(clone_info);
00581 montage->scene=0;
00582 images_per_page=(number_images-1)/(tiles_per_row*tiles_per_column)+1;
00583 tiles=0;
00584 total_tiles=(unsigned long) number_images;
00585 for (i=0; i < (long) images_per_page; i++)
00586 {
00587
00588
00589
00590 tiles_per_page=tiles_per_row*tiles_per_column;
00591 x_offset=0;
00592 y_offset=0;
00593 if (montage_info->tile != (char *) NULL)
00594 GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
00595 &sans,&sans);
00596 tiles_per_page=tiles_per_row*tiles_per_column;
00597 y_offset+=(long) title_offset;
00598 max_height=0;
00599 bounds.width=0;
00600 bounds.height=0;
00601 width=0;
00602 for (tile=0; tile < (long) tiles_per_page; tile++)
00603 {
00604 if (tile < (long) number_images)
00605 {
00606 width=concatenate != MagickFalse ? image_list[tile]->columns :
00607 extract_info.width;
00608 if (image_list[tile]->rows > max_height)
00609 max_height=image_list[tile]->rows;
00610 }
00611 x_offset+=width+(extract_info.x+border_width)*2;
00612 if (x_offset > (long) bounds.width)
00613 bounds.width=(unsigned long) x_offset;
00614 if (((tile+1) == (long) tiles_per_page) ||
00615 (((tile+1) % tiles_per_row) == 0))
00616 {
00617 x_offset=0;
00618 if (montage_info->tile != (char *) NULL)
00619 GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y,
00620 &sans,&sans);
00621 height=concatenate != MagickFalse ? max_height : extract_info.height;
00622 y_offset+=(unsigned long) (height+(extract_info.y+border_width)*2+
00623 (metrics.ascent-metrics.descent+4)*number_lines+
00624 (montage_info->shadow != MagickFalse ? 4 : 0));
00625 if (y_offset > (long) bounds.height)
00626 bounds.height=(unsigned long) y_offset;
00627 max_height=0;
00628 }
00629 }
00630 if (montage_info->shadow != MagickFalse)
00631 bounds.width+=4;
00632
00633
00634
00635 (void) CopyMagickString(montage->filename,montage_info->filename,
00636 MaxTextExtent);
00637 montage->columns=bounds.width;
00638 montage->rows=bounds.height;
00639 (void) SetImageBackgroundColor(montage);
00640
00641
00642
00643 montage->montage=AcquireString((char *) NULL);
00644 tile=0;
00645 extent=1;
00646 while (tile < MagickMin((long) tiles_per_page,(long) number_images))
00647 {
00648 extent+=strlen(image_list[tile]->filename)+1;
00649 tile++;
00650 }
00651 montage->directory=(char *) AcquireQuantumMemory(extent,
00652 sizeof(*montage->directory));
00653 if ((montage->montage == (char *) NULL) ||
00654 (montage->directory == (char *) NULL))
00655 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
00656 x_offset=0;
00657 y_offset=0;
00658 if (montage_info->tile != (char *) NULL)
00659 GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
00660 &sans,&sans);
00661 y_offset+=(long) title_offset;
00662 (void) FormatMagickString(montage->montage,MaxTextExtent,"%ldx%ld%+ld%+ld",
00663 (long) (extract_info.width+(extract_info.x+border_width)*2),
00664 (long) (extract_info.height+(extract_info.y+border_width)*2+
00665 (metrics.ascent-metrics.descent+4)*number_lines+
00666 (montage_info->shadow != MagickFalse ? 4 : 0)),x_offset,y_offset);
00667 *montage->directory='\0';
00668 tile=0;
00669 while (tile < MagickMin((long) tiles_per_page,(long) number_images))
00670 {
00671 (void) ConcatenateMagickString(montage->directory,
00672 image_list[tile]->filename,extent);
00673 (void) ConcatenateMagickString(montage->directory,"\n",extent);
00674 tile++;
00675 }
00676 progress_monitor=SetImageProgressMonitor(montage,(MagickProgressMonitor)
00677 NULL,montage->client_data);
00678 if (texture != (Image *) NULL)
00679 (void) TextureImage(montage,texture);
00680 if (montage_info->title != (char *) NULL)
00681 {
00682 char
00683 geometry[MaxTextExtent];
00684
00685 DrawInfo
00686 *clone_info;
00687
00688 TypeMetric
00689 metrics;
00690
00691
00692
00693
00694 clone_info=CloneDrawInfo(image_info,draw_info);
00695 clone_info->gravity=CenterGravity;
00696 clone_info->pointsize*=2.0;
00697 (void) GetTypeMetrics(image_list[0],clone_info,&metrics);
00698 (void) FormatMagickString(geometry,MaxTextExtent,"%lux%lu%+ld%+ld",
00699 montage->columns,(unsigned long) (metrics.ascent-metrics.descent),
00700 0L,(long) extract_info.y+4);
00701 (void) CloneString(&clone_info->geometry,geometry);
00702 (void) CloneString(&clone_info->text,title);
00703 (void) AnnotateImage(montage,clone_info);
00704 clone_info=DestroyDrawInfo(clone_info);
00705 }
00706 (void) SetImageProgressMonitor(montage,progress_monitor,
00707 montage->client_data);
00708
00709
00710
00711 x_offset=0;
00712 y_offset=0;
00713 if (montage_info->tile != (char *) NULL)
00714 GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
00715 &sans,&sans);
00716 x_offset+=extract_info.x;
00717 y_offset+=(long) title_offset+extract_info.y;
00718 max_height=0;
00719 for (tile=0; tile < MagickMin((long) tiles_per_page,(long) number_images); tile++)
00720 {
00721
00722
00723
00724 image=CloneImage(image_list[tile],0,0,MagickTrue,exception);
00725 progress_monitor=SetImageProgressMonitor(image,
00726 (MagickProgressMonitor) NULL,image->client_data);
00727 width=concatenate != MagickFalse ? image->columns : extract_info.width;
00728 if (image->rows > max_height)
00729 max_height=image->rows;
00730 height=concatenate != MagickFalse ? max_height : extract_info.height;
00731 if (border_width != 0)
00732 {
00733 Image
00734 *border_image;
00735
00736 RectangleInfo
00737 border_info;
00738
00739
00740
00741
00742 border_info.width=border_width;
00743 border_info.height=border_width;
00744 if (montage_info->frame != (char *) NULL)
00745 {
00746 border_info.width=(width-image->columns+1)/2;
00747 border_info.height=(height-image->rows+1)/2;
00748 }
00749 border_image=BorderImage(image,&border_info,exception);
00750 if (border_image != (Image *) NULL)
00751 {
00752 image=DestroyImage(image);
00753 image=border_image;
00754 }
00755 if ((montage_info->frame != (char *) NULL) &&
00756 (image->compose == DstOutCompositeOp))
00757 (void) NegateImageChannel(image,OpacityChannel,MagickFalse);
00758 }
00759
00760
00761
00762 tile_image->columns=width;
00763 tile_image->rows=height;
00764 tile_image->gravity=montage_info->gravity;
00765 if (image->gravity != UndefinedGravity)
00766 tile_image->gravity=image->gravity;
00767 (void) FormatMagickString(tile_geometry,MaxTextExtent,"%lux%lu+0+0",
00768 image->columns,image->rows);
00769 flags=ParseGravityGeometry(tile_image,tile_geometry,&geometry,exception);
00770 x=(long) (geometry.x+border_width);
00771 y=(long) (geometry.y+border_width);
00772 if ((montage_info->frame != (char *) NULL) && (bevel_width != 0))
00773 {
00774 FrameInfo
00775 extract_info;
00776
00777 Image
00778 *frame_image;
00779
00780
00781
00782
00783 extract_info=frame_info;
00784 extract_info.width=width+2*frame_info.width;
00785 extract_info.height=height+2*frame_info.height;
00786 value=GetImageProperty(image,"label");
00787 if (value != (const char *) NULL)
00788 extract_info.height+=(unsigned long) ((metrics.ascent-
00789 metrics.descent+4)*MultilineCensus(value));
00790 frame_image=FrameImage(image,&extract_info,exception);
00791 if (frame_image != (Image *) NULL)
00792 {
00793 image=DestroyImage(image);
00794 image=frame_image;
00795 }
00796 x=0;
00797 y=0;
00798 }
00799 if (LocaleCompare(image->magick,"NULL") != 0)
00800 {
00801
00802
00803
00804 if (montage_info->shadow != MagickFalse)
00805 {
00806 Image
00807 *shadow_image;
00808
00809
00810
00811
00812 (void) QueryColorDatabase("#000000",&image->background_color,
00813 exception);
00814 shadow_image=ShadowImage(image,80.0,2.0,5,5,exception);
00815 if (shadow_image != (Image *) NULL)
00816 {
00817 InheritException(&shadow_image->exception,exception);
00818 (void) CompositeImage(shadow_image,OverCompositeOp,image,0,0);
00819 image=DestroyImage(image);
00820 image=shadow_image;
00821 }
00822 }
00823 (void) CompositeImage(montage,OverCompositeOp,image,x_offset+x,
00824 y_offset+y);
00825 value=GetImageProperty(image,"label");
00826 if (value != (const char *) NULL)
00827 {
00828 char
00829 geometry[MaxTextExtent];
00830
00831
00832
00833
00834 (void) FormatMagickString(geometry,MaxTextExtent,
00835 "%lux%lu%+ld%+ld",(montage_info->frame ? image->columns :
00836 width)-2*border_width,(unsigned long) (metrics.ascent-
00837 metrics.descent+4)*MultilineCensus(value),x_offset+
00838 border_width,(montage_info->frame ? y_offset+height+
00839 border_width+4 : y_offset+extract_info.height+border_width+
00840 (montage_info->shadow != MagickFalse ? 4 : 0)));
00841 (void) CloneString(&draw_info->geometry,geometry);
00842 (void) CloneString(&draw_info->text,value);
00843 (void) AnnotateImage(montage,draw_info);
00844 }
00845 }
00846 x_offset+=width+(extract_info.x+border_width)*2;
00847 if (((tile+1) == (long) tiles_per_page) ||
00848 (((tile+1) % tiles_per_row) == 0))
00849 {
00850 x_offset=extract_info.x;
00851 y_offset+=(unsigned long) (height+(extract_info.y+border_width)*2+
00852 (metrics.ascent-metrics.descent+4)*number_lines+
00853 (montage_info->shadow != MagickFalse ? 4 : 0));
00854 max_height=0;
00855 }
00856 if ((images->progress_monitor != (MagickProgressMonitor) NULL) &&
00857 (QuantumTick(tiles,total_tiles) != MagickFalse))
00858 {
00859 status=images->progress_monitor(MontageImageTag,tiles,total_tiles,
00860 images->client_data);
00861 if (status == MagickFalse)
00862 break;
00863 }
00864 image_list[tile]=DestroyImage(image_list[tile]);
00865 image=DestroyImage(image);
00866 tiles++;
00867 }
00868 if ((i+1) < (long) images_per_page)
00869 {
00870
00871
00872
00873 AcquireNextImage(clone_info,montage);
00874 if (GetNextImageInList(montage) == (Image *) NULL)
00875 {
00876 montage=DestroyImageList(montage);
00877 return((Image *) NULL);
00878 }
00879 montage=GetNextImageInList(montage);
00880 image_list+=tiles_per_page;
00881 number_images-=tiles_per_page;
00882 }
00883 }
00884 tile_image=DestroyImage(tile_image);
00885 if (texture != (Image *) NULL)
00886 texture=DestroyImage(texture);
00887 master_list=(Image **) RelinquishMagickMemory(master_list);
00888 draw_info=DestroyDrawInfo(draw_info);
00889 clone_info=DestroyImageInfo(clone_info);
00890 while (GetPreviousImageInList(montage) != (Image *) NULL)
00891 montage=GetPreviousImageInList(montage);
00892 return(montage);
00893 }