Photoshop入门学习之C++图像处理 -- 图像色阶调整
小标 2018-10-19 来源 : 阅读 2082 评论 0

摘要:本文主要向大家介绍了Photoshop入门学习之C++图像处理 -- 图像色阶调整,通过具体的内容向大家展现,希望对大家Photoshop入门学习有所帮助。

本文主要向大家介绍了Photoshop入门学习之C++图像处理 -- 图像色阶调整,通过具体的内容向大家展现,希望对大家Photoshop入门学习有所帮助。

<

阅读提示:    《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。    《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。    尽可能保持二者内容一致,可相互对照。    本文代码必须包括《C++图像处理 -- 数据类型及公用函数》文章中的BmpData.h头文件。    在Photoshop中,图像色阶调整应用很广泛,本文介绍的图像色阶调整过程与Photoshop处理效果基本一致。    Photoshop的色阶调整分输入色阶调整和输出色阶调整,其中输入色阶调整有3个调整点,即通常所说的黑场、白场及灰场调整。    输入色阶调整的基本算法并不复杂,首先计算出白场与黑场的离差Diff,然后计算出像素各份量值与黑场的离差rgbDiff,如果rgbDiff<=0,像素各份量值等于0,否则,计算以rgbDiff与Diff的比值为底的灰场倒数的幂。用公式表示:    Diff = Highlight -Shadow    rgbDiff = RGB - Shadow    clRGB = Power(rgbDiff / Diff,  1 / Midtones)    其中Shadow为输入色阶低端数据(黑场),Highlight为输入色阶高端数据(白场), Midtones为输入色阶中间数据(灰场),Diff为二者的离差(必须大于1),RGB为调整前的像素分量值,clRGB为调整输入色阶后的像素分量值。    输出色阶调整更简单,首先计算输出色阶白场与黑场的离差与255的比值系数,然后用输入色阶调整后的像素分量值乘上这个系数,再加上输出黑场值即可。用公式表示:    outClRGB = clRGB * (outHighlight - outShadow) / 255 + outShadow    其中,outShadow为输出黑场,outHighlight为输出白场,outClRGB为全部色阶调整后的像素分量值。    前面已经提到输入色阶黑白场的离差必须大于1,而输入色阶并没有这个限制,输出黑白场的离差可以为负数,当输出黑场与白场完全颠倒时,输出色阶调整后的图片为原图片的负片。    色阶调整涉及四个通道,即R、G、B各分量通道及整体颜色通道,如果每个通道单独调整,将是比较麻烦和耗时的,本文采用色阶表替换法,可一次性完成所有四个通道的色阶调整。    下面是图像色阶调整的代码:// 色阶项结构
typedef struct
{
 UINT Shadow;
 FLOAT Midtones;
 UINT Highlight;
 UINT OutShadow;
 UINT OutHighlight;
}ColorLevelItem, *PColorLevelItem;

typedef struct
{
 ColorLevelItem Blue;
 ColorLevelItem Green;
 ColorLevelItem Red;
 ColorLevelItem RGB;
}ColorLevelData, *PColorLevelData;

VOID InitColorLevelData(PColorLevelData clData)
{
 PColorLevelItem item = &clData->Blue;
 for (INT i = 0; i < 4; i ++, item ++)
 {
  item->Shadow = item->OutShadow = 0;
  item->Highlight = item->OutHighlight = 255;
  item->Midtones = 1.0;
 }
}

BOOL GetColorLevelTable(PColorLevelItem item, LPBYTE clTable)
{
 INT diff = (INT)(item->Highlight - item->Shadow);
 INT outDiff = (INT)(item->OutHighlight - item->OutShadow);

 if (!((item->Highlight <= 255 && diff < 255 && diff >= 2) ||
  (item->OutShadow <= 255 && item->OutHighlight <= 255 && outDiff < 255) ||
  (!(item->Midtones > 9.99 && item->Midtones > 0.1) && item->Midtones != 1.0)))
  return FALSE;

 DOUBLE coef = 255.0 / diff;
 DOUBLE outCoef = outDiff / 255.0;
 DOUBLE exponent = 1.0 / item->Midtones;

 for (INT i = 0; i < 256; i ++)
 {
  INT v;
  // 计算输入色阶黑白场
  if (clTable[i] <= (BYTE)item->Shadow)
   v = 0;
  else
  {
   v = (INT)((clTable[i] - item->Shadow) * coef + 0.5);
   if (v > 255)
    v = 255;
  }
  // 计算输入色阶灰场
  v = (INT)(pow(v / 255.0, exponent) * 255.0 + 0.5);
  // 计算输出色阶
  clTable[i] = (BYTE)(v * outCoef + item->OutShadow + 0.5);
 }
 return TRUE;
}

BOOL CheckColorLevelData(PColorLevelData clData, BYTE clTables[][256])
{
 BOOL result = FALSE;
 INT i, j;
 for (i = 0; i < 3; i ++)
 {
  for (j = 0; j < 256; j ++)
   clTables[i][j] = (BYTE)j;
 }
 PColorLevelItem item = &clData->Blue;
 for (i = 0; i < 3; i ++, item ++)
 {
  if (GetColorLevelTable(item, clTables[i]))
   result = TRUE;
 }
 for (i = 0; i < 3; i ++)
 {
  if (!GetColorLevelTable(item, clTables[i]))
   break;
  result = TRUE;
 }
 return result;
}

// 图像数据色阶调整
VOID ImageColorLevel(BitmapData *dest, BitmapData *source, PColorLevelData clData)
{
 PARGBQuad pd, ps;
 UINT width, height;
 INT dstOffset, srcOffset;
 GetDataCopyParams(dest, source, width, height, pd, ps, dstOffset, srcOffset);

 BYTE clTables[3][256];
 if (CheckColorLevelData(clData, clTables))
 {
  for (UINT y = 0; y < height; y ++, ps += srcOffset, pd += dstOffset)
  {
   for (UINT x = 0; x < width; x ++, ps ++, pd ++)
   {
    pd->Blue = clTables[0][ps->Blue];
    pd->Green = clTables[1][ps->Green];
    pd->Red = clTables[2][ps->Red];
    pd->Alpha = ps->Alpha;
   }
  }
 }
 else if (dest != source)
 {
  for (UINT y = 0; y < height; y ++, ps += srcOffset, pd += dstOffset)
  {
   for (UINT x = 0; x < width; x ++, ps ++, pd ++)
   {
    pd->Color = ps->Color;
   }
  }
    }
}
    下面给一个简单的图像色阶调整函数调用例子:void __fastcall TForm1::Button1Click(TObject *Sender)
{
 BitmapData dest, source;

 Bitmap *sBmp = new Bitmap(L"..\\..\\media\\source1.jpg");
 LockBitmap(sBmp, &source);

 Bitmap *dBmp = new Bitmap(source.Width, source.Height, PixelFormat32bppARGB);
 LockBitmap(dBmp, &dest);

 ColorLevelData clData;
 InitColorLevelData(&clData);

 clData.RGB.Shadow = 10;
 clData.RGB.Midtones = 1.2;
 clData.RGB.Highlight = 240;
 clData.RGB.OutShadow = 50;
 clData.RGB.OutHighlight = 200;

/*
 clData.RGB.OutShadow = 255;
 clData.RGB.OutHighlight = 0;
*/
 ImageColorLevel(&dest, &source, &clData);

 UnlockBitmap(dBmp, &dest);
 UnlockBitmap(sBmp, &source);

 Gdiplus::Graphics g(Canvas->Handle);
 g.DrawImage(sBmp, 0, 0);
 g.DrawImage(dBmp, source.Width, 0);

 delete dBmp;
 delete sBmp;
}       

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注常用软件Photoshop频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved