|
MagickWand
6.7.7
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % W W AAA N N DDDD % 00006 % W W A A NN N D D % 00007 % W W W AAAAA N N N D D % 00008 % WW WW A A N NN D D % 00009 % W W A A N N DDDD % 00010 % % 00011 % V V IIIII EEEEE W W % 00012 % V V I E W W % 00013 % V V I EEE W W W % 00014 % V V I E WW WW % 00015 % V IIIII EEEEE W W % 00016 % % 00017 % % 00018 % MagickWand Wand View Methods % 00019 % % 00020 % Software Design % 00021 % John Cristy % 00022 % March 2003 % 00023 % % 00024 % % 00025 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00026 % dedicated to making software imaging solutions freely available. % 00027 % % 00028 % You may not use this file except in compliance with the License. You may % 00029 % obtain a copy of the License at % 00030 % % 00031 % http://www.imagemagick.org/script/license.php % 00032 % % 00033 % Unless required by applicable law or agreed to in writing, software % 00034 % distributed under the License is distributed on an "AS IS" BASIS, % 00035 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00036 % See the License for the specific language governing permissions and % 00037 % limitations under the License. % 00038 % % 00039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00040 % 00041 % 00042 % 00043 */ 00044 00045 /* 00046 Include declarations. 00047 */ 00048 #include "MagickWand/studio.h" 00049 #include "MagickWand/MagickWand.h" 00050 #include "MagickWand/magick-wand-private.h" 00051 #include "MagickWand/wand.h" 00052 #include "MagickCore/monitor-private.h" 00053 #include "MagickCore/thread-private.h" 00054 /* 00055 Define declarations. 00056 */ 00057 #define WandViewId "WandView" 00058 00059 /* 00060 Typedef declarations. 00061 */ 00062 struct _WandView 00063 { 00064 size_t 00065 id; 00066 00067 char 00068 name[MaxTextExtent], 00069 *description; 00070 00071 RectangleInfo 00072 extent; 00073 00074 MagickWand 00075 *wand; 00076 00077 Image 00078 *image; 00079 00080 CacheView 00081 *view; 00082 00083 PixelWand 00084 ***pixel_wands; 00085 00086 ExceptionInfo 00087 *exception; 00088 00089 MagickBooleanType 00090 debug; 00091 00092 size_t 00093 signature; 00094 }; 00095 00096 /* 00097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00098 % % 00099 % % 00100 % % 00101 % C l o n e W a n d V i e w % 00102 % % 00103 % % 00104 % % 00105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00106 % 00107 % CloneWandView() makes a copy of the specified wand view. 00108 % 00109 % The format of the CloneWandView method is: 00110 % 00111 % WandView *CloneWandView(const WandView *wand_view) 00112 % 00113 % A description of each parameter follows: 00114 % 00115 % o wand_view: the wand view. 00116 % 00117 */ 00118 WandExport WandView *CloneWandView(const WandView *wand_view) 00119 { 00120 WandView 00121 *clone_view; 00122 00123 register ssize_t 00124 i; 00125 00126 assert(wand_view != (WandView *) NULL); 00127 assert(wand_view->signature == WandSignature); 00128 if (wand_view->debug != MagickFalse) 00129 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name); 00130 clone_view=(WandView *) AcquireMagickMemory(sizeof(*clone_view)); 00131 if (clone_view == (WandView *) NULL) 00132 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 00133 wand_view->name); 00134 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view)); 00135 clone_view->id=AcquireWandId(); 00136 (void) FormatLocaleString(clone_view->name,MaxTextExtent,"%s-%.20g", 00137 WandViewId,(double) clone_view->id); 00138 clone_view->description=ConstantString(wand_view->description); 00139 clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue, 00140 wand_view->exception); 00141 clone_view->view=CloneCacheView(wand_view->view); 00142 clone_view->extent=wand_view->extent; 00143 clone_view->exception=AcquireExceptionInfo(); 00144 InheritException(clone_view->exception,wand_view->exception); 00145 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++) 00146 clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **) 00147 wand_view->pixel_wands[i],wand_view->extent.width); 00148 clone_view->debug=wand_view->debug; 00149 if (clone_view->debug != MagickFalse) 00150 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name); 00151 clone_view->signature=WandSignature; 00152 return(clone_view); 00153 } 00154 00155 /* 00156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00157 % % 00158 % % 00159 % % 00160 % D e s t r o y W a n d V i e w % 00161 % % 00162 % % 00163 % % 00164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00165 % 00166 % DestroyWandView() deallocates memory associated with a wand view. 00167 % 00168 % The format of the DestroyWandView method is: 00169 % 00170 % WandView *DestroyWandView(WandView *wand_view) 00171 % 00172 % A description of each parameter follows: 00173 % 00174 % o wand_view: the wand view. 00175 % 00176 */ 00177 00178 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands, 00179 const size_t number_wands) 00180 { 00181 register ssize_t 00182 i; 00183 00184 assert(pixel_wands != (PixelWand ***) NULL); 00185 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++) 00186 if (pixel_wands[i] != (PixelWand **) NULL) 00187 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands); 00188 pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands); 00189 return(pixel_wands); 00190 } 00191 00192 WandExport WandView *DestroyWandView(WandView *wand_view) 00193 { 00194 assert(wand_view != (WandView *) NULL); 00195 assert(wand_view->signature == WandSignature); 00196 wand_view->pixel_wands=DestroyPixelsThreadSet(wand_view->pixel_wands, 00197 wand_view->extent.width); 00198 wand_view->image=DestroyImage(wand_view->image); 00199 wand_view->view=DestroyCacheView(wand_view->view); 00200 wand_view->exception=DestroyExceptionInfo(wand_view->exception); 00201 wand_view->signature=(~WandSignature); 00202 RelinquishWandId(wand_view->id); 00203 wand_view=(WandView *) RelinquishMagickMemory(wand_view); 00204 return(wand_view); 00205 } 00206 00207 /* 00208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00209 % % 00210 % % 00211 % % 00212 % D u p l e x T r a n s f e r W a n d V i e w I t e r a t o r % 00213 % % 00214 % % 00215 % % 00216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00217 % 00218 % DuplexTransferWandViewIterator() iterates over three wand views in 00219 % parallel and calls your transfer method for each scanline of the view. The 00220 % source and duplex pixel extent is not confined to the image canvas-- that is 00221 % you can include negative offsets or widths or heights that exceed the image 00222 % dimension. However, the destination wand view is confined to the image 00223 % canvas-- that is no negative offsets or widths or heights that exceed the 00224 % image dimension are permitted. 00225 % 00226 % The callback signature is: 00227 % 00228 % MagickBooleanType DuplexTransferImageViewMethod(const WandView *source, 00229 % const WandView *duplex,WandView *destination,const ssize_t y, 00230 % const int thread_id,void *context) 00231 % 00232 % Use this pragma if the view is not single threaded: 00233 % 00234 % #pragma omp critical 00235 % 00236 % to define a section of code in your callback transfer method that must be 00237 % executed by a single thread at a time. 00238 % 00239 % The format of the DuplexTransferWandViewIterator method is: 00240 % 00241 % MagickBooleanType DuplexTransferWandViewIterator(WandView *source, 00242 % WandView *duplex,WandView *destination, 00243 % DuplexTransferWandViewMethod transfer,void *context) 00244 % 00245 % A description of each parameter follows: 00246 % 00247 % o source: the source wand view. 00248 % 00249 % o duplex: the duplex wand view. 00250 % 00251 % o destination: the destination wand view. 00252 % 00253 % o transfer: the transfer callback method. 00254 % 00255 % o context: the user defined context. 00256 % 00257 */ 00258 WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source, 00259 WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer, 00260 void *context) 00261 { 00262 Image 00263 *destination_image, 00264 *source_image; 00265 00266 MagickBooleanType 00267 status; 00268 00269 MagickOffsetType 00270 progress; 00271 00272 size_t 00273 height, 00274 width; 00275 00276 ssize_t 00277 y; 00278 00279 assert(source != (WandView *) NULL); 00280 assert(source->signature == WandSignature); 00281 if (transfer == (DuplexTransferWandViewMethod) NULL) 00282 return(MagickFalse); 00283 source_image=source->wand->images; 00284 destination_image=destination->wand->images; 00285 status=SetImageStorageClass(destination_image,DirectClass, 00286 destination->exception); 00287 if (status == MagickFalse) 00288 return(MagickFalse); 00289 status=MagickTrue; 00290 progress=0; 00291 height=source->extent.height-source->extent.y; 00292 width=source->extent.width-source->extent.x; 00293 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00294 #pragma omp parallel for schedule(static) shared(progress,status) \ 00295 dynamic_number_threads(source_image,width,height,1) 00296 #endif 00297 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 00298 { 00299 const int 00300 id = GetOpenMPThreadId(); 00301 00302 MagickBooleanType 00303 sync; 00304 00305 register const Quantum 00306 *restrict duplex_pixels, 00307 *restrict pixels; 00308 00309 register ssize_t 00310 x; 00311 00312 register Quantum 00313 *restrict destination_pixels; 00314 00315 if (status == MagickFalse) 00316 continue; 00317 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y, 00318 source->extent.width,1,source->exception); 00319 if (pixels == (const Quantum *) NULL) 00320 { 00321 status=MagickFalse; 00322 continue; 00323 } 00324 for (x=0; x < (ssize_t) source->extent.width; x++) 00325 { 00326 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]); 00327 pixels+=GetPixelChannels(source->image); 00328 } 00329 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y, 00330 duplex->extent.width,1,duplex->exception); 00331 if (duplex_pixels == (const Quantum *) NULL) 00332 { 00333 status=MagickFalse; 00334 continue; 00335 } 00336 for (x=0; x < (ssize_t) duplex->extent.width; x++) 00337 { 00338 PixelSetQuantumPixel(duplex->image,duplex_pixels, 00339 duplex->pixel_wands[id][x]); 00340 duplex_pixels+=GetPixelChannels(duplex->image); 00341 } 00342 destination_pixels=GetCacheViewAuthenticPixels(destination->view, 00343 destination->extent.x,y,destination->extent.width,1, 00344 destination->exception); 00345 if (destination_pixels == (Quantum *) NULL) 00346 { 00347 status=MagickFalse; 00348 continue; 00349 } 00350 for (x=0; x < (ssize_t) destination->extent.width; x++) 00351 { 00352 PixelSetQuantumPixel(destination->image,destination_pixels, 00353 destination->pixel_wands[id][x]); 00354 destination_pixels+=GetPixelChannels(destination->image); 00355 } 00356 if (transfer(source,duplex,destination,y,id,context) == MagickFalse) 00357 status=MagickFalse; 00358 destination_pixels=GetCacheViewAuthenticPixels(destination->view, 00359 destination->extent.x,y,destination->extent.width,1, 00360 destination->exception); 00361 for (x=0; x < (ssize_t) destination->extent.width; x++) 00362 { 00363 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x], 00364 destination_pixels); 00365 destination_pixels+=GetPixelChannels(destination->image); 00366 } 00367 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception); 00368 if (sync == MagickFalse) 00369 status=MagickFalse; 00370 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 00371 { 00372 MagickBooleanType 00373 proceed; 00374 00375 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00376 #pragma omp critical (MagickWand_DuplexTransferWandViewIterator) 00377 #endif 00378 proceed=SetImageProgress(source_image,source->description,progress++, 00379 source->extent.height); 00380 if (proceed == MagickFalse) 00381 status=MagickFalse; 00382 } 00383 } 00384 return(status); 00385 } 00386 00387 /* 00388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00389 % % 00390 % % 00391 % % 00392 % G e t W a n d V i e w E x c e p t i o n % 00393 % % 00394 % % 00395 % % 00396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00397 % 00398 % GetWandViewException() returns the severity, reason, and description of any 00399 % error that occurs when utilizing a wand view. 00400 % 00401 % The format of the GetWandViewException method is: 00402 % 00403 % char *GetWandViewException(const WandView *wand_view, 00404 % ExceptionType *severity) 00405 % 00406 % A description of each parameter follows: 00407 % 00408 % o wand_view: the pixel wand_view. 00409 % 00410 % o severity: the severity of the error is returned here. 00411 % 00412 */ 00413 WandExport char *GetWandViewException(const WandView *wand_view, 00414 ExceptionType *severity) 00415 { 00416 char 00417 *description; 00418 00419 assert(wand_view != (const WandView *) NULL); 00420 assert(wand_view->signature == WandSignature); 00421 if (wand_view->debug != MagickFalse) 00422 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name); 00423 assert(severity != (ExceptionType *) NULL); 00424 *severity=wand_view->exception->severity; 00425 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent, 00426 sizeof(*description)); 00427 if (description == (char *) NULL) 00428 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 00429 wand_view->name); 00430 *description='\0'; 00431 if (wand_view->exception->reason != (char *) NULL) 00432 (void) CopyMagickString(description,GetLocaleExceptionMessage( 00433 wand_view->exception->severity,wand_view->exception->reason), 00434 MaxTextExtent); 00435 if (wand_view->exception->description != (char *) NULL) 00436 { 00437 (void) ConcatenateMagickString(description," (",MaxTextExtent); 00438 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage( 00439 wand_view->exception->severity,wand_view->exception->description), 00440 MaxTextExtent); 00441 (void) ConcatenateMagickString(description,")",MaxTextExtent); 00442 } 00443 return(description); 00444 } 00445 00446 /* 00447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00448 % % 00449 % % 00450 % % 00451 % G e t W a n d V i e w E x t e n t % 00452 % % 00453 % % 00454 % % 00455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00456 % 00457 % GetWandViewExtent() returns the wand view extent. 00458 % 00459 % The format of the GetWandViewExtent method is: 00460 % 00461 % RectangleInfo GetWandViewExtent(const WandView *wand_view) 00462 % 00463 % A description of each parameter follows: 00464 % 00465 % o wand_view: the wand view. 00466 % 00467 */ 00468 WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view) 00469 { 00470 assert(wand_view != (WandView *) NULL); 00471 assert(wand_view->signature == WandSignature); 00472 return(wand_view->extent); 00473 } 00474 00475 /* 00476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00477 % % 00478 % % 00479 % % 00480 % G e t W a n d V i e w I t e r a t o r % 00481 % % 00482 % % 00483 % % 00484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00485 % 00486 % GetWandViewIterator() iterates over the wand view in parallel and calls 00487 % your get method for each scanline of the view. The pixel extent is 00488 % not confined to the image canvas-- that is you can include negative offsets 00489 % or widths or heights that exceed the image dimension. Any updates to 00490 % the pixels in your callback are ignored. 00491 % 00492 % The callback signature is: 00493 % 00494 % MagickBooleanType GetImageViewMethod(const WandView *source, 00495 % const ssize_t y,const int thread_id,void *context) 00496 % 00497 % Use this pragma if the view is not single threaded: 00498 % 00499 % #pragma omp critical 00500 % 00501 % to define a section of code in your callback get method that must be 00502 % executed by a single thread at a time. 00503 % 00504 % The format of the GetWandViewIterator method is: 00505 % 00506 % MagickBooleanType GetWandViewIterator(WandView *source, 00507 % GetWandViewMethod get,void *context) 00508 % 00509 % A description of each parameter follows: 00510 % 00511 % o source: the source wand view. 00512 % 00513 % o get: the get callback method. 00514 % 00515 % o context: the user defined context. 00516 % 00517 */ 00518 WandExport MagickBooleanType GetWandViewIterator(WandView *source, 00519 GetWandViewMethod get,void *context) 00520 { 00521 Image 00522 *source_image; 00523 00524 MagickBooleanType 00525 status; 00526 00527 MagickOffsetType 00528 progress; 00529 00530 size_t 00531 height, 00532 width; 00533 00534 ssize_t 00535 y; 00536 00537 assert(source != (WandView *) NULL); 00538 assert(source->signature == WandSignature); 00539 if (get == (GetWandViewMethod) NULL) 00540 return(MagickFalse); 00541 source_image=source->wand->images; 00542 status=MagickTrue; 00543 progress=0; 00544 height=source->extent.height-source->extent.y; 00545 width=source->extent.width-source->extent.x; 00546 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00547 #pragma omp parallel for schedule(static) shared(progress,status) \ 00548 dynamic_number_threads(source_image,width,height,1) 00549 #endif 00550 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 00551 { 00552 const int 00553 id = GetOpenMPThreadId(); 00554 00555 register const Quantum 00556 *pixels; 00557 00558 register ssize_t 00559 x; 00560 00561 if (status == MagickFalse) 00562 continue; 00563 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y, 00564 source->extent.width,1,source->exception); 00565 if (pixels == (const Quantum *) NULL) 00566 { 00567 status=MagickFalse; 00568 continue; 00569 } 00570 for (x=0; x < (ssize_t) source->extent.width; x++) 00571 { 00572 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]); 00573 pixels+=GetPixelChannels(source->image); 00574 } 00575 if (get(source,y,id,context) == MagickFalse) 00576 status=MagickFalse; 00577 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 00578 { 00579 MagickBooleanType 00580 proceed; 00581 00582 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00583 #pragma omp critical (MagickWand_GetWandViewIterator) 00584 #endif 00585 proceed=SetImageProgress(source_image,source->description,progress++, 00586 source->extent.height); 00587 if (proceed == MagickFalse) 00588 status=MagickFalse; 00589 } 00590 } 00591 return(status); 00592 } 00593 00594 /* 00595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00596 % % 00597 % % 00598 % % 00599 % G e t W a n d V i e w P i x e l s % 00600 % % 00601 % % 00602 % % 00603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00604 % 00605 % GetWandViewPixels() returns the wand view pixel_wands. 00606 % 00607 % The format of the GetWandViewPixels method is: 00608 % 00609 % PixelWand *GetWandViewPixels(const WandView *wand_view) 00610 % 00611 % A description of each parameter follows: 00612 % 00613 % o wand_view: the wand view. 00614 % 00615 */ 00616 WandExport PixelWand **GetWandViewPixels(const WandView *wand_view) 00617 { 00618 const int 00619 id = GetOpenMPThreadId(); 00620 00621 assert(wand_view != (WandView *) NULL); 00622 assert(wand_view->signature == WandSignature); 00623 return(wand_view->pixel_wands[id]); 00624 } 00625 00626 /* 00627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00628 % % 00629 % % 00630 % % 00631 % G e t W a n d V i e w W a n d % 00632 % % 00633 % % 00634 % % 00635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00636 % 00637 % GetWandViewWand() returns the magick wand associated with the wand view. 00638 % 00639 % The format of the GetWandViewWand method is: 00640 % 00641 % MagickWand *GetWandViewWand(const WandView *wand_view) 00642 % 00643 % A description of each parameter follows: 00644 % 00645 % o wand_view: the wand view. 00646 % 00647 */ 00648 WandExport MagickWand *GetWandViewWand(const WandView *wand_view) 00649 { 00650 assert(wand_view != (WandView *) NULL); 00651 assert(wand_view->signature == WandSignature); 00652 return(wand_view->wand); 00653 } 00654 00655 /* 00656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00657 % % 00658 % % 00659 % % 00660 % I s W a n d V i e w % 00661 % % 00662 % % 00663 % % 00664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00665 % 00666 % IsWandView() returns MagickTrue if the the parameter is verified as a wand 00667 % view object. 00668 % 00669 % The format of the IsWandView method is: 00670 % 00671 % MagickBooleanType IsWandView(const WandView *wand_view) 00672 % 00673 % A description of each parameter follows: 00674 % 00675 % o wand_view: the wand view. 00676 % 00677 */ 00678 WandExport MagickBooleanType IsWandView(const WandView *wand_view) 00679 { 00680 size_t 00681 length; 00682 00683 if (wand_view == (const WandView *) NULL) 00684 return(MagickFalse); 00685 if (wand_view->signature != WandSignature) 00686 return(MagickFalse); 00687 length=strlen(WandViewId); 00688 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0) 00689 return(MagickFalse); 00690 return(MagickTrue); 00691 } 00692 00693 /* 00694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00695 % % 00696 % % 00697 % % 00698 % N e w W a n d V i e w % 00699 % % 00700 % % 00701 % % 00702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00703 % 00704 % NewWandView() returns a wand view required for all other methods in the 00705 % Wand View API. 00706 % 00707 % The format of the NewWandView method is: 00708 % 00709 % WandView *NewWandView(MagickWand *wand) 00710 % 00711 % A description of each parameter follows: 00712 % 00713 % o wand: the wand. 00714 % 00715 */ 00716 00717 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands) 00718 { 00719 PixelWand 00720 ***pixel_wands; 00721 00722 register ssize_t 00723 i; 00724 00725 size_t 00726 number_threads; 00727 00728 number_threads=GetOpenMPMaximumThreads(); 00729 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads, 00730 sizeof(*pixel_wands)); 00731 if (pixel_wands == (PixelWand ***) NULL) 00732 return((PixelWand ***) NULL); 00733 (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands)); 00734 for (i=0; i < (ssize_t) number_threads; i++) 00735 { 00736 pixel_wands[i]=NewPixelWands(number_wands); 00737 if (pixel_wands[i] == (PixelWand **) NULL) 00738 return(DestroyPixelsThreadSet(pixel_wands,number_wands)); 00739 } 00740 return(pixel_wands); 00741 } 00742 00743 WandExport WandView *NewWandView(MagickWand *wand) 00744 { 00745 ExceptionInfo 00746 *exception; 00747 00748 WandView 00749 *wand_view; 00750 00751 assert(wand != (MagickWand *) NULL); 00752 assert(wand->signature == WandSignature); 00753 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view)); 00754 if (wand_view == (WandView *) NULL) 00755 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 00756 GetExceptionMessage(errno)); 00757 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view)); 00758 wand_view->id=AcquireWandId(); 00759 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g", 00760 WandViewId,(double) wand_view->id); 00761 wand_view->description=ConstantString("WandView"); 00762 wand_view->wand=wand; 00763 exception=AcquireExceptionInfo(); 00764 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception); 00765 wand_view->extent.width=wand->images->columns; 00766 wand_view->extent.height=wand->images->rows; 00767 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width); 00768 wand_view->exception=exception; 00769 if (wand_view->pixel_wands == (PixelWand ***) NULL) 00770 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 00771 GetExceptionMessage(errno)); 00772 wand_view->debug=IsEventLogging(); 00773 wand_view->signature=WandSignature; 00774 return(wand_view); 00775 } 00776 00777 /* 00778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00779 % % 00780 % % 00781 % % 00782 % N e w W a n d V i e w E x t e n t % 00783 % % 00784 % % 00785 % % 00786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00787 % 00788 % NewWandViewExtent() returns a wand view required for all other methods 00789 % in the Wand View API. 00790 % 00791 % The format of the NewWandViewExtent method is: 00792 % 00793 % WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x, 00794 % const ssize_t y,const size_t width,const size_t height) 00795 % 00796 % A description of each parameter follows: 00797 % 00798 % o wand: the magick wand. 00799 % 00800 % o x,y,columns,rows: These values define the perimeter of a extent of 00801 % pixel_wands view. 00802 % 00803 */ 00804 WandExport WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x, 00805 const ssize_t y,const size_t width,const size_t height) 00806 { 00807 ExceptionInfo 00808 *exception; 00809 00810 WandView 00811 *wand_view; 00812 00813 assert(wand != (MagickWand *) NULL); 00814 assert(wand->signature == WandSignature); 00815 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view)); 00816 if (wand_view == (WandView *) NULL) 00817 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 00818 GetExceptionMessage(errno)); 00819 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view)); 00820 wand_view->id=AcquireWandId(); 00821 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g", 00822 WandViewId,(double) wand_view->id); 00823 wand_view->description=ConstantString("WandView"); 00824 exception=AcquireExceptionInfo(); 00825 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception); 00826 wand_view->wand=wand; 00827 wand_view->extent.width=width; 00828 wand_view->extent.height=height; 00829 wand_view->extent.x=x; 00830 wand_view->extent.y=y; 00831 wand_view->exception=exception; 00832 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width); 00833 if (wand_view->pixel_wands == (PixelWand ***) NULL) 00834 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 00835 GetExceptionMessage(errno)); 00836 wand_view->debug=IsEventLogging(); 00837 wand_view->signature=WandSignature; 00838 return(wand_view); 00839 } 00840 00841 /* 00842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00843 % % 00844 % % 00845 % % 00846 % S e t W a n d V i e w D e s c r i p t i o n % 00847 % % 00848 % % 00849 % % 00850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00851 % 00852 % SetWandViewDescription() associates a description with an image view. 00853 % 00854 % The format of the SetWandViewDescription method is: 00855 % 00856 % void SetWandViewDescription(WandView *image_view,const char *description) 00857 % 00858 % A description of each parameter follows: 00859 % 00860 % o wand_view: the wand view. 00861 % 00862 % o description: the wand view description. 00863 % 00864 */ 00865 MagickExport void SetWandViewDescription(WandView *wand_view, 00866 const char *description) 00867 { 00868 assert(wand_view != (WandView *) NULL); 00869 assert(wand_view->signature == WandSignature); 00870 wand_view->description=ConstantString(description); 00871 } 00872 00873 /* 00874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00875 % % 00876 % % 00877 % % 00878 % S e t W a n d V i e w I t e r a t o r % 00879 % % 00880 % % 00881 % % 00882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00883 % 00884 % SetWandViewIterator() iterates over the wand view in parallel and calls 00885 % your set method for each scanline of the view. The pixel extent is 00886 % confined to the image canvas-- that is no negative offsets or widths or 00887 % heights that exceed the image dimension. The pixels are initiallly 00888 % undefined and any settings you make in the callback method are automagically 00889 % synced back to your image. 00890 % 00891 % The callback signature is: 00892 % 00893 % MagickBooleanType SetImageViewMethod(ImageView *destination, 00894 % const ssize_t y,const int thread_id,void *context) 00895 % 00896 % Use this pragma if the view is not single threaded: 00897 % 00898 % #pragma omp critical 00899 % 00900 % to define a section of code in your callback set method that must be 00901 % executed by a single thread at a time. 00902 % 00903 % The format of the SetWandViewIterator method is: 00904 % 00905 % MagickBooleanType SetWandViewIterator(WandView *destination, 00906 % SetWandViewMethod set,void *context) 00907 % 00908 % A description of each parameter follows: 00909 % 00910 % o destination: the wand view. 00911 % 00912 % o set: the set callback method. 00913 % 00914 % o context: the user defined context. 00915 % 00916 */ 00917 WandExport MagickBooleanType SetWandViewIterator(WandView *destination, 00918 SetWandViewMethod set,void *context) 00919 { 00920 Image 00921 *destination_image; 00922 00923 MagickBooleanType 00924 status; 00925 00926 MagickOffsetType 00927 progress; 00928 00929 size_t 00930 height, 00931 width; 00932 00933 ssize_t 00934 y; 00935 00936 assert(destination != (WandView *) NULL); 00937 assert(destination->signature == WandSignature); 00938 if (set == (SetWandViewMethod) NULL) 00939 return(MagickFalse); 00940 destination_image=destination->wand->images; 00941 status=SetImageStorageClass(destination_image,DirectClass, 00942 destination->exception); 00943 if (status == MagickFalse) 00944 return(MagickFalse); 00945 status=MagickTrue; 00946 progress=0; 00947 height=destination->extent.height-destination->extent.y; 00948 width=destination->extent.width-destination->extent.x; 00949 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00950 #pragma omp parallel for schedule(static) shared(progress,status) \ 00951 dynamic_number_threads(destination_image,width,height,1) 00952 #endif 00953 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++) 00954 { 00955 const int 00956 id = GetOpenMPThreadId(); 00957 00958 MagickBooleanType 00959 sync; 00960 00961 register ssize_t 00962 x; 00963 00964 register Quantum 00965 *restrict pixels; 00966 00967 if (status == MagickFalse) 00968 continue; 00969 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x, 00970 y,destination->extent.width,1,destination->exception); 00971 if (pixels == (Quantum *) NULL) 00972 { 00973 status=MagickFalse; 00974 continue; 00975 } 00976 if (set(destination,y,id,context) == MagickFalse) 00977 status=MagickFalse; 00978 for (x=0; x < (ssize_t) destination->extent.width; x++) 00979 { 00980 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x], 00981 pixels); 00982 pixels+=GetPixelChannels(destination->image); 00983 } 00984 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception); 00985 if (sync == MagickFalse) 00986 status=MagickFalse; 00987 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL) 00988 { 00989 MagickBooleanType 00990 proceed; 00991 00992 #if defined(MAGICKCORE_OPENMP_SUPPORT) 00993 #pragma omp critical (MagickWand_SetWandViewIterator) 00994 #endif 00995 proceed=SetImageProgress(destination_image,destination->description, 00996 progress++,destination->extent.height); 00997 if (proceed == MagickFalse) 00998 status=MagickFalse; 00999 } 01000 } 01001 return(status); 01002 } 01003 01004 /* 01005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01006 % % 01007 % % 01008 % % 01009 % T r a n s f e r W a n d V i e w I t e r a t o r % 01010 % % 01011 % % 01012 % % 01013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01014 % 01015 % TransferWandViewIterator() iterates over two wand views in parallel and 01016 % calls your transfer method for each scanline of the view. The source pixel 01017 % extent is not confined to the image canvas-- that is you can include 01018 % negative offsets or widths or heights that exceed the image dimension. 01019 % However, the destination wand view is confined to the image canvas-- that 01020 % is no negative offsets or widths or heights that exceed the image dimension 01021 % are permitted. 01022 % 01023 % The callback signature is: 01024 % 01025 % MagickBooleanType TransferImageViewMethod(const WandView *source, 01026 % WandView *destination,const ssize_t y,const int thread_id, 01027 % void *context) 01028 % 01029 % Use this pragma if the view is not single threaded: 01030 % 01031 % #pragma omp critical 01032 % 01033 % to define a section of code in your callback transfer method that must be 01034 % executed by a single thread at a time. 01035 % 01036 % The format of the TransferWandViewIterator method is: 01037 % 01038 % MagickBooleanType TransferWandViewIterator(WandView *source, 01039 % WandView *destination,TransferWandViewMethod transfer,void *context) 01040 % 01041 % A description of each parameter follows: 01042 % 01043 % o source: the source wand view. 01044 % 01045 % o destination: the destination wand view. 01046 % 01047 % o transfer: the transfer callback method. 01048 % 01049 % o context: the user defined context. 01050 % 01051 */ 01052 WandExport MagickBooleanType TransferWandViewIterator(WandView *source, 01053 WandView *destination,TransferWandViewMethod transfer,void *context) 01054 { 01055 Image 01056 *destination_image, 01057 *source_image; 01058 01059 MagickBooleanType 01060 status; 01061 01062 MagickOffsetType 01063 progress; 01064 01065 size_t 01066 height, 01067 width; 01068 01069 ssize_t 01070 y; 01071 01072 assert(source != (WandView *) NULL); 01073 assert(source->signature == WandSignature); 01074 if (transfer == (TransferWandViewMethod) NULL) 01075 return(MagickFalse); 01076 source_image=source->wand->images; 01077 destination_image=destination->wand->images; 01078 status=SetImageStorageClass(destination_image,DirectClass, 01079 destination->exception); 01080 if (status == MagickFalse) 01081 return(MagickFalse); 01082 status=MagickTrue; 01083 progress=0; 01084 height=source->extent.height-source->extent.y; 01085 width=source->extent.width-source->extent.x; 01086 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01087 #pragma omp parallel for schedule(static) shared(progress,status) \ 01088 dynamic_number_threads(source_image,width,height,1) 01089 #endif 01090 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 01091 { 01092 const int 01093 id = GetOpenMPThreadId(); 01094 01095 MagickBooleanType 01096 sync; 01097 01098 register const Quantum 01099 *restrict pixels; 01100 01101 register ssize_t 01102 x; 01103 01104 register Quantum 01105 *restrict destination_pixels; 01106 01107 if (status == MagickFalse) 01108 continue; 01109 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y, 01110 source->extent.width,1,source->exception); 01111 if (pixels == (const Quantum *) NULL) 01112 { 01113 status=MagickFalse; 01114 continue; 01115 } 01116 for (x=0; x < (ssize_t) source->extent.width; x++) 01117 { 01118 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]); 01119 pixels+=GetPixelChannels(source->image); 01120 } 01121 destination_pixels=GetCacheViewAuthenticPixels(destination->view, 01122 destination->extent.x,y,destination->extent.width,1, 01123 destination->exception); 01124 if (destination_pixels == (Quantum *) NULL) 01125 { 01126 status=MagickFalse; 01127 continue; 01128 } 01129 for (x=0; x < (ssize_t) destination->extent.width; x++) 01130 { 01131 PixelSetQuantumPixel(destination->image,destination_pixels, 01132 destination->pixel_wands[id][x]); 01133 destination_pixels+=GetPixelChannels(destination->image); 01134 } 01135 if (transfer(source,destination,y,id,context) == MagickFalse) 01136 status=MagickFalse; 01137 destination_pixels=GetCacheViewAuthenticPixels(destination->view, 01138 destination->extent.x,y,destination->extent.width,1, 01139 destination->exception); 01140 for (x=0; x < (ssize_t) destination->extent.width; x++) 01141 { 01142 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x], 01143 destination_pixels); 01144 destination_pixels+=GetPixelChannels(destination->image); 01145 } 01146 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception); 01147 if (sync == MagickFalse) 01148 status=MagickFalse; 01149 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 01150 { 01151 MagickBooleanType 01152 proceed; 01153 01154 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01155 #pragma omp critical (MagickWand_TransferWandViewIterator) 01156 #endif 01157 proceed=SetImageProgress(source_image,source->description,progress++, 01158 source->extent.height); 01159 if (proceed == MagickFalse) 01160 status=MagickFalse; 01161 } 01162 } 01163 return(status); 01164 } 01165 01166 /* 01167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01168 % % 01169 % % 01170 % % 01171 % U p d a t e W a n d V i e w I t e r a t o r % 01172 % % 01173 % % 01174 % % 01175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01176 % 01177 % UpdateWandViewIterator() iterates over the wand view in parallel and calls 01178 % your update method for each scanline of the view. The pixel extent is 01179 % confined to the image canvas-- that is no negative offsets or widths or 01180 % heights that exceed the image dimension are permitted. Updates to pixels 01181 % in your callback are automagically synced back to the image. 01182 % 01183 % The callback signature is: 01184 % 01185 % MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y, 01186 % const int thread_id,void *context) 01187 % 01188 % Use this pragma if the view is not single threaded: 01189 % 01190 % #pragma omp critical 01191 % 01192 % to define a section of code in your callback update method that must be 01193 % executed by a single thread at a time. 01194 % 01195 % The format of the UpdateWandViewIterator method is: 01196 % 01197 % MagickBooleanType UpdateWandViewIterator(WandView *source, 01198 % UpdateWandViewMethod update,void *context) 01199 % 01200 % A description of each parameter follows: 01201 % 01202 % o source: the source wand view. 01203 % 01204 % o update: the update callback method. 01205 % 01206 % o context: the user defined context. 01207 % 01208 */ 01209 WandExport MagickBooleanType UpdateWandViewIterator(WandView *source, 01210 UpdateWandViewMethod update,void *context) 01211 { 01212 Image 01213 *source_image; 01214 01215 MagickBooleanType 01216 status; 01217 01218 MagickOffsetType 01219 progress; 01220 01221 size_t 01222 height, 01223 width; 01224 01225 ssize_t 01226 y; 01227 01228 assert(source != (WandView *) NULL); 01229 assert(source->signature == WandSignature); 01230 if (update == (UpdateWandViewMethod) NULL) 01231 return(MagickFalse); 01232 source_image=source->wand->images; 01233 status=SetImageStorageClass(source_image,DirectClass,source->exception); 01234 if (status == MagickFalse) 01235 return(MagickFalse); 01236 status=MagickTrue; 01237 progress=0; 01238 height=source->extent.height-source->extent.y; 01239 width=source->extent.width-source->extent.x; 01240 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01241 #pragma omp parallel for schedule(static) shared(progress,status) \ 01242 dynamic_number_threads(source_image,width,height,1) 01243 #endif 01244 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 01245 { 01246 const int 01247 id = GetOpenMPThreadId(); 01248 01249 MagickBooleanType 01250 sync; 01251 01252 register ssize_t 01253 x; 01254 01255 register Quantum 01256 *restrict pixels; 01257 01258 if (status == MagickFalse) 01259 continue; 01260 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y, 01261 source->extent.width,1,source->exception); 01262 if (pixels == (Quantum *) NULL) 01263 { 01264 status=MagickFalse; 01265 continue; 01266 } 01267 for (x=0; x < (ssize_t) source->extent.width; x++) 01268 { 01269 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]); 01270 pixels+=GetPixelChannels(source->image); 01271 } 01272 if (update(source,y,id,context) == MagickFalse) 01273 status=MagickFalse; 01274 for (x=0; x < (ssize_t) source->extent.width; x++) 01275 { 01276 PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels); 01277 pixels+=GetPixelChannels(source->image); 01278 } 01279 sync=SyncCacheViewAuthenticPixels(source->view,source->exception); 01280 if (sync == MagickFalse) 01281 status=MagickFalse; 01282 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 01283 { 01284 MagickBooleanType 01285 proceed; 01286 01287 #if defined(MAGICKCORE_OPENMP_SUPPORT) 01288 #pragma omp critical (MagickWand_UpdateWandViewIterator) 01289 #endif 01290 proceed=SetImageProgress(source_image,source->description,progress++, 01291 source->extent.height); 01292 if (proceed == MagickFalse) 01293 status=MagickFalse; 01294 } 01295 } 01296 return(status); 01297 }