Backward compatibility broken on big profiles in JPG images
Posted: 2007-06-23T08:09:00-07:00
Hi,
I am using JMagick, which at several places use the ImageMagick API as it was
used in 2003, including the use of color_profile and iptc_profile members.
IMs changelog states:
2003-09-21 Cristy <yarrow@image...>
* Image profiles are now conveniently handled with a hashmap
structure. The color_profile and iptc_profile members of the Image
structure are still maintained for backwards compatibility, however,
we encourage you to use the new PutImageProfile(), GetImageProfile(),
and DeleteImageProfile() methods.
However, the color_profile and iptc_profile members are broken.
They are set in SetImageProfile, which is only invoked for the FIRST
chunk of profile data. So big profiles will retain only the first chunk
(typically 32000 bytes).
Look at ReadIPTCProfile in coders/jpeg.c line 489:
if (iptc_profile != (StringInfo *) NULL)
{
ConcatenateStringInfo(iptc_profile,profile);
profile=DestroyStringInfo(profile);
}
else
{
status=SetImageProfile(image,"8bim",profile);
profile=DestroyStringInfo(profile);
if (status == MagickFalse)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
If there are already some IPTC data, new IPTC is concatenated with
ConcatenateStringInfo() and SetImageProfile() is NOT invoked.
I think you should either delete the color_profile and iptc_profile altogether
(thus breaking compatility with JMagick totally), or fix this (preferred).
A quick fix, which works for me, is to repeatedly set the profile for each
chunk. Chunks are typically 32000 byte long, so only for extremely big
profiles would this make a performance difference.
if (iptc_profile != (StringInfo *) NULL)
{
ConcatenateStringInfo(iptc_profile,profile);
status=SetImageProfile(image,"8bim",iptc_profile);
profile=DestroyStringInfo(profile);
}
else
{
status=SetImageProfile(image,"8bim",profile);
profile=DestroyStringInfo(profile);
if (status == MagickFalse)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
You might prefer another solution.
This should also be fixed in line 393 (concerning ICC profile data).
Jacob
I am using JMagick, which at several places use the ImageMagick API as it was
used in 2003, including the use of color_profile and iptc_profile members.
IMs changelog states:
2003-09-21 Cristy <yarrow@image...>
* Image profiles are now conveniently handled with a hashmap
structure. The color_profile and iptc_profile members of the Image
structure are still maintained for backwards compatibility, however,
we encourage you to use the new PutImageProfile(), GetImageProfile(),
and DeleteImageProfile() methods.
However, the color_profile and iptc_profile members are broken.
They are set in SetImageProfile, which is only invoked for the FIRST
chunk of profile data. So big profiles will retain only the first chunk
(typically 32000 bytes).
Look at ReadIPTCProfile in coders/jpeg.c line 489:
if (iptc_profile != (StringInfo *) NULL)
{
ConcatenateStringInfo(iptc_profile,profile);
profile=DestroyStringInfo(profile);
}
else
{
status=SetImageProfile(image,"8bim",profile);
profile=DestroyStringInfo(profile);
if (status == MagickFalse)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
If there are already some IPTC data, new IPTC is concatenated with
ConcatenateStringInfo() and SetImageProfile() is NOT invoked.
I think you should either delete the color_profile and iptc_profile altogether
(thus breaking compatility with JMagick totally), or fix this (preferred).
A quick fix, which works for me, is to repeatedly set the profile for each
chunk. Chunks are typically 32000 byte long, so only for extremely big
profiles would this make a performance difference.
if (iptc_profile != (StringInfo *) NULL)
{
ConcatenateStringInfo(iptc_profile,profile);
status=SetImageProfile(image,"8bim",iptc_profile);
profile=DestroyStringInfo(profile);
}
else
{
status=SetImageProfile(image,"8bim",profile);
profile=DestroyStringInfo(profile);
if (status == MagickFalse)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
You might prefer another solution.
This should also be fixed in line 393 (concerning ICC profile data).
Jacob