Hi guys,
i wrote a gstreamer wrapper element for littlecms ( https://
bugzilla.gnome.org/attachment.cgi?id=327238 )
I've observed that the functions cmsDoTransformStride and cmsDoTransform
overwrite the subsequent data in my buffer plane if input and output pointers
are pointing to the same position in memory (in-place transformation).
i wrote a simple test case which shows this issue.
$ gcc -Wall -g `pkg-config lcms2 --cflags --libs` lcms-memory-corruption-
testcase.c -o lcms-memory-corruption-testcase
$ ./lcms-memory-corruption-testcase CP955_F.icc
initalize 3 rows with 4 bpp = 12 bytes of source data...
initalized source data looks like:
row 0@0x1f63a20 0xF0E0D0FF
row 1@0x1f63a24 0xF1E1D1FF
row 2@0x1f63a28 0xF2E2D2FF
doing transformation data->new_data...
row 0@0x1f63a20 0xF0E0D0FF (subsequent data 0xF1E1D1FF) => 0xF2E3D1FE
row 1@0x1f63a24 0xF1E1D1FF (subsequent data 0xF2E2D2FF) => 0xFED7CEFE
row 2@0x1f63a28 0xF2E2D2FF => 0xB7EDCEF7
doing IN PLACE transformation...
row 0@0x1f63a20 0xF0E0D0FF (subsequent data 0xF1E1D1FF) => 0xF2E3D1FE
row 1@0x1f63a24 0xB6ECCEF7 (subsequent data 0xFED8D2FF) => 0xC3E3D1FD
row 2@0x1f63a28 0xFDD4D2FD => 0xEBE0D0F7
so first a buffer is filled with data and then a test transformation is
performed into a newly allocated buffer. the result is as expect.
then another transform is done with output buffer = input buffer, and then the
subsequent input data is changed by the the cmsDoTransform call even though
the given size is correctly specified with 4 bpp. therefore, the result is
incorrect, except for the very first transformation. it happens with 3 bpp
aswell.
this in-place transformation is optional in gstreamer and just saves a memcpy,
so the simplest workaround is operating my gstreamer element in a way where
input and output buffers are different memory, but I'd like to find out why the
in-place transformation corrupts the input.
the tutorial says on page 15 that it is okay to use the same memory block for
input and output as long as the formats are the same. i haven't debugged yet,
before i investigate more, i'd like to find out if maybe i'm just doing it
wrong?
cheers
fraxinas
#include <lcms2.h>
#include <stdlib.h>
// test case for lcms2 memory corruption
// gcc -Wall -g `pkg-config lcms2 --cflags --libs` lcms-memory-corruption-testcase.c -o lcms-memory-corruption-testcase
int main(int argc, char* argv[])
{
cmsHPROFILE hInProfile, hOutProfile;
cmsHTRANSFORM hTransform;
if (argc != 2)
{
printf ("usage: %s output-profile.ICC\n", argv[0]);
return (-1);
}
hInProfile = cmsCreate_sRGBProfile();
hOutProfile = cmsOpenProfileFromFile(argv[1], "r");
hTransform = cmsCreateTransform(hInProfile, TYPE_BGR_8, hOutProfile, TYPE_BGR_8, INTENT_PERCEPTUAL, 0);
cmsCloseProfile(hInProfile);
cmsCloseProfile(hOutProfile);
unsigned char *data, *p, *new_data;
int width = 3;
int bpp = 4;
int stride = width * bpp;
int x;
data = (unsigned char *) malloc (stride+1 * sizeof(unsigned char));
new_data = (unsigned char *) malloc (stride+1 * sizeof(unsigned char));
printf ("initalize %i rows with %i bpp = %i bytes of source data...\n", width, bpp, stride);
p = data;
for (x = 0; x < width; x++)
{
p[x] = 0xF0+x;
p[x+1] = 0xE0+x;
p[x+2] = 0xD0+x;
p[x+3] = 0xFF;
p += bpp;
}
p = data;
printf ("initalized source data looks like:\n");
for (x = 0; x < width; x++)
{
printf ("row %i@%p 0x%02X%02X%02X%02X\n", x, p, p[x], p[x+1], p[x+2], p[x+3]);
p += bpp;
}
p = data;
printf ("\ndoing transformation data->new_data...\n");
for (x = 0; x < width; x++)
{
printf ("row %i@%p 0x%02X%02X%02X%02X", x, p, p[x], p[x+1], p[x+2], p[x+3]);
if (x < width-1)
printf (" (subsequent data 0x%02X%02X%02X%02X)", p[x+5], p[x+6], p[x+7], p[x+8]);
cmsDoTransform(hTransform, p, new_data, bpp);
printf (" => 0x%02X%02X%02X%02X \n", new_data[x], new_data[x+1], new_data[x+2], new_data[x+3]);
p += bpp;
}
p = data;
printf ("\ndoing IN PLACE transformation...\n");
for (x = 0; x < width; x++)
{
printf ("row %i@%p 0x%02X%02X%02X%02X", x, p, p[x], p[x+1], p[x+2], p[x+3]);
if (x < width-1)
printf (" (subsequent data 0x%02X%02X%02X%02X)", p[x+5], p[x+6], p[x+7], p[x+8]);
cmsDoTransform(hTransform, p, p, bpp);
printf (" => 0x%02X%02X%02X%02X \n", p[x], p[x+1], p[x+2], p[x+3]);
p += bpp;
}
cmsDeleteTransform(hTransform);
return 0;
}
------------------------------------------------------------------------------
Find and fix application performance issues faster with Applications Manager
Applications Manager provides deep performance insights into multiple tiers of
your business applications. It resolves application problems quickly and
reduces your MTTR. Get your free trial!
https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
_______________________________________________
Lcms-user mailing list
Lcms-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lcms-user