今天看到一個朋友的Blog, 就忍不住把以前寫的這個代碼拿出來了, 不然這代碼閑著也是閑著. 當(dāng)然沒有必要照搬全部, 只要中間的那個 zoomImage() 方法即可. 當(dāng)然還有設(shè)置圖片部分透明的方法.
?
/*
* @(#)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 分鐘更新一次郵件, 發(fā)布博客并更新用戶產(chǎn)量.
* 郵件 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 - 處理結(jié)果
*/
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, 將文章發(fā)表, 并將附件圖片轉(zhuǎn)換為 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. 假定發(fā)件人為手機號, 并嘗試根據(jù)手機號查找用戶
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. 嘗試讀取郵件正文
// 復(fù)合郵件
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) {
// 需要反編碼郵件文件名, 有的郵件的附件的文件名是經(jīng)過編碼的,
// 但是 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;
// 轉(zhuǎn)換非 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. 創(chuàng)建博客記錄
content.setPictureId(picture.getId());
if(content.create() > 0) {
// 更新用戶產(chǎn)量
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) {
// 更新用戶產(chǎn)量
user.setPostTimes(user.getPostTimes() + 1);
user.update();
}
}
}
// 測試, 嘗試連接一次到郵件服務(wù)器
public static void main(String[] args) {
BlogMailHandler handler = new BlogMailHandler();
// TODO: debug, 請在 JSP 里面設(shè)置圖片目錄的根路徑
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圖片為紫色)的像素點的透明度設(shè)為透明
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;
}
// 判斷兩個整數(shù)的差是否在一定范圍之內(nèi)
private boolean isDeltaInRange(int first, int second, int range) {
if (first - second <= range && second - first <= range)
return true;
return false;
}
}