精华内容
下载资源
问答
  • VBA列数字与字母互换

    千次阅读 2018-01-31 12:33:24
    vba列数字与字母互换: 方案一:速度:快 Function NumToStr(ByVal Num As Long) As String '数字转字母  Dim M As Long  If Num  Do  M = Num Mod 26  If M = 0 Then M = 26  NumToStr
    <内容来至Excelhome>


    vba列数字与字母互换:


    方案一:速度:快


    Function NumToStr(ByVal Num As Long) As String   '数字转字母
        Dim M As Long
        If Num < 1 Then Exit Function
        Do
            M = Num Mod 26
            If M = 0 Then M = 26
            NumToStr = Chr(64 + M) & NumToStr
            Num = (Num - M) / 26
        Loop Until Num <= 0
    End Function




    Function StrToNum(ByVal Str As String) As Long '字母转数字
        Dim s As String, S1 As String
        If Str = "" Then Exit Function
        Str = UCase(Str)
        s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        For i = 1 To Len(Str)
            S1 = Mid(Str, i, 1)
            If InStr(s, S1) = 0 Then Crazy_Num = -1: Exit Function
            StrToNum = StrToNum + InStr(s, S1) * 26 ^ (Len(Str) - i)
        Next
    End Function
    方案二:迭代 速度:略快 


    Function colinf(t) '列标签字母⇔列序号数值 相互转换
        If t = "" Then colinf = "": Exit Function '如果引用単元格=空白 即返回空白退出
        If IsNumeric(t) Then '如果引用単元格=数值(列序号),計算返回列标签大写英文字母
            If t < 1 Then colinf = "": Exit Function '如果数是0或負数返回空白退出
            Do
                colinf = Chr((t - 1) Mod 26 + 65) & colinf '以26除数反複Mod求余得到1-26字母
                t = Int((t - 1) / 26) '求余后再用26除后Int取整……
            Loop Until t <= 0 '反複迭代计算直至数t已不能除26求余止
        Else '如果引用単元格=文本字符,計算返回序号数値
            t = UCase(t) '首先文本転換大写字母
            For i = 1 To Len(t) '遍各字符
                colinf = colinf + (Asc(Mid(t, i, 1)) - 64) * 26 ^ (Len(t) - i) '按26冪乗計算累計数
            Next
        End If
    End Function




    方案三:递归 速度:略快 


    Function getColStr$(n) '列序号数字→列标签字母
        Dim s$, t as long
        t = n
        Do
            s = Chr((t - 1) Mod 26 + 65) & s
            t = Int((t - 1) / 26)
        Loop Until t <= 0
        getColStr = s
    End Function


    方案四:


    Function getC_Str(n) '列序号数字→列标签字母


        getC_Str = Split(Cells(1, n).Address, "$")(1)


    End Function


    ------------------以下为测试3种方案全码-----------------
    Sub test()
        dqT = Timer
        M = 1000: n = 10000
        Dim strTmp


        For i = 1 To M
            For j = 1 To n
                strTmp = getC_Str(n)
            Next j
        Next i


        dqT1 = Timer
        For i = 1 To M
            For j = 1 To n
                strTmp = getColStr(j)
            Next j
        Next i
        dqT2 = Timer


        For i = 1 To M
            For j = 1 To n
                strTmp = NumToStr(n)
            Next j
        Next i


        MsgBox " getC_Str  用时:" & Format(Timer - dqT1, "0.0000") & vbLf & "getColStr 用时:" & Format(dqT2 - dqT1, "0.0000") & vbLf & "NumToStr用时:" & Format(Timer - dqT2, "0.0000")
    End Sub


    Function getColStr$(n) '列序号数字→列标签字母
         Dim s$, t as long
        t = n
        Do
            s = Chr((t - 1) Mod 26 + 65) & s
            t = Int((t - 1) / 26)
        Loop Until t <= 0
        getColStr = s
    End Function


    Function NumToStr(ByVal Num As Long) As String   '数字转字母
        Dim M As Long
        If Num < 1 Then Exit Function
        Do
            M = Num Mod 26
            If M = 0 Then M = 26
            NumToStr = Chr(64 + M) & NumToStr
            Num = (Num - M) / 26
        Loop Until Num <= 0
    End Function


    Function getC_Str(n) '列序号数字→列标签字母


        getC_Str = Split(Cells(1, n).Address, "$")(1)


    End Function
    展开全文
  • Java poi Excel xls数字转字母

    千次阅读 2016-12-02 16:24:42
    最近遇到导出的xls中 是动态生成的,且单元格中需要用到公式,而xls公式不是用数字列号而是用字母来表示的,这时需要把数字号转成该对应的字母。因为是按月导出 一个月最多31天,所以刚开始采用的办法是...

    最近遇到导出的xls中 列是动态生成的,且单元格中需要用到公式,而xls公式不是用数字列号而是用列字母来表示的,这时需要把数字的列号转成该列对应的字母。因为是按月导出 一个月最多31天,所以刚开始采用的办法是定义一个包含1到31列字母的数组。后来想想这样总不是个办法 万一列数更多 且是不确定的呢。于是研究了下 怎么把xls数字列号转成对应的字母。

    先来看xlsx中的字母规律。在xls中,1到26列是A~Z,从第27列开始 是2个以上的字母组合 AA AB ... AZ 然后到BA BB ... BZ 直到 ZA ZB ... ZZ 这时两个字母的组合完了 接下来到3个字母 AAA AAB ... AAZ 然后到ABA ABB ... ABZ 一直到AZZ 然后是BAA BAB ... BZZ最后到ZAA ... ZZZ,接下来又是4个字母的组合如此循环...  。

    于是发现了规律: AA~AZ是在A~Z前面加了A,BA~BZ是在A~Z前面加了B,... ZA~ZZ是在A~Z前面加了Z,这时两个字母组合完毕;到3个字母 AAA~AAZ是在AA~AZ前面加了A,ABA~ABZ是在BA~BZ前面加了A,... AZA~AZZ是在ZA~ZZ前面加了A,这时AA~ZZ遍历完了一次(这里的AA~ZZ是前面两个字母组合里出现过的);接下来到下一轮遍历 在前面加B,BAA~BAZ是在AA~AZ前面加了B,... BZA~BZZ是在ZA~ZZ前面加了B,这时AA~ZZ又遍历完了一次;再进行下一轮遍历 一直到在所有两个字母的组合前都加过A~Z,这时3个字母的组合就全部组合完毕了。接下来到4个字母的组合 跟前面的2个、3个字母的组合类似,都是在上一个组合的基础上分别在前面加上A~Z。如下图


    字母组合是从第27列开始,每次的组合都是在上一个组合的基础上分别在前面加上A~Z。比如计算n=3个字母的组合AAA~ZZZ(上图红色竖线箭头部分):2个字母组合所在的范围是AA~ZZ(上图红色的“currentLen”部分),当前数组的位置(比如AAB)i与currentLen进行取余运算(i%currentLen)得到的结果就是要与2个字母组合的哪个种组合进行字符串拼接(该值还要与“lastLen”(上图红色lastLen)相加才能定位到该位置对应的字母),比如当前是第一轮遍历 则是A与AB进行拼接成AAB,这也就是上面举例的当前数组位置对应的字母(AAB)。假设我们用变量letterIdx表示第几轮,每上个组合遍历完一次letterIdx都要+1,表示下一个要拼接在前面的字母。因为拼接在前面的字母是A~Z 所以每次取该轮字母时都要跟26取余(letterIdx%26),当letterIdx%26=0时 说明A~Z都与上个组合拼接过了 也就是当前n个字母组合所有情况都组合过了,再进行下一轮n+1个(4个)字母的组合(上图黑色竖线箭头部分),这时currentLen变成了上一个组合的长度(上图黑色的currentLen),而lastLen变成了“上个组合的currentLen+lastLen”(上图黑色的lastLen部分),接下来的循环遍历跟上个组合一样进行。

    上代码:(代码里的注释请结合上文来看,注释里说到的“组合的情形”是指该组合的某一种组合,如BK、AH、XI都是2个字母组合的一种情形。因为实在也不知道应该用哪个词来表达)

    public final class Columns {
    
    	private Columns() {}
    
    	private static String[] sources = new String[]{
    		"A","B","C","D","E","F","G","H",
    		"I","J","K","L","M","N","O","P",
    		"Q","R","S","T","U","V","W","X","Y","Z"
    	};
    
    	/**
    	 * (256 for *.xls, 16384 for *.xlsx)
    	 * @param columnNum 列的个数,至少要为1
    	 * @throws IllegalArgumentException 如果 columnNum 超出该范围 [1,16384]
    	 * @return 返回[1,columnNum]共columnNum个对应xls列字母的数组
    	 */
    	public static String[] getColumnLabels(int columnNum) {
    		if(columnNum<1||columnNum>16384)
    			throw new IllegalArgumentException();
    		String[] columns = new String[columnNum];
    		if(columnNum<27){	//小于27列 不用组合
    			System.arraycopy(sources, 0, columns, 0, columnNum);
    			return columns;
    		}		
    		System.arraycopy(sources, 0, columns, 0, 26);	//前26列不需要进行组合
    
    		//因为基于数组是从0开始,每到新一轮letterIdx 会递增,所以第一轮 在递增前是-1
    		int letterIdx = -1;
    		int currentLen = 26;//第一轮组合(2个字母的组合)是分别与A-Z进行拼接 所以是26
    		int remainder;
    		int lastLen = 0;	//用于定位上文提到的i%currentLen实际在数组中的位置		
    		int totalLen = 26;	//totalLen=currentLen+lastLen
    		int currentLoopIdx = 0; //用来记录当前组合所有情形的个数
    
    		for(int i=26;i<columnNum;i++){ //第27列(对应数组的第26个位置)开始组合
    
    	//currentLen是上个组合所有情形的个数,与它取余找到要与上个组合的哪种情形进行拼接
    			remainder = currentLoopIdx%currentLen;
    
    			if(remainder==0){
    				letterIdx++; //完成一次上个组合的遍历,转到下个字母进行拼接
    				int j = letterIdx%26;
    
    			//A-Z 26个子母都与上个组合所有情形都进行过拼接了,需要进行下个组合的拼接
    				if(j==0&&letterIdx!=0){ 
    					lastLen = totalLen; //下个组合的lastLen是上个组合的totalLen
    
    				/**
    	 		     * 下个组合的currentLen是上个组合的所有组合情形的个数
    	 		     * (等于上个组合的currentLen*26),26也就是拼接在前面的A-Z的个数
    	 		     */			 
    					currentLen = 26*currentLen;
    
    					totalLen = currentLen+lastLen; //为下一轮的开始做准备
    					currentLoopIdx = 0; //到下一轮了 因此需要重置
    				}
    			}
    			/**
    	 	     * sources[letterIdx%26]是该轮要拼接在前面的字母
    	 	     * columns[remainder+lastLen]是上个组合被拼接的情形
    	 	     */		
    			columns[i] = sources[letterIdx%26]+columns[remainder+lastLen];
    			currentLoopIdx++;
    		}
    		return columns;
    	}
    }
    测试:
    public static void main(String[] args) {
    	String[] columns = getColumnLabels(37 );
    	System.out.println("1到37列:"+Arrays.toString(columns));
    	System.out.println();
    	long start = System.nanoTime();
    	columns = getColumnLabels(256);
    	System.out.println("创建"+columns.length+"列用时(纳秒):"
    					   +(System.nanoTime()-start));
    	System.out.println("xls第"+columns.length+"列:"
    					   +columns[columns.length-1]);
    	System.out.println();
    	start = System.nanoTime();
    	columns = getColumnLabels(16384);
    	System.out.println("创建"+columns.length+"列用时(纳秒):"
    					   +(System.nanoTime()-start));
    	System.out.println("xlsx第"+columns.length+"列:"
    					   +columns[columns.length-1]);
    }

    打印:
    1到37列:[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, 
    U, V, W, X, Y, Z, AA, AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK]
    
    创建256列用时(纳秒):192833
    xls第256列:IV
    
    创建16384列用时(纳秒):9574147
    xlsx第16384列:XFD

    ------------------------------------------------------分隔线-----------------------------------------------------------------

    后来有想到,如果是不需要(或者条件不允许)提前创建(这么大的)数组呢,这时需要通过列号直接获取该列对应的字母。于是又想 应该怎么转换。。。
    先看看从字母转数字的,比如BGQCV 转成数字(虽然xlsx最后一列是XFD,这里只讨论数字与字母的互转):该列标有5个字母,说明前面已经有4个字母、3、2、1个字母的全组合了 才会到5个字母的组合,于是W1=26^4+26^3+26^2+26^1,BGQCV 的第一个字母是B,说明前面有Axxxx的全组合了,于是有该组合数T1=1*(26^4)。再来看第二个字母是G,说明前面已经有BAxxx~BFxxx的全组合了,于是有该组合数T2=6*(26^3)。第三个字母是Q,说明前面已经有BGAxx~BGPxx的全组合了,于是有该组合数T3=16*(26^2)。第四个字母是C,说明前面已有BGQAx~BGQBx的全组合了,该组合数T4=2*(26^1)。最后一个字母是V,说明前缀是BGQC的组合BGQCA~BGQCV共有T5=22个。
    好了,BGQCV 所处的列数W=W1+T1+T2+T3+T4+T5=(26^4+26^3+26^2+26^1)+1*(26^4)+6*(26^3)+16*(26^2)+2*(26^1)+22 = 1048576。
    String[] sources = new String[]{"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
    数组sources作为我们解决问题的字母来源(当然也可以不定义数组而是用ASCII码)。
    现在知道了通过字母列标是如何求出其对应的第几列,我们把问题一般化:求第W列对应的列标。设第W列对应的字母有n个,根据上面的分析可知W1=26^(n-1)+26^(n-2)+26^(n-3)+...+26^2+26^1。我们规定A对应1,B对应2 ... Z对应26。设第1个字母对应数字是num_1,第二个字母对应的数字是num_2,...,第n个字母对应数字num_n。根据上面的分析 于是有T1=(num_1-1)*26^(n-1),T2=(num_2-1)*26^(n-2),...,Tn=(num_n-1)*26^0。
    整合起来,又因为26^0=1 于是有W=W1+T1+T2+...+Tn=(26^(n-1)+26^(n-2)+26^(n-3)+...+26^2+26^1)+(num_1-1)*26^(n-1)+(num_2-1)*26^(n-2)+...+(num_(n-1)-1)*26^1+(num_n-1)。
    除了最右边的字母(也就是第n个字母)对应的位置的数字num_n-1除外,其它字母对应的位置的数字均是26的倍数。于是  第一次W对26取余W%26的结果所对应的字母(还记得吗 我们用1代表A,2代表B,... ,26代表Z)就是最右边的字母。好了 现在已经求出了最右边的字母,还剩n-1个未知字母,采用同样的办法可求出次右边的字母:W-(num_n-1)然后再除以26,得到的结果再减去1(因为W1中存在26^1,其除以26后结果就是1,为了保证除了次右边字母对应的位置的数字外,其余各字母对应的位置的数字均是26的倍数),把结果赋回给W,这时求次右边的字母就跟求最右边的字母类似了:
    W-(num_n-1)=(26^(n-1)+26^(n-2)+26^(n-3)+...+26^2+26^1)+(num_1-1)*26^(n-1)+(num_2-1)*26^(n-2)+...+(num_(n-1)-1)*26^1
    然后两边除以26:(W-(num_n-1))/26=(26^(n-2)+26^(n-3)+26^(n-4)+...+26^1+1)+(num_1-1)*26^(n-2)+(num_2-1)*26^(n-3)+...+(num_(n-1)-1)
    然后两边再减去1:(W-(num_n-1))/26-1=(26^(n-2)+26^(n-3)+26^(n-4)+...+26^1)+(num_1-1)*26^(n-2)+(num_2-1)*26^(n-3)+...+(num_(n-1)-1)
    然后把左边的(W-(num_n-1))/26-1看成整体的W,是不是跟最开始求最右边字母的很类似?
    这样从右往左求出来的字符串 跟所要的结果恰好是相反的 所要需要反转。
    上代码:
    /**
     * 返回该列号对应的字母
     * @param columnNo (xls的)第几列(从1开始)
     */
    public static String getCorrespondingLabel(int columnNo){
    	if(columnNo<1/**||columnNo>16384**/)
    		throw new IllegalArgumentException();
    	String[] sources = new String[]{"A","B","C","D","E","F","G","H","I","J","K","L","M"
    		,"N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
    	StringBuilder sb = new StringBuilder(5);
    	int remainder = columnNo%26;	//求最右边的字母
    	if(remainder==0){	//说明(num_n-1)=26,第26个字母是Z
    		sb.append("Z");
    		remainder = 26;	//因为接下来W-(num_n-1)也就是columnNo-remainder,所以需要把remainder赋值回26
    	}
    	else{  //如果最右边字母不是Z的话,就去sources数组相应的位置取字母,remainder不用变
    	  sb.append(sources[remainder-1]);
    	}
    	columnNo = (columnNo-remainder)/26-1;	//用来判断接下来是否还有其他字母
    
    	//当 当前循环是求最后一个字母时(从右往左),(columnNo-remainder)/26就会是0,再减1也就是-1。
    	//因此通过判断(columnNo-remainder)/26-1是否大于-1来判断结束
    	while(columnNo>-1){
    		remainder = columnNo%26;
    		sb.append(sources[remainder]);
    		columnNo = (columnNo-remainder)/26-1;
    	}
    
    	return sb.reverse().toString();	//因为是从右往左解析的 所以需要反转
    }


    测试:
    public static void main(String[] args) {
    	String label = getCorrespondingLabel(37 );
    	System.out.println("第37列:"+label);
    	System.out.println();
    	long start = System.nanoTime();
    	label = getCorrespondingLabel(256);
    	System.out.println("查找第256列对应字母 用时(纳秒):"
    					   +(System.nanoTime()-start));
    	System.out.println("xls第256列:"+label);
    	System.out.println();
    	
    	label = getCorrespondingLabel(16384);
    	
    	System.out.println("xlsx第16384列:"+label);
    }
    打印:
    第37列:AK
    
    查找第256列对应字母 用时(纳秒):7776
    xls第256列:IV
    
    xlsx第16384列:XFD
    这时又想到,求n列列标 用方法1好一点呢 还是用方法2循环n次好呢。。。
    方法1求数组的 对于26+26*26=702列以下,可以将求组合部分抽出来,减少不必要的求余运算multiple%26,因为这时multiple不会超过26。方法2也可以改成从0开始的 毕竟poi列数是从0开始的。不预定义字母数组的话 也可以用ASCII码来转换。
    -----------------------------------------------分隔线-----------------------------------------------------

    最终代码:

    /**
     * 
     * Excel列号转字母工具类
     * 
     */
    public final class Columns {
    
    	private Columns() {
    	}
    
    	private static String[] sources = new String[] { "A", "B", "C", "D", "E",
    			"F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
    			"S", "T", "U", "V", "W", "X", "Y", "Z" };
    
    	/**
    	 * (256 for *.xls, 16384 for *.xlsx)
    	 * 
    	 * @param columnNum
    	 *            列的个数,从1开始
    	 * @throws IllegalArgumentException
    	 *             如果 columnNum 超出该范围 [1,16384]
    	 * @return 返回[1,columnNum]共columnNum个对应xls列字母的数组
    	 */
    	public static String[] getColumnLabels(int columnNum) {
    		if (columnNum < 1 || columnNum > 16384)
    			throw new IllegalArgumentException();
    		String[] columns = new String[columnNum];
    		if (columnNum < 27) {
    			System.arraycopy(sources, 0, columns, 0, columnNum);
    			return columns;
    		}
    		int multiple = -1;
    		int remainder;
    		System.arraycopy(sources, 0, columns, 0, 26);
    		int currentLoopIdx = 0;
    		if (columnNum < 703) {
    			for (int i = 26; i < columnNum; i++) {
    				remainder = currentLoopIdx % 26;
    				if (remainder == 0) {
    					multiple++;
    				}
    				columns[i] = sources[multiple] + columns[remainder];
    				currentLoopIdx++;
    			}
    		} else {
    			int currentLen = 26;
    			int totalLen = 26;
    			int lastLen = 0;
    			for (int i = 26; i < columnNum; i++) {
    				remainder = currentLoopIdx % currentLen;
    				if (remainder == 0) {
    					multiple++;
    					int j = multiple % 26;
    					if (j == 0 && multiple != 0) {
    						lastLen = totalLen;
    						currentLen = 26 * currentLen;
    						totalLen = currentLen + lastLen;
    						currentLoopIdx = 0;
    					}
    				}
    				columns[i] = sources[multiple % 26]
    						+ columns[remainder + lastLen];
    				currentLoopIdx++;
    			}
    		}
    
    		return columns;
    	}
    
    	/**
    	 * 返回该列号对应的字母
    	 * 
    	 * @param columnNo
    	 *            (xls的)第几列(从1开始)
    	 */
    	private static String getCorrespondingLabel(int columnNo) {
    		if (columnNo < 1/** ||columnNo>16384 **/
    		)
    			throw new IllegalArgumentException();
    
    		StringBuilder sb = new StringBuilder(5);
    		int remainder = columnNo % 26;
    		if (remainder == 0) {
    			sb.append("Z");
    			remainder = 26;
    		} else {
    			sb.append(sources[remainder - 1]);
    		}
    
    		while ((columnNo = (columnNo - remainder) / 26 - 1) > -1) {
    			remainder = columnNo % 26;
    			sb.append(sources[remainder]);
    		}
    
    		return sb.reverse().toString();
    	}
    
    	/**
    	 * 列号转字母
    	 * 
    	 * @param columnIndex
    	 *            poi里xls的列号(从0开始)
    	 * @throws IllegalArgumentException
    	 *             if columnIndex less than 0
    	 * @return 该列对应的字母
    	 */
    	public static String getIndexLabel(int columnIndex) {
    		return getCorrespondingLabel(columnIndex + 1);
    	}
    
    }
    展开全文
  • 什么是数字水印

    千次阅读 2020-08-05 22:47:09
    经常有文章把数字签名和数字水印“傻傻分不清”,那今天就介绍一下数字水印。 一、数字水印技术原理 数字水印是一种信息隐藏技术,它利用人体感官的限制,将数字信号,如图像、文字、符号、数字等一切可以作为标记、...

    经常有文章把数字签名和数字水印“傻傻分不清”,那今天就介绍一下数字水印。

    一、数字水印技术原理

    数字水印是一种信息隐藏技术,它利用人体感官的限制,将数字信号,如图像、文字、符号、数字等一切可以作为标记、标识的信息与原始数据(如图像、音频、视频数据)紧密结合并隐藏其中,并可以经历一些不破坏源数据价值的操作而能保存下来。

    一般地,数字水印应具有如下的基本特性:

    (1)可证明性:水印应能为受到版权保护的信息产品的归属提供完全和可靠的证据。

    (2)不可感知性:不可感知包含两方面的意思,一个指视觉上的不可感知性(对听觉也是同样的要求),即因嵌入水印导致图像的变化对观察者的视觉系统来讲应该是不可察觉的,最理想的情况是水印图像与原始图像在视觉上一模一样,这是绝大多数水印算法所应达到的要求;另一方面水印用统计方法也是不能恢复的,如对大量的用同样方法和水印处理过的信息产品即使用统计方法也无法提取水印或确定水印的存在。

    (3)鲁棒性:鲁棒性即健壮性,它对水印而言极为重要。一个鲁棒性强的数字水印应该能够承受大量的、不同的物理和几何失真,包括有意的(如恶意攻击)或无意的(如图像压缩、滤波、扫描与复印、噪声污染、尺寸变化等等)。但易碎水印技术恰恰与之相反,其鲁棒性很低,它所保护信息的微小变化都会引起水印被破坏。

    二、一种使用易碎水印保护图像的方法

    基于易碎水印的基本原理,我们可以使用它来保护图像,即当图像被更改后,哪怕是一个像素,都会破坏水印本身,从而达到验证保护的目的。

    其基本思想是修改原图像中的每一个像素点的值,使得修改后的图像经过某一种算法的运算可以得到一个新的二值图像或文本,即水印。基本步骤为:

    1. 首先设定一个映射函数f,通过此函数可以将原图像g的每一个像素值映射成一个二值L(0或1):

    在这里插入图片描述

    1. 设要嵌入的水印为W,W可以是一个二值图像,也可以是经过编码的字符串,这里面所使用水印为二值图像。根据以下公式修改原图像g的每一个像素值,使得修改后的g中每一个像素点的值通过f运算后都与W相同(要注意的是,修改幅度必须足够小,使肉眼观察不能察觉):
      在这里插入图片描述

    这样水印图像就被嵌入到原图像中了。

    1. 提取、验证水印。假设待提取水印的原图像为g,验证对照的水印图像为W。通过f函数算出g每个像素的对应二值W’,即为提出的水印。
      在这里插入图片描述

    将提取出的水印图像W’与W比较,就可以判断原图像g是否被更改过

    在这里插入图片描述

    下图就展示了水印保护的效果示意,原图像被修改后,对应的水印部分就会被破坏。
    在这里插入图片描述

    三、数字水印嵌入与提取

    根据易碎水印保护图像的基本原理,可以设计出以下使用流程。

    1.在原图像中的水印嵌入步骤

    1)首先选择一张8位二值BMP图片作为水印图像;

    2)从原图像的第一行第一列开始,逐个像素进行运算,

    3)将当前像素的红、绿、蓝 三原色值取出,分别为R、G、B;

    4)将R、G、B在映射表(Table)中所对应的映射结果(0或1)取出,并进行异或运算,得到运算结果P;

    5)取出水印图像对应位置像素的值,并除以255,得到结果W。因为水印为二值图像,像素值为0或255,故除以255后变成0和1方可做下面比较;

    6)若P=W,则跳回步骤2),进行下一像素的运算;

    7)若P<>W,在R、G、B中随机选中一个,修改其数值。如果数值大于175,数值减去1,如果数值等于或小于175,则数值加1;

    8)跳到步骤3)重新进行运算;

    9)原图像全部像素处理完毕,水印嵌入完成。

    2.在图像中提取水印嵌入步骤

    1)从图像的第一行第一列开始,逐个像素进行运算,

    2)将当前像素的红、绿、蓝 三原色值取出,分别为R’、G’、B’;

    3)将R’、G’、B’在映射表(Table)中所对应的映射结果(0或1)取出,并进行异或运算,得到运算结果P’;

    4)将P’值乘以255,得到结果W’。即为水印图案在此位置的像素值;

    5)跳回步骤2),进行下一像素的运算;

    7)最后得到水印图像。

    通过提取图像中的数字水印,并与原水印对比,可以检测图像是否被篡改过。正是因为数字水印也可以用来检测数据的完整性,所以出现了把数字签名称为数字水印的情况,通过上面的介绍就应该知道,数字签名和数字水印是完全不同的技术。

    四、强壮性数字水印的使用

    上面提出了用易碎水印保护图像完整性的方法。其实数字水印更多地被用于多媒体数据的版权保护。比如以前的画家用印章或签名标识作品的作者,那么今天的艺术家可以通过数字水印将自己的名字添加到作品中来完成著作权的标识。同样,影视音像公司也可以把公司的名字、标志等信息添加到出版的多媒体数字产品中。这样通过跟踪多媒体数据中的数字水印信息来保护多媒体数据的版权。这里的水印都是鲁棒性强的水印,也就是强壮性水印。因为只有采用强壮性的水印,才能保证无论盗版者怎么修改、压缩、转换数字作品,里面的数字水印信息都能尽量的保留下来,以作为版权拥有者追究盗版行为的有利证据和武器。

    除了在版权保护方面的应用,数字水印技术在文档(印刷品、电子文档等)的真伪认证上面也有很大的用途,将某些难以察觉的数字水印信息添加到文件中,大大增加了文件被伪造的难度。例如护照持有人的姓名在护照中被明显印刷出来,也可以在头像中将持有人姓名做为数字水印被隐藏起来,如果某人想通过更换头像来伪造一份护照,那么通过扫描护照就有可能检测出隐藏在头像中的水印信息与打印在护照上的姓名不符合,从而发现被伪造的护照。

    展开全文
  • 页脚行一般用于在一列数字的下方显示不断累加的总计。例如,您可以在零用金报销单表单模板上给位于一列零用金下方的页脚行添加“合计”文本框。要在列中添加值,您可以在页脚行中将 sum 函数与“合计”文本框关联。...

    在表单模板中插入重复表 (重复表:表单上的一个控件,该控件包含表格式的其他控件且在需要时可以重复。用户在填写表单时可以插入多个行。)时,Microsoft Office InfoPath 会自动在表的顶部添加标题行,以便您可以为表列键入标签。您可以选择在重复表的底部添加页脚行。页脚行一般用于在一列数字的下方显示不断累加的总计。例如,您可以在零用金报销单表单模板上给位于一列零用金下方的页脚行添加“合计”文本框。要在列中添加值,您可以在页脚行中将 sum 函数与“合计”文本框关联。

     


     

    步骤 1:给重复表添加页脚行

    步骤 2:给页脚行添加“合计”文本框

    步骤 3:在重复表中对一列数字求和

    步骤 1:给重复表添加页脚行

    1. 在表单模板上双击表下方的“重复表”标签。
    2. 单击“显示”选项卡。
    1. 在“选项”下,选中“包含页脚”复选框。

     提示   要在重复表的结尾处添加其他表页脚,请右键单击您插入的第一个页脚行中的某个空单元格,指向快捷菜单上的“插入”,然后单击“行(在上方)”或“行(在下方)”。

    返回页首 返回页首

    步骤 2:给页脚行添加“合计”文本框

    您在给重复表添加了页脚行之后,就可以给页脚行添加“合计”文本框了。

     注释   您要将“合计”文本框添加到页脚行,而不是数据行,因为表单用户可以添加数据行的多个实例,而您并不希望“合计”框在用户的表单上出现多次。

    1. 在页脚行中,单击您要添加“合计”框的列中的单元格。
    2. 在“插入”菜单中,单击“文本框”。

     提示   您可以使用格式文本框或表达式框,而不使用文本框。表达式框只显示数据,不存储数据。所以,只有在您不需要在另一计算中使用计算和时,或者在不需要将计算和保存为表单模板的一部分时,才应使用表达式框。

    1. 在页脚行中,在紧挨着您插入了文本框的单元格左边的单元格中单击。这里是您将要添加文本框标签的位置。
    2. 键入合计:,然后选定文本。
    3. 在“常用”工具栏上,单击“右对齐”按钮图像
    4. 双击您在步骤 2 中添加的文本框。
    5. 单击“数据”选项卡。
    1. 在“域名称”框中,键入标签,如 totalExpenses。
    2. 在“数据类型”列表中,将数据类型从“文本(string)”更改为“小数(double)”。这样您就可以显示带有小数位的数字了,如 ¥1234.12。
    3. 单击“格式”按钮。
    4. 在“十进制格式”对话框中的“格式”下,单击“货币”,然后选择需要使用的货币。

    返回页首 返回页首

    步骤 3:在重复表中对一列数字求和

    如果您使用重复表从用户那里收集数值型数据,可使用 sum 函数把用户在表中输入的数字加起来。用户在填写表单时,给表添加多少行或输入多少数字都是没有关系的。只要您使用 sum 函数,文本框中的计算值将会自行作出相应调整。

    公式存储在数据源 (数据源:为 InfoPath 表单定义和存储数据的字段和组的集合。表单中的控件绑定到数据源中的字段和组。)中的 (域:数据源中可包含数据的元素或属性。如果域为元素,则可包含属性域。域用于存储输入控件的数据。)中,并在绑定 (绑定:将控件连接到数据源中的字段或组,以便可以保存输入控件的数据。未绑定控件时,表明它未连接到字段或组,输入控件中的数据不会被保存。)到这些域的控件中显示。设计表单模板时,您可以通过使用文本框、格式文本框或表达式框来创建公式,用于对重复表中的一列数字求和。

    1. 在页脚行中,双击您在页脚行中插入的文本框。
    2. 单击“数据”选项卡。
    1. 在“默认值”下,单击“插入公式”按钮图像
    2. 在“插入公式”对话框中,单击“插入函数”。
    3. 在“类别”列表中,单击“数学”。
    4. 在“函数”列表中,单击“sum”,然后单击“确定”以返回“插入公式”对话框。

    此时,您应该会在“插入公式”对话框中看到以下公式。

     

    1. 在“公式”框中,双击括号中的文字。

    此时会出现“选择域或组”对话框。

    1. 在“数据源”列表中,单击要对其值求和的域。
    展开全文
  • 下面蜜姐就来给大家通俗的讲解一下什么是数字货币主流币? 数字货币主流币是什么意思? 主流币,如同字面意义所说,是受到币圈主流认可的数字货币。主流币的概念比较模糊,简单的说就是大多数人都知道这个币,而且认
  • 只记得该列数字下方有个小小的1,坚信一定有个快捷的方法,一开始以为是什么公式,而结果发现却不是的,经百度一下终于得到了答案,具体的操作步骤如下,高手请别见笑,直接上图。 1.如图,需要将年龄这一列的每个...
  • 利用Python,获取Excel某中(该中每个单元格既有中文又有数字)的数字!!!!先看一下原始数据,如下图:我们要处理后的目标数据,如下图:使用正则表达式来解决此问题 正则表达式是一种用来匹配字符串的强...
  • 使用map的方法就可以实现把某一的字符类型的值转换为数字。...首先定义一个字典,然后使用map方法就可以把某一的字符类型的值转换为数字。 以上就是对使用pandas把某一的字符值转换为数字的认识。 ...
  • 1.常用的linux文件权限:444 -r--r--r-- 600 -rw------- 644 -rw-r--r-- 666 -rw-rw-rw- ...注:使用ll命令查看文件/文件夹属性时候,一共有10,第一个小格表示是文件夹或者连接等等 d表示文件夹...
  • WPF的DataGrid中只能输入数字

    千次阅读 2018-09-26 20:42:50
    最近做一个WPF小程序,需要在DataGrid中的某限制用户只能输入数字。在网上找了找,看到一些解决方法,最后是stackoverflow上的一个页面上的方法觉得不错,特拿来与大家分享。 方法一:从DataGridTextColumn扩展一...
  • 图像理论知识_什么是数字图像处理?

    万次阅读 多人点赞 2018-04-21 16:54:26
    数字图像处理,即数字,将图像转化为数字的形式,对图像做处理,我们平时所见到的图像,在计算机中都是一组数字,当通过相机捕获现实世界的景物时,相机会捕获现实世界的光源信号,并转化为数字信号保存到存储器上,...
  • 1.常用的linux文件权限:444 -r--r--r-- 600 -rw------- 644 -rw-r--r-- ...注:使用ll命令查看文件/文件夹属性时候,一共有10,第一个小格表示是文件夹或者连接等等 d表示文件夹,l表示连接文件,-表示...
  • 在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*) 把一条线段分割为两部分,使较大部分与全长的比值等于较小部分与较大的比值,则这个比值即为黄金分割。其比值是...
  • ls -l 每一含义

    千次阅读 2018-11-04 22:22:06
    10个字符确定不同用户能对文件干什么 第一个字符代表文件(-)、目录(d),链接(l) 其余字符每3个一组(rwx),读(r)、写(w)、执行(x) 第一组rwx:文件所有者的权限是读、写和执行 ...
  • CGFT考试中Python语言的学员知识点众多,学员在学习的时候,一定要充分...确定性指程序能够正确且无歧义地解读数据所代表的类型含义。高效性指程序能够为数字运算提供较高的计算速度,同时具备较少的存储空间代价。...
  • 编写Java程序,在控制台中输入一个数字,要求定义方法实现找出能够整除该数字的所有数字。 实现思路: 定义方法findNums(),用于实现查找所有能够整除指定数字的所有数字。 根据需求说明要求,方法findNums()...
  • package org.westos_02_二维数组; import java.util.Scanner; ... * 需求:打印杨辉三角形(行数可以键盘录入) ...1)任何一行的第一和最后一都是1 2)从第三行开始,该数据等于上一行的前一
  • 问题:从键盘接受一个数字出该数字的中文表示格式,例如:键盘输入123,打印出一二三;键盘输入3103,打印出三一零三。 功能:传入一个参数,并且转换为对应的汉字数字显示 传入参数:int类型的值 处理方法...
  • [SQLObject官方文档] 类型定义

    千次阅读 2007-01-16 17:45:00
    ·Col类,定义列列的列表是Col对象的列表。这些对象本身并没有功能,用于定义列。dbName:数据库的列名,如果不指定你指定的Python名称将会从大小写混用的形式转换到小写加下划线的形式。default:的缺省值,在...
  • 在我们平常的开发中可能会遇到这样的问题,就是判断某一是否全部由数字组成,我们都知道oracle并没有给我们提供这样一个现成的函数,那么根据我的经验我总结了两个行之有效的方法(列名:column,表名:table):...
  • 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞, 求给定矩形阵列的细胞个数 分析 1.从文件中读入m*n矩阵阵列,将其转换为boolean矩阵存入bz数组中 2.沿bz...
  • Git Shell 颜色及数字含义

    千次阅读 2014-06-26 11:00:09
    在使用指令版控的過程中,經常有機會用到 Git Shell 這套優異的 Git 版控環境,一來他使用 Windows PowerShell 為核心,其訊息顯示與輸入都支援 Unicode,比較不會有中文字集轉換的問題;二來輸入命令或分支名稱的...
  • 作者|Reda Hmeid 译者|大愚若智 充分理解数字化,明确数字化...而充分理解数字化转型的具体定义,理解数字化这个概念本身,至少可以确定出正确的方向。 我刚刚采访完一位架构师。采访中我问了一个自己最喜欢的
  • 然后一看 AA = 26 这是什么东东? 00 这个是没有的。 思路不对 如果个位的A=0 B=1...Z=25 非个位的 A=1 B=2 ... Z=26 是否对呢? 验证一下  AA= 1 * 26+0=26 AAA = 1*26*26+1*26+0 = 702 AAAA...
  • 定义一个方法 private   void  TextBoxDec_KeyPress( object  sender, KeyPressEventArgs e) {   if  (e.KeyChar  !=   8   &&   ! Char.IsDigit(e.KeyChar)  &&  e.KeyChar  !=   ' . ' )  {...
  • 使用Microsoft.Jet.OLEDB.4.0读取数据会出现当某一字段内分别含有文本和数字的混合数据时,某一类型的数据会产生丢失。 产生这种问题的根源与Excel ISAM[3](Indexed Sequential Access Method,即索引顺序存取方法...
  • linux之chmod 777 或者644数字含义

    千次阅读 2017-05-05 22:10:36
    例如我用ls -l命令文件表时,得到如下输出: -rw-r--r-- 1 bu users 2254 2006-05-20 13:47 tt.htm 从第二个字符起rw-是说用户bu有读、写权,没有运行权,接着的r--表示用户组users只有读权限,没有运行权,最后...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 457,955
精华内容 183,182
关键字:

列数字的定义是什么