I saw some C functions take a void*
pointer as an argument, then in the body of the function, the only usage of the pointer is done after casting it to the same type each time it is used (unsigned char*
in my case).
I know this is a legal operation, my question is why not just accept a pointer to unsigned char
instead of accepting a void*
and casting it each time? Is there some performance improvement or some limitation on doing this?
If you want a code example, have a look at profileImage method (line 933) at the parameter datum
(and the cast is at line 989):
MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
const void *datum,const size_t length,ExceptionInfo *exception)
{
#define ProfileImageTag "Profile/Image"
#ifndef TYPE_XYZ_8
#define TYPE_XYZ_8 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(1))
#endif
#define ThrowProfileException(severity,tag,context) \
{ \
if (profile != (StringInfo *) NULL) \
profile=DestroyStringInfo(profile); \
if (cms_context != (cmsContext) NULL) \
cmsDeleteContext(cms_context); \
if (source_info.profile != (cmsHPROFILE) NULL) \
(void) cmsCloseProfile(source_info.profile); \
if (target_info.profile != (cmsHPROFILE) NULL) \
(void) cmsCloseProfile(target_info.profile); \
ThrowBinaryException(severity,tag,context); \
}
MagickBooleanType
status;
StringInfo
*profile;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(name != (const char *) NULL);
if (IsEventLogging() != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if ((datum == (const void *) NULL) || (length == 0))
{
char
*next;
/*
Delete image profile(s).
*/
ResetImageProfileIterator(image);
for (next=GetNextImageProfile(image); next != (const char *) NULL; )
{
if (IsOptionMember(next,name) != MagickFalse)
{
(void) DeleteImageProfile(image,next);
ResetImageProfileIterator(image);
}
next=GetNextImageProfile(image);
}
return(MagickTrue);
}
/*
Add a ICC, IPTC, or generic profile to the image.
*/
status=MagickTrue;
profile=AcquireStringInfo((size_t) length);
SetStringInfoDatum(profile,(unsigned char *) datum);
if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
status=SetImageProfile(image,name,profile,exception);
else
{
const StringInfo
*icc_profile;
icc_profile=GetImageProfile(image,"icc");
if ((icc_profile != (const StringInfo *) NULL) &&
(CompareStringInfo(icc_profile,profile) == 0))
{
const char
*value;
value=GetImageProperty(image,"exif:ColorSpace",exception);
(void) value;
if (LocaleCompare(value,"1") != 0)
(void) SetsRGBImageProfile(image,exception);
value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
if (LocaleCompare(value,"R98.") != 0)
(void) SetsRGBImageProfile(image,exception);
icc_profile=GetImageProfile(image,"icc");
}
if ((icc_profile != (const StringInfo *) NULL) &&
(CompareStringInfo(icc_profile,profile) == 0))
{
profile=DestroyStringInfo(profile);
return(MagickTrue);
}
#if !defined(MAGICKCORE_LCMS_DELEGATE)
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
"'%s' (LCMS)",image->filename);
#else
{
cmsContext
cms_context;
CMSExceptionInfo
cms_exception;
LCMSInfo
source_info,
target_info;
/*
Transform pixel colors as defined by the color profiles.
*/
cms_exception.image=image;
cms_exception.exception=exception;
cms_context=cmsCreateContext(NULL,&cms_exception);
if (cms_context == (cmsContext) NULL)
{
profile=DestroyStringInfo(profile);
ThrowBinaryException(ResourceLimitError,
"ColorspaceColorProfileMismatch",name);
}
cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
GetStringInfoDatum(profile),(cmsUInt32Number)
GetStringInfoLength(profile));
if (source_info.profile == (cmsHPROFILE) NULL)
{
profile=DestroyStringInfo(profile);
cmsDeleteContext(cms_context);
ThrowBinaryException(ResourceLimitError,
"ColorspaceColorProfileMismatch",name);
}
if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
(icc_profile == (StringInfo *) NULL))
status=SetImageProfile(image,name,profile,exception);
else
{
CacheView
*image_view;
cmsColorSpaceSignature
signature;
cmsHTRANSFORM
*magick_restrict transform;
cmsUInt32Number
flags;
MagickBooleanType
highres;
MagickOffsetType
progress;
ssize_t
y;
target_info.profile=(cmsHPROFILE) NULL;
if (icc_profile != (StringInfo *) NULL)
{
target_info.profile=source_info.profile;
source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
GetStringInfoDatum(icc_profile),(cmsUInt32Number)
GetStringInfoLength(icc_profile));
if (source_info.profile == (cmsHPROFILE) NULL)
ThrowProfileException(ResourceLimitError,
"ColorspaceColorProfileMismatch",name);
}
highres=MagickTrue;
#if !defined(MAGICKCORE_HDRI_SUPPORT) || (MAGICKCORE_QUANTUM_DEPTH > 16)
{
const char
*artifact;
artifact=GetImageArtifact(image,"profile:highres-transform");
if (IsStringFalse(artifact) != MagickFalse)
highres=MagickFalse;
}
#endif
SetLCMSInfoScale(&source_info,1.0);
SetLCMSInfoTranslate(&source_info,0.0);
source_info.colorspace=sRGBColorspace;
source_info.channels=3;
switch (cmsGetColorSpace(source_info.profile))
{
case cmsSigCmykData:
{
source_info.colorspace=CMYKColorspace;
source_info.channels=4;
if (highres != MagickFalse)
{
source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
SetLCMSInfoScale(&source_info,100.0);
}
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
#endif
break;
}
case cmsSigGrayData:
{
source_info.colorspace=GRAYColorspace;
source_info.channels=1;
if (highres != MagickFalse)
source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
#endif
break;
}
case cmsSigLabData:
{
source_info.colorspace=LabColorspace;
if (highres != MagickFalse)
{
source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
source_info.scale[0]=100.0;
source_info.scale[1]=255.0;
source_info.scale[2]=255.0;
source_info.translate[1]=(-0.5);
source_info.translate[2]=(-0.5);
}
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
source_info.type=(cmsUInt32Number) TYPE_Lab_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
source_info.type=(cmsUInt32Number) TYPE_Lab_16;
#endif
break;
}
case cmsSigRgbData:
{
source_info.colorspace=sRGBColorspace;
if (highres != MagickFalse)
source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
source_info.type=(cmsUInt32Number) TYPE_RGB_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
source_info.type=(cmsUInt32Number) TYPE_RGB_16;
#endif
break;
}
case cmsSigXYZData:
{
source_info.colorspace=XYZColorspace;
if (highres != MagickFalse)
source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
#endif
break;
}
default:
ThrowProfileException(ImageError,
"ColorspaceColorProfileMismatch",name);
}
signature=cmsGetPCS(source_info.profile);
if (target_info.profile != (cmsHPROFILE) NULL)
signature=cmsGetColorSpace(target_info.profile);
SetLCMSInfoScale(&target_info,1.0);
SetLCMSInfoTranslate(&target_info,0.0);
target_info.channels=3;
switch (signature)
{
case cmsSigCmykData:
{
target_info.colorspace=CMYKColorspace;
target_info.channels=4;
if (highres != MagickFalse)
{
target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
SetLCMSInfoScale(&target_info,0.01);
}
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
#endif
break;
}
case cmsSigGrayData:
{
target_info.colorspace=GRAYColorspace;
target_info.channels=1;
if (highres != MagickFalse)
target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
#endif
break;
}
case cmsSigLabData:
{
target_info.colorspace=LabColorspace;
if (highres != MagickFalse)
{
target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
target_info.scale[0]=0.01;
target_info.scale[1]=1/255.0;
target_info.scale[2]=1/255.0;
target_info.translate[1]=0.5;
target_info.translate[2]=0.5;
}
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
target_info.type=(cmsUInt32Number) TYPE_Lab_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
target_info.type=(cmsUInt32Number) TYPE_Lab_16;
#endif
break;
}
case cmsSigRgbData:
{
target_info.colorspace=sRGBColorspace;
if (highres != MagickFalse)
target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
target_info.type=(cmsUInt32Number) TYPE_RGB_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
target_info.type=(cmsUInt32Number) TYPE_RGB_16;
#endif
break;
}
case cmsSigXYZData:
{
target_info.colorspace=XYZColorspace;
if (highres != MagickFalse)
target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
else
target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
else
source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
#endif
break;
}
default:
ThrowProfileException(ImageError,
"ColorspaceColorProfileMismatch",name);
}
switch (image->rendering_intent)
{
case AbsoluteIntent:
{
target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
break;
}
case PerceptualIntent:
{
target_info.intent=INTENT_PERCEPTUAL;
break;
}
case RelativeIntent:
{
target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
break;
}
case SaturationIntent:
{
target_info.intent=INTENT_SATURATION;
break;
}
default:
{
target_info.intent=INTENT_PERCEPTUAL;
break;
}
}
flags=cmsFLAGS_HIGHRESPRECALC;
#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
if (image->black_point_compensation != MagickFalse)
flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
#endif
transform=AcquireTransformTLS(&source_info,&target_info,flags,
cms_context);
if (transform == (cmsHTRANSFORM *) NULL)
ThrowProfileException(ImageError,"UnableToCreateColorTransform",
name);
/*
Transform image as dictated by the source & target image profiles.
*/
source_info.pixels=AcquirePixelTLS(image->columns,
source_info.channels,highres);
target_info.pixels=AcquirePixelTLS(image->columns,
target_info.channels,highres);
if ((source_info.pixels == (void **) NULL) ||
(target_info.pixels == (void **) NULL))
{
target_info.pixels=DestroyPixelTLS(target_info.pixels);
source_info.pixels=DestroyPixelTLS(source_info.pixels);
transform=DestroyTransformTLS(transform);
ThrowProfileException(ResourceLimitError,
"MemoryAllocationFailed",image->filename);
}
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
{
target_info.pixels=DestroyPixelTLS(target_info.pixels);
source_info.pixels=DestroyPixelTLS(source_info.pixels);
transform=DestroyTransformTLS(transform);
if (source_info.profile != (cmsHPROFILE) NULL)
(void) cmsCloseProfile(source_info.profile);
if (target_info.profile != (cmsHPROFILE) NULL)
(void) cmsCloseProfile(target_info.profile);
return(MagickFalse);
}
if (target_info.colorspace == CMYKColorspace)
(void) SetImageColorspace(image,target_info.colorspace,exception);
progress=0;
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static) shared(status) \
magick_number_threads(image,image,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
const int
id = GetOpenMPThreadId();
MagickBooleanType
sync;
Quantum
*magick_restrict q;
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
exception);
if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
if (highres != MagickFalse)
TransformDoublePixels(id,image,&source_info,&target_info,
transform,q);
else
TransformQuantumPixels(id,image,&source_info,&target_info,
transform,q);
sync=SyncCacheViewAuthenticPixels(image_view,exception);
if (sync == MagickFalse)
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
MagickBooleanType
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp atomic
#endif
progress++;
proceed=SetImageProgress(image,ProfileImageTag,progress,
image->rows);
if (proceed == MagickFalse)
status=MagickFalse;
}
}
image_view=DestroyCacheView(image_view);
(void) SetImageColorspace(image,target_info.colorspace,exception);
switch (signature)
{
case cmsSigRgbData:
{
image->type=image->alpha_trait == UndefinedPixelTrait ?
TrueColorType : TrueColorAlphaType;
break;
}
case cmsSigCmykData:
{
image->type=image->alpha_trait == UndefinedPixelTrait ?
ColorSeparationType : ColorSeparationAlphaType;
break;
}
case cmsSigGrayData:
{
image->type=image->alpha_trait == UndefinedPixelTrait ?
GrayscaleType : GrayscaleAlphaType;
break;
}
default:
break;
}
target_info.pixels=DestroyPixelTLS(target_info.pixels);
source_info.pixels=DestroyPixelTLS(source_info.pixels);
transform=DestroyTransformTLS(transform);
if ((status != MagickFalse) &&
(cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
status=SetImageProfile(image,name,profile,exception);
if (target_info.profile != (cmsHPROFILE) NULL)
(void) cmsCloseProfile(target_info.profile);
}
(void) cmsCloseProfile(source_info.profile);
cmsDeleteContext(cms_context);
}
#endif
}
profile=DestroyStringInfo(profile);
return(status);
}