blog

枪手亨利

博客园 首页 新随笔 联系 订阅 管理

因为前段时间跟CG方面打了不少交道,所以产生了今天的问题.

对于视频的合成,我们可能都需要用到很多地方的素材,来源于各个地方,包括电视台,大部分素材都有一个共同点,都加了水印或台标.可以想像,在制作我们自己的作品时,肯定不能出现别人的标志,所以我们得去除原来的水印(注:在不侵犯别人的权利的前提下).今天我们只讨论对简单水印的处理.

先看一张加了水印的图:

<img src=http://www.bezier.com.cn/study/1.jpg>

 

其实我们可以看出,这个最终的图(C)其实是用另一张标志图(B)与原图(A)叠加而得到(叠加的方式这里就不作讨论,有兴趣的可以去参看参考书),叠加时赋予了一定的透明度(Tran).

这时,我们可以大概的形成一个公式:

A+ B*Tran=C

但是按此公式的话,原图像没有任何修改,标志图的象素值全部叠加原图像上,最张图像应该变亮,而事实上却没有,那肯定原图像在叠加过程中也有了一定的衰减过程(Atten)

:

A*Atten + B*Tran=C

推测标志图增加了多少值,原图像应该减少多少,即Atten=1-Tran.

经测试确实是如此(测试过程省略)

A*(1-Tran) + B*Tran=C

由此,我们如果想把加过水印的图像恢复到原样,只需要:

A=(C-B*Tran)/(1-Tran).

公式已经出来了,下面我们就开时做了。

这时候我们引入一个常用且普通的图像文件类型:TGA

这种文件格式简单,它由头文件、数据文件、附加文件构成。

TGA头文件结构

struct TargaHeader

{

BYTE IDLength;

BYTE ColormapType;

BYTE ImageType;//如果为02则表示未压缩,(A0)表示压缩

BYTE ColormapSpecification[5];

WORD XOrigin;

WORD YOrigin;

WORD ImageWidth;//图像宽度

WORD ImageHeight;//图像高度

BYTE PixelDepth;//图像色彩位数

BYTE ImageDescriptor;//应该是表示图像反正的,08表示反,其他表示正(或者反着来)

} tga;

//总共18个字节

我们进行处理时,只要先跳过前18个字节,直接对其数据部分进行处理。数据部分是按BGRA来排列,即蓝色、绿色、红色、Alpha通道值来分布。所以我们要处理的数据部分的大小为ImageWidth* ImageHeight*4。之所以用这种文件格式,因为其格式简单,同时,这种文件包含了图像的Alpha通道信息,有了这层Alpha值信息,我们可很容易的把图像中所需要的部分提取出来,这里就不多讲了,有兴趣的朋友可以跟我联系。

现在我们来读原图像文件(代码中,padfile,tran都是另外定义):

int RemoveMask(char *filename)

{

//这里读入加了水印的图像

FILE *fp=fopen(filename, "rb");

    fseek(fp, 0, SEEK_END);

    int len=ftell(fp);

    unsigned char *tgadata;

    tgadata=new unsigned char[len+1];

    tgadata[len]=0;

    fseek(fp, 0, SEEK_SET);

    fread(tgadata, len, 1, fp);

    fclose(fp);        

    if(!((tgadata[16]==24 || tgadata[16]==32) && (tgadata[2]==2 || tgadata[2]==10)))//判断图像色彩位数和压缩属性是否正确

        return 0;

    int sx=*((unsigned short *)&tgadata[12]);//获得图像x大小

    int sy=*((unsigned short *)&tgadata[14]);// 获得图像y大小

///这里读入单纯的水印图像文件。这里不免有人问,这个文件哪来呢?本例子中因为是我自己做的,所以有原始的标志文件,但用别人的加了水印的文件时,哪来的这个文件呢?我这里只可以说的是,可以用Photoshop做一个,当然怎么做这些问题我就不提了。

FILE *fp2=fopen(psdfile, "rb");

    fseek(fp2, 0, SEEK_END);

    int len2=ftell(fp2);

    unsigned char *psddata;

    psddata=new unsigned char[len2+1];

    psddata[len2]=0;

    fseek(fp2, 0, SEEK_SET);

    fread(psddata, len2, 1, fp2);

    fclose(fp2);   

    if(!((psddata[16]==24 || psddata[16]==32) && (psddata[2]==2 || psddata[2]==10)))

        return 0;

    //////////////去除标志运算//////////////////////////////

    int pixel=1;

    int allpixel=sx*sy;

    for(int j=18;j<allpixel*4+18;j+=4)//跳过头文件进行检测,每四个象素值为一个单元

    {

       

        if(psddata[j+3]!=0)//此值为通道值,如果通道值为0,表示该单元的色彩信息是不显示的,这里就涉及到了刚才所说的Alpha值的应用

        {

                    pixel=(int)((tgadata[j]-psddata[j]*tran*psddata[j+3]/255)/(1-tran*psddata[j+3]/255));//这里就为刚才的公式的应用,对原象素的值进行还原,依次对BGA各值进行还原,此处为蓝色值

            if(pixel>255)

                tgadata[j]=255;

            else if (pixel<0) tgadata[j]=0;

            else

                tgadata[j]=(unsigned char)pixel;

            /////////GGGG////////

            pixel=(int)((tgadata[j+1]-psddata[j+1]*tran*psddata[j+3]/255)/(1-tran*psddata[j+3]/255));// 此处为绿色值

            if(pixel>255)

                tgadata[j+1]=255;

            else if (pixel<0) tgadata[j+1]=0;

            else

                tgadata[j+1]=(unsigned char)pixel;

       

            pixel=(int)((tgadata[j+2]-psddata[j+2]*tran*psddata[j+3]/255)/(1-tran*psddata[j+3]/255)); //此处为红色值

            if(pixel>255)

                tgadata[j+2]=255;

            else if (pixel<0) tgadata[j+2]=0;

            else

                tgadata[j+2]=(unsigned char)pixel;

        }

    }

    //////////////////保存为文件////////////////////////////////

    if ((fp=fopen(filename,"wb"))!=0)

    {

        fwrite(tgadata,1,len,fp);//每个值已经进行了还原,写入覆盖原文件

    }

    fclose(fp);

    delete []tgadata;

    delete []psddata;

    return 1;

}

<img src=http://www.bezier.com.cn/study/2.jpg>

值得说明的是,此法只针对用图像进行叠加所产生的水印,如用Photoshop或后期软件进行轨道的合成,比如Adobe Premiere, Sony Vegas等。在对视频文件时,我们可以用这些软件把其导出成TGA序列,然后对每帧序列文件进行处理,最后再合成,就形成了原始的视频文件了。

同时,由公式可以看出,当水印是不用透明度,完全叠加时,就失去原图的信息,此法就不合适了.同时,水印透明度的指定也是先依照估计,然后逐渐取最近值的做法

警告:此法只供学习交流使用,禁止用于非法途径,尊重知识产权!

有兴趣的朋友可以跟我继续交流。大家也可以尝试采用BMP,JPG文件结构。

posted on 2005-12-21 19:28  henry  阅读(510)  评论(0)    收藏  举报