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/blob.h"
00045 #include "magick/blob-private.h"
00046 #include "magick/cache.h"
00047 #include "magick/cache-private.h"
00048 #include "magick/color-private.h"
00049 #include "magick/composite-private.h"
00050 #include "magick/exception.h"
00051 #include "magick/exception-private.h"
00052 #include "magick/list.h"
00053 #include "magick/log.h"
00054 #include "magick/magick.h"
00055 #include "magick/memory_.h"
00056 #include "magick/pixel-private.h"
00057 #include "magick/quantum.h"
00058 #include "magick/random_.h"
00059 #include "magick/resource_.h"
00060 #include "magick/semaphore.h"
00061 #include "magick/splay-tree.h"
00062 #include "magick/string_.h"
00063 #include "magick/utility.h"
00064 #if defined(MAGICKCORE_ZLIB_DELEGATE)
00065 #include "zlib.h"
00066 #endif
00067 #if defined(MAGICKCORE_HAVE_PTHREAD)
00068 #include <pthread.h>
00069 #endif
00070 #if defined(__WINDOWS__)
00071 #include <windows.h>
00072 #endif
00073
00074
00075
00076
00077 struct _NexusInfo
00078 {
00079 MagickBooleanType
00080 mapped;
00081
00082 RectangleInfo
00083 region;
00084
00085 MagickSizeType
00086 length;
00087
00088 PixelPacket
00089 *cache,
00090 *pixels;
00091
00092 IndexPacket
00093 *indexes;
00094
00095 unsigned long
00096 signature;
00097 };
00098
00099
00100
00101
00102 #if defined(__cplusplus) || defined(c_plusplus)
00103 extern "C" {
00104 #endif
00105
00106 static const IndexPacket
00107 *GetVirtualIndexesFromCache(const Image *);
00108
00109 static const PixelPacket
00110 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const long,
00111 const long,const unsigned long,const unsigned long,ExceptionInfo *),
00112 *GetVirtualPixelsCache(const Image *);
00113
00114 static MagickBooleanType
00115 GetOneAuthenticPixelFromCache(Image *,const long,const long,PixelPacket *,
00116 ExceptionInfo *),
00117 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
00118 const long,const long,PixelPacket *,ExceptionInfo *),
00119 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
00120 ReadPixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
00121 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
00122 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
00123 WritePixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
00124 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
00125
00126 static PixelPacket
00127 *GetAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
00128 const unsigned long,ExceptionInfo *),
00129 *QueueAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
00130 const unsigned long,ExceptionInfo *),
00131 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *);
00132
00133 #if defined(__cplusplus) || defined(c_plusplus)
00134 }
00135 #endif
00136
00137
00138
00139
00140 static volatile MagickBooleanType
00141 instantiate_cache = MagickFalse;
00142
00143 static SemaphoreInfo
00144 *cache_semaphore = (SemaphoreInfo *) NULL;
00145
00146 static SplayTreeInfo
00147 *cache_resources = (SplayTreeInfo *) NULL;
00148
00149
00150
00151
00152 MagickExport unsigned long GetPixelCacheMaximumThreads(void)
00153 {
00154 static unsigned long
00155 maximum_threads = 0;
00156
00157 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00158 if (omp_get_max_threads() > (long) maximum_threads)
00159 maximum_threads=omp_get_max_threads();
00160 #else
00161 maximum_threads=1;
00162 #endif
00163 return(maximum_threads);
00164 }
00165
00166 MagickExport long GetPixelCacheThreadId(void)
00167 {
00168 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00169 return(omp_get_thread_num());
00170 #else
00171 return(0);
00172 #endif
00173 }
00174
00175 MagickExport void SetPixelCacheMaximumThreads(const unsigned long threads)
00176 {
00177 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00178 omp_set_num_threads(threads);
00179 #else
00180 (void) threads;
00181 #endif
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 MagickExport Cache AcquirePixelCacheInfo(const unsigned long number_threads)
00207 {
00208 CacheInfo
00209 *cache_info;
00210
00211 cache_info=(CacheInfo *) AcquireMagickMemory(sizeof(*cache_info));
00212 if (cache_info == (CacheInfo *) NULL)
00213 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00214 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
00215 cache_info->type=UndefinedCache;
00216 cache_info->colorspace=RGBColorspace;
00217 cache_info->file=(-1);
00218 #if defined(MAGICKCORE_HAVE_PTHREAD)
00219 cache_info->id=pthread_self();
00220 #elif defined(__WINDOWS__)
00221 cache_info->id=GetCurrentThreadId();
00222 #else
00223 cache_info->id=getpid();
00224 #endif
00225 cache_info->number_threads=number_threads;
00226 if (number_threads == 0)
00227 cache_info->number_threads=GetPixelCacheMaximumThreads();
00228 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
00229 if (cache_info->nexus_info == (NexusInfo **) NULL)
00230 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00231 GetPixelCacheMethods(&cache_info->methods);
00232 cache_info->reference_count=1;
00233 cache_info->semaphore=AllocateSemaphoreInfo();
00234 cache_info->disk_semaphore=AllocateSemaphoreInfo();
00235 cache_info->debug=IsEventLogging();
00236 cache_info->signature=MagickSignature;
00237 if ((cache_resources == (SplayTreeInfo *) NULL) &&
00238 (instantiate_cache == MagickFalse))
00239 {
00240 AcquireSemaphoreInfo(&cache_semaphore);
00241 if ((cache_resources == (SplayTreeInfo *) NULL) &&
00242 (instantiate_cache == MagickFalse))
00243 {
00244 cache_resources=NewSplayTree((int (*)(const void *,const void *))
00245 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
00246 instantiate_cache=MagickTrue;
00247 }
00248 RelinquishSemaphoreInfo(cache_semaphore);
00249 }
00250 (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
00251 return((Cache ) cache_info);
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 MagickExport NexusInfo **AcquirePixelCacheNexus(
00277 const unsigned long number_threads)
00278 {
00279 register long
00280 i;
00281
00282 NexusInfo
00283 **nexus_info;
00284
00285 nexus_info=(NexusInfo **) AcquireQuantumMemory(number_threads,
00286 sizeof(*nexus_info));
00287 if (nexus_info == (NexusInfo **) NULL)
00288 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00289 for (i=0; i < (long) number_threads; i++)
00290 {
00291 nexus_info[i]=(NexusInfo *) AcquireMagickMemory(sizeof(**nexus_info));
00292 if (nexus_info[i] == (NexusInfo *) NULL)
00293 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00294 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
00295 nexus_info[i]->signature=MagickSignature;
00296 }
00297 return(nexus_info);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 static MagickBooleanType ClipPixelCacheNexus(Image *image,
00330 NexusInfo *nexus_info,ExceptionInfo *exception)
00331 {
00332 CacheInfo
00333 *cache_info;
00334
00335 MagickSizeType
00336 number_pixels;
00337
00338 NexusInfo
00339 **clip_nexus,
00340 **image_nexus;
00341
00342 register const PixelPacket
00343 *r;
00344
00345 register IndexPacket
00346 *nexus_indexes,
00347 *indexes;
00348
00349 register long
00350 i;
00351
00352 register PixelPacket
00353 *p,
00354 *q;
00355
00356
00357
00358
00359 if (image->debug != MagickFalse)
00360 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00361 if (image->clip_mask == (Image *) NULL)
00362 return(MagickFalse);
00363 cache_info=GetImagePixelCache(image,MagickTrue,exception);
00364 if (cache_info == (Cache) NULL)
00365 return(MagickFalse);
00366 image_nexus=AcquirePixelCacheNexus(1);
00367 clip_nexus=AcquirePixelCacheNexus(1);
00368 if ((image_nexus == (NexusInfo **) NULL) ||
00369 (clip_nexus == (NexusInfo **) NULL))
00370 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
00371 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
00372 nexus_info->region.width,nexus_info->region.height,image_nexus[0],
00373 exception);
00374 indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
00375 q=nexus_info->pixels;
00376 nexus_indexes=nexus_info->indexes;
00377 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
00378 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
00379 nexus_info->region.height,clip_nexus[0],exception);
00380 number_pixels=(MagickSizeType) nexus_info->region.width*
00381 nexus_info->region.height;
00382 for (i=0; i < (long) number_pixels; i++)
00383 {
00384 if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
00385 break;
00386 if (PixelIntensityToQuantum(r) > ((Quantum) QuantumRange/2))
00387 {
00388 q->red=p->red;
00389 q->green=p->green;
00390 q->blue=p->blue;
00391 q->opacity=p->opacity;
00392 if (cache_info->active_index_channel != MagickFalse)
00393 nexus_indexes[i]=indexes[i];
00394 }
00395 p++;
00396 q++;
00397 r++;
00398 }
00399 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
00400 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
00401 if (i < (long) number_pixels)
00402 return(MagickFalse);
00403 return(MagickTrue);
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 static inline MagickBooleanType GetVirtualPixelsFromNexusPixels(
00434 NexusInfo *nexus_info)
00435 {
00436 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
00437 return(MagickFalse);
00438 nexus_info->mapped=MagickFalse;
00439 nexus_info->cache=(PixelPacket *) AcquireMagickMemory((size_t)
00440 nexus_info->length);
00441 if (nexus_info->cache == (PixelPacket *) NULL)
00442 {
00443 nexus_info->mapped=MagickTrue;
00444 nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
00445 nexus_info->length);
00446 }
00447 return(nexus_info->cache == (PixelPacket *) NULL ? MagickFalse : MagickTrue);
00448 }
00449
00450 static MagickBooleanType ClonePixelCacheNexus(CacheInfo *destination,
00451 CacheInfo *source)
00452 {
00453 MagickBooleanType
00454 status;
00455
00456 MagickSizeType
00457 number_pixels;
00458
00459 register long
00460 i;
00461
00462 register NexusInfo
00463 *p;
00464
00465 register NexusInfo
00466 *q;
00467
00468 destination->nexus_info=AcquirePixelCacheNexus(source->number_threads);
00469 if (destination->nexus_info == (NexusInfo **) NULL)
00470 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00471 status=MagickTrue;
00472 for (i=0; i < (long) source->number_threads; i++)
00473 {
00474 p=source->nexus_info[i];
00475 q=destination->nexus_info[i];
00476 q->mapped=p->mapped;
00477 q->region=p->region;
00478 q->length=p->length;
00479 q->cache=p->cache;
00480 q->pixels=p->pixels;
00481 q->indexes=p->indexes;
00482 if (p->cache != (PixelPacket *) NULL)
00483 {
00484 status=GetVirtualPixelsFromNexusPixels(q);
00485 if (status != MagickFalse)
00486 {
00487 (void) CopyMagickMemory(q->cache,p->cache,(size_t) p->length);
00488 q->pixels=q->cache;
00489 q->indexes=(IndexPacket *) NULL;
00490 number_pixels=(MagickSizeType) q->region.width*q->region.height;
00491 if (p->indexes != (IndexPacket *) NULL)
00492 q->indexes=(IndexPacket *) (q->pixels+number_pixels);
00493 }
00494 }
00495 }
00496 return(status);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
00527 {
00528 int
00529 status;
00530
00531 AcquireSemaphoreInfo(&cache_info->disk_semaphore);
00532 status=close(cache_info->file);
00533 cache_info->file=(-1);
00534 RelinquishMagickResource(FileResource,1);
00535 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00536 return(status == -1 ? MagickFalse : MagickTrue);
00537 }
00538
00539 static void LimitPixelCacheDescriptors(void)
00540 {
00541 register CacheInfo
00542 *p,
00543 *q;
00544
00545
00546
00547
00548 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
00549 return;
00550 AcquireSemaphoreInfo(&cache_semaphore);
00551 if (cache_resources == (SplayTreeInfo *) NULL)
00552 {
00553 RelinquishSemaphoreInfo(cache_semaphore);
00554 return;
00555 }
00556 ResetSplayTreeIterator(cache_resources);
00557 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00558 while (p != (CacheInfo *) NULL)
00559 {
00560 if ((p->type == DiskCache) && (p->file != -1))
00561 {
00562 #if defined(MAGICKCORE_HAVE_PTHREAD)
00563 if (pthread_equal(p->id,pthread_self()) != 0)
00564 #elif defined(__WINDOWS__)
00565 if (p->id == GetCurrentThreadId())
00566 #else
00567 if (p->id == getpid())
00568 #endif
00569 break;
00570 }
00571 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00572 }
00573 for (q=p; p != (CacheInfo *) NULL; )
00574 {
00575 if ((p->type == DiskCache) && (p->file != -1) &&
00576 (p->timestamp < q->timestamp))
00577 {
00578 #if defined(MAGICKCORE_HAVE_PTHREAD)
00579 if (pthread_equal(p->id,pthread_self()) != 0)
00580 #elif defined(__WINDOWS__)
00581 if (p->id == GetCurrentThreadId())
00582 #else
00583 if (p->id == getpid())
00584 #endif
00585 q=p;
00586 }
00587 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00588 }
00589 if (q != (CacheInfo *) NULL)
00590 (void) ClosePixelCacheOnDisk(q);
00591 RelinquishSemaphoreInfo(cache_semaphore);
00592 }
00593
00594 static inline MagickSizeType MagickMax(const MagickSizeType x,
00595 const MagickSizeType y)
00596 {
00597 if (x > y)
00598 return(x);
00599 return(y);
00600 }
00601
00602 static inline MagickSizeType MagickMin(const MagickSizeType x,
00603 const MagickSizeType y)
00604 {
00605 if (x < y)
00606 return(x);
00607 return(y);
00608 }
00609
00610 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
00611 const MapMode mode)
00612 {
00613 int
00614 file;
00615
00616
00617
00618
00619 AcquireSemaphoreInfo(&cache_info->disk_semaphore);
00620 if (cache_info->file != -1)
00621 {
00622 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00623 return(MagickTrue);
00624 }
00625 LimitPixelCacheDescriptors();
00626 if (*cache_info->cache_filename == '\0')
00627 file=AcquireUniqueFileResource(cache_info->cache_filename);
00628 else
00629 switch (mode)
00630 {
00631 case ReadMode:
00632 {
00633 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
00634 break;
00635 }
00636 case WriteMode:
00637 {
00638 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
00639 O_EXCL,S_MODE);
00640 if (file == -1)
00641 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
00642 break;
00643 }
00644 case IOMode:
00645 default:
00646 {
00647 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
00648 O_EXCL,S_MODE);
00649 if (file == -1)
00650 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
00651 break;
00652 }
00653 }
00654 if (file == -1)
00655 {
00656 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00657 return(MagickFalse);
00658 }
00659 (void) AcquireMagickResource(FileResource,1);
00660 cache_info->file=file;
00661 cache_info->timestamp=time(0);
00662 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00663 return(MagickTrue);
00664 }
00665
00666 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
00667 const MagickOffsetType offset,const MagickSizeType length,
00668 unsigned char *buffer)
00669 {
00670 register MagickOffsetType
00671 i;
00672
00673 ssize_t
00674 count;
00675
00676 #if !defined(MAGICKCORE_HAVE_PREAD)
00677 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00678 cache_info->timestamp=time(0);
00679 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
00680 {
00681 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00682 return((MagickOffsetType) -1);
00683 }
00684 #endif
00685 count=0;
00686 for (i=0; i < (MagickOffsetType) length; i+=count)
00687 {
00688 #if !defined(MAGICKCORE_HAVE_PREAD)
00689 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00690 (MagickSizeType) SSIZE_MAX));
00691 #else
00692 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00693 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
00694 #endif
00695 if (count > 0)
00696 continue;
00697 count=0;
00698 if (errno != EINTR)
00699 {
00700 i=(-1);
00701 break;
00702 }
00703 }
00704 #if !defined(MAGICKCORE_HAVE_PREAD)
00705 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00706 #endif
00707 return(i);
00708 }
00709
00710 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
00711 const MagickOffsetType offset,const MagickSizeType length,
00712 const unsigned char *buffer)
00713 {
00714 register MagickOffsetType
00715 i;
00716
00717 ssize_t
00718 count;
00719
00720 #if !defined(MAGICKCORE_HAVE_PWRITE)
00721 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00722 cache_info->timestamp=time(0);
00723 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
00724 {
00725 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00726 return((MagickOffsetType) -1);
00727 }
00728 #endif
00729 count=0;
00730 for (i=0; i < (MagickOffsetType) length; i+=count)
00731 {
00732 #if !defined(MAGICKCORE_HAVE_PWRITE)
00733 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00734 (MagickSizeType) SSIZE_MAX));
00735 #else
00736 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00737 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
00738 #endif
00739 if (count > 0)
00740 continue;
00741 count=0;
00742 if (errno != EINTR)
00743 {
00744 i=(-1);
00745 break;
00746 }
00747 }
00748 #if !defined(MAGICKCORE_HAVE_PWRITE)
00749 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00750 #endif
00751 return(i);
00752 }
00753
00754 static MagickBooleanType CloneDiskToDiskPixelCache(CacheInfo *clone_info,
00755 CacheInfo *cache_info,ExceptionInfo *exception)
00756 {
00757 MagickOffsetType
00758 count,
00759 offset,
00760 source_offset;
00761
00762 MagickSizeType
00763 length;
00764
00765 register long
00766 y;
00767
00768 register PixelPacket
00769 *pixels;
00770
00771 unsigned long
00772 columns,
00773 rows;
00774
00775 if (cache_info->debug != MagickFalse)
00776 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
00777 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
00778 {
00779 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00780 clone_info->cache_filename);
00781 return(MagickFalse);
00782 }
00783 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
00784 {
00785 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00786 cache_info->cache_filename);
00787 return(MagickFalse);
00788 }
00789 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
00790 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
00791 if ((clone_info->active_index_channel != MagickFalse) &&
00792 (cache_info->active_index_channel != MagickFalse))
00793 {
00794 register IndexPacket
00795 *indexes;
00796
00797
00798
00799
00800 length=MagickMax(clone_info->columns,cache_info->columns)*
00801 sizeof(*indexes);
00802 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
00803 if (indexes == (IndexPacket *) NULL)
00804 {
00805 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00806 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00807 return(MagickFalse);
00808 }
00809 (void) ResetMagickMemory(indexes,0,(size_t) length);
00810 length=columns*sizeof(*indexes);
00811 source_offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
00812 sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
00813 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
00814 sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
00815 for (y=0; y < (long) rows; y++)
00816 {
00817 source_offset-=cache_info->columns*sizeof(*indexes);
00818 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
00819 source_offset,length,(unsigned char *) indexes);
00820 if ((MagickSizeType) count != length)
00821 break;
00822 offset-=clone_info->columns*sizeof(*indexes);
00823 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00824 (unsigned char *) indexes);
00825 if ((MagickSizeType) count != length)
00826 break;
00827 }
00828 if (y < (long) rows)
00829 {
00830 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00831 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00832 cache_info->cache_filename);
00833 return(MagickFalse);
00834 }
00835 if (clone_info->columns > cache_info->columns)
00836 {
00837 length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
00838 (void) ResetMagickMemory(indexes,0,(size_t) length);
00839 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
00840 sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
00841 for (y=0; y < (long) rows; y++)
00842 {
00843 offset-=clone_info->columns*sizeof(*indexes);
00844 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
00845 length,(unsigned char *) indexes);
00846 if ((MagickSizeType) count != length)
00847 break;
00848 }
00849 if (y < (long) rows)
00850 {
00851 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00852 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00853 cache_info->cache_filename);
00854 return(MagickFalse);
00855 }
00856 }
00857 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00858 }
00859
00860
00861
00862 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
00863 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
00864 if (pixels == (PixelPacket *) NULL)
00865 {
00866 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00867 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00868 return(MagickFalse);
00869 }
00870 (void) ResetMagickMemory(pixels,0,(size_t) length);
00871 length=columns*sizeof(*pixels);
00872 source_offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
00873 offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
00874 for (y=0; y < (long) rows; y++)
00875 {
00876 source_offset-=cache_info->columns*sizeof(*pixels);
00877 count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
00878 length,(unsigned char *) pixels);
00879 if ((MagickSizeType) count != length)
00880 break;
00881 offset-=clone_info->columns*sizeof(*pixels);
00882 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00883 (unsigned char *) pixels);
00884 if ((MagickSizeType) count != length)
00885 break;
00886 }
00887 if (y < (long) rows)
00888 {
00889 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00890 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00891 cache_info->cache_filename);
00892 return(MagickFalse);
00893 }
00894 if (clone_info->columns > cache_info->columns)
00895 {
00896 offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
00897 sizeof(*pixels);
00898 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
00899 (void) ResetMagickMemory(pixels,0,(size_t) length);
00900 for (y=0; y < (long) rows; y++)
00901 {
00902 offset-=clone_info->columns*sizeof(*pixels);
00903 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00904 (unsigned char *) pixels);
00905 if ((MagickSizeType) count != length)
00906 break;
00907 }
00908 if (y < (long) rows)
00909 {
00910 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00911 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00912 cache_info->cache_filename);
00913 return(MagickFalse);
00914 }
00915 }
00916 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00917 return(MagickTrue);
00918 }
00919
00920 static MagickBooleanType CloneDiskToMemoryPixelCache(CacheInfo *clone_info,
00921 CacheInfo *cache_info,ExceptionInfo *exception)
00922 {
00923 MagickOffsetType
00924 count,
00925 offset;
00926
00927 MagickSizeType
00928 length;
00929
00930 register long