侧边栏壁纸
  • 累计撰写 27 篇文章
  • 累计创建 9 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

java图片处理,自己踩过的那些坑。java.awt的学习笔记!!!

仓鼠
2024-03-04 / 0 评论 / 0 点赞 / 67 阅读 / 20621 字 / 正在检测是否收录...

序言

大学毕设做的是 游戏-QQ机器人查询工具,选择的国外super cell的游戏COC(也是因为国内的游戏生态不提供API接口,一般都被鹅厂、猪场"独裁"了,甚至super cell最近上线的荒野行动国服,也被鹅肠进行了掌控)。
选择的QQ作为载体,所以很多大数据量的情况加就需要弃用文字,使用图片。那么使用图片就需要进行图片生成,所以开始在java.awt.* 的包下进行各种踩坑之旅。

都说java处理图片,没有python优秀。但是既然选择了java,就要对他负责到底。
java只是一门语言,优秀与否,还是取决去使用它的人!

  • 首先亮出两张java生成后的图片给大家看效果。

这里并不完全都是代码生成的,模板是提前做好的!其目的也是为了减少代码的重复工作!

在开发过程中,使用BufferedImage遇到的问题,解决的和未解决的问题!

1.锯齿效果(已解决)

之前生成的图片,文字放大后完全不能看,被啃了一样,文字小的看了也别扭!

public static void main(String[] args) {
		try {
			BufferedImage image = new BufferedImage(800, 900, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = (Graphics2D)image.createGraphics();
			g.setFont(new Font("微软雅黑", Font.BOLD, 100));
			g.setColor(Color.white);
			g.drawString("文字测试", 60, 200);
			ImageIO.write(image, "png", new File("G:\\image\\test2.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

上面是正常情况下写的代码,但是生成的图片,文字和“狗啃了”差不多,于是在百度的了解下,加入代码!

g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);

完美解决!!!

20200713161707606.png


2.自定义文字颜色and文字字体(已解决)

在生成图片中,java自带的字体、颜色不够我们使用。

颜色的问题,Color类就自带的有使用RGB来进行绘色!

Color color = new Color(红,绿,蓝)

字体的问题,【后期以及全部用java自带的字体】
①首先贴出一段查询自己电脑可以使用那些文字,以及文字使用后效果的代码。直接复制运行即可。

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageFont {
	private static String saveFile = "c://fontAll.png";
	public static void main(String[] args) {
		try {
			java.awt.GraphicsEnvironment eq = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
			String[] a = eq.getAvailableFontFamilyNames(); 
			
			BufferedImage image = new BufferedImage(1600, (a.length+2)*30 + 80, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = (Graphics2D)image.createGraphics();
			g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
			for (int i = 1; i < a.length+1; i++) {
				Font font = new Font(a[i-1],Font.CENTER_BASELINE,25);
				g.setFont(font);
				g.drawString(a[i-1], 10, 30*i);
				g.drawString("1234567890N一", 800, 30*i);
			}
			ImageIO.write(image, "png", new File(saveFile));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

②引入自定义字体
【经过测试,执行速度没有使用java自带的字体执行快】

这里就不引入代码了,我做了简单封装,可能大家并不适用,但是论坛有相关帖子java引入自定义字体的方法。直接食用。展示引入“包图小白体”后的效果图:

3.文字居中 自动换行的处理。(未完美处理)

20200713165340677.png

g.drawString(内容,X, y);
  • 因为文字是根据文字内容,XY坐标从做往右进行排列,并不会进行居中,和自动换行操作
  • 自认为,换行处理没有处理的完美。 代码冗余,使用的substring分割的字符串。
  • 文字换行处理方式:
    分割字符串 --> 分割后循环遍历,增加y轴高度。

这里有个很严重的问题,就是 汉字 和 数字字母符号 长度不同,对于处理文字+数字的方式,界面极不友好美观,所以在处理字符串的时候将所有字符进行的全角处理!当然字体也会影响文字的大小!


  • 文本内容居中 代码如下
Font font=new Font("微软雅黑",Font.PLAIN,50);  
FontMetrics fontMetrics = g.getFontMetrics(Font);
int textWidth = fontMetrics .stringWidth(文本内容);
int X = (图片宽度 - textWidth) / 2;

是否居中一目了然,如下生成的文字居中图片

20200713182021177.png

4.特殊文字处理,只显示方框(部分处理)

这个坑,确实难填。因为coc是一款全球游戏,覆盖了各国语言,所以很多种语言,或者符号,drawString 都是不认可的,所以只能在填入的text文本内容之前,对text进行处理了,这点没啥好说的,转换字符集。百度各种办法,但是用到对于特殊符号,最好的解决办法还是使用“Menlo”的的字体!!!

 Font font = new Font("Menlo", Font.BOLD, 120)

5.图片处理问题--压缩、水印、旋转、拼接

这里推荐Google的java开源 thumbnailator !!!

BufferedImage - Graphics2D 图片处理 文字居中换行util

/***
 *
 * @param g Graphics2D
 * @param font Font
 * @param text 文本内容
 * @param x    起始点X轴坐标
 * @param y    起始点Y轴坐标
 * @param maxWidth  文字最大长度
 */
public static void content(Graphics2D g , Font font , String text , int x , int y , int maxWidth) {
    FontMetrics fontMetrics = g.getFontMetrics(font);
    int textWidth = fontMetrics.stringWidth(text);
    int X = (maxWidth - textWidth) / 2;
    g.drawString(text,x+X,y);
}

BufferedImage - Graphics2D 图片处理 文字自动换行util

/***
*
* @param g Graphics2D
* @param font Font
* @param text 文本内容
* @param x    起始点X轴坐标
* @param y    起始点Y轴坐标
* @param maxWidth  文字最大长度
*/
public static void drawString(Graphics2D g , Font font , String text , int x , int y , int maxWidth) {
    JLabel label = new JLabel(text);
     label.setFont(font);
     FontMetrics metrics = label.getFontMetrics(label.getFont());
     int textH = metrics.getHeight();
     int textW = metrics.stringWidth(label.getText()); //字符串的宽
     String tempText = text;
     while(textW > maxWidth) {
         int n = textW / maxWidth;
         int subPos = tempText.length() / n;
         String drawText = tempText.substring(0 , subPos);
         int subTxtW = metrics.stringWidth(drawText);
         while(subTxtW > maxWidth) {
             subPos--;
             drawText = tempText.substring(0 , subPos);
             subTxtW = metrics.stringWidth(drawText);
         }
         g.drawString(drawText , x , y);
         y += textH;
         textW = textW - subTxtW;
         tempText = tempText.substring(subPos);
     }

     g.drawString(tempText , x , y);
 }

1.关于获取网络图片

网络图片,通过HTTP获取图片,然后进行处理,或者拼接!


如下,httpsGet 方法,可获取HTTPS 需要进行SSL校验的请求,并获取返回的BufferedImage
HTTP获取的方法,网络有很多。其中只需要通过InputStream 流获取,然后通过ImageIO.read(InputStream);的方式将内容转换成BufferedImage供我们进行操作

  • 如下提供一个发送HTTPS请求的工具类,需要HttpClient工具 ,如下导入maven
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.7</version>
</dependency>

import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpUtils;

import org.apache.commons.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Https {
	
	
	private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    /**
     * 定义类型,用于获取不同类型的httpclient
     */
    enum CLIENT_TYPE {
        HTTP, HTTPS
    }

    /**
     * https post请求
     *
     * @param url        请求地址
     * @param headerMap  请求头信息
     * @param contentMap 请求体信息
     * @return 结果返回
     */
    public static String httpsPost(String url, Map<String, String> headerMap, Map<String, String> contentMap) {
        return httpsPost(url, headerMap, contentMap, "UTF-8");
    }

    /**
     * http post请求
     *
     * @param url        请求地址
     * @param headerMap  请求头信息
     * @param contentMap 请求体信息
     * @return 结果返回
     */
    public static String httpPost(String url, Map<String, String> headerMap, Map<String, String> contentMap) {
        return httpPost(url, headerMap, contentMap, "UTF-8");
    }

    /**
     * https get请求
     *
     * @param url      请求地址
     * @param paramMap 请求参数
     * @return 结果返回
     */
    public static BufferedImage httpsGet(String url, Map<String, String> paramMap) {
        return httpsGet(url, paramMap, "UTF-8");
    }
    /**
     * https get请求
     *
     * @param url      请求地址
     * @param paramMap 请求参数
     * @return 结果返回
     */
    public static String httpsGetTxt(String url, Map<String, String> paramMap) {
        return httpsGetTxt(url, paramMap, "UTF-8");
    }

    /**
     * http get请求
     *
     * @param url      请求地址
     * @param paramMap 请求参数
     * @return 结果返回
     */
    public static BufferedImage httpGet(String url, Map<String, String> paramMap) {
        return httpGet(url, paramMap, "UTF-8");
    }

    /**
     * @param url        请求地址
     * @param headerMap  请求头信息
     * @param contentMap 请求体信息
     * @param charset    编码类型
     * @return 结果返回
     */
    public static String httpsPost(String url, Map<String, String> headerMap, Map<String, String> contentMap, String charset) {
        return post(url, headerMap, contentMap, charset, CLIENT_TYPE.HTTPS);
    }

    /**
     * @param url        请求地址
     * @param headerMap  请求头信息
     * @param contentMap 请求体信息
     * @param charset    编码类型
     * @return 结果返回
     */
    public static String httpPost(String url, Map<String, String> headerMap, Map<String, String> contentMap, String charset) {
        return post(url, headerMap, contentMap, charset, CLIENT_TYPE.HTTP);
    }

    /**
     * @param url      请求地址
     * @param paramMap 请求参数
     * @param charset  编码类型
     * @return 结果返回
     */
    public static BufferedImage httpsGet(String url, Map<String, String> paramMap, String charset) {
        return get(url, paramMap, charset, CLIENT_TYPE.HTTPS);
    }
    /**
     * @param url      请求地址
     * @param paramMap 请求参数
     * @param charset  编码类型
     * @return 结果返回
     */
    public static String httpsGetTxt(String url, Map<String, String> paramMap, String charset) {
        return getTxt(url, paramMap, charset, CLIENT_TYPE.HTTPS);
    }
    /**
     * @param url      请求地址
     * @param paramMap 请求参数
     * @param charset  编码类型
     * @return 结果返回
     */
    public static BufferedImage httpGet(String url, Map<String, String> paramMap, String charset) {
        return get(url, paramMap, charset, CLIENT_TYPE.HTTP);
    }

    /**
     * post 请求的实际方法
     *
     * @param url        请求地址
     * @param headerMap  请求头信息
     * @param contentMap 请求体信息
     * @param charset    编码类型
     * @param type       协议类型
     * @return 结果返回
     */
    private static String post(String url, Map<String, String> headerMap, Map<String, String> contentMap, String charset, CLIENT_TYPE type) {

        String result = null;
        HttpClient httpClient = null;
        try {
            HttpPost post = new HttpPost(url);
            if (MapUtils.isNotEmpty(headerMap)) {// 设置请求头
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    post.addHeader(entry.getKey(), entry.getValue());
                }
            }

            if (MapUtils.isNotEmpty(contentMap)) {// 设置请求体
                List<NameValuePair> content = getNameValuePairList(contentMap);
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(content, charset);
                post.setEntity(entity);
            }

            httpClient = getClient(type);//这里是重点,根据不同协议获取不同类型的client端
            HttpResponse response = httpClient.execute(post);//发送请求并接收返回数据
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
            return result;
        } catch (Exception ex) {
            throw new RuntimeException("请求:" + url + " 异常:" + ex.getMessage());
        } finally {
            try {
                if (null != httpClient && null != httpClient.getConnectionManager()) {
                    httpClient.getConnectionManager().shutdown();
                }
            } catch (Exception e) {
                logger.error("请求:" + url + " 流关闭异常或者httpclient关闭异常");
            }
        }
    }

    /**
     * get 请求的实际方法
     *
     * @param url      请求地址
     * @param paramMap 请求参数
     * @param charset  编码类型
     * @param type     协议类型
     * @return 结果返回
     */
    private static BufferedImage get(String url, Map<String, String> paramMap, String charset, CLIENT_TYPE type) {

        HttpClient httpClient = null;
        try {
            if (MapUtils.isNotEmpty(paramMap)) {// 拼接参数
                // 设置请求体
                List<NameValuePair> content = getNameValuePairList(paramMap);
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(content, charset);
                String params = EntityUtils.toString(entity);
                url = url + "?" + params;
            }
            HttpGet get = new HttpGet(url);
            get.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36");
            get.addHeader("authorization", "Bearer"+BackEndHttpRequest.API);
            httpClient = getClient(type);
            RequestConfig config = RequestConfig.custom().setConnectTimeout(1000) //连接超时时间
                    .setSocketTimeout(1000*10) //数据传输的超时时间
                    .build();
            get.setConfig(config);
            HttpResponse response = httpClient.execute(get);            //发送请求并接收返回数据
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                String value = resEntity.getContentType().getValue();
                System.out.println("返回图片为"+value);
                InputStream content = resEntity.getContent();
                BufferedImage image = ImageIO.read(content);
                return image;
            }
            return null;
        } catch (Exception ex) {
            throw new RuntimeException("请求:" + url + " 异常:" + ex.getMessage());
        } finally {
            try {
            	
            } catch (Exception e) {
                logger.error("请求:" + url + " 流关闭异常或者httpclient关闭异常");
            }
        }
    }
    /**
     * get 请求的实际方法
     *
     * @param url      请求地址
     * @param paramMap 请求参数
     * @param charset  编码类型
     * @param type     协议类型
     * @return 结果返回
     */
    private static String getTxt(String url, Map<String, String> paramMap, String charset, CLIENT_TYPE type) {
    	String result = "";
        HttpClient httpClient = null;
        try {
            if (MapUtils.isNotEmpty(paramMap)) {// 拼接参数
                // 设置请求体
                List<NameValuePair> content = getNameValuePairList(paramMap);
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(content, charset);
                String params = EntityUtils.toString(entity);
                url = url + "?" + params;
            }
            HttpGet get = new HttpGet(url);
            get.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36");
            get.addHeader("authorization", "Bearer"+BackEndHttpRequest.API);
            httpClient = getClient(type);
            RequestConfig config = RequestConfig.custom().setConnectTimeout(1000) //连接超时时间
                    .setSocketTimeout(1000*10) //数据传输的超时时间
                    .build();
            get.setConfig(config);
            HttpResponse response = httpClient.execute(get);            //发送请求并接收返回数据
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
                return result;
            }
            return null;
        } catch (Exception ex) {
            throw new RuntimeException("请求:" + url + " 异常:" + ex.getMessage());
        } finally {
            try {
            	
            } catch (Exception e) {
                logger.error("请求:" + url + " 流关闭异常或者httpclient关闭异常");
            }
        }
    }
    private static List<NameValuePair> getNameValuePairList(Map<String, String> paramMap) {
        List<NameValuePair> content = null;
        if (MapUtils.isNotEmpty(paramMap)) {
            // 设置请求体
            content = new ArrayList<NameValuePair>();
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                content.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }
        return content;
    }

    /**
     * 根据指定类型返回http、https类型的客户端
     *
     * @param type 类型
     * @return 客户端
     * @throws Exception 异常信息
     */
    private static DefaultHttpClient getClient(CLIENT_TYPE type) throws Exception {
        if (type == CLIENT_TYPE.HTTP) {//http类型
            return new DefaultHttpClient();
        } else if (type == CLIENT_TYPE.HTTPS) {//https类型
            return new SSLClient();
        } else {
            throw new RuntimeException("未知协议类型,请重新指定");
        }
    }

    /**
     * 自定义SSL client
     */
    static class SSLClient extends DefaultHttpClient {
        public SSLClient() throws Exception {
            super();
            X509TrustManager tm = new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            //传输协议需要根据自己的判断 
            //SSLContext ctx = SSLContext.getInstance("TLSv1.2");
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[]{tm}, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = this.getConnectionManager();
            SchemeRegistry sr = ccm.getSchemeRegistry();
            sr.register(new Scheme("https", 443, ssf));
        }
    }

    
}

0

评论区