% Methods to Paint on an Image %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1998 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2014 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 %
Include declarations.
*/
#include "MagickCore/studio.h"
+#include "MagickCore/channel.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/colorspace-private.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/paint.h"
#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/resource_.h"
#include "MagickCore/statistic.h"
#include "MagickCore/string_.h"
#include "MagickCore/thread-private.h"
const ssize_t y_offset,const MagickBooleanType invert,
ExceptionInfo *exception)
{
-#define MaxStacksize (1UL << 15)
+#define MaxStacksize 131072UL
#define PushSegmentStack(up,left,right,delta) \
{ \
if (s >= (segment_stack+MaxStacksize)) \
skip,
status;
+ MemoryInfo
+ *segment_info;
+
PixelInfo
fill_color,
pixel;
return(MagickFalse);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
- if (image->matte == MagickFalse)
- (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
+ if (IsGrayColorspace(image->colorspace) != MagickFalse)
+ (void) SetImageColorspace(image,sRGBColorspace,exception);
+ if ((image->alpha_trait != BlendPixelTrait) &&
+ (draw_info->fill.alpha_trait == BlendPixelTrait))
+ (void) SetImageAlpha(image,OpaqueAlpha,exception);
/*
Set floodfill state.
*/
exception);
if (floodplane_image == (Image *) NULL)
return(MagickFalse);
+ floodplane_image->alpha_trait=UndefinedPixelTrait;
floodplane_image->colorspace=GRAYColorspace;
- (void) EvaluateImage(floodplane_image,SetEvaluateOperator,0.0,exception);
- segment_stack=(SegmentInfo *) AcquireQuantumMemory(MaxStacksize,
- sizeof(*segment_stack));
- if (segment_stack == (SegmentInfo *) NULL)
+ (void) QueryColorCompliance("#000",AllCompliance,
+ &floodplane_image->background_color,exception);
+ (void) SetImageBackgroundColor(floodplane_image,exception);
+ segment_info=AcquireVirtualMemory(MaxStacksize,sizeof(*segment_stack));
+ if (segment_info == (MemoryInfo *) NULL)
{
floodplane_image=DestroyImage(floodplane_image);
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
+ segment_stack=(SegmentInfo *) GetVirtualMemoryBlob(segment_info);
/*
Push initial segment on stack.
*/
PushSegmentStack(y,x,x,1);
PushSegmentStack(y+1,x,x,-1);
GetPixelInfo(image,&pixel);
- image_view=AcquireCacheView(image);
- floodplane_view=AcquireCacheView(floodplane_image);
+ image_view=AcquireVirtualCacheView(image,exception);
+ floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception);
while (s > segment_stack)
{
register const Quantum
}
floodplane_view=DestroyCacheView(floodplane_view);
image_view=DestroyCacheView(image_view);
- segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack);
+ segment_info=RelinquishVirtualMemory(segment_info);
floodplane_image=DestroyImage(floodplane_image);
return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
}
/*
Draw a gradient on the image.
*/
+ (void) SetImageColorspace(image,start_color->colorspace,exception);
status=DrawGradientImage(image,draw_info,exception);
draw_info=DestroyDrawInfo(draw_info);
- if ((start_color->alpha == OpaqueAlpha) && (stop_color->alpha == OpaqueAlpha))
- image->matte=MagickFalse;
- if ((IsPixelInfoGray(start_color) != MagickFalse) &&
- (IsPixelInfoGray(stop_color) != MagickFalse))
- image->type=GrayscaleType;
return(status);
}
\f
i;
assert(histogram != (size_t **) NULL);
- for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
+ for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
if (histogram[i] != (size_t *) NULL)
histogram[i]=(size_t *) RelinquishMagickMemory(histogram[i]);
histogram=(size_t **) RelinquishMagickMemory(histogram);
**histogram,
number_threads;
- number_threads=GetOpenMPMaximumThreads();
+ number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
histogram=(size_t **) AcquireQuantumMemory(number_threads,sizeof(*histogram));
if (histogram == (size_t **) NULL)
return((size_t **) NULL);
*paint_view;
Image
+ *linear_image,
*paint_image;
MagickBooleanType
width;
ssize_t
+ center,
y;
/*
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
width=GetOptimalKernelWidth2D(radius,sigma);
+ linear_image=CloneImage(image,0,0,MagickTrue,exception);
paint_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
- if (paint_image == (Image *) NULL)
- return((Image *) NULL);
+ if ((linear_image == (Image *) NULL) || (paint_image == (Image *) NULL))
+ {
+ if (linear_image != (Image *) NULL)
+ linear_image=DestroyImage(linear_image);
+ if (paint_image != (Image *) NULL)
+ linear_image=DestroyImage(paint_image);
+ return((Image *) NULL);
+ }
if (SetImageStorageClass(paint_image,DirectClass,exception) == MagickFalse)
{
+ linear_image=DestroyImage(linear_image);
paint_image=DestroyImage(paint_image);
return((Image *) NULL);
}
histograms=AcquireHistogramThreadSet(NumberPaintBins);
if (histograms == (size_t **) NULL)
{
+ linear_image=DestroyImage(linear_image);
paint_image=DestroyImage(paint_image);
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
}
*/
status=MagickTrue;
progress=0;
- image_view=AcquireCacheView(image);
- paint_view=AcquireCacheView(paint_image);
+ center=(ssize_t) GetPixelChannels(linear_image)*(linear_image->columns+width)*
+ (width/2L)+GetPixelChannels(linear_image)*(width/2L);
+ image_view=AcquireVirtualCacheView(linear_image,exception);
+ paint_view=AcquireAuthenticCacheView(paint_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ magick_threads(linear_image,paint_image,linear_image->rows,1)
#endif
- for (y=0; y < (ssize_t) image->rows; y++)
+ for (y=0; y < (ssize_t) linear_image->rows; y++)
{
register const Quantum
*restrict p;
if (status == MagickFalse)
continue;
p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
- (width/2L),image->columns+width,width,exception);
+ (width/2L),linear_image->columns+width,width,exception);
q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
exception);
if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
continue;
}
histogram=histograms[GetOpenMPThreadId()];
- for (x=0; x < (ssize_t) image->columns; x++)
+ for (x=0; x < (ssize_t) linear_image->columns; x++)
{
register ssize_t
i,
ssize_t
j,
k,
+ n,
v;
/*
Assign most frequent color.
*/
- i=0;
+ k=0;
j=0;
count=0;
- (void) ResetMagickMemory(histogram,0,NumberPaintBins*sizeof(*histogram));
+ (void) ResetMagickMemory(histogram,0,NumberPaintBins* sizeof(*histogram));
for (v=0; v < (ssize_t) width; v++)
{
for (u=0; u < (ssize_t) width; u++)
{
- k=(ssize_t) ScaleQuantumToChar(GetPixelIntensity(image,p+
- GetPixelChannels(image)*(u+i)));
- histogram[k]++;
- if (histogram[k] > count)
+ n=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(
+ linear_image,p+GetPixelChannels(linear_image)*(u+k))));
+ histogram[n]++;
+ if (histogram[n] > count)
{
- j=i+u;
- count=histogram[k];
+ j=k+u;
+ count=histogram[n];
}
}
- i+=(ssize_t) (image->columns+width);
+ k+=(ssize_t) (linear_image->columns+width);
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(linear_image); i++)
+ {
+ PixelChannel channel=GetPixelChannelChannel(linear_image,i);
+ PixelTrait traits=GetPixelChannelTraits(linear_image,channel);
+ PixelTrait paint_traits=GetPixelChannelTraits(paint_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (paint_traits == UndefinedPixelTrait))
+ continue;
+ if (((paint_traits & CopyPixelTrait) != 0) ||
+ (GetPixelReadMask(linear_image,p) == 0))
+ {
+ SetPixelChannel(paint_image,channel,p[center+i],q);
+ continue;
+ }
+ SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(linear_image)+
+ i],q);
}
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- SetPixelRed(paint_image,GetPixelRed(image,p+j*
- GetPixelChannels(image)),q);
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- SetPixelGreen(paint_image,GetPixelGreen(image,p+j*
- GetPixelChannels(image)),q);
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- SetPixelBlue(paint_image,GetPixelBlue(image,p+j*
- GetPixelChannels(image)),q);
- if ((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0)
- SetPixelBlack(paint_image,GetPixelBlack(image,p+j*
- GetPixelChannels(image)),q);
- if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
- SetPixelAlpha(paint_image,GetPixelAlpha(image,p+j*
- GetPixelChannels(image)),q);
- p+=GetPixelChannels(image);
+ p+=GetPixelChannels(linear_image);
q+=GetPixelChannels(paint_image);
}
if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse)
status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ if (linear_image->progress_monitor != (MagickProgressMonitor) NULL)
{
MagickBooleanType
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_OilPaintImage)
+ #pragma omp critical (MagickCore_OilPaintImage)
#endif
- proceed=SetImageProgress(image,OilPaintImageTag,progress++,image->rows);
+ proceed=SetImageProgress(linear_image,OilPaintImageTag,progress++,
+ linear_image->rows);
if (proceed == MagickFalse)
status=MagickFalse;
}
paint_view=DestroyCacheView(paint_view);
image_view=DestroyCacheView(image_view);
histograms=DestroyHistogramThreadSet(histograms);
+ linear_image=DestroyImage(linear_image);
if (status == MagickFalse)
paint_image=DestroyImage(paint_image);
return(paint_image);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
+ if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
+ (IsPixelInfoGray(fill) == MagickFalse))
+ (void) SetImageColorspace(image,sRGBColorspace,exception);
+ if ((fill->alpha_trait == BlendPixelTrait) &&
+ (image->alpha_trait != BlendPixelTrait))
+ (void) SetImageAlpha(image,OpaqueAlpha,exception);
/*
Make image color opaque.
*/
status=MagickTrue;
progress=0;
GetPixelInfo(image,&zero);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ magick_threads(image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_OpaquePaintImage)
+ #pragma omp critical (MagickCore_OpaquePaintImage)
#endif
proceed=SetImageProgress(image,OpaquePaintImageTag,progress++,
image->rows);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
- if (image->matte == MagickFalse)
+ if (image->alpha_trait != BlendPixelTrait)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
/*
Make image color transparent.
status=MagickTrue;
progress=0;
GetPixelInfo(image,&zero);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ magick_threads(image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_TransparentPaintImage)
+ #pragma omp critical (MagickCore_TransparentPaintImage)
#endif
proceed=SetImageProgress(image,TransparentPaintImageTag,progress++,
image->rows);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
- if (image->matte == MagickFalse)
+ if (image->alpha_trait != BlendPixelTrait)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
/*
Make image color transparent.
*/
status=MagickTrue;
progress=0;
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ magick_threads(image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_TransparentPaintImageChroma)
+ #pragma omp critical (MagickCore_TransparentPaintImageChroma)
#endif
proceed=SetImageProgress(image,TransparentPaintImageTag,progress++,
image->rows);