中文名称:游程长度编码
英文名称:run-length coding;RLC
定义:为减少传真信号的冗余度,而对连续的相同光密度像素的扫描游程长度(以像素数来表示)进行编码的方法。
游程长度编码(run-length code) 游程长度编码是栅格数据压缩的重要编码方法,它的基本思路是:对于一幅栅格图像,常常有行(或列)方向上相邻的若干点具有相同的属性代码,因而可采取某种方法压缩那些重复的记录内容。其编码方案是,只在各行(或列)数据的代码发生变化时依次记录该代码以及相同代码重复的个数,从而实现数据的压缩。 例如对图1所示的栅格数据,可沿行方向进行如下游程长度编码: (9,4),(0,4),(9,3),(0,5),(0,1)(9,2),(0,1),(7,2),(0,2),(0,4),(7,2),(0,2),(0,4),(7,4),(0,4),(7,4) ,(0,4),(7,4) ,(0,4),(7,4) 游程长度编码对图3-6(a)只用了40个整数就可以表示,而如果用前述的直接编码却需要64个整数表示,可见游程长度编码压缩数据是十分有效又简便的。事实上,压缩比的大小是与图的复杂程度成反比的,在变化多的部分,游程数就多,变化少的部分游程数就少,图件越简单,压缩效率就越高。 游程长度编码在栅格加密时,数据量没有明显增加,压缩效率较高,且易于检索,叠加合并等操作,运算简单,适用于机器存贮容量小,数据需大量压缩,而又要避免复杂的编码解码运算增加处理和操作时间的情况。 [font id="zoom" class="zoom"]游程长度RL (Run—Length),简称游程或游长,指的是由字符(或信号取样值)构成的数据流中各个字符重复出现而形成的字符的长度.如果给出了形成申的字符,申的长度及申的位置,就能恢复出原来的数据流,游程长度编码(RLC)就是用二进制码字给出这些信息的一类方法。游程长度编码的主要思想是将一个相同值的连续申用其值和申长(重复的个数)的数对二元组来替代.例如,在图像编码中,可以定义沿特定方向上具有相同灰度值的相邻像素为一轮,其延续的长度称之为延续的行程,即游程.游程终点位置由前一游程终点的相对距离确定,这样就可以由灰度游程串来表示图像数据.例如,若沿水平方向有一申M 个像素具有相同的灰度N,则按游程长度编码后,只传递两个值(N,M )就可以代替这M个像素的M个灰度值N。简单来说,游程长度编码的主要任务是统计连续相同字符的个数,解码时要根据字符及连续相同字符的个数,恢复原来的数据.在多媒体信息量激增、网络特性和速度都飞速提高的今天,游程长度编码是一种十分简单的压缩方法,编码/解码的速度也非常快,可广泛应用于多媒体信息的存储,传输。
package com.folkSeal.test;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import com.folkSeal.data.Pub;
import com.folkSeal.util.FileOperate;
public class Test {
public static final String seal_front_color = "000000";//印章前景,黑色
public static final String seal_back_color = "FFFFFF";//印章北景,白色
public static final String seal_coding_color = "00FF00";//印章编码,绿色
public static final String seal_front_feature_color = "0000FF";//前景中的辅助识别特征,蓝色
public static final String seal_back_feature_color = "FFFF00";//背景中的辅助识别特征,黄色
public static void main(String[] args) {
//Test.test();
Test test = new Test();
String [][] arrImagePixel2 = test.getImagePixelByRunLengthCoding("", 80, 80);
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
System.out.println(arrImagePixel2[i][j]);
}
}
}
public static void test() {
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("");
List objArrList = new ArrayList();
try {
conn = Pub.getConn();
stat = conn.createStatement();
String sql = "select * from user_tab_comments";
System.out.println("sql=="+sql);
rs = stat.executeQuery(sql);
int i = 0;
while (rs.next()) {
i ++;
String table_name = rs.getString("TABLE_NAME");
String comments = rs.getString("COMMENTS");
Object[] objArr = new Object[3];
objArr[0] = i;
objArr[1] = table_name;
objArr[2] = comments;
objArrList.add(objArr);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
Pub.close(conn, stat, rs);
}
for (int i = 0; i < objArrList.size(); i++) {
Object[] objArr = objArrList.get(i);
String table_name = objArr[1].toString();
String comments = objArr[2].toString();
stringBuffer.append("").append("").append(objArr[0].toString()).append("、").append(comments).append(" ").append(table_name).append(" ").append(" ").append("\n");
stringBuffer.append("");
stringBuffer.append("");
stringBuffer.append("").append("英文名").append(" ");
stringBuffer.append("").append("中文名").append(" ");
stringBuffer.append("").append("类型").append(" ");
stringBuffer.append("").append("长度").append(" ");
stringBuffer.append("").append("是否为空").append(" ");
stringBuffer.append("").append("主键/外键").append(" ");
stringBuffer.append(" ");
try {
conn = Pub.getConn();
stat = conn.createStatement();
String sql = "SELECT USER_TAB_COLS.COLUMN_NAME , USER_TAB_COLS.DATA_TYPE, USER_TAB_COLS.DATA_LENGTH,user_tab_cols.DATA_PRECISION,user_tab_cols.DATA_SCALE, USER_TAB_COLS.NULLABLE,user_col_comments.comments FROM USER_TAB_COLS inner join user_col_comments on user_col_comments.TABLE_NAME=USER_TAB_COLS.TABLE_NAME and user_col_comments.COLUMN_NAME=USER_TAB_COLS.COLUMN_NAME and user_col_comments.table_name='"+table_name+"' order by user_tab_cols.COLUMN_ID";
System.out.println("sql=="+sql);
rs = stat.executeQuery(sql);
boolean b = true;
while (rs.next()) {
String column_name = rs.getString("column_name");
String data_type = rs.getString("DATA_TYPE");
int data_length = rs.getInt("DATA_LENGTH");
int data_percision = rs.getInt("DATA_PRECISION");
int data_scale = rs.getInt("DATA_SCALE");
String nullable = rs.getString("NULLABLE");
String ccomments = rs.getString("COMMENTS");
String temp_data_length;
if ("NUMBER".equals(data_type)) {
if (data_scale == 0) {
temp_data_length = data_percision+"";
}else {
temp_data_length = data_percision+","+data_scale;
}
}else {
temp_data_length = data_length+ "";
}
String pk ="";
if (b) {
pk = "PK";
b = false;
}
stringBuffer.append("");
stringBuffer.append("").append(column_name).append(" ");
stringBuffer.append("").append(ccomments).append(" ");
stringBuffer.append("").append(data_type).append(" ");
stringBuffer.append("").append(temp_data_length).append(" ");
stringBuffer.append("").append(nullable).append(" ");
stringBuffer.append("").append(pk).append(" ");
stringBuffer.append(" ");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
Pub.close(conn, stat, rs);
}
stringBuffer.append("
");
stringBuffer.append(" ");
}
stringBuffer.append("");
FileOperate fo = new FileOperate();
fo.createFile("D:\\My Documents\\桌面", "写中文文字.htm");
fo.writeFile("D:\\My Documents\\桌面\\写中文文字.htm", stringBuffer.toString());
System.out.println(stringBuffer.toString());
}
/**
* 获得图片的像素RGB值List
* @param imageFilePath
* @return
*/
public List> getImagePixelRgbList(String imageFilePath){
List> list = new ArrayList>();
try {
BufferedImage img = ImageIO.read(new File(imageFilePath));
int tileHeight = img.getTileHeight();
int tileWidth = img.getTileWidth();
for (int y = 0; y < tileHeight; y++) {
List listX = new ArrayList();
for (int x = 0; x < tileWidth; x++) {
listX.add(Integer.toHexString(img.getRGB(x, y)).substring(2));
}
list.add(listX);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 获得图片的像素RGB值替换后的List
* @param imageFilePath
* @return
*/
public List> getImagePixelReplaceRgbToIntList(String imageFilePath){
List> list = new ArrayList>();
try {
BufferedImage img = ImageIO.read(new File(imageFilePath));
int tileHeight = img.getTileHeight();
int tileWidth = img.getTileWidth();
for (int y = 0; y < tileHeight; y++) {
List listX = new ArrayList();
for (int x = 0; x < tileWidth; x++) {
String rgbHex = Integer.toHexString(img.getRGB(x, y)).substring(2);
int intTemp = getImagePixelReplaceRgbToInt(rgbHex);
listX.add(intTemp);
}
list.add(listX);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 获得像素颜色替换值
* @param rgbHex
* @return
*/
public int getImagePixelReplaceRgbToInt(String rgbHex) {
int rgb = 0;
if (rgbHex.equalsIgnoreCase(seal_front_color)) {
rgb = 0;
}else if(rgbHex.equalsIgnoreCase(seal_back_color)) {
rgb = 1;
}else if(rgbHex.equalsIgnoreCase(seal_coding_color)) {
rgb = 2;
}else if(rgbHex.equalsIgnoreCase(seal_front_feature_color)) {
rgb = 3;
}else if(rgbHex.equalsIgnoreCase(seal_back_feature_color)) {
rgb = 4;
}else {
//rgb = 5;
}
return rgb;
}
/**
* 获得像素颜色
* @param rgbHex
* @return
*/
public String getImagePixelColorByInt(int i) {
String rgbStr = "";
switch (i) {
case 0:
rgbStr = seal_front_color;
break;
case 1:
rgbStr = seal_back_color;
break;
case 2:
rgbStr = seal_coding_color;
break;
case 3:
rgbStr = seal_front_feature_color;
break;
case 4:
rgbStr = seal_back_feature_color;
break;
default:
break;
}
return rgbStr;
}
/**
* 获得二维游程编码
* @param list
*/
public String getRunLengthCoding(List> list) {
String str = "";
try {
String arrStr = "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < list.size(); i++) {
List intList = list.get(i);
int intTemp = -1;
int countTemp = -1;
for (int j = 0; j < intList.size(); j++) {
if (j == 0) {
countTemp = 1;
intTemp = intList.get(j);
}else if (j == intList.size()-1) {
if (intTemp == intList.get(j)) {
countTemp = countTemp + 1;
arrStr = getArrStr(intTemp, countTemp);
sb.append(arrStr);
intTemp = -1;
countTemp = -1;
}else {
arrStr = getArrStr(intTemp, countTemp);
sb.append(arrStr);
intTemp = intList.get(j);
countTemp = 1;
arrStr = getArrStr(intTemp, countTemp);
sb.append(arrStr);
intTemp = -1;
countTemp = -1;
}
}else {
if (intTemp == intList.get(j)) {
countTemp = countTemp + 1;
}else {
arrStr = getArrStr(intTemp, countTemp);
sb.append(arrStr);
countTemp = 1;
intTemp = intList.get(j);
}
}
}
}
str = sb.toString().substring(0,sb.toString().length()-1);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
/**
* 获得二维游程编码的单个数组
* @param intTemp
* @param countTemp
* @return
*/
public String getArrStr(int intTemp,int countTemp) {
String str = +intTemp+","+countTemp+";";
return str;
}
/**
* 根据图片像素的宽度、高度、二维游标编码获得相片的像素颜色值数组
* @param rlcStr
* @param tileWidth
* @param tileHeight
* @return
*/
public String [][] getImagePixelByRunLengthCoding(String rlcStr,int tileWidth,int tileHeight) {
rlcStr = "1,7;0,37;1,9;0,18;1,9;1,7;0,37;1,3;0,1;1,5;0,19;1,8;1,7;0,37;1,2;0,3;1,4;0,20;1,7;1,5;0,67;1,8;1,3;0,70;1,7;1,2;0,60;4,1;0,10;1,7;1,2;0,71;1,7;1,1;0,72;1,7;1,1;0,60;4,1;0,11;1,7;0,15;2,2;0,55;1,8;0,15;2,3;0,54;1,8;0,13;2,5;0,54;1,8;0,12;2,8;0,52;1,8;0,13;2,7;0,52;1,8;1,1;0,13;2,4;0,54;1,8;1,1;0,14;2,2;0,55;1,8;1,1;0,70;1,9;1,2;0,69;1,9;1,3;0,67;1,10;1,4;0,67;1,9;1,5;0,67;1,8;1,6;0,53;4,1;0,11;1,9;1,6;0,64;1,10;1,6;0,20;1,2;0,41;1,11;1,6;0,20;1,2;0,31;4,1;0,9;1,11;1,6;0,20;1,2;0,20;1,1;0,20;1,11;1,5;0,21;1,2;0,20;1,1;0,20;1,11;1,2;0,46;1,1;0,20;1,11;1,1;0,68;1,11;0,69;1,11;0,70;1,10;0,70;1,10;0,71;1,9;0,71;1,9;0,38;3,1;0,33;1,8;0,37;3,3;0,33;1,7;0,36;3,5;0,32;1,7;0,33;3,1;0,2;3,6;0,31;1,7;0,36;3,5;0,32;1,7;0,37;3,4;0,32;1,7;0,38;3,2;0,19;4,1;0,12;1,8;0,38;3,1;0,33;1,8;0,72;1,8;0,71;1,9;1,1;0,69;1,10;1,2;0,67;1,11;1,5;0,64;1,11;1,6;0,53;4,1;0,9;1,11;1,6;0,20;1,3;0,40;1,11;1,6;0,20;1,3;0,40;1,11;1,6;0,20;1,3;0,41;1,10;1,6;0,20;1,3;0,42;1,9;1,6;0,66;1,8;1,6;0,53;4,1;0,13;1,7;1,5;0,68;1,7;1,4;0,69;1,7;1,3;0,70;1,7;1,3;0,70;1,7;1,2;0,71;1,7;1,1;0,58;4,1;0,13;1,7;1,1;0,57;4,3;0,12;1,7;1,1;0,55;4,6;0,11;1,7;1,1;0,55;4,7;0,10;1,7;1,1;0,56;4,5;0,11;1,7;1,2;0,56;4,3;0,12;1,7;1,2;0,57;4,1;0,12;1,8;1,2;0,57;4,1;0,12;1,8;1,3;0,68;1,9;1,4;0,67;1,9;1,5;0,65;1,10;1,6;0,63;1,11;1,6;0,63;1,11;1,6;0,20;1,3;0,40;1,11;1,6;0,20;1,3;0,40;1,11;1,6;0,20;1,4;0,18;1,1;0,20;1,11;1,6;0,20;1,4;0,18;1,2;0,19;1,11;1,7;0,19;1,5;0,16;1,3;0,18;1,12;1,7;0,18;1,6;0,16;1,3;0,18;1,12;1,7;0,18;1,7;0,14;1,5;0,16;1,13;1,8;0,16;1,10;0,10;1,7;0,16;1,13";
String [] arrRunLengthCoding = rlcStr.split(";");
String [][] arrImagePixel2 = new String[tileWidth][tileHeight];
int xTemp = 0;
int yTemp = 0;
for (int i = 0; i < arrRunLengthCoding.length; i++) {
if (xTemp == tileWidth) {
xTemp = 0;
yTemp = yTemp + 1;
}
String arrTemp[] = arrRunLengthCoding[i].split(",");
int a1 = Integer.valueOf(arrTemp[0]);
int a2 = Integer.valueOf(arrTemp[1]);
String color = getImagePixelColorByInt(a1);
for (int j = 0; j < a2; j++) {
arrImagePixel2[yTemp][xTemp + j] = color;
System.out.println("["+yTemp+","+(xTemp + j)+"]=="+color);
}
xTemp = xTemp + a2;
}
return arrImagePixel2;
}
}