Browse Source
* commit 'f169fb0b0fe07b3ebf32bb10d24f8c79d696622b': REPORT-8357 .0之前开发的功能与bug patch到10.0 图片压缩master
superman
7 years ago
14 changed files with 1105 additions and 443 deletions
@ -0,0 +1,154 @@
|
||||
package com.fr.design.gui.frpane; |
||||
|
||||
import com.fr.base.BaseUtils; |
||||
import com.fr.base.Style; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.style.background.image.ImageFileChooser; |
||||
import com.fr.design.style.background.image.ImagePreviewer; |
||||
import com.fr.design.utils.ImageUtils; |
||||
import com.fr.general.ImageWithSuffix; |
||||
import com.fr.general.Inter; |
||||
import com.fr.stable.CoreGraphHelper; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.JFileChooser; |
||||
import javax.swing.SwingWorker; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import java.awt.Image; |
||||
import java.io.File; |
||||
|
||||
/** |
||||
* 图片选择框包装类 |
||||
* Created by zack on 2018/3/9. |
||||
*/ |
||||
public class ImgChooseWrapper { |
||||
private ImagePreviewer previewPane = null; |
||||
|
||||
private ImageFileChooser imageFileChooser = null; |
||||
|
||||
private Style imageStyle = null; |
||||
|
||||
private SwingWorker<Void, Void> imageWorker; |
||||
private ChangeListener changeListener; |
||||
|
||||
private transient Image selectImage; |
||||
private UILabel imageSizeLabel; |
||||
|
||||
public static ImgChooseWrapper getInstance(ImagePreviewer previewPane, ImageFileChooser imageFileChooser, Style imageStyle) { |
||||
return getInstance(previewPane, imageFileChooser, imageStyle, null); |
||||
} |
||||
|
||||
public static ImgChooseWrapper getInstance(ImagePreviewer previewPane, ImageFileChooser imageFileChooser, Style imageStyle, ChangeListener changeListener) { |
||||
return new ImgChooseWrapper(previewPane, imageFileChooser, imageStyle, changeListener, null, null); |
||||
} |
||||
|
||||
public static ImgChooseWrapper getInstance(Image selectImage, UILabel imageSizeLabel, ImageFileChooser imageFileChooser) { |
||||
return new ImgChooseWrapper(null, imageFileChooser, null, null, selectImage, imageSizeLabel); |
||||
} |
||||
|
||||
private ImgChooseWrapper(ImagePreviewer previewPane, ImageFileChooser imageFileChooser, Style imageStyle, ChangeListener changeListener, Image selectImage, UILabel imageSizeLabel) { |
||||
this.previewPane = previewPane; |
||||
this.imageFileChooser = imageFileChooser; |
||||
this.imageStyle = imageStyle; |
||||
this.changeListener = changeListener; |
||||
this.selectImage = selectImage; |
||||
this.imageSizeLabel = imageSizeLabel; |
||||
} |
||||
|
||||
|
||||
public void setPreviewPane(ImagePreviewer previewPane) { |
||||
this.previewPane = previewPane; |
||||
} |
||||
|
||||
public ImageFileChooser getImageFileChooser() { |
||||
return imageFileChooser; |
||||
} |
||||
|
||||
public void setImageFileChooser(ImageFileChooser imageFileChooser) { |
||||
this.imageFileChooser = imageFileChooser; |
||||
} |
||||
|
||||
public Style getImageStyle() { |
||||
return imageStyle; |
||||
} |
||||
|
||||
public void setImageStyle(Style imageStyle) { |
||||
this.imageStyle = imageStyle; |
||||
} |
||||
|
||||
public SwingWorker<Void, Void> getImageWorker() { |
||||
return imageWorker; |
||||
} |
||||
|
||||
public void setImageWorker(SwingWorker<Void, Void> imageWorker) { |
||||
this.imageWorker = imageWorker; |
||||
} |
||||
|
||||
public void dealWithImageFile(int returnVal) { |
||||
if (returnVal != JFileChooser.CANCEL_OPTION) { |
||||
final File selectedFile = imageFileChooser.getSelectedFile(); |
||||
|
||||
if (selectedFile != null && selectedFile.isFile()) { |
||||
if (previewPane != null) { |
||||
previewPane.showLoading(); |
||||
} |
||||
if (imageWorker != null && !imageWorker.isDone()) { |
||||
imageWorker = null; |
||||
} |
||||
imageWorker = new SwingWorker<Void, Void>() { |
||||
@Override |
||||
protected Void doInBackground() throws Exception { |
||||
ImageWithSuffix imageWithSuffix = null; |
||||
if (imageFileChooser.isCheckSelected()) { |
||||
imageWithSuffix = ImageUtils.defaultImageCompWithSuff(selectedFile); |
||||
} else { |
||||
Image image = BaseUtils.readImage(selectedFile.getPath()); |
||||
String type = ImageUtils.getImageType(selectedFile); |
||||
imageWithSuffix = new ImageWithSuffix(image, type); |
||||
} |
||||
|
||||
CoreGraphHelper.waitForImage(imageWithSuffix); |
||||
|
||||
if (previewPane != null) { |
||||
previewPane.setImageStyle(imageStyle); |
||||
previewPane.setImageWithSuffix(imageWithSuffix); |
||||
previewPane.repaint(); |
||||
} |
||||
checkLabelText(); |
||||
fireChangeListener(); |
||||
return null; |
||||
} |
||||
}; |
||||
imageWorker.execute(); |
||||
} else { |
||||
if (previewPane != null) { |
||||
previewPane.setImage(null); |
||||
} |
||||
|
||||
} |
||||
if (previewPane != null) { |
||||
previewPane.repaint(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void fireChangeListener() { |
||||
if (this.changeListener != null) { |
||||
ChangeEvent evt = new ChangeEvent(this); |
||||
this.changeListener.stateChanged(evt); |
||||
} |
||||
} |
||||
|
||||
private void checkLabelText() { |
||||
if (imageSizeLabel == null) { |
||||
return; |
||||
} |
||||
if (selectImage == null) { |
||||
imageSizeLabel.setText(StringUtils.EMPTY); |
||||
} else { |
||||
imageSizeLabel.setText(selectImage.getWidth(null) + "x" |
||||
+ selectImage.getHeight(null) + Inter.getLocText("px")); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,196 @@
|
||||
package com.fr.design.style.background.image; |
||||
|
||||
import com.fr.base.BaseUtils; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.icheckbox.UICheckBox; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.general.Inter; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.JDialog; |
||||
import javax.swing.JFileChooser; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.plaf.metal.MetalFileChooserUI; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.Container; |
||||
import java.awt.Dimension; |
||||
import java.awt.Insets; |
||||
import java.awt.LayoutManager; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
/** |
||||
* 扩展的文件选择框(底部控制区域扩展一个复选框) |
||||
* Created by zack on 2018/3/8. |
||||
*/ |
||||
public class ExpandFileChooser extends JFileChooser { |
||||
private JDialog dialog; |
||||
private UICheckBox checkBox;//选择框底部的复选按钮
|
||||
private int retVal = ERROR_OPTION; |
||||
private UIButton approve; |
||||
private UIButton cancel; |
||||
private static final int DEFAULT_WIDTH = 520; |
||||
|
||||
public ExpandFileChooser() { |
||||
this(StringUtils.EMPTY, StringUtils.EMPTY); |
||||
} |
||||
|
||||
public ExpandFileChooser(String checkBoxText, String approveButtonText) { |
||||
JPanel previewContainerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
MetalFileChooserUI chooserUI = (MetalFileChooserUI) getUI(); |
||||
String approveText = StringUtils.isEmpty(approveButtonText) ? chooserUI.getApproveButtonText(this) : approveButtonText; |
||||
dialog = new JDialog(); |
||||
|
||||
dialog.setSize(new Dimension(DEFAULT_WIDTH, 362)); |
||||
dialog.add(previewContainerPane); |
||||
dialog.setIconImage(BaseUtils.readImage("/com/fr/base/images/oem/logo.png")); |
||||
dialog.setTitle(approveText); |
||||
previewContainerPane.add(this, BorderLayout.CENTER); |
||||
|
||||
|
||||
JPanel bottomControlPanel = new JPanel(); |
||||
bottomControlPanel.setLayout(new ImageAreaLayout()); |
||||
bottomControlPanel.setPreferredSize(new Dimension(DEFAULT_WIDTH, 40)); |
||||
|
||||
approve = new UIButton(approveText); |
||||
cancel = new UIButton(Inter.getLocText("FR-Designer_Button-Cancel")); |
||||
if (StringUtils.isNotEmpty(checkBoxText)) { |
||||
checkBox = new UICheckBox(checkBoxText); |
||||
checkBox.setSelected(DesignerEnvManager.getEnvManager().isImageCompress()); |
||||
bottomControlPanel.add(checkBox); |
||||
checkBox.addActionListener(checkAction()); |
||||
} |
||||
bottomControlPanel.add(approve); |
||||
approve.addActionListener(chooserUI.getApproveSelectionAction()); |
||||
cancel.addActionListener(chooserUI.getCancelSelectionAction()); |
||||
bottomControlPanel.add(cancel); |
||||
previewContainerPane.add(bottomControlPanel, BorderLayout.SOUTH); |
||||
GUICoreUtils.centerWindow(dialog); |
||||
} |
||||
|
||||
public ActionListener checkAction() { |
||||
return null; |
||||
} |
||||
|
||||
public boolean isCheckSelected() { |
||||
if (checkBox != null) { |
||||
return checkBox.isSelected(); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int showDialog(Component parent, String approveButtonText) { |
||||
dialog.setModal(true); |
||||
dialog.setVisible(true); |
||||
return retVal; |
||||
} |
||||
|
||||
@Override |
||||
public void approveSelection() { |
||||
retVal = APPROVE_OPTION; |
||||
if (dialog != null) { |
||||
dialog.setVisible(false); |
||||
} |
||||
fireActionPerformed(APPROVE_SELECTION); |
||||
} |
||||
|
||||
@Override |
||||
public void cancelSelection() { |
||||
retVal = CANCEL_OPTION; |
||||
if (dialog != null) { |
||||
dialog.setVisible(false); |
||||
} |
||||
fireActionPerformed(CANCEL_SELECTION); |
||||
} |
||||
|
||||
@Override |
||||
public boolean getControlButtonsAreShown() { |
||||
return false;//隐藏默认的控制按钮(打开/取消)
|
||||
} |
||||
|
||||
private class ImageAreaLayout implements LayoutManager { |
||||
private static final int TEN = 10; |
||||
private int hGap = 5; |
||||
private int topMargin = TEN; |
||||
private int leftMargin = TEN; |
||||
private int leftStart = 8; |
||||
|
||||
@Override |
||||
public void addLayoutComponent(String string, Component comp) { |
||||
} |
||||
|
||||
@Override |
||||
public void layoutContainer(Container container) { |
||||
Component[] children = container.getComponents(); |
||||
|
||||
if (children != null && children.length > 0) { |
||||
int numChildren = children.length; |
||||
Dimension[] sizes = new Dimension[numChildren]; |
||||
Insets insets = container.getInsets(); |
||||
int yLocation = insets.top + topMargin; |
||||
int maxWidth = 0; |
||||
|
||||
for (int counter = 0; counter < numChildren; counter++) { |
||||
sizes[counter] = children[counter].getPreferredSize(); |
||||
maxWidth = Math.max(maxWidth, sizes[counter].width); |
||||
} |
||||
int xLocation, xOffset; |
||||
if (container.getComponentOrientation().isLeftToRight()) { |
||||
xLocation = container.getSize().width - insets.left - maxWidth - leftMargin; |
||||
xOffset = hGap + maxWidth; |
||||
} else { |
||||
xLocation = insets.left; |
||||
xOffset = -(hGap + maxWidth); |
||||
} |
||||
//单独设置图片压缩按钮的位置
|
||||
children[0].setBounds(leftStart, yLocation, |
||||
maxWidth, sizes[0].height); |
||||
|
||||
for (int counter = numChildren - 1; counter >= 1; counter--) { |
||||
children[counter].setBounds(xLocation, yLocation, |
||||
maxWidth, sizes[counter].height); |
||||
xLocation -= xOffset; |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Dimension minimumLayoutSize(Container c) { |
||||
if (c != null) { |
||||
Component[] children = c.getComponents(); |
||||
|
||||
if (children != null && children.length > 0) { |
||||
int numChildren = children.length; |
||||
int height = 0; |
||||
Insets cInsets = c.getInsets(); |
||||
int extraHeight = topMargin + cInsets.top + cInsets.bottom; |
||||
int extraWidth = cInsets.left + cInsets.right; |
||||
int maxWidth = 0; |
||||
|
||||
for (int counter = 0; counter < numChildren; counter++) { |
||||
Dimension aSize = children[counter].getPreferredSize(); |
||||
height = Math.max(height, aSize.height); |
||||
maxWidth = Math.max(maxWidth, aSize.width); |
||||
} |
||||
return new Dimension(extraWidth + numChildren * maxWidth + |
||||
(numChildren - 1) * hGap, |
||||
extraHeight + height); |
||||
} |
||||
} |
||||
return new Dimension(0, 0); |
||||
} |
||||
|
||||
@Override |
||||
public Dimension preferredLayoutSize(Container c) { |
||||
return minimumLayoutSize(c); |
||||
} |
||||
|
||||
@Override |
||||
public void removeLayoutComponent(Component c) { |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,40 @@
|
||||
package com.fr.design.style.background.image; |
||||
|
||||
import com.fr.base.Style; |
||||
import com.fr.general.ImageWithSuffix; |
||||
|
||||
import java.awt.Image; |
||||
|
||||
/** |
||||
* 图片预览接口(由于子类上层父类差别较大,无奈的接口) |
||||
* Created by zack on 2018/3/10. |
||||
*/ |
||||
public interface ImagePreviewer { |
||||
/** |
||||
* 设置图片样式(平铺,拉伸) |
||||
* @param style 样式 |
||||
*/ |
||||
void setImageStyle(Style style); |
||||
|
||||
/** |
||||
* 设置图片 |
||||
* @param image 图片 |
||||
*/ |
||||
void setImage(Image image); |
||||
|
||||
/** |
||||
* 设置图片(带格式) |
||||
* @param image 图片 |
||||
*/ |
||||
void setImageWithSuffix(ImageWithSuffix image); |
||||
|
||||
/** |
||||
* 显示正在加载 |
||||
*/ |
||||
void showLoading(); |
||||
|
||||
/** |
||||
* 重绘 |
||||
*/ |
||||
void repaint(); |
||||
} |
@ -0,0 +1,285 @@
|
||||
package com.fr.design.utils; |
||||
|
||||
import com.fr.base.BaseUtils; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.general.FRLogger; |
||||
import com.fr.general.ImageWithSuffix; |
||||
import com.fr.stable.CoreGraphHelper; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.imageio.IIOImage; |
||||
import javax.imageio.ImageIO; |
||||
import javax.imageio.ImageReader; |
||||
import javax.imageio.ImageWriteParam; |
||||
import javax.imageio.ImageWriter; |
||||
import javax.imageio.stream.ImageInputStream; |
||||
import javax.imageio.stream.ImageOutputStream; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.Image; |
||||
import java.awt.Transparency; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.math.BigDecimal; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* 设计器部分的图片处理工具类 |
||||
* Created by zack on 2018/3/8. |
||||
*/ |
||||
public class ImageUtils { |
||||
public static final String TYPE_JPEG = "JPEG"; |
||||
public static final String TYPE_PNG = "png"; |
||||
|
||||
/** |
||||
* 默认压缩算法,采用75%质量压缩,带透明度的png默认使用缩放的方式实现压缩尺寸压缩50%,大小大约为1/4 |
||||
* |
||||
* @param imageFile 原文件 |
||||
* @return 压缩后的BufferedImage对象 |
||||
*/ |
||||
public static Image defaultImageCompress(File imageFile) { |
||||
if (imageFile == null || !imageFile.exists()) { |
||||
return null; |
||||
} |
||||
try { |
||||
BufferedImage srcImg = BaseUtils.readImage(imageFile.getPath()); |
||||
if (canbeCompressedToJPEG(imageFile)) { |
||||
return jpegCompress(srcImg, 0.75f); |
||||
} else if (isPNGType(imageFile)) { |
||||
//带透明度的采用缩放的方式
|
||||
return scale(srcImg, 0.5f, true); |
||||
} |
||||
} catch (IOException e) { |
||||
FRLogger.getLogger().info("image compress failed!"); |
||||
|
||||
} |
||||
return BaseUtils.readImage(imageFile.getPath()); |
||||
} |
||||
|
||||
/** |
||||
* 默认压缩算法,返回带格式的image |
||||
* |
||||
* @param imageFile 原文件 |
||||
* @return 压缩后的BufferedImage对象 |
||||
*/ |
||||
public static ImageWithSuffix defaultImageCompWithSuff(File imageFile) { |
||||
if (imageFile == null || !imageFile.exists()) { |
||||
return null; |
||||
} |
||||
BufferedImage srcImg = BaseUtils.readImage(imageFile.getPath()); |
||||
Image desImg = srcImg; |
||||
try { |
||||
|
||||
if (canbeCompressedToJPEG(imageFile)) { |
||||
return new ImageWithSuffix(jpegCompress(srcImg, 0.75f), TYPE_JPEG); |
||||
} else if (isPNGType(imageFile)) { |
||||
//带透明度的采用缩放的方式
|
||||
desImg = scale(srcImg, 0.5f, true); |
||||
} |
||||
} catch (IOException e) { |
||||
FRLogger.getLogger().info("image compress failed!"); |
||||
|
||||
} |
||||
return new ImageWithSuffix(desImg, TYPE_PNG); |
||||
} |
||||
|
||||
public static boolean canbeCompressedToJPEG(File imageFile) { |
||||
String imageType = getImageType(imageFile); |
||||
if (ComparatorUtils.equals(imageType, TYPE_JPEG)) {//JPEG大写
|
||||
return true; |
||||
} |
||||
if (ComparatorUtils.equals(imageType, TYPE_PNG)) {//png小写
|
||||
return !isAlphaAreaOverload(imageFile);//少量透明度系数的png直接压缩jpg
|
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 判断图片是否是png类型 |
||||
* |
||||
* @param imageFile |
||||
* @return |
||||
*/ |
||||
public static boolean isPNGType(File imageFile) { |
||||
if (ComparatorUtils.equals(getImageType(imageFile), TYPE_PNG)) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* JPEG格式图片压缩 |
||||
* |
||||
* @param image 压缩源图片 |
||||
* @param quality 压缩质量,在0-1之间, |
||||
* @return 返回的字节数组 |
||||
*/ |
||||
public static BufferedImage jpegCompress(BufferedImage image, float quality) throws IOException { |
||||
if (image == null) { |
||||
return null; |
||||
} |
||||
// 得到指定Format图片的writer
|
||||
Iterator<ImageWriter> iter = ImageIO |
||||
.getImageWritersByFormatName("jpeg");// 得到迭代器
|
||||
ImageWriter writer = iter.next(); |
||||
|
||||
// 得到指定writer的输出参数设置(ImageWriteParam )
|
||||
ImageWriteParam iwp = writer.getDefaultWriteParam(); |
||||
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 设置可否压缩
|
||||
iwp.setCompressionQuality(quality); // 设置压缩质量参数
|
||||
iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED); |
||||
|
||||
// 开始打包图片,写入byte[]
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
||||
ImageOutputStream ios = null; |
||||
ByteArrayInputStream in = null; |
||||
try { |
||||
image = copy(image, BufferedImage.TYPE_INT_RGB); |
||||
ios = ImageIO.createImageOutputStream(byteArrayOutputStream); |
||||
writer.setOutput(ios); |
||||
writer.write(null, new IIOImage(image, null, null), iwp); |
||||
in = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); |
||||
if (ios == null || in == null) { |
||||
throw new IOException("The image file cannot be compressed"); |
||||
} |
||||
return ImageIO.read(in); |
||||
} finally { |
||||
writer.dispose(); |
||||
byteArrayOutputStream.close(); |
||||
if (ios != null) { |
||||
ios.close(); |
||||
} |
||||
if (in != null) { |
||||
in.close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 判断图片中是否包含多于5%的透明区域,这个5%随便定的 |
||||
* |
||||
* @param imageFile 目标图片 |
||||
* @return 含透明度像素占比 |
||||
*/ |
||||
public static boolean isAlphaAreaOverload(File imageFile) { |
||||
if (imageFile == null || !imageFile.isFile()) { |
||||
return false; |
||||
} |
||||
BufferedImage bufferedImage = BaseUtils.readImage(imageFile.getPath()); |
||||
int width = bufferedImage.getWidth(); |
||||
int height = bufferedImage.getHeight(); |
||||
long alphaCount = 0; |
||||
for (int i = 0; i < width; i++) { |
||||
for (int j = 0; j < height; j++) { |
||||
int rgb = bufferedImage.getRGB(i, j); |
||||
int a = (0xff & (rgb >> 24)); |
||||
if (a != 0xff) { |
||||
alphaCount++; |
||||
} |
||||
} |
||||
} |
||||
return alphaCount / (double) (width * height) > 0.05; |
||||
} |
||||
|
||||
/** |
||||
* 获取图片类型 |
||||
* |
||||
* @param imageFile 图片文件 |
||||
* @return 图片类型(JPEG, PNG, GIF) |
||||
*/ |
||||
public static String getImageType(File imageFile) { |
||||
try { |
||||
ImageInputStream iis = ImageIO.createImageInputStream(imageFile); |
||||
Iterator<ImageReader> iter = ImageIO.getImageReaders(iis); |
||||
if (!iter.hasNext()) { |
||||
return StringUtils.EMPTY; |
||||
} |
||||
ImageReader reader = iter.next(); |
||||
iis.close(); |
||||
return reader.getFormatName(); |
||||
} catch (IOException ignore) { |
||||
} |
||||
return StringUtils.EMPTY; |
||||
} |
||||
|
||||
private static BufferedImage copy(BufferedImage img, int imageType) { |
||||
int width = img.getWidth(); |
||||
int height = img.getHeight(); |
||||
|
||||
BufferedImage newImage = CoreGraphHelper.createBufferedImage(width, height, imageType); |
||||
Graphics g = newImage.createGraphics(); |
||||
|
||||
g.drawImage(img, 0, 0, null); |
||||
|
||||
g.dispose(); |
||||
|
||||
return newImage; |
||||
} |
||||
|
||||
/** |
||||
* 缩放图像(按比例缩放) |
||||
* |
||||
* @param srcImg 源图像来源流 |
||||
* @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 |
||||
* @param opacityCompatible 是否处理背景透明 |
||||
*/ |
||||
public static Image scale(BufferedImage srcImg, float scale, boolean opacityCompatible) { |
||||
if (scale < 0) { |
||||
// 自动修正负数
|
||||
scale = -scale; |
||||
} |
||||
|
||||
int width = mul(Integer.toString(srcImg.getWidth(null)), Float.toString(scale)).intValue(); // 得到源图宽
|
||||
int height = mul(Integer.toString(srcImg.getHeight(null)), Float.toString(scale)).intValue(); // 得到源图长
|
||||
return scale(srcImg, width, height, opacityCompatible); |
||||
} |
||||
|
||||
private static BigDecimal mul(String v1, String v2) { |
||||
return mul(new BigDecimal(v1), new BigDecimal(v2)); |
||||
} |
||||
|
||||
private static BigDecimal mul(BigDecimal v1, BigDecimal v2) { |
||||
return v1.multiply(v2); |
||||
} |
||||
|
||||
/** |
||||
* 缩放图像(按长宽缩放) |
||||
* 目标长宽与原图不成比例会变形 |
||||
* |
||||
* @param srcImg 源图像来源流 |
||||
* @param width 目标宽度 |
||||
* @param height 目标高度 |
||||
* @param opacityCompatible 是否处理背景透明 |
||||
* @return {@link Image} |
||||
*/ |
||||
private static Image scale(BufferedImage srcImg, int width, int height, boolean opacityCompatible) { |
||||
int srcHeight = srcImg.getHeight(null); |
||||
int srcWidth = srcImg.getWidth(null); |
||||
int scaleType; |
||||
if (srcHeight == height && srcWidth == width) { |
||||
// 源与目标长宽一致返回原图
|
||||
return srcImg; |
||||
} else if (srcHeight < height || srcWidth < width) { |
||||
// 放大图片使用平滑模式
|
||||
scaleType = Image.SCALE_SMOOTH; |
||||
} else { |
||||
scaleType = Image.SCALE_DEFAULT; |
||||
} |
||||
if (opacityCompatible) {//需要保留透明度背景
|
||||
BufferedImage toImg = CoreGraphHelper.createBufferedImage(width, height, srcImg.getType()); |
||||
Graphics2D g2d = toImg.createGraphics(); |
||||
toImg = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); |
||||
g2d.dispose(); |
||||
|
||||
g2d = toImg.createGraphics(); |
||||
Image from = srcImg.getScaledInstance(width, height, scaleType); |
||||
g2d.drawImage(from, 0, 0, null); |
||||
g2d.dispose(); |
||||
return toImg; |
||||
} |
||||
return srcImg.getScaledInstance(width, height, scaleType); |
||||
} |
||||
} |
Loading…
Reference in new issue