【图像】图像降级,空间逼近式矩阵抖动算法,C语言实现(DLL)【效果不好,别用】
有关抖动算法的原理请看这个帖子:http://www.0xaa55.com/thread-671-1-1.html源码:
Dither.c://=============================================================================
//DitherFunc.c:
//实现抖动算法
//作者:0xAA55
//论坛:http://www.0xaa55.com/
//版权所有 (C) 2013-2014 技术宅的结界
//请保留原作者信息,否则视为侵权
//-----------------------------------------------------------------------------
#include<windows.h>
#include<math.h>
#define MaxDist 64
#define MaxDistSq (MaxDist*MaxDist)
#define MaxColorValue 255
#define MaxColorDistance (MaxColorValue*MaxColorValue*3)
externBYTE LightMatrix;
UINT WINAPI Dither
(
DWORD x, //像素点X坐标
DWORD y, //像素点Y坐标
RGBQUAD*pColor, //原始颜色值
RGBQUAD*pPalette, //调色板
DWORD dwNbColors //调色板颜色数
)
{
doubleLMValue=(double)LightMatrix[(x & 0xF)|((y & 0xF)<<4)]/255;
UINT i;
doubleRDiff,GDiff,BDiff;//红色差,绿色差,蓝色差
doubleiNewDistSq; //新计算出来的距离平方
doubleVec1R,Vec1G,Vec1B;//颜色向量1
doubleVec2R,Vec2G,Vec2B;//颜色向量2
doubleVec3R,Vec3G,Vec3B;//颜色向量3
doubleVec4R,Vec4G,Vec4B;//颜色向量4
//颜色向量指的是从原始颜色到调色板颜色的向量
UINT Value1,Value2,Value3,Value4;
doubleiDistanceSq=MaxColorDistance;
//第一步:找出最接近颜色
for(i=0;i<dwNbColors;i++)
{
//计算颜色差
BDiff=(double)(pPalette.rgbBlue)-(double)(pColor->rgbBlue);
GDiff=(double)(pPalette.rgbGreen)-(double)(pColor->rgbGreen);
RDiff=(double)(pPalette.rgbRed)-(double)(pColor->rgbRed);
//计算颜色距离平方
iNewDistSq=RDiff*RDiff+GDiff*GDiff+BDiff*BDiff;
if(iNewDistSq<iDistanceSq && iNewDistSq<=MaxDistSq)//选出更接近的颜色
{
Vec1R=RDiff;
Vec1G=GDiff;
Vec1B=BDiff;
Value1=i;
iDistanceSq=iNewDistSq;
}
}
//第二步:找出最接近的颜色对面的颜色
Value2=Value1;
iDistanceSq=MaxColorDistance;
for(i=0;i<dwNbColors;i++)
{
//计算颜色差
BDiff=(double)(pPalette.rgbBlue)-(double)(pColor->rgbBlue);
GDiff=(double)(pPalette.rgbGreen)-(double)(pColor->rgbGreen);
RDiff=(double)(pPalette.rgbRed)-(double)(pColor->rgbRed);
//判断是否在对面
if(RDiff*Vec1R+GDiff*Vec1G+BDiff*Vec1B < 0)
{
iNewDistSq=RDiff*RDiff+GDiff*GDiff+BDiff*BDiff;
if(iNewDistSq<iDistanceSq && iNewDistSq<=MaxDistSq)//选出更接近的颜色
{
Vec2R=RDiff;
Vec2G=GDiff;
Vec2B=BDiff;
Value2=i;
iDistanceSq=iNewDistSq;
}
}
}
//第三步:找出上面两个颜色对面的颜色
Value3=Value2;
iDistanceSq=MaxColorDistance;
for(i=0;i<dwNbColors;i++)
{
//计算颜色差
BDiff=(double)(pPalette.rgbBlue)-(double)(pColor->rgbBlue);
GDiff=(double)(pPalette.rgbGreen)-(double)(pColor->rgbGreen);
RDiff=(double)(pPalette.rgbRed)-(double)(pColor->rgbRed);
//判断是否在对面
if( RDiff*Vec1R+GDiff*Vec1G+BDiff*Vec1B < 0 &&
RDiff*Vec2R+GDiff*Vec2G+BDiff*Vec2B < 0)
{
iNewDistSq=RDiff*RDiff+GDiff*GDiff+BDiff*BDiff;
if(iNewDistSq<iDistanceSq && iNewDistSq<=MaxDistSq)//选出更接近的颜色
{
Vec3R=RDiff;
Vec3G=GDiff;
Vec3B=BDiff;
Value3=i;
iDistanceSq=iNewDistSq;
}
}
}
//第四步:找出上面三个颜色对面的颜色
Value4=Value3;
iDistanceSq=MaxColorDistance;
for(i=0;i<dwNbColors;i++)
{
//计算颜色差
BDiff=(double)(pPalette.rgbBlue)-(double)(pColor->rgbBlue);
GDiff=(double)(pPalette.rgbGreen)-(double)(pColor->rgbGreen);
RDiff=(double)(pPalette.rgbRed)-(double)(pColor->rgbRed);
//判断是否在对面
if( RDiff*Vec1R+GDiff*Vec1G+BDiff*Vec1B < 0 &&
RDiff*Vec2R+GDiff*Vec2G+BDiff*Vec2B < 0 &&
RDiff*Vec3R+GDiff*Vec3G+BDiff*Vec3B < 0)
{
iNewDistSq=RDiff*RDiff+GDiff*GDiff+BDiff*BDiff;
if(iNewDistSq<iDistanceSq && iNewDistSq<=MaxDistSq)//选出更接近的颜色
{
Vec4R=RDiff;
Vec4G=GDiff;
Vec4B=BDiff;
Value4=i;
iDistanceSq=iNewDistSq;
}
}
}
if(Value1==Value2 && Value2==Value3 && Value3==Value4)
return Value1;
else if(Value1!=Value2 && Value2==Value3 && Value3==Value4)
{
/* Src
/|~"-,_
/ | ~"-,_
/| ~"-,_
/ | ~"-,_
/ | ~"-,_
Value1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Value2*/
doubleVec1To2R=Vec2R-Vec1R,
Vec1To2G=Vec2G-Vec1G,
Vec1To2B=Vec2B-Vec1B;//颜色1到2的向量
doubleVec1To2Dist=sqrt( Vec1To2R*Vec1To2R+
Vec1To2G*Vec1To2G+
Vec1To2B*Vec1To2B);//颜色1到2的距离
if((( -Vec1R*Vec1To2R
-Vec1G*Vec1To2G
-Vec1B*Vec1To2B)/Vec1To2Dist)/Vec1To2Dist<=LMValue)//抖动“插值”
return Value1;
else
return Value2;
}
else if(Value1!=Value2 && Value2!=Value3 && Value3==Value4)
{
doubleVec1To2R=Vec2R-Vec1R,
Vec1To2G=Vec2G-Vec1G,
Vec1To2B=Vec2B-Vec1B,//颜色1到2的向量
Vec2To3R=Vec3R-Vec2R,
Vec2To3G=Vec3G-Vec2G,
Vec2To3B=Vec3B-Vec2B;//颜色2到3的向量
double
R1=(double)(pPalette.rgbRed),
G1=(double)(pPalette.rgbGreen),
B1=(double)(pPalette.rgbBlue),//颜色1的值
R2=(double)(pPalette.rgbRed),
G2=(double)(pPalette.rgbGreen),
B2=(double)(pPalette.rgbBlue),//颜色2的值
R3=(double)(pPalette.rgbRed),
G3=(double)(pPalette.rgbGreen),
B3=(double)(pPalette.rgbBlue);//颜色3的值
double
SrcR=(double)(pColor->rgbRed),
SrcG=(double)(pColor->rgbGreen),
SrcB=(double)(pColor->rgbBlue);
double Plane123A,Plane123B,Plane123C,Plane123D,Plane123ABCLen;
double PlaneFace23A,PlaneFace23B,PlaneFace23C,PlaneFace23D,PlaneFace23ABCLen;
double P2ToPlaneDist,P3ToPlaneDist,PlaneCutPosition;
double PlaneCut23ToSrcR,PlaneCut23ToSrcG,PlaneCut23ToSrcB;
double VecFrom1ToThatPointR,VecFrom1ToThatPointG,VecFrom1ToThatPointB,VecFrom1ToThatPointLen;
BYTE Value23;
//颜色1、2、3建立平面
Plane123A=Vec1To2G*Vec2To3B-Vec1To2B*Vec2To3G,
Plane123B=Vec1To2B*Vec2To3R-Vec1To2R*Vec2To3B,
Plane123C=Vec1To2R*Vec2To3G-Vec1To2G*Vec2To3R;
Plane123D=-(Plane123A*R1+
Plane123B*G1+
Plane123C*B1),
Plane123ABCLen=sqrt(Plane123A*Plane123A+
Plane123B*Plane123B+
Plane123C*Plane123C);
Plane123A/=Plane123ABCLen;
Plane123B/=Plane123ABCLen;
Plane123C/=Plane123ABCLen;
Plane123D/=Plane123ABCLen;
//建立垂直于平面123,并且过原始颜色和颜色1的平面(面向2、3)
PlaneFace23A=Vec1G*Plane123C-Vec1B*Plane123B;
PlaneFace23B=Vec1B*Plane123A-Vec1R*Plane123C;
PlaneFace23C=Vec1R*Plane123B-Vec1G*Plane123A;
PlaneFace23D=-( PlaneFace23A*R1+
PlaneFace23B*G1+
PlaneFace23C*B1);
PlaneFace23ABCLen=sqrt( PlaneFace23A*PlaneFace23A+
PlaneFace23B*PlaneFace23B+
PlaneFace23C*PlaneFace23C);
PlaneFace23A/=PlaneFace23ABCLen;
PlaneFace23B/=PlaneFace23ABCLen;
PlaneFace23C/=PlaneFace23ABCLen;
PlaneFace23D/=PlaneFace23ABCLen;
//点2到平面的距离和点3到平面的距离
P2ToPlaneDist=fabs(R2*PlaneFace23A+G2*PlaneFace23B+B2*PlaneFace23C+PlaneFace23D);
P3ToPlaneDist=fabs(R3*PlaneFace23A+G3*PlaneFace23B+B3*PlaneFace23C+PlaneFace23D);
//2到3之间的插值
PlaneCutPosition=P2ToPlaneDist/(P2ToPlaneDist+P3ToPlaneDist);
if(PlaneCutPosition<=LMValue)//颜色2、3的插值
Value23=Value2;
else
Value23=Value3;
//计算从原始颜色到线段23与平面的交点的向量
PlaneCut23ToSrcR=R2+Vec2To3R*PlaneCutPosition-SrcR;
PlaneCut23ToSrcG=G2+Vec2To3G*PlaneCutPosition-SrcG;
PlaneCut23ToSrcB=B2+Vec2To3B*PlaneCutPosition-SrcB;
//从颜色1到线段23与平面交点的向量
VecFrom1ToThatPointR=PlaneCut23ToSrcR-Vec1R;
VecFrom1ToThatPointG=PlaneCut23ToSrcG-Vec1G;
VecFrom1ToThatPointB=PlaneCut23ToSrcB-Vec1B;
VecFrom1ToThatPointLen=sqrt(VecFrom1ToThatPointR*VecFrom1ToThatPointR+
VecFrom1ToThatPointG*VecFrom1ToThatPointG+
VecFrom1ToThatPointB*VecFrom1ToThatPointB);
VecFrom1ToThatPointR/=VecFrom1ToThatPointLen;
VecFrom1ToThatPointG/=VecFrom1ToThatPointLen;
VecFrom1ToThatPointB/=VecFrom1ToThatPointLen;
if((( -Vec1R*VecFrom1ToThatPointR
-Vec1G*VecFrom1ToThatPointG
-Vec1B*VecFrom1ToThatPointB)/VecFrom1ToThatPointLen)<=LMValue)
return Value1;
else
return Value23;
}
else
{
double Plane12PA,Plane12PB,Plane12PC,Plane12PD,Plane12PABCLen;
double Plane34PA,Plane34PB,Plane34PC,Plane34PD,Plane34PABCLen;
double Distance1ToP34,Distance2ToP34;
double Distance3ToP12,Distance4ToP12;
double P12Cut34,P34Cut12;
double CutPoint1R,CutPoint1G,CutPoint1B;
double CutPoint2R,CutPoint2G,CutPoint2B;
double Dist12,Dist34;
double
SrcR=(double)(pColor->rgbRed),
SrcG=(double)(pColor->rgbGreen),
SrcB=(double)(pColor->rgbBlue);//原始颜色
BYTE Value12,Value34;
doubleVec1To2R=Vec2R-Vec1R,
Vec1To2G=Vec2G-Vec1G,
Vec1To2B=Vec2B-Vec1B,//颜色1到2的向量
Vec3To4R=Vec4R-Vec3R,
Vec3To4G=Vec4G-Vec3G,
Vec3To4B=Vec4B-Vec3B;//颜色3到4的向量
Plane12PA=Vec1G*Vec2B-Vec1B*Vec2G;
Plane12PB=Vec1B*Vec2R-Vec1R*Vec2B;
Plane12PC=Vec1R*Vec2G-Vec1G*Vec2R;//颜色12与原始颜色的平面
Plane34PA=Vec3G*Vec4B-Vec3B*Vec4G;
Plane34PB=Vec3B*Vec4R-Vec3R*Vec4B;
Plane34PC=Vec3R*Vec4G-Vec3G*Vec4R;//颜色34与原始颜色的平面
Plane12PD=-Plane12PA*SrcR
-Plane12PB*SrcG
-Plane12PC*SrcB;
Plane34PD=-Plane34PA*SrcR
-Plane34PB*SrcG
-Plane34PC*SrcB;
Plane12PABCLen=sqrt(Plane12PA*Plane12PA+
Plane12PB*Plane12PB+
Plane12PC*Plane12PC);
Plane34PABCLen=sqrt(Plane34PA*Plane34PA+
Plane34PB*Plane34PB+
Plane34PC*Plane34PC);
Plane12PA/=Plane12PABCLen;
Plane12PB/=Plane12PABCLen;
Plane12PC/=Plane12PABCLen;
Plane12PD/=Plane12PABCLen;
Plane34PA/=Plane34PABCLen;
Plane34PB/=Plane34PABCLen;
Plane34PC/=Plane34PABCLen;
Plane34PD/=Plane34PABCLen;
Distance1ToP34=fabs(Vec1R*Plane34PA+Vec1G*Plane34PB+Vec1B*Plane34PC+Plane34PD);
Distance2ToP34=fabs(Vec2R*Plane34PA+Vec2G*Plane34PB+Vec2B*Plane34PC+Plane34PD);
Distance3ToP12=fabs(Vec3R*Plane12PA+Vec3G*Plane12PB+Vec3B*Plane12PC+Plane12PD);
Distance4ToP12=fabs(Vec4R*Plane12PA+Vec4G*Plane12PB+Vec4B*Plane12PC+Plane12PD);
P12Cut34=Distance3ToP12+(Distance3ToP12+Distance4ToP12);
P34Cut12=Distance1ToP34+(Distance1ToP34+Distance2ToP34);
if(P12Cut34<=LMValue)//从颜色34中插值
Value34=Value3;
else
Value34=Value4;
if(P34Cut12<=LMValue)//从颜色12中插值
Value12=Value1;
else
Value12=Value2;
CutPoint1R=Vec1R+Vec1To2R*P34Cut12;
CutPoint1G=Vec1G+Vec1To2G*P34Cut12;
CutPoint1B=Vec1B+Vec1To2B*P34Cut12;
CutPoint2R=Vec3R+Vec3To4R*P12Cut34;
CutPoint2G=Vec3G+Vec3To4G*P12Cut34;
CutPoint2B=Vec3B+Vec3To4B*P12Cut34;
Dist12=sqrt(CutPoint1R*CutPoint1R+
CutPoint1G*CutPoint1G+
CutPoint1B*CutPoint1B);
Dist34=sqrt(CutPoint2R*CutPoint2R+
CutPoint2G*CutPoint2G+
CutPoint2B*CutPoint2B);
if(Dist12/(Dist12+Dist34)<=LMValue)//从刚才得到的两个颜色中插值
return Value12;
else
return Value34;
}
}Dither.asm:;==============================================================================
;作者:0xAA55
;论坛:http://www.0xaa55.com/
;版权所有 (C) 2013-2014 技术宅的结界
;请保留原作者信息,否则视为侵权
;------------------------------------------------------------------------------
globalDistISq ;REAL WINAPI DistISq(DWORD x1,DWORD y1,DWORD z1);
globalDistISq2P ;REAL WINAPI DistISq2P(DWORD x1,DWORD y1,DWORD z1,DWORD x2,DWORD y2,DWORD z2);
globalDistFSq ;REAL WINAPI DistISq(float x1,float y1,float z1);
globalDistFSq2P ;REAL WINAPI DistISq2P(float x1,float y1,float z1,float x2,float y2,float z2);
globalDitherMatrix ;DWORD WINAPI DitherMatrix(DWORD x,DWORD y);
global_LightMatrix ;extern BYTE LightMatrix;
segment .text
;==============================================================================
;DistISq:
;取得三维向量模平方。参数是整数。
;------------------------------------------------------------------------------
DistISq: ;REAL WINAPI DistISq(DWORD x1,DWORD y1,DWORD z1)
fild dword
fmul st0
fild dword
fmul st0
fadd
fild dword
fmul st0
fadd
ret 24
;==============================================================================
;DistISq2P:
;取得三维空间中两点的距离。参数是整数。
;------------------------------------------------------------------------------
DistISq2P: ;REAL WINAPI DistISq2P(DWORD x1,DWORD y1,DWORD z1,DWORD x2,DWORD y2,DWORD z2)
fild dword
fisub dword
fmul st0
fild dword
fisub dword
fmul st0
fadd
fild dword
fisub dword
fmul st0
fadd
ret 24
;==============================================================================
;DistISq:
;取得三维向量模平方。参数是浮点数。
;------------------------------------------------------------------------------
DistFSq: ;REAL WINAPI DistFSq(float x1,float y1,float z1)
fld dword
fmul st0
fld dword
fmul st0
fadd
fld dword
fmul st0
fadd
ret 24
;==============================================================================
;DistFSq2P:
;取得三维空间中两点的距离。参数是浮点数。
;------------------------------------------------------------------------------
DistFSq2P: ;REAL WINAPI DistFSq2P(float x1,float y1,float z1,float x2,float y2,float z2)
fld dword
fsub dword
fmul st0
fld dword
fsub dword
fmul st0
fadd
fld dword
fsub dword
fmul st0
fadd
ret 24
;==============================================================================
;DitherMatrix:
;从抖动矩阵中取得值
;------------------------------------------------------------------------------
DitherMatrix: ;DWORD WINAPI DitherMatrix(DWORD x,DWORD y)
mov dl,
and dl,0xF
movzx eax,byte
and al,0xF
shl al,4
or al,dl
movzx eax,byte
ret 8
segment .data
_LightMatrix:
db0x00,0xEB,0x3B,0xDB,0x0F,0xE7,0x37,0xD7, 0x02,0xE8,0x38,0xD9,0x0C,0xE5,0x34,0xD5
db0x80,0x40,0xBB,0x7B,0x8F,0x4F,0xB7,0x77, 0x82,0x42,0xB8,0x78,0x8C,0x4C,0xB4,0x74
db0x21,0xC0,0x10,0xFB,0x2F,0xCF,0x1F,0xF7, 0x22,0xC2,0x12,0xF8,0x2C,0xCC,0x1C,0xF4
db0xA1,0x61,0x90,0x50,0xAF,0x6F,0x9F,0x5F, 0xA2,0x62,0x92,0x52,0xAC,0x6C,0x9C,0x5C
db0x08,0xE1,0x30,0xD0,0x05,0xEF,0x3F,0xDF, 0x0A,0xE2,0x32,0xD2,0x06,0xEC,0x3C,0xDC
db0x88,0x48,0xB0,0x70,0x85,0x45,0xBF,0x7F, 0x8A,0x4A,0xB2,0x72,0x86,0x46,0xBC,0x7C
db0x29,0xC8,0x18,0xF0,0x24,0xC5,0x14,0xFF, 0x2A,0xCA,0x1A,0xF2,0x26,0xC6,0x16,0xFC
db0xA9,0x69,0x98,0x58,0xA4,0x64,0x94,0x54, 0xAA,0x6A,0x9A,0x5A,0xA6,0x66,0x96,0x56
db0x03,0xE9,0x39,0xD8,0x0D,0xE4,0x35,0xD4, 0x01,0xEA,0x3A,0xDA,0x0E,0xE6,0x36,0xD6
db0x83,0x43,0xB9,0x79,0x8D,0x4D,0xB5,0x75, 0x81,0x41,0xBA,0x7A,0x8E,0x4E,0xB6,0x76
db0x23,0xC3,0x13,0xF9,0x2D,0xCD,0x1D,0xF5, 0x20,0xC1,0x11,0xFA,0x2E,0xCE,0x1E,0xF6
db0xA3,0x63,0x93,0x53,0xAD,0x6D,0x9D,0x5D, 0xA0,0x60,0x91,0x51,0xAE,0x6E,0x9E,0x5E
db0x0B,0xE3,0x33,0xD3,0x07,0xED,0x3D,0xDD, 0x09,0xE0,0x31,0xD1,0x04,0xEE,0x3E,0xDE
db0x8B,0x4B,0xB3,0x73,0x87,0x47,0xBD,0x7D, 0x89,0x49,0xB1,0x71,0x84,0x44,0xBE,0x7E
db0x2B,0xCB,0x1B,0xF3,0x27,0xC7,0x17,0xFD, 0x28,0xC9,0x19,0xF1,0x25,0xC4,0x15,0xFE
db0xAB,0x6B,0x9B,0x5B,0xA7,0x67,0x97,0x57, 0xA8,0x68,0x99,0x59,0xA5,0x65,0x95,0x55Dither.def:LIBRARY
EXPORTS
DistISq
DistISq2P
DistFSq
DistFSq2P
DitherMatrix
Dither看起来好像是很屌的代码。没错,可以拿去做好莱坞特效了。
SRC:
BIN:
页:
[1]