WEB开发网
开发学院软件开发VC GDI+ ColorMatrix的完全揭秘与代码实现(下) 阅读

GDI+ ColorMatrix的完全揭秘与代码实现(下)

 2008-09-09 19:25:20 来源:WEB开发网   
核心提示: 因代码已经有了注释,而实现原理、公式已经在《GDI+ ColorMatrix的完全揭秘与代码实现(上)》中进行了详尽的介绍,GDI+ ColorMatrix的完全揭秘与代码实现(下)(2),所以本文不再累述,该过程代码的特点是简单易读,处理所有颜色变换elsebegin// 扩大256倍,

因代码已经有了注释,而实现原理、公式已经在《GDI+ ColorMatrix的完全揭秘与代码实现(上)》中进行了详尽的介绍,所以本文不再累述。

该过程代码的特点是简单易读,缺点是效率较低,在我的P4 2.8G计算机上,处理一张千万像素的照片,耗时为1000ms左右(不包括GDI+图像格式转换耗时。千万像素的24位格式图像转换为32位格式,耗时就达650ms)。

下面是一个以汇编为核心代码的整数ColorMatrix实现代码:

  procedure SetColorMatrix(Data: TImageData; Matrix: TColorMatrix);
  var
  I, J: Integer;
  MatrixI: array[0..4, 0..4] of Word;
  v: Integer;
  MainValue: Boolean;
  procedure SetMainLineData;
  asm
  push   edi
  lea    edi, Data
  mov    ecx, [edi + 4]     // ecx = Data.Width * Data.Height
  imul   ecx, [edi]
  mov    edi, [edi + 16]    // edi = Data.Scan0
  cld
  pxor   mm7, mm7
  movq   mm1, qword ptr MatrixI // 颜色矩阵中argb主对角线值
  @Loop1:              // 以下按像素个数循环操作:
  movd   mm0, dword ptr [edi]  //  装入像素argb
  punpcklbw mm0, mm7        //  argb由字节扩展到字
  pmullw  mm0, mm1        //  argb分别乘主角线上对应的值
  psrlw   mm0, 8         //  argb分别除以256
  packuswb mm0, mm0        //  argb由字压缩为字节
  movd   eax, mm0
  stosd              //  *(int*)edi ++ = argb
  loop   @Loop1
  pop    edi
  emms
  end;
  procedure SetImageData;
  asm
  push   esi
  push   edi
  push   ebx
  lea    esi, MatrixI      // 分别计算argb平移量并压入栈
  add    esi, 8
  mov    ecx, 4
  @Loop0:
  movzx   eax, word ptr [esi]
  imul   eax, 255
  push   eax
  add    esi, 10
  loop   @Loop0
  lea    edi, Data
  mov    ebx, [edi + 4]     // 像素总数 = Data.Width * Data.Height
  imul   ebx, [edi]
  mov    edi, [edi + 16]    // 图像扫描线首地址 = Data.Scan0
  pxor   mm7, mm7
  cld
  @Loop1:              // 以下按像素个数循环操作:
  movd   mm3, dword ptr [edi]  //  装入像素argb
  punpcklbw mm3, mm7        //  argb由字节扩展到字
  lea    esi, MatrixI      //  载入矩阵
  mov    ecx, 4         //  以下按矩阵行分别计算argb
  @Loop2:              //  计算顺序为b,g,r,a:
  movq   mm0, qword ptr [esi]  //   装入argb对应矩阵行
  pmaddwd  mm0, mm3        //   计算4组可能的线性变换
  movd   eax, mm0        //   将2个32位计算结果分别取出
  punpckhdq mm0, mm0
  movd   edx, mm0
  add    eax, edx        //   2个32位结果相加
  add    eax, [esp + ecx * 4 - 4]//  再加上平移量
  sar    eax, 8         //   还原因矩阵整数化时扩大的256倍
  jns    @@1
  xor    eax, eax
  jmp    @@2
  @@1:
  cmp    eax, 255
  jle    @@2
  mov    eax, 255
  @@2:
  stosb              //   设置argb为计算结果
  add    esi, 10
  loop   @Loop2
  dec    ebx
  jnz    @Loop1
  add    esp, 16
  pop    ebx
  pop    edi
  pop    esi
  emms
  end;
  begin
  MainValue := True;
  // 处理矩阵中大与255的值(取模),并判断主对角线外是否存在数据
  for I := 0 to 4 do
  for J := 0 to 4 do
  begin
  v := Round(Matrix[I, J]) div 256;
  if v > 0 then
  Matrix[I, J] := Matrix[I, J] - 256.0 * v;
  if (I <> J) and (Matrix[I, J] <> 0) then
  MainValue := False;
  end;
  // 如果只存在主对角线数据,转换主对角线浮点数为整数,只处理颜色缩放
  if MainValue then
  begin
  // 扩大256倍,并交换0行和2行,与argb顺序对应
  MatrixI[0, 0] := Round(Matrix[2, 2] * 256);
  MatrixI[0, 1] := Round(Matrix[1, 1] * 256);
  MatrixI[0, 2] := Round(Matrix[0, 0] * 256);
  MatrixI[0, 3] := Round(Matrix[3, 3] * 256);
  SetMainLineData;
  end
  // 否则,转换整个浮点矩阵为整数矩阵,处理所有颜色变换
  else
  begin              // 扩大256倍,并将矩阵列转换为矩阵行
  for I := 0 to 4 do
  for J := 0 to 4 do
  MatrixI[I, J] := Round(Matrix[J, I] * 256);
  for I := 0 to 4 do       // 交换0行和2行,与argb顺序对应
  begin
  v := MatrixI[I, 0];
  MatrixI[I, 0] := MatrixI[I, 2];
  MatrixI[I, 2] := v;
  end;
  for I := 0 to 4 do       // 交换0列和2列,与argb顺序对应
  begin
  v := MatrixI[0, I];
  MatrixI[0, I] := MatrixI[2, I];
  MatrixI[2, I] := v;
  end;
  SetImageData;
  end;
  end;

上一页  1 2 3 4  下一页

Tags:GDI ColorMatrix 完全

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接