forked from openkylin/imagemagick
1271 lines
45 KiB
C
1271 lines
45 KiB
C
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% IIIII M M AAA GGGG EEEEE %
|
||
% I MM MM A A G E %
|
||
% I M M M AAAAA G GG EEE %
|
||
% I M M A A G G E %
|
||
% IIIII M M A A GGGG EEEEE %
|
||
% %
|
||
% V V IIIII EEEEE W W %
|
||
% V V I E W W %
|
||
% V V I EEE W W W %
|
||
% V V I E WW WW %
|
||
% V IIIII EEEEE W W %
|
||
% %
|
||
% %
|
||
% MagickCore Image View Methods %
|
||
% %
|
||
% Software Design %
|
||
% Cristy %
|
||
% March 2003 %
|
||
% %
|
||
% %
|
||
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
|
||
% dedicated to making software imaging solutions freely available. %
|
||
% %
|
||
% You may not use this file except in compliance with the License. You may %
|
||
% obtain a copy of the License at %
|
||
% %
|
||
% https://imagemagick.org/script/license.php %
|
||
% %
|
||
% Unless required by applicable law or agreed to in writing, software %
|
||
% distributed under the License is distributed on an "AS IS" BASIS, %
|
||
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
|
||
% See the License for the specific language governing permissions and %
|
||
% limitations under the License. %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
%
|
||
%
|
||
*/
|
||
|
||
/*
|
||
Include declarations.
|
||
*/
|
||
#include "magick/studio.h"
|
||
#include "magick/MagickCore.h"
|
||
#include "magick/exception-private.h"
|
||
#include "magick/monitor-private.h"
|
||
#include "magick/thread-private.h"
|
||
|
||
/*
|
||
Typedef declarations.
|
||
*/
|
||
struct _ImageView
|
||
{
|
||
char
|
||
*description;
|
||
|
||
RectangleInfo
|
||
extent;
|
||
|
||
Image
|
||
*image;
|
||
|
||
CacheView
|
||
*view;
|
||
|
||
size_t
|
||
number_threads;
|
||
|
||
ExceptionInfo
|
||
*exception;
|
||
|
||
MagickBooleanType
|
||
debug;
|
||
|
||
size_t
|
||
signature;
|
||
};
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% C l o n e I m a g e V i e w %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% CloneImageView() makes a copy of the specified image view.
|
||
%
|
||
% The format of the CloneImageView method is:
|
||
%
|
||
% ImageView *CloneImageView(const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport ImageView *CloneImageView(const ImageView *image_view)
|
||
{
|
||
ImageView
|
||
*clone_view;
|
||
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
clone_view=(ImageView *) AcquireMagickMemory(sizeof(*clone_view));
|
||
if (clone_view == (ImageView *) NULL)
|
||
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
|
||
(void) memset(clone_view,0,sizeof(*clone_view));
|
||
clone_view->description=ConstantString(image_view->description);
|
||
clone_view->extent=image_view->extent;
|
||
clone_view->view=CloneCacheView(image_view->view);
|
||
clone_view->number_threads=image_view->number_threads;
|
||
clone_view->exception=AcquireExceptionInfo();
|
||
InheritException(clone_view->exception,image_view->exception);
|
||
clone_view->debug=image_view->debug;
|
||
clone_view->signature=MagickCoreSignature;
|
||
return(clone_view);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% D e s t r o y I m a g e V i e w %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% DestroyImageView() deallocates memory associated with a image view.
|
||
%
|
||
% The format of the DestroyImageView method is:
|
||
%
|
||
% ImageView *DestroyImageView(ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport ImageView *DestroyImageView(ImageView *image_view)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
if (image_view->description != (char *) NULL)
|
||
image_view->description=DestroyString(image_view->description);
|
||
image_view->view=DestroyCacheView(image_view->view);
|
||
image_view->exception=DestroyExceptionInfo(image_view->exception);
|
||
image_view->signature=(~MagickCoreSignature);
|
||
image_view=(ImageView *) RelinquishMagickMemory(image_view);
|
||
return(image_view);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% D u p l e x T r a n s f e r I m a g e V i e w I t e r a t o r %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% DuplexTransferImageViewIterator() iterates over three image views in
|
||
% parallel and calls your transfer method for each scanline of the view. The
|
||
% source and duplex pixel extent is not confined to the image canvas-- that is
|
||
% you can include negative offsets or widths or heights that exceed the image
|
||
% dimension. However, the destination image view is confined to the image
|
||
% canvas-- that is no negative offsets or widths or heights that exceed the
|
||
% image dimension are permitted.
|
||
%
|
||
% The callback signature is:
|
||
%
|
||
% MagickBooleanType DuplexTransferImageViewMethod(const ImageView *source,
|
||
% const ImageView *duplex,ImageView *destination,const ssize_t y,
|
||
% const int thread_id,void *context)
|
||
%
|
||
% Use this pragma if the view is not single threaded:
|
||
%
|
||
% #pragma omp critical
|
||
%
|
||
% to define a section of code in your callback transfer method that must be
|
||
% executed by a single thread at a time.
|
||
%
|
||
% The format of the DuplexTransferImageViewIterator method is:
|
||
%
|
||
% MagickBooleanType DuplexTransferImageViewIterator(ImageView *source,
|
||
% ImageView *duplex,ImageView *destination,
|
||
% DuplexTransferImageViewMethod transfer,void *context)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o source: the source image view.
|
||
%
|
||
% o duplex: the duplex image view.
|
||
%
|
||
% o destination: the destination image view.
|
||
%
|
||
% o transfer: the transfer callback method.
|
||
%
|
||
% o context: the user defined context.
|
||
%
|
||
*/
|
||
MagickExport MagickBooleanType DuplexTransferImageViewIterator(
|
||
ImageView *source,ImageView *duplex,ImageView *destination,
|
||
DuplexTransferImageViewMethod transfer,void *context)
|
||
{
|
||
ExceptionInfo
|
||
*exception;
|
||
|
||
Image
|
||
*destination_image,
|
||
*source_image;
|
||
|
||
MagickBooleanType
|
||
status;
|
||
|
||
MagickOffsetType
|
||
progress;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
size_t
|
||
height;
|
||
#endif
|
||
|
||
ssize_t
|
||
y;
|
||
|
||
assert(source != (ImageView *) NULL);
|
||
assert(source->signature == MagickCoreSignature);
|
||
if (transfer == (DuplexTransferImageViewMethod) NULL)
|
||
return(MagickFalse);
|
||
source_image=source->image;
|
||
destination_image=destination->image;
|
||
if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
|
||
return(MagickFalse);
|
||
status=MagickTrue;
|
||
progress=0;
|
||
exception=destination->exception;
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
height=(size_t) (source->extent.height-source->extent.y);
|
||
#pragma omp parallel for schedule(static) shared(progress,status) \
|
||
magick_number_threads(source_image,destination_image,height,1)
|
||
#endif
|
||
for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
|
||
{
|
||
const int
|
||
id = GetOpenMPThreadId();
|
||
|
||
MagickBooleanType
|
||
sync;
|
||
|
||
const PixelPacket
|
||
*magick_restrict duplex_pixels,
|
||
*magick_restrict pixels;
|
||
|
||
PixelPacket
|
||
*magick_restrict destination_pixels;
|
||
|
||
if (status == MagickFalse)
|
||
continue;
|
||
pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
|
||
source->extent.width,1,source->exception);
|
||
if (pixels == (const PixelPacket *) NULL)
|
||
{
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
|
||
duplex->extent.width,1,duplex->exception);
|
||
if (duplex_pixels == (const PixelPacket *) NULL)
|
||
{
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
destination_pixels=GetCacheViewAuthenticPixels(destination->view,
|
||
destination->extent.x,y,destination->extent.width,1,exception);
|
||
if (destination_pixels == (PixelPacket *) NULL)
|
||
{
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
|
||
status=MagickFalse;
|
||
sync=SyncCacheViewAuthenticPixels(destination->view,exception);
|
||
if (sync == MagickFalse)
|
||
{
|
||
InheritException(destination->exception,GetCacheViewException(
|
||
source->view));
|
||
status=MagickFalse;
|
||
}
|
||
if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
|
||
{
|
||
MagickBooleanType
|
||
proceed;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
#pragma omp atomic
|
||
#endif
|
||
progress++;
|
||
proceed=SetImageProgress(source_image,source->description,progress,
|
||
source->extent.height);
|
||
if (proceed == MagickFalse)
|
||
status=MagickFalse;
|
||
}
|
||
}
|
||
return(status);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w A u t h e n t i c I n d e x e s %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewAuthenticIndexes() returns the image view authentic indexes.
|
||
%
|
||
% The format of the GetImageViewAuthenticPixels method is:
|
||
%
|
||
% IndexPacket *GetImageViewAuthenticIndexes(const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport IndexPacket *GetImageViewAuthenticIndexes(
|
||
const ImageView *image_view)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
return(GetCacheViewAuthenticIndexQueue(image_view->view));
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w A u t h e n t i c P i x e l s %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewAuthenticPixels() returns the image view authentic pixels.
|
||
%
|
||
% The format of the GetImageViewAuthenticPixels method is:
|
||
%
|
||
% PixelPacket *GetImageViewAuthenticPixels(const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport PixelPacket *GetImageViewAuthenticPixels(
|
||
const ImageView *image_view)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
return(GetCacheViewAuthenticPixelQueue(image_view->view));
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w E x c e p t i o n %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewException() returns the severity, reason, and description of any
|
||
% error that occurs when utilizing a image view.
|
||
%
|
||
% The format of the GetImageViewException method is:
|
||
%
|
||
% char *GetImageViewException(const PixelImage *image_view,
|
||
% ExceptionType *severity)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the pixel image_view.
|
||
%
|
||
% o severity: the severity of the error is returned here.
|
||
%
|
||
*/
|
||
MagickExport char *GetImageViewException(const ImageView *image_view,
|
||
ExceptionType *severity)
|
||
{
|
||
char
|
||
*description;
|
||
|
||
assert(image_view != (const ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
assert(severity != (ExceptionType *) NULL);
|
||
*severity=image_view->exception->severity;
|
||
description=(char *) AcquireQuantumMemory(MaxTextExtent,
|
||
2*sizeof(*description));
|
||
if (description == (char *) NULL)
|
||
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
|
||
*description='\0';
|
||
if (image_view->exception->reason != (char *) NULL)
|
||
(void) CopyMagickString(description,GetLocaleExceptionMessage(
|
||
image_view->exception->severity,image_view->exception->reason),
|
||
MaxTextExtent);
|
||
if (image_view->exception->description != (char *) NULL)
|
||
{
|
||
(void) ConcatenateMagickString(description," (",MaxTextExtent);
|
||
(void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
|
||
image_view->exception->severity,image_view->exception->description),
|
||
MaxTextExtent);
|
||
(void) ConcatenateMagickString(description,")",MaxTextExtent);
|
||
}
|
||
return(description);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w E x t e n t %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewExtent() returns the image view extent.
|
||
%
|
||
% The format of the GetImageViewExtent method is:
|
||
%
|
||
% RectangleInfo GetImageViewExtent(const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
return(image_view->extent);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w I m a g e %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewImage() returns the image associated with the image view.
|
||
%
|
||
% The format of the GetImageViewImage method is:
|
||
%
|
||
% MagickCore *GetImageViewImage(const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport Image *GetImageViewImage(const ImageView *image_view)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
return(image_view->image);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w I t e r a t o r %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewIterator() iterates over the image view in parallel and calls
|
||
% your get method for each scanline of the view. The pixel extent is
|
||
% not confined to the image canvas-- that is you can include negative offsets
|
||
% or widths or heights that exceed the image dimension. Any updates to
|
||
% the pixels in your callback are ignored.
|
||
%
|
||
% The callback signature is:
|
||
%
|
||
% MagickBooleanType GetImageViewMethod(const ImageView *source,
|
||
% const ssize_t y,const int thread_id,void *context)
|
||
%
|
||
% Use this pragma if the view is not single threaded:
|
||
%
|
||
% #pragma omp critical
|
||
%
|
||
% to define a section of code in your callback get method that must be
|
||
% executed by a single thread at a time.
|
||
%
|
||
% The format of the GetImageViewIterator method is:
|
||
%
|
||
% MagickBooleanType GetImageViewIterator(ImageView *source,
|
||
% GetImageViewMethod get,void *context)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o source: the source image view.
|
||
%
|
||
% o get: the get callback method.
|
||
%
|
||
% o context: the user defined context.
|
||
%
|
||
*/
|
||
MagickExport MagickBooleanType GetImageViewIterator(ImageView *source,
|
||
GetImageViewMethod get,void *context)
|
||
{
|
||
Image
|
||
*source_image;
|
||
|
||
MagickBooleanType
|
||
status;
|
||
|
||
MagickOffsetType
|
||
progress;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
size_t
|
||
height;
|
||
#endif
|
||
|
||
ssize_t
|
||
y;
|
||
|
||
assert(source != (ImageView *) NULL);
|
||
assert(source->signature == MagickCoreSignature);
|
||
if (get == (GetImageViewMethod) NULL)
|
||
return(MagickFalse);
|
||
source_image=source->image;
|
||
status=MagickTrue;
|
||
progress=0;
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
height=(size_t) (source->extent.height-source->extent.y);
|
||
#pragma omp parallel for schedule(static) shared(progress,status) \
|
||
magick_number_threads(source_image,source_image,height,1)
|
||
#endif
|
||
for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
|
||
{
|
||
const int
|
||
id = GetOpenMPThreadId();
|
||
|
||
const PixelPacket
|
||
*pixels;
|
||
|
||
if (status == MagickFalse)
|
||
continue;
|
||
pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
|
||
source->extent.width,1,source->exception);
|
||
if (pixels == (const PixelPacket *) NULL)
|
||
{
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
if (get(source,y,id,context) == MagickFalse)
|
||
status=MagickFalse;
|
||
if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
|
||
{
|
||
MagickBooleanType
|
||
proceed;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
#pragma omp atomic
|
||
#endif
|
||
progress++;
|
||
proceed=SetImageProgress(source_image,source->description,progress,
|
||
source->extent.height);
|
||
if (proceed == MagickFalse)
|
||
status=MagickFalse;
|
||
}
|
||
}
|
||
return(status);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w V i r t u a l I n d e x e s %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewVirtualIndexes() returns the image view virtual indexes.
|
||
%
|
||
% The format of the GetImageViewVirtualIndexes method is:
|
||
%
|
||
% const IndexPacket *GetImageViewVirtualIndexes(
|
||
% const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport const IndexPacket *GetImageViewVirtualIndexes(
|
||
const ImageView *image_view)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
return(GetCacheViewVirtualIndexQueue(image_view->view));
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% G e t I m a g e V i e w V i r t u a l P i x e l s %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% GetImageViewVirtualPixels() returns the image view virtual pixels.
|
||
%
|
||
% The format of the GetImageViewVirtualPixels method is:
|
||
%
|
||
% const PixelPacket *GetImageViewVirtualPixels(const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport const PixelPacket *GetImageViewVirtualPixels(
|
||
const ImageView *image_view)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
return(GetCacheViewVirtualPixelQueue(image_view->view));
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% I s I m a g e V i e w %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% IsImageView() returns MagickTrue if the parameter is verified as a image
|
||
% view object.
|
||
%
|
||
% The format of the IsImageView method is:
|
||
%
|
||
% MagickBooleanType IsImageView(const ImageView *image_view)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
*/
|
||
MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
|
||
{
|
||
if (image_view == (const ImageView *) NULL)
|
||
return(MagickFalse);
|
||
if (image_view->signature != MagickCoreSignature)
|
||
return(MagickFalse);
|
||
return(MagickTrue);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% N e w I m a g e V i e w %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% NewImageView() returns a image view required for all other methods in the
|
||
% Image View API.
|
||
%
|
||
% The format of the NewImageView method is:
|
||
%
|
||
% ImageView *NewImageView(MagickCore *wand)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o wand: the wand.
|
||
%
|
||
*/
|
||
MagickExport ImageView *NewImageView(Image *image)
|
||
{
|
||
ImageView
|
||
*image_view;
|
||
|
||
assert(image != (Image *) NULL);
|
||
assert(image->signature == MagickCoreSignature);
|
||
image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
|
||
if (image_view == (ImageView *) NULL)
|
||
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
|
||
(void) memset(image_view,0,sizeof(*image_view));
|
||
image_view->description=ConstantString("ImageView");
|
||
image_view->image=image;
|
||
image_view->exception=AcquireExceptionInfo();
|
||
image_view->view=AcquireVirtualCacheView(image_view->image,
|
||
image_view->exception);
|
||
image_view->extent.width=image->columns;
|
||
image_view->extent.height=image->rows;
|
||
image_view->extent.x=0;
|
||
image_view->extent.y=0;
|
||
image_view->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
|
||
image_view->debug=IsEventLogging();
|
||
image_view->signature=MagickCoreSignature;
|
||
return(image_view);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% N e w I m a g e V i e w R e g i o n %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% NewImageViewRegion() returns a image view required for all other methods
|
||
% in the Image View API.
|
||
%
|
||
% The format of the NewImageViewRegion method is:
|
||
%
|
||
% ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
|
||
% const ssize_t y,const size_t width,const size_t height)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o wand: the magick wand.
|
||
%
|
||
% o x,y,columns,rows: These values define the perimeter of a extent of
|
||
% pixel_wands view.
|
||
%
|
||
*/
|
||
MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
|
||
const ssize_t y,const size_t width,const size_t height)
|
||
{
|
||
ImageView
|
||
*image_view;
|
||
|
||
assert(image != (Image *) NULL);
|
||
assert(image->signature == MagickCoreSignature);
|
||
image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
|
||
if (image_view == (ImageView *) NULL)
|
||
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
|
||
(void) memset(image_view,0,sizeof(*image_view));
|
||
image_view->description=ConstantString("ImageView");
|
||
image_view->exception=AcquireExceptionInfo();
|
||
image_view->view=AcquireVirtualCacheView(image_view->image,
|
||
image_view->exception);
|
||
image_view->image=image;
|
||
image_view->extent.width=width;
|
||
image_view->extent.height=height;
|
||
image_view->extent.x=x;
|
||
image_view->extent.y=y;
|
||
image_view->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
|
||
image_view->debug=IsEventLogging();
|
||
image_view->signature=MagickCoreSignature;
|
||
return(image_view);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% S e t I m a g e V i e w D e s c r i p t i o n %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% SetImageViewDescription() associates a description with an image view.
|
||
%
|
||
% The format of the SetImageViewDescription method is:
|
||
%
|
||
% void SetImageViewDescription(ImageView *image_view,
|
||
% const char *description)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
% o description: the image view description.
|
||
%
|
||
*/
|
||
MagickExport void SetImageViewDescription(ImageView *image_view,
|
||
const char *description)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
image_view->description=ConstantString(description);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% S e t I m a g e V i e w I t e r a t o r %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% SetImageViewIterator() iterates over the image view in parallel and calls
|
||
% your set method for each scanline of the view. The pixel extent is
|
||
% confined to the image canvas-- that is no negative offsets or widths or
|
||
% heights that exceed the image dimension. The pixels are initiallly
|
||
% undefined and any settings you make in the callback method are automagically
|
||
% synced back to your image.
|
||
%
|
||
% The callback signature is:
|
||
%
|
||
% MagickBooleanType SetImageViewMethod(ImageView *destination,
|
||
% const ssize_t y,const int thread_id,void *context)
|
||
%
|
||
% Use this pragma if the view is not single threaded:
|
||
%
|
||
% #pragma omp critical
|
||
%
|
||
% to define a section of code in your callback set method that must be
|
||
% executed by a single thread at a time.
|
||
%
|
||
% The format of the SetImageViewIterator method is:
|
||
%
|
||
% MagickBooleanType SetImageViewIterator(ImageView *destination,
|
||
% SetImageViewMethod set,void *context)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o destination: the image view.
|
||
%
|
||
% o set: the set callback method.
|
||
%
|
||
% o context: the user defined context.
|
||
%
|
||
*/
|
||
MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
|
||
SetImageViewMethod set,void *context)
|
||
{
|
||
ExceptionInfo
|
||
*exception;
|
||
|
||
Image
|
||
*destination_image;
|
||
|
||
MagickBooleanType
|
||
status;
|
||
|
||
MagickOffsetType
|
||
progress;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
size_t
|
||
height;
|
||
#endif
|
||
|
||
ssize_t
|
||
y;
|
||
|
||
assert(destination != (ImageView *) NULL);
|
||
assert(destination->signature == MagickCoreSignature);
|
||
if (set == (SetImageViewMethod) NULL)
|
||
return(MagickFalse);
|
||
destination_image=destination->image;
|
||
if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
|
||
return(MagickFalse);
|
||
status=MagickTrue;
|
||
progress=0;
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
height=(size_t) (destination->extent.height-destination->extent.y);
|
||
#endif
|
||
exception=destination->exception;
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
#pragma omp parallel for schedule(static) shared(progress,status) \
|
||
magick_number_threads(destination_image,destination_image,height,1)
|
||
#endif
|
||
for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
|
||
{
|
||
const int
|
||
id = GetOpenMPThreadId();
|
||
|
||
MagickBooleanType
|
||
sync;
|
||
|
||
PixelPacket
|
||
*magick_restrict pixels;
|
||
|
||
if (status == MagickFalse)
|
||
continue;
|
||
pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
|
||
y,destination->extent.width,1,exception);
|
||
if (pixels == (PixelPacket *) NULL)
|
||
{
|
||
InheritException(destination->exception,GetCacheViewException(
|
||
destination->view));
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
if (set(destination,y,id,context) == MagickFalse)
|
||
status=MagickFalse;
|
||
sync=SyncCacheViewAuthenticPixels(destination->view,exception);
|
||
if (sync == MagickFalse)
|
||
{
|
||
InheritException(destination->exception,GetCacheViewException(
|
||
destination->view));
|
||
status=MagickFalse;
|
||
}
|
||
if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
|
||
{
|
||
MagickBooleanType
|
||
proceed;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
#pragma omp atomic
|
||
#endif
|
||
progress++;
|
||
proceed=SetImageProgress(destination_image,destination->description,
|
||
progress,destination->extent.height);
|
||
if (proceed == MagickFalse)
|
||
status=MagickFalse;
|
||
}
|
||
}
|
||
return(status);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% S e t I m a g e V i e w T h r e a d s %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% SetImageViewThreads() sets the number of threads in a thread team.
|
||
%
|
||
% The format of the SetImageViewDescription method is:
|
||
%
|
||
% void SetImageViewThreads(ImageView *image_view,
|
||
% const size_t number_threads)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o image_view: the image view.
|
||
%
|
||
% o number_threads: the number of threads in a thread team.
|
||
%
|
||
*/
|
||
MagickExport void SetImageViewThreads(ImageView *image_view,
|
||
const size_t number_threads)
|
||
{
|
||
assert(image_view != (ImageView *) NULL);
|
||
assert(image_view->signature == MagickCoreSignature);
|
||
image_view->number_threads=number_threads;
|
||
if (number_threads > (size_t) GetMagickResourceLimit(ThreadResource))
|
||
image_view->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% T r a n s f e r I m a g e V i e w I t e r a t o r %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% TransferImageViewIterator() iterates over two image views in parallel and
|
||
% calls your transfer method for each scanline of the view. The source pixel
|
||
% extent is not confined to the image canvas-- that is you can include
|
||
% negative offsets or widths or heights that exceed the image dimension.
|
||
% However, the destination image view is confined to the image canvas-- that
|
||
% is no negative offsets or widths or heights that exceed the image dimension
|
||
% are permitted.
|
||
%
|
||
% The callback signature is:
|
||
%
|
||
% MagickBooleanType TransferImageViewMethod(const ImageView *source,
|
||
% ImageView *destination,const ssize_t y,const int thread_id,
|
||
% void *context)
|
||
%
|
||
% Use this pragma if the view is not single threaded:
|
||
%
|
||
% #pragma omp critical
|
||
%
|
||
% to define a section of code in your callback transfer method that must be
|
||
% executed by a single thread at a time.
|
||
%
|
||
% The format of the TransferImageViewIterator method is:
|
||
%
|
||
% MagickBooleanType TransferImageViewIterator(ImageView *source,
|
||
% ImageView *destination,TransferImageViewMethod transfer,void *context)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o source: the source image view.
|
||
%
|
||
% o destination: the destination image view.
|
||
%
|
||
% o transfer: the transfer callback method.
|
||
%
|
||
% o context: the user defined context.
|
||
%
|
||
*/
|
||
MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
|
||
ImageView *destination,TransferImageViewMethod transfer,void *context)
|
||
{
|
||
ExceptionInfo
|
||
*exception;
|
||
|
||
Image
|
||
*destination_image,
|
||
*source_image;
|
||
|
||
MagickBooleanType
|
||
status;
|
||
|
||
MagickOffsetType
|
||
progress;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
size_t
|
||
height;
|
||
#endif
|
||
|
||
ssize_t
|
||
y;
|
||
|
||
assert(source != (ImageView *) NULL);
|
||
assert(source->signature == MagickCoreSignature);
|
||
if (transfer == (TransferImageViewMethod) NULL)
|
||
return(MagickFalse);
|
||
source_image=source->image;
|
||
destination_image=destination->image;
|
||
if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
|
||
return(MagickFalse);
|
||
status=MagickTrue;
|
||
progress=0;
|
||
exception=destination->exception;
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
height=(size_t) (source->extent.height-source->extent.y);
|
||
#pragma omp parallel for schedule(static) shared(progress,status) \
|
||
magick_number_threads(source_image,destination_image,height,1)
|
||
#endif
|
||
for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
|
||
{
|
||
const int
|
||
id = GetOpenMPThreadId();
|
||
|
||
MagickBooleanType
|
||
sync;
|
||
|
||
const PixelPacket
|
||
*magick_restrict pixels;
|
||
|
||
PixelPacket
|
||
*magick_restrict destination_pixels;
|
||
|
||
if (status == MagickFalse)
|
||
continue;
|
||
pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
|
||
source->extent.width,1,source->exception);
|
||
if (pixels == (const PixelPacket *) NULL)
|
||
{
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
destination_pixels=GetCacheViewAuthenticPixels(destination->view,
|
||
destination->extent.x,y,destination->extent.width,1,exception);
|
||
if (destination_pixels == (PixelPacket *) NULL)
|
||
{
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
if (transfer(source,destination,y,id,context) == MagickFalse)
|
||
status=MagickFalse;
|
||
sync=SyncCacheViewAuthenticPixels(destination->view,exception);
|
||
if (sync == MagickFalse)
|
||
{
|
||
InheritException(destination->exception,GetCacheViewException(
|
||
source->view));
|
||
status=MagickFalse;
|
||
}
|
||
if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
|
||
{
|
||
MagickBooleanType
|
||
proceed;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
#pragma omp atomic
|
||
#endif
|
||
progress++;
|
||
proceed=SetImageProgress(source_image,source->description,progress,
|
||
source->extent.height);
|
||
if (proceed == MagickFalse)
|
||
status=MagickFalse;
|
||
}
|
||
}
|
||
return(status);
|
||
}
|
||
|
||
/*
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
% %
|
||
% %
|
||
% %
|
||
% U p d a t e I m a g e V i e w I t e r a t o r %
|
||
% %
|
||
% %
|
||
% %
|
||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||
%
|
||
% UpdateImageViewIterator() iterates over the image view in parallel and calls
|
||
% your update method for each scanline of the view. The pixel extent is
|
||
% confined to the image canvas-- that is no negative offsets or widths or
|
||
% heights that exceed the image dimension are permitted. Updates to pixels
|
||
% in your callback are automagically synced back to the image.
|
||
%
|
||
% The callback signature is:
|
||
%
|
||
% MagickBooleanType UpdateImageViewMethod(ImageView *source,
|
||
% const ssize_t y,const int thread_id,void *context)
|
||
%
|
||
% Use this pragma if the view is not single threaded:
|
||
%
|
||
% #pragma omp critical
|
||
%
|
||
% to define a section of code in your callback update method that must be
|
||
% executed by a single thread at a time.
|
||
%
|
||
% The format of the UpdateImageViewIterator method is:
|
||
%
|
||
% MagickBooleanType UpdateImageViewIterator(ImageView *source,
|
||
% UpdateImageViewMethod update,void *context)
|
||
%
|
||
% A description of each parameter follows:
|
||
%
|
||
% o source: the source image view.
|
||
%
|
||
% o update: the update callback method.
|
||
%
|
||
% o context: the user defined context.
|
||
%
|
||
*/
|
||
MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
|
||
UpdateImageViewMethod update,void *context)
|
||
{
|
||
ExceptionInfo
|
||
*exception;
|
||
|
||
Image
|
||
*source_image;
|
||
|
||
MagickBooleanType
|
||
status;
|
||
|
||
MagickOffsetType
|
||
progress;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
size_t
|
||
height;
|
||
#endif
|
||
|
||
ssize_t
|
||
y;
|
||
|
||
assert(source != (ImageView *) NULL);
|
||
assert(source->signature == MagickCoreSignature);
|
||
if (update == (UpdateImageViewMethod) NULL)
|
||
return(MagickFalse);
|
||
source_image=source->image;
|
||
if (SetImageStorageClass(source_image,DirectClass) == MagickFalse)
|
||
return(MagickFalse);
|
||
status=MagickTrue;
|
||
progress=0;
|
||
exception=source->exception;
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
height=(size_t) (source->extent.height-source->extent.y);
|
||
#pragma omp parallel for schedule(static) shared(progress,status) \
|
||
magick_number_threads(source_image,source_image,height,1)
|
||
#endif
|
||
for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
|
||
{
|
||
const int
|
||
id = GetOpenMPThreadId();
|
||
|
||
PixelPacket
|
||
*magick_restrict pixels;
|
||
|
||
if (status == MagickFalse)
|
||
continue;
|
||
pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
|
||
source->extent.width,1,exception);
|
||
if (pixels == (PixelPacket *) NULL)
|
||
{
|
||
InheritException(source->exception,GetCacheViewException(source->view));
|
||
status=MagickFalse;
|
||
continue;
|
||
}
|
||
if (update(source,y,id,context) == MagickFalse)
|
||
status=MagickFalse;
|
||
if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
|
||
{
|
||
InheritException(source->exception,GetCacheViewException(source->view));
|
||
status=MagickFalse;
|
||
}
|
||
if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
|
||
{
|
||
MagickBooleanType
|
||
proceed;
|
||
|
||
#if defined(MAGICKCORE_OPENMP_SUPPORT)
|
||
#pragma omp atomic
|
||
#endif
|
||
progress++;
|
||
proceed=SetImageProgress(source_image,source->description,progress,
|
||
source->extent.height);
|
||
if (proceed == MagickFalse)
|
||
status=MagickFalse;
|
||
}
|
||
}
|
||
return(status);
|
||
}
|