BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

RGB to CMYK conversion

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Graphics)
View previous topic :: View next topic  
Author Message
Frans Vander Meiren
Guest





PostPosted: Mon Jan 12, 2004 10:18 am    Post subject: RGB to CMYK conversion Reply with quote



Hi

Anyone who can explain me to convert a 24-bit RGB bitmap (DIB-format) to a
32-bit CMYK bitmap by using an ICM colorprofile?
Thanks

Frans Vander Meiren


Back to top
Damon Chandler (TeamB)
Guest





PostPosted: Fri Jan 16, 2004 8:39 am    Post subject: Re: RGB to CMYK conversion Reply with quote



Hi Frans,
The TranslateBitmapBits() function should do this for you if you use a
CMYK profile as the "destination" profile. Here's a rough example that
creates a 32-bpp CMYK bitmap from a 24-bpp sRGB bitmap...

#include <icm.h>
#pragma link "mscms.lib"

Graphics::TBitmap* sRGB2CMYKBitmap(
Graphics::TBitmap& SrcBitmap,
AnsiString cmyk_profilename
)
{
// copy the file-name of the target (CMYK) profile
TCHAR tgt_profilename[MAX_PATH];
lstrcpyn(tgt_profilename,
cmyk_profilename.c_str(), MAX_PATH);

// initialize a PROFILE structure
PROFILE tgt_profile;
tgt_profile.dwType = PROFILE_FILENAME;
tgt_profile.pProfileData = static_cast<void*>(tgt_profilename);
tgt_profile.cbDataSize =
(lstrlen(tgt_profilename) + 1) * sizeof(TCHAR);

// create the color profile object
HPROFILE const hTgtProfile = OpenColorProfile(
&tgt_profile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING
);
if (hTgtProfile == NULL)
{
throw EWin32Error("OpenColorProfile() failed.");
}

// force the source bitmap to 24 bpp
SrcBitmap.PixelFormat = pf24bit;

// create the target bitmap object
std::auto_ptr<Graphics::TBitmap>
TgtBitmap(new Graphics::TBitmap());
TgtBitmap->PixelFormat = pf32bit;
TgtBitmap->Width = SrcBitmap.Width;
TgtBitmap->Height = SrcBitmap.Height;

//
// perform the color conversion...
//
try
{
// validate the profile's contents
BOOL is_valid = FALSE;
IsColorProfileValid(hTgtProfile, &is_valid);
if (!is_valid)
{
throw EWin32Error("bad profile");
}

// initialize a LOGCOLORSPACE struct
LOGCOLORSPACE lcs = {
LCS_SIGNATURE, 0x400, sizeof(LOGCOLORSPACE)
};
// sRGB color space
lcs.lcsCSType = LCS_sRGB;
// perceptual rendering intent
lcs.lcsIntent = LCS_GM_IMAGES;

// create a color transform object
HTRANSFORM const hColorTransform = CreateColorTransform(
&lcs, hTgtProfile, NULL, NORMAL_MODE + ENABLE_GAMUT_CHECKING
);
if (hColorTransform == NULL)
{
throw EWin32Error("CreateColorTransform() failed.");
}
try
{
// grab a pointer to the pixels
BITMAP src_bmp, tgt_bmp;
GetObject(SrcBitmap.Handle, sizeof(BITMAP), &src_bmp);
GetObject(TgtBitmap->Handle, sizeof(BITMAP), &tgt_bmp);

// color-match the bitmap's pixels
const bool match_ok =
TranslateBitmapBits(
hColorTransform,
src_bmp.bmBits, BM_RGBTRIPLETS,
src_bmp.bmWidth, src_bmp.bmHeight, 0,
tgt_bmp.bmBits, BM_CMYKQUADS, 0,
NULL, 0
);
if (!match_ok)
{
throw EWin32Error("TranslateBitmapBits() failed.");
}
}
__finally
{
// destroy the color transform object
DeleteColorTransform(hColorTransform);
}
}
__finally
{
// destroy the color profile object
CloseColorProfile(hTgtProfile);
}

// caller assumes ownership
return TgtBitmap.release();
}

The cmyk_profilename parameter must indicate the fully-qualified
file-name of a valid CMYK profile (you can get some here
[url]http://www.adobe.com/support/downloads/detail.jsp?ftpID=2348)[/url].

After the conversion, you can access the C, M, Y, and K values from the
returned CMYK bitmap by casting each scanline to a COLORREF and then
using the GetCValue(), GetMValue(), GetYValue(), and GetKValue()
macros. For example...

inline BYTE clip(int x)
{
if (x > 255) return 255;
if (x < 0) return 0;
return x;
}

void __fastcall TForm1::
ColorMatchButtonClick(TObject *Sender)
{
std::auto_ptr sRGB2CMYKBitmap(
*Image1->Picture->Bitmap, "c:\USWebUncoated.icc"
)
);

// convert back to uncalibrated RGB as a sanity check
int const cx = CMYKBitmap->Width;
int const cy = CMYKBitmap->Height;
for (int y0 = 0; y0 < cy; ++y0)
{
RGBQUAD* const pRGBRow = static_cast CMYKBitmap->ScanLine[y0]
);
COLORREF const* const pColorRow = static_cast<COLORREF*>(
CMYKBitmap->ScanLine[y0]
);
for (int x0 = 0; x0 < cx; ++x0)
{
int const c = GetCValue(pColorRow[x0]);
int const m = GetMValue(pColorRow[x0]);
int const y = GetYValue(pColorRow[x0]);
int const k = GetKValue(pColorRow[x0]);

pRGBRow[x0].rgbRed = clip(255 - (c + k));
pRGBRow[x0].rgbGreen = clip(255 - (m + k));
pRGBRow[x0].rgbBlue = clip(255 - (y + k));
}
}

// display the bitmap
Image2->Picture->Assign(CMYKBitmap.get());
}

HTH,
Damon (TeamB)
Back to top
Frans Vander Meiren
Guest





PostPosted: Wed Jan 28, 2004 6:55 pm    Post subject: Re: RGB to CMYK conversion Reply with quote



Thanks Deamon

Greetings, Frans Vander Meiren


"Damon Chandler (TeamB)" <dmc27 (AT) cornell (DOT) edu> schreef in bericht
news:4007A334.69D35C77 (AT) cornell (DOT) edu...
Quote:
Hi Frans,
The TranslateBitmapBits() function should do this for you if you use a
CMYK profile as the "destination" profile. Here's a rough example that
creates a 32-bpp CMYK bitmap from a 24-bpp sRGB bitmap...

#include <icm.h
#pragma link "mscms.lib"

Graphics::TBitmap* sRGB2CMYKBitmap(
Graphics::TBitmap& SrcBitmap,
AnsiString cmyk_profilename
)
{
// copy the file-name of the target (CMYK) profile
TCHAR tgt_profilename[MAX_PATH];
lstrcpyn(tgt_profilename,
cmyk_profilename.c_str(), MAX_PATH);

// initialize a PROFILE structure
PROFILE tgt_profile;
tgt_profile.dwType = PROFILE_FILENAME;
tgt_profile.pProfileData = static_cast tgt_profile.cbDataSize =
(lstrlen(tgt_profilename) + 1) * sizeof(TCHAR);

// create the color profile object
HPROFILE const hTgtProfile = OpenColorProfile(
&tgt_profile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING
);
if (hTgtProfile == NULL)
{
throw EWin32Error("OpenColorProfile() failed.");
}

// force the source bitmap to 24 bpp
SrcBitmap.PixelFormat = pf24bit;

// create the target bitmap object
std::auto_ptr<Graphics::TBitmap
TgtBitmap(new Graphics::TBitmap());
TgtBitmap->PixelFormat = pf32bit;
TgtBitmap->Width = SrcBitmap.Width;
TgtBitmap->Height = SrcBitmap.Height;

//
// perform the color conversion...
//
try
{
// validate the profile's contents
BOOL is_valid = FALSE;
IsColorProfileValid(hTgtProfile, &is_valid);
if (!is_valid)
{
throw EWin32Error("bad profile");
}

// initialize a LOGCOLORSPACE struct
LOGCOLORSPACE lcs = {
LCS_SIGNATURE, 0x400, sizeof(LOGCOLORSPACE)
};
// sRGB color space
lcs.lcsCSType = LCS_sRGB;
// perceptual rendering intent
lcs.lcsIntent = LCS_GM_IMAGES;

// create a color transform object
HTRANSFORM const hColorTransform = CreateColorTransform(
&lcs, hTgtProfile, NULL, NORMAL_MODE + ENABLE_GAMUT_CHECKING
);
if (hColorTransform == NULL)
{
throw EWin32Error("CreateColorTransform() failed.");
}
try
{
// grab a pointer to the pixels
BITMAP src_bmp, tgt_bmp;
GetObject(SrcBitmap.Handle, sizeof(BITMAP), &src_bmp);
GetObject(TgtBitmap->Handle, sizeof(BITMAP), &tgt_bmp);

// color-match the bitmap's pixels
const bool match_ok =
TranslateBitmapBits(
hColorTransform,
src_bmp.bmBits, BM_RGBTRIPLETS,
src_bmp.bmWidth, src_bmp.bmHeight, 0,
tgt_bmp.bmBits, BM_CMYKQUADS, 0,
NULL, 0
);
if (!match_ok)
{
throw EWin32Error("TranslateBitmapBits() failed.");
}
}
__finally
{
// destroy the color transform object
DeleteColorTransform(hColorTransform);
}
}
__finally
{
// destroy the color profile object
CloseColorProfile(hTgtProfile);
}

// caller assumes ownership
return TgtBitmap.release();
}

The cmyk_profilename parameter must indicate the fully-qualified
file-name of a valid CMYK profile (you can get some here
[url]http://www.adobe.com/support/downloads/detail.jsp?ftpID=2348)[/url].

After the conversion, you can access the C, M, Y, and K values from the
returned CMYK bitmap by casting each scanline to a COLORREF and then
using the GetCValue(), GetMValue(), GetYValue(), and GetKValue()
macros. For example...

inline BYTE clip(int x)
{
if (x > 255) return 255;
if (x < 0) return 0;
return x;
}

void __fastcall TForm1::
ColorMatchButtonClick(TObject *Sender)
{
std::auto_ptr sRGB2CMYKBitmap(
*Image1->Picture->Bitmap, "c:\USWebUncoated.icc"
)
);

// convert back to uncalibrated RGB as a sanity check
int const cx = CMYKBitmap->Width;
int const cy = CMYKBitmap->Height;
for (int y0 = 0; y0 < cy; ++y0)
{
RGBQUAD* const pRGBRow = static_cast CMYKBitmap->ScanLine[y0]
);
COLORREF const* const pColorRow = static_cast<COLORREF*>(
CMYKBitmap->ScanLine[y0]
);
for (int x0 = 0; x0 < cx; ++x0)
{
int const c = GetCValue(pColorRow[x0]);
int const m = GetMValue(pColorRow[x0]);
int const y = GetYValue(pColorRow[x0]);
int const k = GetKValue(pColorRow[x0]);

pRGBRow[x0].rgbRed = clip(255 - (c + k));
pRGBRow[x0].rgbGreen = clip(255 - (m + k));
pRGBRow[x0].rgbBlue = clip(255 - (y + k));
}
}

// display the bitmap
Image2->Picture->Assign(CMYKBitmap.get());
}

HTH,
Damon (TeamB)



Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Graphics) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.