一个蛋疼的需求,蛋疼 的完成。。。Graphics2D 绘图,求改进!

客户要搞什么,通知公告,什么格式啊,分页啊,全都要用java绘图制作,超蛋疼。因为时间有点急,只是单纯实现他所说的去了,写的不好 :oops: ,求批斗,求提高,求意见,直接上代码啦。
package com.ztenc.oa.proj.util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.AttributedString;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.xml.crypto.Data;

import org.eclipse.emf.ecore.InternalEObject.EStore;
import org.jgroups.demos.Chat;

import com.sun.corba.se.spi.orb.StringPair;
import com.sun.corba.se.spi.orbutil.fsm.Guard.Result;

/**
* 文字写入图层背景工具类
*
* 内容过多自动分页
*
* 落款自动写入格式
*
* @author fule
*/
public class ImageWUtil {

// 常量字体大小
public final static int LARGESIZE = 100; // 大字体
public final static int NORMALSIZE = 50; // 普通字体
public final static int SMALLSIZE = 30; // 小字体
// 段间距
public final static int SECTSIZE = 80;
// 文字区边距
public final static int PADDING = 100;
public final static Color DEAUFT_COLOR = Color.WHITE;

// 连续书写时的记录位
int pointIndex;

// title书写之后的记录位
int pointOnTitle;

// 当前第几页
int indexPage = 1;

Map<Integer, String> map;

/**
* 设置当前书写的像素位子
*
* @return
*/
private int setPointIndex(int increment) {
pointIndex += increment;
return pointIndex;
}

/**
* 内容区字体大小
*/
private int contentFontSize = NORMALSIZE;

/**
* 标题字体大小
*/
private int titleFontSize = LARGESIZE;

/**
* 段间距
*/
private int secttSize = SECTSIZE;

/**
* 文本域边距大小
*/
private int contentPadding = PADDING;

/**
* 画笔颜色
*/

private Color color;

/**
* 背景图片
*/
private File bgFile;

/**
* 设置背景图
*
* @param bgFile
*/
public void setBgFile(File bgFile) {
this.bgFile = bgFile;
}

/**
* 设置画笔颜色 默认白色
*
* @param color
*/
public void setColor(Color color) {
this.color = color;
}

/**
* 设置内容区字体大小 默认NORMALSIZE = 50
*/
public void setContentFontSize(int contentFontSize) {
this.contentFontSize = contentFontSize;
}

/**
* 设置标题字体大小 默认LARGESIZE = 100
*/
public void setTitleFontSize(int titleFontSize) {
this.titleFontSize = titleFontSize;
}

/**
* 设置段间距 默认SECTSIZE = 70
*
* @param secttSize
*/
public void setSecttSize(int secttSize) {
this.secttSize = secttSize;
}

/**
* 设置文本边距 默认PADDING70
*
* @param contentPadding
*/
public void setContentPadding(int contentPadding) {
this.contentPadding = contentPadding;
}

/**
* 合成图片 title 标题 testContext 段落
* 分页产生的图片名
* 递增1
* @return
* @throws Exception
*/

public int compound(String strTitleString, String context,
String[] luokuan) throws Exception {
int resultCount=0;//生成的图片张数
BufferedImage bi = null;
try {
bi = ImageIO.read(bgFile);
} catch (IOException e) {
e.printStackTrace();
}
int imgWidth = bi.getWidth();
int ImgHeight = bi.getHeight();
Graphics2D g = getGraphics(bi);
Font titleFont = new Font("微软雅黑", Font.PLAIN, titleFontSize);// 标题
Font contentFont = new Font("微软雅黑", Font.PLAIN, contentFontSize);// 内容
Font luoKuanFont = new Font("微软雅黑", Font.PLAIN, contentFontSize);// 落款
if (strTitleString == null && context == null && luokuan == null) {
throw new Exception("没有数据,没有写入任何数据");
} else {
g.setFont(contentFont);
Map<Integer, String> pagemap = getPageStrings(imgWidth, ImgHeight,
strTitleString, context);
resultCount = pagemap.size();
for (int i = 1; i <= resultCount; i++) {
pointIndex = 0;// 初始化
String pageContent = pagemap.get(i);
if (strTitleString != null) {
drawTitle(titleFont, imgWidth, strTitleString, g);
}
String[] testContext = getContents(pageContent);// 每一页段数据
if (testContext != null) {
for (int j = 0; j < testContext.length; j++) {
drawContent(imgWidth, testContext[j], g);
}
if (pagemap.size() == 1 || i == pagemap.size()) {
setPointIndex(2 * secttSize);// 设置落款 开始位置
if (luokuan != null) {
drawLuoKuan(imgWidth, luokuan, luoKuanFont, g);
}
}
}
try {
String fatherPath = bgFile.getParent();
String fileAbName = bgFile.getName();
String fn = fileAbName.substring(0,fileAbName.lastIndexOf("."));//文件名前缀
String filenameString = fatherPath+"/"+fn + i + ".jpg";
File f = new File(filenameString);
ImageIO.write(bi, "jpg", f);
bi = ImageIO.read(bgFile);
g = getGraphics(bi);
g.setFont(contentFont);
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
g.dispose();
bgFile.delete();//删除背景
System.out.println("合成完毕");
return resultCount;
}

}//end

private Graphics2D getGraphics(BufferedImage bi) {
Graphics2D g = bi.createGraphics();
// 字体平滑
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
return g;
}

/**
* 写入标题 居中 字数过多换行
*
* @param width
* @param title
* @param g
*/
public void drawTitle(Font font, int width, String title, Graphics2D g) {
AttributedString as = null;
title = ToSBC(title);
int fullLen = (width - contentPadding * 2) / titleFontSize;// 一行的最多容量
int titleLen = title.length();
if (titleLen > fullLen) {
String s = title;
int writeLen = (s.length() + fullLen - 1) / fullLen;// 可写入行数
String string;
int sum = 0;
for (int i = 0; i < writeLen - 1; i++) {
int begin = i * fullLen;
int end = begin + fullLen;
string = s.substring(begin, end);// TODO
int sl = string.length();// 实际每行写入字数
as = new AttributedString(string);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - sl / 2
* titleFontSize, pointIndex
+ (titleFontSize + secttSize / 2) * (i + 1));// i+1
// 去除二段重行
}
string = s.substring((writeLen - 1) * fullLen);
as = new AttributedString(string);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - string.length() / 2
* titleFontSize, pointIndex
+ (titleFontSize + secttSize / 2) * writeLen);// 最后一行
sum += (titleFontSize + secttSize) * writeLen;
setPointIndex(sum);
} else {
as = new AttributedString(title);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - titleLen / 2
* titleFontSize, setPointIndex(titleFontSize + secttSize));

}
pointOnTitle = pointIndex;
}

/**
* 写入落款
*
* 从后面往前写
*
* @param width
* @param wsString
* 内容
* @param g
* @throws Exception
*/
public void drawLuoKuan(int width, String[] wsString, Font font,
Graphics2D g) throws Exception {
AttributedString as = null;
int padding = 2;
int fontsize = font.getSize();
int fullLen = (width - contentPadding * 2) / fontsize;// 一行的最多容量
for (int i = 0; i < wsString.length; i++) {
wsString[i] = ToSBC(wsString[i]);
if (wsString[i].length() > fullLen) {
throw new Exception("落款长度过长");
}
as = new AttributedString(wsString[i]);
as.addAttribute(TextAttribute.FONT, font);
if (wsString[0].length() > wsString[1].length()) {
if (i == 0) {
g.drawString(as.getIterator(),
(fullLen - wsString[0].length() + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
setPointIndex(-(secttSize / 2));
} else {
g.drawString(
as.getIterator(),
(fullLen
- wsString[1].length()
+ ((wsString[1].length() - wsString[0]
.length()) / 2) + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
}
} else if (wsString[0].length() < wsString[1].length()) {
if (i == 0) {
g.drawString(
as.getIterator(),
(fullLen
- wsString[0].length()
+ ((wsString[0].length() - wsString[1]
.length()) / 2) + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
setPointIndex(-(secttSize / 2));
} else {
g.drawString(as.getIterator(),
(fullLen - wsString[1].length() + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
}
}else {
g.drawString(as.getIterator(),
(fullLen - wsString[0].length() + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
setPointIndex(-(secttSize / 2));
}
}

}

/**
* 文本边距为1个字符,首行缩进2个字符
*
* 写入段落 内容区 一个字的像素为SMALLSIZE
*
* @param width
* 图片宽度
* @param height
* 图片高度
* @param content
* @param g
*/
public void drawContent(int width, String content, Graphics2D g) {
content = ToSBC(content);
int fullFontLen = (width - contentPadding * 2) / contentFontSize;// 满行写入
// 可写长度(字数)
String duanshou;
int writeLen;
int sum = 0;
if (content.length() < fullFontLen - 2) {
duanshou = content;
writeLen = 1;
g.drawString(duanshou, contentPadding + 2 * contentFontSize,
setPointIndex(2 * secttSize));
} else {
duanshou = content.substring(0, fullFontLen - 2);// 段首 缩进两个字
writeLen = (content.substring(duanshou.length() + 1).length()
+ fullFontLen - 1)
/ fullFontLen; // 可写入行数 不含段首行

// 写入段首 段的开始 2*secttSize 段分割行
g.drawString(duanshou, contentPadding + 2 * contentFontSize,
setPointIndex(2 * secttSize));
// 除去段首的内容区
String str = content.substring(duanshou.length());
// 写入内容
String string;
for (int i = 0; i < writeLen - 1; i++) {
int begin = i * fullFontLen;
int end = begin + fullFontLen;
string = str.substring(begin, end);// TODO
g.drawString(string, contentPadding, pointIndex + secttSize
+ secttSize * i);
}
string = str.substring((writeLen - 1) * fullFontLen);
g.drawString(string, contentPadding, pointIndex + secttSize
+ secttSize * (writeLen - 1));// 最后一行d
sum += ((secttSize) * (writeLen));// 段落之间的间隙
setPointIndex(sum);
}

}

/**
* 是否存在下一页
*
* @param point
* @param height
* @return
*/
public boolean hasNextPage(int height) {
if (pointIndex > (height - 2 * secttSize)) {
// 存在下一页新页开始
pointIndex = 0;
return true;
} else {
return false;
}
}

/**
* 写入内容时是否产生分页 TODO 第一段就超出页 除第一段之后的超页
*
* @param height
* 高度
* @param width
* 宽度
* @param testContext
* @return map<页码,内容>
*/
private Map<Integer, String> getPageStrings(int width, int height,
String title, String testContext) {
title = ToSBC(title);
int titleFullLen = (width - contentPadding * 2) / titleFontSize;// 一行标题的最多容量
int titleWriteLen = (title.length() + titleFullLen - 1) / titleFullLen;// 标题占有行
int titleHeight = titleWriteLen * (titleFontSize + secttSize);// 标题高度

int fullFontLen = (width - contentPadding * 2) / contentFontSize;// 满行写入可写长度(字数)

int contentHeight = getDuanLuoHeight(fullFontLen, titleHeight, height,
testContext);

// int contentHeight = getContents(testContext).length * 2 *
// secttSize;// 满区内容段落间距总高度

int bgTotalRows = (height - titleHeight - contentHeight) / secttSize
- 3;// 除去落款,背景可书写总行数

int vTotalRows = (testContext.length() + fullFontLen - 1) / fullFontLen;// 实际内容所需行数

// TDOD
int fullWord = bgTotalRows * fullFontLen;// 满屏写入内容字数
if (map == null) {
map = new HashMap<Integer, String>();
}
if (vTotalRows < bgTotalRows) {
map.put(indexPage, testContext);
} else {
int count = 0;

int pageCount = (vTotalRows + bgTotalRows - 1) / bgTotalRows;// 需要总页数
String string;
for (int i = count; i < pageCount; i++) {
if (i == pageCount - 1) {
string = testContext.substring(i * fullWord);// 最后一页
} else {
string = testContext.substring(i * fullWord, (i + 1)
* fullWord);
}
// System.out.println("当页内容:\n"+string);
map.put(indexPage, string);
indexPage++;

}
}
System.out.println("总页数" + map.size());
return map;
}

// 每页段落总间隙
// 如果是第一页 写入 如果是其他的 算满屏额
private int getDuanLuoHeight(int fullFontLen, int titleHeight, int height,
String testContext) {
int bgTotalRows = (height - titleHeight) / secttSize - 4;// 满页可写入行数
int fullWord = bgTotalRows * fullFontLen;// 满屏写入内容字数
int wlen = testContext.length();
if (wlen < fullWord) {
return getContents(testContext).length * 2 * secttSize;
} else {
return getContents(testContext.substring(0, fullWord)).length * 2
* secttSize;
}
}

/**
* 字符串处理
*/
private String[] getContents(String str) {
while (str.startsWith("\r\n")) {
str = str.substring(2);
}
String[] a = str.split("\\s{1,}");
return a.length == 0 ? null : a;
}

/**
* 字符串处理
*
* @param str
* @return
* @deprecated
*/
private String[] getContent(String str) {

String string = str.replace("\r\n", "");
string = string.replace("<p>", "{");
string = string.replace("</p>", "}");
List<String> list = new ArrayList<String>();
while (string.indexOf("{") > -1) {
int start = string.indexOf("{") + 1;
int end = string.indexOf("}");
String st = string.substring(start, end);
list.add(st);
string = string.substring(end + 1);
}
for (int i = 0; i < list.size(); i++) {
if ("".equals(list.get(i)) || list.get(i) == null) {
list.remove(i);
}
}
String[] a = list.toArray(new String[0]);
return a.length == 0 ? null : a;
}

// 半角转全角:
public static String ToSBC(String input) {
char[] c = input.toCharArray();
for (int i = 0; i < c.length; i++) {
if (c[i] == 32) {
c[i] = (char) 12288;
continue;
}
if (c[i] < 127)
c[i] = (char) (c[i] + 65248);
}
return new String(c);
}


public static char conversionNum(int c){
char rc = 0;
switch (c) {
case 1: rc='一';
break;
case 2:rc='二';
break;
case 3:rc='三';
break;
case 4:rc='四';
break;
case 5:rc='五';
break;
case 6:rc='六';
break;
case 7:rc='七';
break;
case 8:rc='八';
break;
case 9:rc='九';
break;
case 10:rc='十';
break;
case 0:rc='〇';
}
return rc;
}

//解析月/日
public static String conversionMouth(int a){
if (a<=10) {
return String.valueOf(conversionNum(a));
}else {
int gw=a%10;
int sw=a/10;
String swString = String.valueOf(conversionNum(sw));
String gwString = String.valueOf(conversionNum(gw));
if (a<20) {
return "十"+gwString;
}else {
return swString+"十"+gwString;
}
}
}

//首零的处理
public String removeBeginZ(String str){
if (str.startsWith("0")) {
int index = str.indexOf("0");
return str.substring(index);
}else {
return str;
}

}

/**
* 转化为中文日期格式
* 形式如:二〇一〇年十月二十一
* 转入格式:yyyy-MM-dd
* @param str
* @return 中文日期格式
* @throws Exception
*/
public static String toCN_Date(String str) throws Exception{
String eL = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}";//匹配正则
Pattern p = Pattern.compile(eL);
Matcher m = p.matcher(str);
boolean dateFlag = m.matches();
if (dateFlag) {
String[] strings = str.split("-");
char[] y = strings[0].toCharArray();//年
StringBuffer cndate = new StringBuffer();
for (int i = 0; i < y.length; i++) {
char cy =conversionNum((int)y[i]-48);
cndate.append(cy);
}
String mounth = conversionMouth(Integer.parseInt(String.valueOf(strings[1])));
String daString = conversionMouth(Integer.parseInt(String.valueOf(strings[2])));
cndate.append("年"+mounth+"月");
cndate.append(daString+"日");
return cndate.toString();
}else {
throw new Exception("请使用正确格式的日期字符串");
}
}

/**
* @param args
* @throws Exception
*
*/

public static void main(String[] args) throws Exception {
/*
ImageWUtil iUtil = new ImageWUtil();
try {
System.out.println(iUtil.toCN_Date("2012-12-22"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
iUtil.setBgFile(new File("D:/testbook/bg.jpg"));
iUtil.setColor(Color.WHITE);
iUtil.setTitleFontSize(60);
iUtil.setContentFontSize(45);
iUtil.setContentPadding(70);
iUtil.setSecttSize(70);
String d = "";
FileInputStream fInputStream = new FileInputStream(new File(
"D:/testbook/testbook.txt"));
byte[] by2 = new byte[5 * 1024];

int temp = fInputStream.read(by2);

d = new String(by2, 0, temp);

// System.out.println(d);
fInputStream.close();
String t = "编程改革";
String lk1 = "卡卡卡办公厅发";
String lk2 = "二零一二年世界的风行 谨在此";
try {
iUtil.compound(t, d, new String[] { lk1, lk2 });
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

String
test="\r\n\r\n\r\n\r\n\r\nasasa\r\n\r\nsasa\r\n\r\nsdasda\r\n\r\n";
String s[] =iUtil.getContents(test); System.out.println(s.length);
for (String string : s) { System.out.println(string); }
*/
}

}



分割线
================================================================
后面改进了下,解决一行中字母数字干扰行字数的问题,一行容量整齐了些,以及一些更多的一些设置。





import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.AttributedString;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.xml.crypto.Data;

import org.eclipse.emf.ecore.InternalEObject.EStore;
import org.jgroups.demos.Chat;

import com.sun.corba.se.spi.orb.StringPair;
import com.sun.corba.se.spi.orbutil.fsm.Guard.Result;
import com.ztenc.oa.proj.json.JSONArray;
import com.ztenc.oa.proj.json.JSONObject;

/**
* 文字写入图层背景工具类
*
* 内容过多自动分页,生成的图片名 为源文件名加上序号
*
* 落款自动写入格式
*
* 过滤连续出现的换行符
*
* 设置基本属性,调用compound方法即可
*
* @author fule
*/
public class ImageWUtil {

// 常量字体大小
public final static int LARGESIZE = 100; // 大字体
public final static int NORMALSIZE = 50; // 普通字体
public final static int SMALLSIZE = 30; // 小字体
// 段间距
public final static int SECTSIZE = 80;
// 文字区边距
public final static int PADDING = 100;
public final static Color DEAUFT_COLOR = Color.WHITE;

// 连续书写时的记录位
int pointIndex;

// title书写之后的记录位
int pointOnTitle;

// 当前第几页
int indexPage = 1;

Map<Integer, String> map;

/**
* 设置当前书写的像素位子
*
* @return
*/
private int setPointIndex(int increment) {
pointIndex += increment;
return pointIndex;
}

/**
* 内容区字体大小
*/
private int contentFontSize = NORMALSIZE;

/**
* 标题字体大小
*/
private int titleFontSize = LARGESIZE;

/**
* 段间距
*/
private int secttSize = SECTSIZE;

/**
* 文本域边距大小
*/
private int contentPadding = PADDING;

/**
* 标题字体
*/
private String titleFontStyle;

/**
* 设置字体类型
* @param titleFontStyle
*/
public void setTitleFontStyle(String titleFontStyle) {
this.titleFontStyle = titleFontStyle;
}

public String getTitleFontStyle() {
return titleFontStyle;
}

/**
* 标题字体粗细斜体设置
*
*/
private int titleFontBlod;


/**
* 标题字体粗细斜体设置
*
*/
public void setTitleFontBlod(int titleFontBlod) {
this.titleFontBlod = titleFontBlod;
}

public int getTitleFontBlod() {
return titleFontBlod;
}

/**
* 内容字体粗细斜体设置
*/
private int contentFontBlod;

/**
* 内容字体粗细斜体设置
* 将同时设置正文与尾款
*/
public void setContentFontBlod(int contentFontBlod) {
this.contentFontBlod = contentFontBlod;
}

public int getContentFontBlod() {
return contentFontBlod;
}



/**
* 内容字体
*/
private String contentFontStyle;

public void setContentFontStyle(String contentFontStyle) {
this.contentFontStyle = contentFontStyle;
}

public String getContentFontStyle() {
return contentFontStyle;
}

/**
* 画笔颜色
*/

private Color color;

/**
* 背景图片
*/
private File bgFile;

/**
* 设置背景图
*
* @param bgFile
*/
public void setBgFile(File bgFile) {
this.bgFile = bgFile;
}

/**
* 设置画笔颜色 默认白色
*
* @param color
*/
public void setColor(Color color) {
this.color = color;
}

/**
* 设置内容区字体大小 默认NORMALSIZE = 50
*/
public void setContentFontSize(int contentFontSize) {
this.contentFontSize = contentFontSize;
}

/**
* 设置标题字体大小 默认LARGESIZE = 100
*/
public void setTitleFontSize(int titleFontSize) {
this.titleFontSize = titleFontSize;
}

/**
* 设置段间距 默认SECTSIZE = 70
*
* @param secttSize
*/
public void setSecttSize(int secttSize) {
this.secttSize = secttSize;
}

/**
* 设置文本边距 默认PADDING70
*
* @param contentPadding
*/
public void setContentPadding(int contentPadding) {
this.contentPadding = contentPadding;
}

/**
* 合成图片
* <p>
* strTitleString 标题
* </p>
* <p>
* context 正文
* </p>
* <p>
* luokuan 落款
* </p>
* 分页产生的图片名 递增1
*
* @return
* @throws Exception
*/

public int compound(String strTitleString, String context, String[] luokuan)
throws Exception {
int resultCount = 0;// 生成的图片张数
BufferedImage bi = null;
try {
bi = ImageIO.read(bgFile);
} catch (IOException e) {
e.printStackTrace();
}
int imgWidth = bi.getWidth();
int ImgHeight = bi.getHeight();
Graphics2D g = getGraphics(bi);
Font titleFont = new Font(titleFontStyle, titleFontBlod, titleFontSize);// 标题
Font contentFont = new Font(contentFontStyle, contentFontBlod,
contentFontSize);// 内容
Font luoKuanFont = new Font(contentFontStyle, contentFontBlod,
contentFontSize);// 落款
if (strTitleString == null && context == null && luokuan == null) {
throw new Exception("没有数据,没有写入任何数据");
} else {
g.setFont(contentFont);
Map<Integer, String> pagemap = getPageStrings(imgWidth, ImgHeight,
strTitleString, context);
resultCount = pagemap.size();
for (int i = 1; i <= resultCount; i++) {
pointIndex = 0;// 初始化
String pageContent = pagemap.get(i);
if (strTitleString != null) {
drawTitle(titleFont, imgWidth, strTitleString, g);
}
String[] testContext = getContents(pageContent);// 每一页段数据
if (testContext != null) {
for (int j = 0; j < testContext.length; j++) {
drawContent(imgWidth, testContext[j], g);
}
if (pagemap.size() == 1 || i == pagemap.size()) {
setPointIndex(2 * secttSize);// 设置落款 开始位置
if (luokuan != null) {
drawLuoKuan(imgWidth, luokuan, luoKuanFont, g);
}
}
}
try {
String fatherPath = bgFile.getParent();
String fileAbName = bgFile.getName();
String fn = fileAbName.substring(0,
fileAbName.lastIndexOf("."));// 文件名前缀
String filenameString = fatherPath + "/" + fn + i + ".jpg";
File f = new File(filenameString);
ImageIO.write(bi, "jpg", f);
bi = ImageIO.read(bgFile);
g = getGraphics(bi);
g.setFont(contentFont);
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
g.dispose();
bgFile.delete();// 删除背景
System.out.println("合成完毕");
return resultCount;
}

}// end

private Graphics2D getGraphics(BufferedImage bi) {
Graphics2D g = bi.createGraphics();
// 字体平滑
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
return g;
}

/**
* 写入标题 居中 字数过多换行
*
* @param width
* @param title
* @param g
*/
public void drawTitle(Font font, int width, String title, Graphics2D g) {
AttributedString as = null;
// title = ToSBC(title);

int fullLen = (width - contentPadding * 2) / titleFontSize;// 一行的最多容量
int titleLen = title.length();
if (titleLen > fullLen) {
String s = title;
int writeLen = (s.length() + fullLen - 1) / fullLen;// 可写入行数
String string;
int sum = 0;
for (int i = 0; i < writeLen - 1; i++) {
int begin = i * fullLen;
int end = begin + fullLen;
string = s.substring(begin, end);
int sl = string.length();// 实际每行写入字数
as = new AttributedString(string);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - sl / 2
* titleFontSize, pointIndex
+ (titleFontSize + secttSize / 2) * (i + 1));// i+1
// 去除二段重行
}
string = s.substring((writeLen - 1) * fullLen);
as = new AttributedString(string);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - string.length() / 2
* titleFontSize, pointIndex
+ (titleFontSize + secttSize / 2) * writeLen);// 最后一行
sum += (titleFontSize + secttSize) * writeLen;
setPointIndex(sum);
} else {
as = new AttributedString(title);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - titleLen / 2
* titleFontSize, setPointIndex(titleFontSize + secttSize));
pointIndex=pointIndex+(int)Math.ceil(1.5*secttSize);

}
pointOnTitle = pointIndex;
}

/*
* 备用方法,形式如段落
* public void drawTitle(Font font, int width, String title, Graphics2D g) {
AttributedString as = null;
// title = ToSBC(title);
// TODO
int fullLen = (width - contentPadding * 2) / titleFontSize;// 一行的最多容量
Map<Integer, String> map = rowAttr(title, fullLen);
Object[] keys = map.keySet().toArray();
String tempStr = "";
if (keys.length == 1) {// 只有一行
tempStr = map.get(0);
as = new AttributedString(title);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - tempStr.length() / 2
* titleFontSize, setPointIndex(titleFontSize + secttSize));
} else {
int sum = 0;
int writeLen = keys.length;
for (int i = 0; i < writeLen - 1; i++) {
tempStr = map.get(keys[i]);
as = new AttributedString(tempStr);
as.addAttribute(TextAttribute.FONT, font);
int sl = tempStr.length();
g.drawString(as.getIterator(), width / 2 - sl / 2
* titleFontSize, pointIndex
+ (titleFontSize + secttSize / 2) * (i + 1));// i+1
}
tempStr = map.get(keys.length - 1);
as = new AttributedString(tempStr);
as.addAttribute(TextAttribute.FONT, font);
g.drawString(as.getIterator(), width / 2 - writeLen / 2
* titleFontSize, pointIndex
+ (titleFontSize + secttSize / 2) * writeLen);// 最后一行
sum += (titleFontSize + secttSize) * writeLen;
setPointIndex(sum);
}
pointOnTitle = pointIndex;
}
*/
/**
* 写入落款
*
* 从后面往前写
*
* @param width
* @param wsString
* 内容
* @param g
* @throws Exception
*/
public void drawLuoKuan(int width, String[] wsString, Font font,
Graphics2D g) throws Exception {
AttributedString as = null;
int padding = 2;
int fontsize = font.getSize();
int fullLen = (width - contentPadding * 2) / fontsize;// 一行的最多容量
for (int i = 0; i < wsString.length; i++) {
// wsString[i] = ToSBC(wsString[i]);
if (wsString[i].length() > fullLen) {
throw new Exception("落款长度过长");
}
as = new AttributedString(wsString[i]);
as.addAttribute(TextAttribute.FONT, font);
if (wsString[0].length() > wsString[1].length()) {
if (i == 0) {
g.drawString(as.getIterator(),
(fullLen - wsString[0].length() + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
setPointIndex(-(secttSize / 2));
} else {
g.drawString(
as.getIterator(),
(fullLen
- wsString[1].length()
+ ((wsString[1].length() - wsString[0]
.length()) / 2) + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
}
} else if (wsString[0].length() < wsString[1].length()) {
if (i == 0) {
g.drawString(
as.getIterator(),
(fullLen
- wsString[0].length()
+ ((wsString[0].length() - wsString[1]
.length()) / 2) + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
setPointIndex(-(secttSize / 2));
} else {
g.drawString(as.getIterator(),
(fullLen - wsString[1].length() + padding)
* fontsize, setPointIndex(fontsize
+ secttSize));
}
} else {
g.drawString(as.getIterator(),
(fullLen - wsString[0].length() + padding) * fontsize,
setPointIndex(fontsize + secttSize));
setPointIndex(-(secttSize / 2));
}
}

}

/**
* 书写段落
*
* 文本边距为1个字符
*
* 写入段落 内容区 一个字的像素为SMALLSIZE
*
* @param width
* 图片宽度
* @param height
* 图片高度
* @param content
* 段落文本
* @param g
*/
public void drawContent(int width, String content, Graphics2D g) {
// content = ToSBC(content);
// TODO
int fullFontLen = (width - contentPadding * 2) / contentFontSize;// 满行写入
// 可写长度(字数)
String duanshou;
int writeLen;
int sum = 0;
if (content.length() < fullFontLen) {
duanshou = content;
writeLen = 1;
g.drawString(duanshou, contentPadding, pointIndex+(2 *secttSize));
setPointIndex(2 * (int)Math.ceil(1.5*secttSize));
} else {
Map<Integer, String> map = rowAttr(content, fullFontLen);
Object[] keys = map.keySet().toArray();
duanshou =map.get(keys[0]) ;//段首行
g.drawString(duanshou, contentPadding + 2 * contentFontSize,pointIndex +(int)Math.ceil(1.5*secttSize));//写入段首行 缩进两个字符

for (int i = 1; i < keys.length; i++) {
String tempStr = map.get(keys[i]);
g.drawString(tempStr, contentPadding, pointIndex +(int)Math.ceil(1.5*secttSize)
+ (int)Math.ceil(1.5*secttSize) * i);
}
writeLen = keys.length;
sum += (((int)Math.ceil(1.5*secttSize)) * (writeLen));// 段落之间的间隙
setPointIndex(sum + secttSize);
}

}

/**
* 内容得知行属性
*
* @param str
* 段落文本
* @return map key:句编号 values:内容 //TODO 内容得知行属性
*/
public Map<Integer, String> rowAttr(String str, int fullFontLen) {
Map<Integer, String> map = new HashMap<Integer, String>();
int fullNum = 2 * fullFontLen;// 满行可写入数字字母的 个数 汉字为双倍
int i = 0;
char[] strArr = str.toCharArray();
int count = 0;// 控制句容量 计数子
int index = 0;// 句号
while (true) {
if (strArr[i] == 32 || strArr[i] < 127) {
count++;
} else {
count += 2;// 汉字两个字符像素位子
}
if (fullNum <= count) {
String s = str.substring(0, i);
if (index==0) {//段首行 满容量缩进两个字符
s=str.substring(0,i-getSuojinNum(s));
}
map.put(index, s);
str = str.substring(s.length());// 取后面新的一句
strArr = str.toCharArray();
index++;
count = 0;
i = 0;
continue;
}
i++;
if (getOccupyNum(str) <= fullNum) {// 最后一句容量小于临界
map.put(index, str);
break;
}

}
return map;

}

/**
* 缩进需要挤出的字符数
* 缩进两个汉字字符
* @param str
* @return
*/
private int getSuojinNum(String str){
char[] strArr = str.toCharArray();
int count = 0;//统计像素
int sum = 0;//统计字数
int i = strArr.length-1;
while(true){
if (strArr[i] == 32 || strArr[i] < 127) {
count++;
} else {
count += 2;// 汉字两个字符像素位子
}
sum++;
if(count>=4){
break;
}
}
return sum;
}

/**
* 得到一句容量
*/
private int getOccupyNum(String str) {
int count = 0;
char[] ch = str.toCharArray();
for (int i = 0; i < ch.length; i++) {
if (ch[i] == 32 || ch[i] < 127) {
count++;
} else {
count += 2;
}
}

return count;
}

/**
* 是否存在下一页
*
* @param point
* @param height
* @return
*/
public boolean hasNextPage(int height) {
if (pointIndex > (height - 2 * secttSize)) {
// 存在下一页新页开始
pointIndex = 0;
return true;
} else {
return false;
}
}

/**
* 写入内容时是否产生分页 TODO 第一段就超出页 除第一段之后的超页
*
* @param height
* 高度
* @param width
* 宽度
* @param testContext
* @return map<页码,内容>
*/
private Map<Integer, String> getPageStrings(int width, int height,
String title, String testContext) {
// title = ToSBC(title);
int titleFullLen = (width - contentPadding * 2) / titleFontSize;// 一行标题的最多容量
int titleWriteLen = (title.length() + titleFullLen - 1) / titleFullLen;// 标题占有行
int titleHeight = titleWriteLen * (titleFontSize + secttSize);// 标题高度

int fullFontLen = (width - contentPadding * 2) / contentFontSize;// 满行写入可写长度(字数)

int contentHeight = getDuanLuoHeight(fullFontLen, titleHeight, height,
testContext);

// int contentHeight = getContents(testContext).length * 2 *
// secttSize;// 满区内容段落间距总高度

int bgTotalRows = (height - titleHeight - contentHeight) / secttSize
- 3;// 除去落款,背景可书写总行数

int vTotalRows = (testContext.length() + fullFontLen - 1) / fullFontLen;// 实际内容所需行数

int fullWord = bgTotalRows * fullFontLen;// 满屏写入内容字数
if (map == null) {
map = new HashMap<Integer, String>();
}
if (vTotalRows < bgTotalRows) {
map.put(indexPage, testContext);
} else {
int count = 0;

int pageCount = (vTotalRows + bgTotalRows - 1) / bgTotalRows;// 需要总页数
String string;
for (int i = count; i < pageCount; i++) {
if (i == pageCount - 1) {
string = testContext.substring(i * fullWord);// 最后一页
} else {
string = testContext.substring(i * fullWord, (i + 1)
* fullWord);
}
// System.out.println("当页内容:\n"+string);
map.put(indexPage, string);
indexPage++;

}
}
System.out.println("总页数" + map.size());
return map;
}

// 每页段落总间隙
// 如果是第一页 写入 如果是其他的 算满屏额
private int getDuanLuoHeight(int fullFontLen, int titleHeight, int height,
String testContext) {
int bgTotalRows = (height - titleHeight) / secttSize - 4;// 满页可写入行数
int fullWord = bgTotalRows * fullFontLen;// 满屏写入内容字数
int wlen = testContext.length();
if (wlen < fullWord) {
return getContents(testContext).length * 2 * secttSize;
} else {
return getContents(testContext.substring(0, fullWord)).length * 2
* secttSize;
}
}

/**
* 字符串处理 解析出段落
*/
private String[] getContents(String str) {
while (str.startsWith("\r\n")) {
str = str.substring(2);
}
str = str.replaceAll("(\r?\n(\\s*\r?\n)+)", "\r\n");// 处理多个连续的\r\n
// 置换成一个/r/n
String[] a = str.split("\r\n");
return a.length == 0 ? null : a;
}

/**
* 字符串处理
*
* @param str
* @return
* @deprecated
*/
private String[] getContent(String str) {

String string = str.replace("\r\n", "");
string = string.replace("<p>", "{");
string = string.replace("</p>", "}");
List<String> list = new ArrayList<String>();
while (string.indexOf("{") > -1) {
int start = string.indexOf("{") + 1;
int end = string.indexOf("}");
String st = string.substring(start, end);
list.add(st);
string = string.substring(end + 1);
}
for (int i = 0; i < list.size(); i++) {
if ("".equals(list.get(i)) || list.get(i) == null) {
list.remove(i);
}
}
String[] a = list.toArray(new String[0]);
return a.length == 0 ? null : a;
}

/**
* 置换日期格式
*
* @param c
* @return
*/
public static char conversionNum(int c) {
char rc = 0;
switch (c) {
case 1:
rc = '一';
break;
case 2:
rc = '二';
break;
case 3:
rc = '三';
break;
case 4:
rc = '四';
break;
case 5:
rc = '五';
break;
case 6:
rc = '六';
break;
case 7:
rc = '七';
break;
case 8:
rc = '八';
break;
case 9:
rc = '九';
break;
case 10:
rc = '十';
break;
case 0:
rc = '〇';
}
return rc;
}

/**
* 解析月/日
*
* @param a
* @return
*/
public static String conversionMouth(int a) {
if (a <= 10) {
return String.valueOf(conversionNum(a));
} else {
int gw = a % 10;
int sw = a / 10;
String swString = String.valueOf(conversionNum(sw));
String gwString = String.valueOf(conversionNum(gw));
if (a < 20) {
return "十" + gwString;
} else {
return swString + "十" + gwString;
}
}
}

// 首零的处理
public String removeBeginZ(String str) {
if (str.startsWith("0")) {
int index = str.indexOf("0");
return str.substring(index);
} else {
return str;
}

}

/**
* 转化为中文日期格式 形式如:二〇一〇年十月二十一
*
* 传入格式:yyyy-MM-dd
*
* @param str
* @return 中文日期格式
* @throws Exception
*/
public static String toCN_Date(String str) throws Exception {
String eL = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}";// 匹配正则
Pattern p = Pattern.compile(eL);
Matcher m = p.matcher(str);
boolean dateFlag = m.matches();
if (dateFlag) {
String[] strings = str.split("-");
char[] y = strings[0].toCharArray();// 年
StringBuffer cndate = new StringBuffer();
for (int i = 0; i < y.length; i++) {
char cy = conversionNum((int) y[i] - 48);
cndate.append(cy);
}
String mounth = conversionMouth(Integer.parseInt(String
.valueOf(strings[1])));
String daString = conversionMouth(Integer.parseInt(String
.valueOf(strings[2])));
cndate.append("年" + mounth + "月");
cndate.append(daString + "日");
return cndate.toString();
} else {
throw new Exception("请使用正确格式的日期字符串,格式为yyyy-MM-dd");
}
}
/**
*//获得当前字体列表
*/
public List<String> getSysFontList(){
List<String> fl = new ArrayList<String>();
String[] fontlist =
GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
String except = "^[a-zA-Z0-9_ -.]+$"; //过滤英文字体
Pattern pattern = Pattern.compile(except);
for (String string : fontlist) {
if (!pattern.matcher(string).matches()) {
System.out.println(string);
fl.add(string);
}
}

return fl;
}
/**
* Test
*
* @param args
* @throws Exception
*
*/

public static void main(String[] args) throws Exception {

File bgFile = new File("D:/bgb.jpg");

ImageWUtil iUtil = new ImageWUtil();
iUtil.setBgFile(bgFile);// 设置背景图片
iUtil.setColor(Color.BLACK);// 设置画笔颜色
iUtil.setTitleFontSize(42);// 设置标题字体大小 一号 42二号
iUtil.setContentFontSize(30);// 设置正文字体 小四号
iUtil.setContentPadding(42);// 设置边距 距背景边界
iUtil.setSecttSize(30);// 设置行高 段间距默认两倍行高

iUtil.setTitleFontBlod(Font.BOLD); //设置字体的样式
iUtil.setContentFontBlod(Font.PLAIN);

iUtil.setTitleFontStyle("黑体");//设置字体的类型
iUtil.setContentFontStyle("宋体");


String strTitleString = "关于积极参与2012第二届";
String context = "积极参与积极参与处室、厅直各单位:\r\n\r\n"
+ "组织开展评选活动组织开展评选活动经启动," + "公众参与网上投票评比时间自2012年9月20日"
+ "起至10月15日23时止。"
+ "\r\n\r\n\r\n\r\n本次评选活动为有奖评选," +
"fdfsffsdfsdfsdfsdfsfs欢组织开展评选活动。各单位要认真"
+ "组织开展评选活动,组织开展评选活动经启动将评选活动通组织开展评选活动经启动。"
+ " \r\n网址:http://www.jxsl.gov.cn/sltvote/";
String[] luokuan = new String[] { "酱油部",
ImageWUtil.toCN_Date("2012-9-21") };
System.out.println(ImageWUtil.toCN_Date("2012-9-21"));
//iUtil.compound(strTitleString, context , luokuan);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值