今天看到一个朋友的Blog, 就忍不住把以前写的这个代码拿出来了, 不然这代码闲着也是闲着. 当然没有必要照搬全部, 只要中间的那个 zoomImage() 方法即可. 当然还有设置图片部分透明的方法.
/*
* @(#)BlogMailHandler.java 1.00 2004-10-4
*
* Copyright 2004 . All rights reserved.
* PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.mail.Address;
import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;
import studio.beansoft.jsp.StringUtil;
import com.keypoint.PngEncoder;
import com.keypoint.PngEncoderB;
import moblog.*;
/**
* BlogMailHandler, 彩E博客邮件的处理程序.
* 每 15 分钟更新一次邮件, 发布博客并更新用户产量.
* 邮件 POP3 帐户信息位于 /blogmail.properties 文件中.
*
* @author 刘长炯
* @version 1.00 2004-10-4
*/
public class BlogMailHandler extends Thread {
/**
* @alias 文件根目录 : String
*/
private String rootDirectory;
// 邮件帐户配置属性
private static Properties props = new Properties();
static {
try {
InputStream in = BlogMailHandler.class
.getResourceAsStream("/blogmail.properties");
props.load(in);
in.close();
} catch (Exception ex) {
System.err.println("无法加载配置文件 blogmail.properties:"
+ ex.getMessage());
ex.printStackTrace();
}
}
// 图像加载的共享实例, 在 Linux 平台上有可能无法生成图形对象
// private static Frame sharedFrame = new Frame();
private boolean shouldExit = false;
public BlogMailHandler() {
}
/** 定时开始读取邮件信息 */
public void startMailProcessCycle() {
start();
}
public void run() {
while(!shouldExit) {
doProcess();
try {
// 每15分钟读取一次
Thread.currentThread().sleep(60 * 15 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** 处理进程 */
private void doProcess() {
try {
Store store = openStore();
Folder inbox = openInbox(store);
processAllMessages(inbox);
inbox.close(true);
store.close();
} catch (Exception e) {
e.printStackTrace();
}
}
protected void finalize() throws Throwable {
shouldExit = true;
}
/**
* 缩放原始图片到合适大小.
*
* @param srcImage - 原始图片
* @return BufferedImage - 处理结果
*/
private BufferedImage zoomImage(BufferedImage srcImage) {
int MAX_WIDTH = 100;// TODO: 缩放后的图片最大宽度
int MAX_HEIGHT = 160;// TODO: 缩放后的图片最大高度
int imageWidth = srcImage.getWidth(null);
int imageHeight = srcImage.getHeight(null);
// determine thumbnail size from MAX_WIDTH and MAX_HEIGHT
int thumbWidth = MAX_WIDTH;
int thumbHeight = MAX_HEIGHT;
double thumbRatio = (double)thumbWidth / (double)thumbHeight;
double imageRatio = (double)imageWidth / (double)imageHeight;
if (thumbRatio < imageRatio) {
thumbHeight = (int)(thumbWidth / imageRatio);
} else {
thumbWidth = (int)(thumbHeight * imageRatio);
}
// 如果图片小于所略图大小, 不作处理
if(imageWidth < MAX_WIDTH && imageHeight < MAX_HEIGHT) {
thumbWidth = imageWidth;
thumbHeight = imageHeight;
}
// draw original image to thumbnail image object and
// scale it to the new size on-the-fly (drawImage is quite powerful)
BufferedImage thumbImage = new BufferedImage(thumbWidth,
thumbHeight, BufferedImage.TYPE_INT_RGB);
//thumbImage.getsc
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(srcImage, 0, 0, thumbWidth, thumbHeight, null);
System.out.println("thumbWidth=" + thumbWidth);
System.out.println("thumbHeight=" + thumbHeight);
return thumbImage;
}
// Open mail Store
private Store openStore() throws Exception {
Store store;
//--[ Set up the default parameters
props.put("mail.transport.protocol", "pop");
props.put("mail.pop.port", "110");
// props.put("mail.debug", "true");
Session session = Session.getInstance(props);
store = session.getStore("pop3");
// void javax.mail.Service.connect(String host, String user, String
// password) throws
// MessagingException
store.connect(props.getProperty("mail.pop3.host"), props
.getProperty("username"), props.getProperty("password"));
return store;
}
// Open Inbox
private Folder openInbox(Store store) throws Exception {
Folder folder = store.getDefaultFolder();
if (folder == null) {
System.out.println("Problem occurred");
System.exit(1);
}
Folder popFolder = folder.getFolder("INBOX");
popFolder.open(Folder.READ_WRITE);
return popFolder;
}
/** Close mail store. */
private void closeStore(Store store) {
try {
store.close();
} catch (MessagingException e) {
e.printStackTrace();
}
}
/**
* 处理账号中的所有邮件并删除这些邮件.
*
* @param folder - Folder, 收件箱
* @throws Exception
*/
private void processAllMessages(Folder folder) throws Exception {
Message[] listOfMessages = folder.getMessages();
FetchProfile fProfile = new FetchProfile();
fProfile.add(FetchProfile.Item.ENVELOPE);
folder.fetch(listOfMessages, fProfile);
for (int i = 0; i < listOfMessages.length; i++) {
try {
processSingleMail(listOfMessages[i]);
} catch (Exception e) {
e.printStackTrace();
}
// Delete mail
listOfMessages[i].setFlag(Flags.Flag.DELETED, true);
}
}
/**
* 处理单个 Email, 将文章发表, 并将附件图片转换为 PNG 后存入用户目录.
*
* @param message -
* Message, email 消息
*/
private void processSingleMail(Message message) throws Exception {
BlogContent content = new BlogContent();
BlogUser user = new BlogUser();
BlogPicture picture = new BlogPicture();
// 1. 假定发件人为手机号, 并尝试根据手机号查找用户
Address[] addList = message.getFrom();
if (addList.length > 0) {
String userMail = ((InternetAddress) addList[0]).getAddress();
// 取出 彩E 邮件用户手机号, 格式: 手机号@someone.com
String mobileNumber = userMail.substring(0, userMail.indexOf("@"));
System.out.println("用户手机号为:" + mobileNumber);
if (!user.findByMDN(mobileNumber)) {
// Not found user, then return
System.err.println("user " + ((InternetAddress) addList[0]).getAddress() + " not found.");
return;
}
}
// 2. 尝试读取邮件正文
// 复合邮件
if (message.isMimeType("multipart/*")) {
// 标记是否处理过图片
boolean imageHasProcessed = false;
Multipart multipart = (Multipart) message.getContent();
for (int i = 0, n = multipart.getCount(); i < n; i++) {
// System.err.println("Reading multipart " + i);
Part part = multipart.getBodyPart(i);
// System.err.println("ContentType = " + part.getContentType());
// 3. 处理附件图片, 只处理第一个图片
String disposition = part.getDisposition();
// System.err.println("disposition = " + disposition);
if (disposition != null
&& (disposition.equals(Part.ATTACHMENT) || disposition
.equals(Part.INLINE)) && !imageHasProcessed) {
// 需要反编码邮件文件名, 有的邮件的附件的文件名是经过编码的,
// 但是 JavaMail 并不能处理出来(BeanSoft, 2004-10-13)
String fileName = MimeUtility.decodeText(part.getFileName());
String ext = StringUtil.getExtension(fileName)
.toLowerCase();
System.err.println("part.getFileName() = " + fileName);
if ("gif".equals(ext) || "jpg".equals(ext)
|| "png".equals(ext)) {
BufferedInputStream dataIn = null;
// 转换非 PNG 格式图片为 PNG 格式 -- 取消
// if (!"png".equals(ext)) {
ByteArrayOutputStream pngOut = new ByteArrayOutputStream();
try {
// Convert image file to PNG file
BufferedImage buffImg = ImageIO.read(part
.getInputStream());
// Read image file from attachment
// 缩放图片
buffImg = zoomImage(buffImg);
int imageWidth = buffImg.getWidth(null);
int imageHeight = buffImg.getHeight(null);
BufferedImage outImg = new BufferedImage(
imageWidth, imageHeight,
// BufferedImage.TYPE_4BYTE_ABGR 是 24 位色深, TYPE_BYTE_INDEXED 是 8 位
BufferedImage.TYPE_INT_RGB);
// 使图片透明
// embossImage(buffImg, outImg);
outImg.getGraphics().drawImage(buffImg, 0, 0, imageWidth, imageHeight, null);
// Save image to PNG output stream
// ImageIO.write(outImg, "png", pngOut);
// Save using keypoint PNG encoder
PngEncoderB pngb = new PngEncoderB(outImg,
PngEncoder.NO_ALPHA, 0, 9);
pngOut.write(pngb.pngEncode());
dataIn = new BufferedInputStream(
new ByteArrayInputStream(pngOut
.toByteArray()));
} catch (Exception e) {
}
// } else {
// dataIn = new BufferedInputStream(part
// .getInputStream());
// }
// All pictures change to png format
ext = "png"
// Insert picture info into database
picture.setBlogID(user.getId());
picture.setCreationTime(new Timestamp(System
.currentTimeMillis()));
picture.setFileEXName(ext);
picture.setTitle(fileName);
picture.create();
// Save png file to user directory, /users/userId/pictureId.png
FileOutputStream outFile = new FileOutputStream(
rootDirectory + File.separatorChar + user.getId() + File.separatorChar
+ picture.getId() + "." + ext);
int c;
while ((c = dataIn.read()) != -1) {
outFile.write(c);
}
outFile.close();
imageHasProcessed = true;
}
}
// 纯文本邮件, 带附件
else if (part.isMimeType("text/plain")) {
String body = part.getContent().toString();
String title = message.getSubject();
content.setBlogID(user.getId());
content.setCreationTime(new Timestamp(System.currentTimeMillis()));
content.setTitle(title);
content.setNote(body);
}
// 典型的 HTML 和 文本邮件可选形式, 进一步分析
if (part.getContent() instanceof Multipart) {
Multipart subPart = (Multipart) part.getContent();
for (int j = 0, m = subPart.getCount(); j < m; j++) {
Part mailText = subPart.getBodyPart(j);
if (mailText.isMimeType("text/plain")) {
String body = mailText.getContent().toString();
String title = message.getSubject();
content.setBlogID(user.getId());
content.setCreationTime(new Timestamp(System.currentTimeMillis()));
content.setTitle(title);
content.setNote(body);
break;
}
}
}
}// End of multipart parse
// 4. 创建博客记录
content.setPictureId(picture.getId());
if(content.create() > 0) {
// 更新用户产量
user.setPostTimes(user.getPostTimes() + 1);
user.update();
}
}
// 纯文本邮件, 无附件
else if (message.isMimeType("text/plain")) {
String body = message.getContent().toString();
String title = message.getSubject();
content.setBlogID(user.getId());
content.setCreationTime(new Timestamp(System.currentTimeMillis()));
content.setTitle(title);
content.setNote(body);
if(content.create() > 0) {
// 更新用户产量
user.setPostTimes(user.getPostTimes() + 1);
user.update();
}
}
}
// 测试, 尝试连接一次到邮件服务器
public static void main(String[] args) {
BlogMailHandler handler = new BlogMailHandler();
// TODO: debug, 请在 JSP 里面设置图片目录的根路径
handler.rootDirectory = "F:/Moblog/users/"
handler.doProcess();
}
/**
* @return Returns the rootDirectory.
*/
public String getRootDirectory() {
return rootDirectory;
}
/**
* @param rootDirectory
* The rootDirectory to set.
*/
public void setRootDirectory(String property1) {
this.rootDirectory = property1;
}
/** Make image transparent */
private void embossImage(BufferedImage srcImage, BufferedImage destImage) {
int width = srcImage.getWidth();
int height = srcImage.getHeight();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int newColor = handlesinglepixel(j, i, srcImage.getRGB(j, i));
destImage.setRGB(j, i, newColor);
}
}
}
// Handle picture single pixel, change 0xff00ff color to transparent
private int handlesinglepixel(int x, int y, int pixel) {
int alpha = (pixel >> 24) & 0xff;
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
// Deal with the pixel as necessary...
// alpha 为 0 时完全透明, 为 255 时不透明
Color back = new Color(0xFF00FF);
// 将与背景色相同(此处PNG图片为紫色)的像素点的透明度设为透明
if (isDeltaInRange(back.getRed(), red, 2)
&& isDeltaInRange(back.getGreen(), green, 2)
&& isDeltaInRange(back.getBlue(), blue, 2)) {
// System.out.println("x=" + x + "y=" + y + " is transparent.");
alpha = 0;
}
// red = red / 2;
// //green = green / 2 + 68;
// blue = blue / 2;
return alpha << 24 | red << 16 | green << 8 | blue;
}
// 判断两个整数的差是否在一定范围之内
private boolean isDeltaInRange(int first, int second, int range) {
if (first - second <= range && second - first <= range)
return true;
return false;
}
}