欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Java生成二維碼分享海報(bào)-創(chuàng)新互聯(lián)

這一篇文章我們就用 Java 來(lái)生成一下仿金山詞霸的海報(bào)。

我們擁有十年網(wǎng)頁(yè)設(shè)計(jì)和網(wǎng)站建設(shè)經(jīng)驗(yàn),從網(wǎng)站策劃到網(wǎng)站制作,我們的網(wǎng)頁(yè)設(shè)計(jì)師為您提供的解決方案。為企業(yè)提供網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序設(shè)計(jì)、手機(jī)網(wǎng)站開發(fā)、HTML5、等業(yè)務(wù)。無(wú)論您有什么樣的網(wǎng)站設(shè)計(jì)或者設(shè)計(jì)方案要求,我們都將富于創(chuàng)造性的提供專業(yè)設(shè)計(jì)服務(wù)并滿足您的需求。

As long as you can still grab a breath, you fight.
只要一息尚存,就不得不戰(zhàn)。

有那么一段時(shí)間,我特別迷戀金山詞霸的每日一句分享海報(bào)。因?yàn)椴粌H海報(bào)上的圖片美,文字也特別美,美得讓我感覺生活都有了詩(shī)意。就像文章開頭的那句中英文對(duì)照,中文和英文都妙極了。

最近,又有很多人迷戀上了流利說(shuō)的小程序分享海報(bào)(朋友圈比比皆是)。但不管是金山詞霸還是流利說(shuō),分享的海報(bào)都不是自己的二維碼,這對(duì)于個(gè)人品牌的締造者來(lái)說(shuō),實(shí)在是一件出力不討好的事。

當(dāng)然了,這種事難不倒作為程序員的我。

01、大致思路

  • 采集網(wǎng)絡(luò)圖片

  • 加載海報(bào)背景和個(gè)人品牌二維碼

  • 利用 Graphics2D 將網(wǎng)絡(luò)圖片繪制成海報(bào)封面

  • 利用 Graphics2D 在海報(bào)上打印中英文對(duì)照語(yǔ)

  • 利用 Graphics2D 在海報(bào)上繪制個(gè)人專屬二維碼

  • 使用 Swing 構(gòu)建圖形化界面

  • 將項(xiàng)目打成 jar 包發(fā)行

  • 運(yùn)行 jar 包,填寫必要信息后生成海報(bào)

02、采集網(wǎng)絡(luò)圖片

第一步,獲取網(wǎng)絡(luò)圖片的路徑。金山詞霸每日一句的圖片路徑地址形式如下所示。可以根據(jù)當(dāng)前日期獲取最新的圖片路徑。

// 金山詞霸的圖片路徑
String formatDate = DateFormatUtils.format(new Date(), "yyyyMMdd");
String picURL = "http://cdn.iciba.com/news/word/big_" + formatDate + "b.jpg";

第二步,有了圖片路徑后,可以根據(jù)此路徑創(chuàng)建 HTTP get 請(qǐng)求。

// 根據(jù)路徑發(fā)起 HTTP get 請(qǐng)求
HttpGet httpget = new HttpGet(picURL);
// 使用 addHeader 方法添加請(qǐng)求頭部
httpget.addHeader("Content-Type", "text/html;charset=UTF-8");

// 配置請(qǐng)求的超時(shí)設(shè)置
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(500).setConnectTimeout(500)
        .setSocketTimeout(500).build();
httpget.setConfig(requestConfig);

第三步,創(chuàng)建 CloseableHttpClient 對(duì)象來(lái)執(zhí)行 HTTP get 請(qǐng)求,并獲取響應(yīng)信息 CloseableHttpResponseCloseableHttpClient 是一個(gè)抽象類,它是 HttpClient 的基本實(shí)現(xiàn),也實(shí)現(xiàn)了 java.io.Closeable 接口。

CloseableHttpClient httpclient = HttpClientBuilder.create().build();
CloseableHttpResponse response = httpclient.execute(httpget);

第四步,從 CloseableHttpResponse 中獲取圖片的輸入流。

HttpEntity entity = response.getEntity();
InputStream picStream = entity.getContent();

第五步,從圖片輸入流中讀取信息,并輸出到本地文件中。

File pic = Files.createTempFile(Paths.get("D:\\test"), "pic_", ".jpg");
FileOutputStream fos = new FileOutputStream(pic);
int read = 0;

// 1024Byte(字節(jié))=1KB 1024KB=1MB
byte[] bytes = new byte[1024 * 100];
while ((read = inputStream.read(bytes)) != -1) {
    fos.write(bytes, 0, read);
}

fos.flush();
fos.close();

在指定的臨時(shí)目錄下可以查看采集到的圖片,如下所示。

Java生成二維碼分享海報(bào)

03、加載海報(bào)背景和個(gè)人品牌二維碼

海報(bào)背景的大小為 678 1013 像素,個(gè)人品牌二維碼的大小為 128 128 像素。兩張圖片都是事先準(zhǔn)備好的,放在 src 目錄下。整個(gè)項(xiàng)目的目錄結(jié)構(gòu)圖如下所示。

Java生成二維碼分享海報(bào)

接下來(lái),我們把這兩張圖片分別讀取到臨時(shí)文件當(dāng)中,供后續(xù)動(dòng)作使用。

第一步,創(chuàng)建 ClassLoader 對(duì)象,從 classpath 的根路徑下查找資源。

ClassLoader classLoader = ReadBgAndQrcode.class.getClassLoader();

第二步,通過 classLoader.getResourceAsStream() 讀取海報(bào)背景和個(gè)人品牌二維碼,復(fù)制到臨時(shí)文件中。

File bgFile = Files.createTempFile(DIRECTORY, "bg_", ".jpg").toFile();
InputStream inputStream = classLoader.getResourceAsStream("default_bgimg.jpg");
FileUtils.copyInputStreamToFile(inputStream, bgFile);
logger.debug("背景:" + bgFile.getAbsolutePath());

File qrcodeFile = Files.createTempFile(DIRECTORY, "qrcode_", ".jpg").toFile();
InputStream qrcodeInputStream = classLoader.getResourceAsStream("default_qrcodeimg.jpg");
FileUtils.copyInputStreamToFile(qrcodeInputStream, qrcodeFile);
logger.debug("二維碼:" + qrcodeFile.getAbsolutePath());

在指定的臨時(shí)目錄下可以查看海報(bào)背景和個(gè)人品牌二維碼,如下所示。

Java生成二維碼分享海報(bào)

05、利用 Graphics2D 將網(wǎng)絡(luò)圖片繪制成海報(bào)封面

Graphics2D 類擴(kuò)展了 Graphics 類,提供了對(duì)幾何形狀、坐標(biāo)轉(zhuǎn)換、顏色管理和文本布局更為復(fù)雜的控制,是用于呈現(xiàn)二維形狀、文本和圖像的基礎(chǔ)類。

BufferedImage 使用可訪問的圖像數(shù)據(jù)緩沖區(qū)描述圖像,由顏色模型和圖像數(shù)據(jù)柵格組成,所有 BufferedImage 對(duì)象的左上角坐標(biāo)為(0,0)。

可以利用 BufferedImage 類的 createGraphics() 方法獲取 Graphics2D 對(duì)象。

第一步,將海報(bào)背景和海報(bào)封面讀入到 BufferedImage 對(duì)象中。注意,deleteOnExit() 方法請(qǐng)求在虛擬機(jī)終止時(shí)刪除此抽象路徑名所表示的文件或目錄。

// 背景
File bgFile = FileUtil.read("bg_", ".jpg", "default_bgimg.jpg");
bgFile.deleteOnExit();
BufferedImage bgImage = ImageIO.read(bgFile);

// 封面圖
File picFile = CapturePic.capture();
picFile.deleteOnExit();
BufferedImage picImage = ImageIO.read(picFile);

第二步,計(jì)算封面圖的起始坐標(biāo),以及高度和寬度。

// 封面圖的起始坐標(biāo)
int pic_x = MARGIN, pic_y = MARGIN;
// 封面圖的寬度
int pic_width = bgImage.getWidth() - MARGIN * 2;
// 封面圖的高度
int pic_height = picImage.getHeight() * pic_width / picImage.getWidth();

第三步,在海報(bào)背景上繪制封面圖。

Graphics2D graphics2d = bgImage.createGraphics();
// 在背景上繪制封面圖
graphics2d.drawImage(picImage, pic_x, pic_y, pic_width, pic_height, null);
// 釋放圖形上下文,以及它正在使用的任何系統(tǒng)資源。
graphics2d.dispose();

第四步,將繪制好的圖像輸出到文件中。

File posterFile = Files.createTempFile(FileUtil.DIRECTORY, "poster_", ".jpg").toFile();
ImageIO.write(bgImage, "jpg", posterFile);

在指定的臨時(shí)目錄下可以查看海報(bào),如下所示。

Java生成二維碼分享海報(bào)

06、利用 Graphics2D 在海報(bào)上打印中文

Font 類表示字體,用于以可見的方式呈現(xiàn)文本。字體提供了將字符序列映射到象形文字序列以及在圖形和組件對(duì)象上呈現(xiàn)象形文字序列所需的信息。

第一步,通過 GraphicsEnvironment 類的 getAvailableFontFamilyNames() 查看計(jì)算機(jī)上允許使用的字體。

String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

for (String fontName : fontNames) {
    System.out.println(fontName);
}

大致的中文字體有這么一些(還有更多,未列出):

宋體
幼圓
微軟雅黑
微軟雅黑 Light
新宋體
方正姚體
方正舒體
楷體
隸書
黑體

第二步,設(shè)置字體和顏色。

// Font 的構(gòu)造參數(shù)依次是字體名字,字體式樣,字體大小
Font font = new Font("微軟雅黑", Font.PLAIN, 28);
g.setFont(font);
// RGB
g.setColor(new Color(71, 71, 71));

第三步,根據(jù)當(dāng)前字體下每個(gè)中文字符的寬度,以及海報(bào)可容納的大文本寬度,對(duì)文本進(jìn)行換行。

計(jì)算每個(gè)字體的寬度時(shí),需要用到 sun.font.FontDesignMetrics,它擴(kuò)展了 java.awt.FontMetricsFentMetrics 類定義了一個(gè)字體度量對(duì)象,該對(duì)象封裝了有關(guān)在特定屏幕上呈現(xiàn)特定字體的信息。FontDesignMetrics 提供了更多指標(biāo)的 Font 信息。

FontDesignMetrics 有幾個(gè)重要的值需要說(shuō)明一下:

  • 基準(zhǔn)點(diǎn)是 baseline
  • ascent 是 baseline 之上至字符最高處的距離
  • descent 是 baseline 之下至字符最低處的距離
  • leading 文檔說(shuō)的很含糊,其實(shí)是上一行字符的 descent 到下一行的 ascent 之間的距離
  • top 指的是指的是最高字符到 baseline 的值,即 ascent 的大值
  • bottom 指的是最下字符到 baseline 的值,即 descent 的大值

Java生成二維碼分享海報(bào)

FontDesignMetricscharWidth() 方法可以計(jì)算字符的寬度。

public static String makeLineFeed(String zh, FontDesignMetrics metrics, int max_width) {
    StringBuilder sb = new StringBuilder();
    int line_width = 0;
    for (int i = 0; i < zh.length(); i++) {
        char c = zh.charAt(i);
        sb.append(c);

        // 如果主動(dòng)換行則跳過
        if (sb.toString().endsWith("\n")) {
            line_width = 0;
            continue;
        }

        // FontDesignMetrics 的 charWidth() 方法可以計(jì)算字符的寬度
        int char_width = metrics.charWidth(c);
        line_width += char_width;

        // 如果當(dāng)前字符的寬度加上之前字符串的已有寬度超出了海報(bào)的大寬度,則換行
        if (line_width >= max_width - char_width) {
            line_width = 0;
            sb.append("\n");
        }
    }
    return sb.toString();
}

假如文本是“沉默王二,《Web 全棧開發(fā)進(jìn)階之路》作者;一個(gè)不止寫代碼的程序員,還寫有趣有益的文字,給不喜歡嚴(yán)肅的你。”我們來(lái)通過 makeLineFeed() 方法試驗(yàn)一下。

Font font = new Font("微軟雅黑", Font.PLAIN, 28);
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);

String zh = "沉默王二,《Web 全棧開發(fā)進(jìn)階之路》作者;一個(gè)不止寫代碼的程序員,還寫有趣有益的文字,給不喜歡嚴(yán)肅的你。";

String[] rows = makeLineFeed(zh, metrics, 600).split("\n");
for (int i = 0; i < rows.length; i++) {
    System.out.println(rows[i]);
}

其結(jié)果如下所示。

沉默王二,《Web 全棧開發(fā)進(jìn)階之路》作者;
一個(gè)不止寫代碼的程序員,還寫有趣有益的文字
,給不喜歡嚴(yán)肅的你。

第四步,將自動(dòng)換行后的文本在海報(bào)背景上打印。

這里需要用到 FontDesignMetricsgetHeight() 方法獲取每行文本的高度。對(duì)照下面的示意圖,理解 height 的具體高度。

Java生成二維碼分享海報(bào)

// 自動(dòng)換行后的文本
String zhWrap = FontUtil.makeLineFeed(graphics2dPoster.getZh(), metrics, graphics2dPoster.getSuitableWidth());

// 拆分行
String[] zhWraps = zhWrap.split("\n");

// 將每一行在海報(bào)背景上打印
for (int i = 0; i < zhWraps.length; i++) {
    graphics2dPoster.addCurrentY(metrics.getHeight());
    graphics2d.drawString(zhWraps[i], MARGIN, graphics2dPoster.getCurrentY());
}

此時(shí)的海報(bào)效果如下圖所示。

Java生成二維碼分享海報(bào)

可以看得出,文字帶有很強(qiáng)的鋸齒感,怎么消除呢?

graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

如果英語(yǔ)不好的話,看起來(lái)這段代碼會(huì)很吃力。ANTIALIASING 單詞的意思就是“消除混疊現(xiàn)象,消除走樣,圖形保真”。

07、利用 Graphics2D 在海報(bào)上打印英文

英文和中文大的不同在于,換行的單位不再是單個(gè)字符,而是整個(gè)單詞。

第一步,根據(jù)當(dāng)前字體下每個(gè)英文單詞的寬度,以及海報(bào)可容納的大文本寬度,對(duì)文本進(jìn)行換行。

public static String makeEnLineFeed(String en, FontDesignMetrics metrics, int max_width) {
    // 每個(gè)單詞后追加空格
    char space = ' ';
    int spaceWidth = metrics.charWidth(space);

    // 按照空格對(duì)英文文本進(jìn)行拆分
    String[] words = en.split(String.valueOf(space));
    // 利用 StringBuilder 對(duì)字符串進(jìn)行修改
    StringBuilder sb = new StringBuilder();
    // 每行文本的寬度
    int len = 0;

    for (int i = 0; i < words.length; i++) {
        String word = words[i];

        int wordWidth = metrics.stringWidth(word);
        // 疊加當(dāng)前單詞的寬度
        len += wordWidth;

        // 超出大寬度,進(jìn)行換行
        if (len > max_width) {
            sb.append("\n");
            sb.append(word);
            sb.append(space);

            // 下一行的起始寬度
            len = wordWidth + spaceWidth;
        } else {
            sb.append(word);
            sb.append(space);

            // 多了一個(gè)空格
            len += spaceWidth;
        }
    }
    return sb.toString();
}

假如文本是“Fear can hold you prisoner. Hope can set you free. It takes a strong man to save himself, and a great man to save another.”我們來(lái)通過 makeEnLineFeed() 方法試驗(yàn)一下。

Font font = new Font("微軟雅黑", Font.PLAIN, 28);
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);

String en = "Fear can hold you prisoner. Hope can set you free. It takes a strong man to save himself, and a great man to save another.";
String[] rows = makeEnLineFeed(en, metrics, 600).split("\n");
for (int i = 0; i < rows.length; i++) {
    System.out.println(rows[i]);
}

其結(jié)果如下所示。

Fear can hold you prisoner. Hope can set
you free. It takes a strong man to save
himself, and a great man to save another.

第三步,將自動(dòng)換行后的文本在海報(bào)背景上打印。

// 設(shè)置封面圖和下方中文之間的距離
graphics2dPoster.addCurrentY(20);

Graphics2D graphics2d = graphics2dPoster.getGraphics2d();
graphics2d.setColor(new Color(157, 157, 157));

FontDesignMetrics metrics = FontDesignMetrics.getMetrics(graphics2d.getFont());
String enWrap = FontUtil.makeEnLineFeed(graphics2dPoster.getEn(), metrics, graphics2dPoster.getSuitableWidth());
String[] enWraps = enWrap.split("\n");
for (int i = 0; i < enWraps.length; i++) {
    graphics2dPoster.addCurrentY(metrics.getHeight());
    graphics2d.drawString(enWraps[i], MARGIN, graphics2dPoster.getCurrentY());
}

此時(shí)的海報(bào)效果如下圖所示。

Java生成二維碼分享海報(bào)

07、利用 Graphics2D 在海報(bào)上繪制個(gè)人專屬二維碼

有了前面繪制海報(bào)封面的經(jīng)驗(yàn),繪制二維碼就變得輕而易舉了。

// 二維碼
File qrcodeFile = FileUtil.read("qrcode_", ".jpg", "default_qrcodeimg.jpg");
qrcodeFile.deleteOnExit();

BufferedImage qrcodeImage = ImageIO.read(qrcodeFile);
// 二維碼起始坐標(biāo)
int qrcode_x = bgImage.getWidth() - qrcodeImage.getWidth() - MARGIN;
int qrcode_y = bgImage.getHeight() - qrcodeImage.getHeight() - MARGIN;
graphics2dPoster.getGraphics2d().drawImage(qrcodeImage, qrcode_x, qrcode_y, qrcodeImage.getWidth(),
        qrcodeImage.getHeight(), null);

此時(shí)的海報(bào)效果如下圖所示。

Java生成二維碼分享海報(bào)

是不是感覺海報(bào)的左下角比較空白,整體的對(duì)稱性不夠自然,那就在左下角追加一些二維碼的描述文本吧。

graphics2d.setColor(new Color(71, 71, 71));
Font font = new Font(USE_FONT_NAME, Font.PLAIN, 22);
graphics2d.setFont(font);
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(graphics2d.getFont());

graphics2d.drawString("沉默王二", MARGIN, bgImage.getHeight() - MARGIN - metrics.getHeight() * 2);
graphics2d.drawString("一個(gè)幽默的程序員", MARGIN, bgImage.getHeight() - MARGIN - metrics.getDescent());

此時(shí)的海報(bào)效果如下圖所示。

Java生成二維碼分享海報(bào)

08、使用 Swing 構(gòu)建圖形化界面

Swing 是一個(gè)用于 Java GUI 編程(圖形界面設(shè)計(jì))的工具包(類庫(kù));換句話說(shuō),Java 之所以可以用來(lái)開發(fā)帶界面的 PC 軟件,就是因?yàn)?Swing 的存在。

Swing 使用純粹的 Java 代碼來(lái)模擬各種控件,沒有使用本地操作系統(tǒng)的內(nèi)在方法,所以 Swing 是跨平臺(tái)的。也正是因?yàn)?Swing 的這種特性,人們通常把 Swing 控件稱為輕量級(jí)控件。

Eclipse 默認(rèn)是不支持可視化的 Swing 編程的,但 Eclipse 的插件市場(chǎng)上有這樣一個(gè)好插件——WindowBuilder,使用它可以大幅度地降低開發(fā)難度,迅速地提升開發(fā)效率。

下載地址:https://marketplace.eclipse.org/content/windowbuilder

可直接拖拽到 Eclipse 進(jìn)行安裝,如下圖。

Java生成二維碼分享海報(bào)

注意,Eclipse 的版本要求為:

2018-09 (4.9), Photon (4.8), Oxygen (4.7), Neon (4.6), 2018-12 (4.10), 2019-03 (4.11)

拖拽到 Eclipse 后的效果如下:

Java生成二維碼分享海報(bào)

安裝完成后,會(huì)提醒你重啟 Eclipse。

溫馨提示:安裝的過程大約持續(xù) 3 分鐘的時(shí)間,中間可能會(huì)失敗,重試幾次即可。不用擔(dān)心,Eclipse 會(huì)智能地保存失敗前的進(jìn)度。

安裝成功后,就可以使用可視化工具設(shè)計(jì)界面了,如下圖所示:

Java生成二維碼分享海報(bào)

09、將項(xiàng)目打成 jar 包發(fā)行

在將應(yīng)用程序進(jìn)行打包時(shí),使用者都希望開發(fā)者只提供一個(gè)單獨(dú)的文件,而不是包含大量源碼的文件夾。jar 包存在的目的正源于此。

將項(xiàng)目打成 jar 包也很簡(jiǎn)單,在 Eclipse 中,可依次右鍵項(xiàng)目→Export→Runnable JAR file。你將會(huì)看到以下界面。

Java生成二維碼分享海報(bào)

選擇 main 方法所在類,指定導(dǎo)出目標(biāo),選擇 Copy required libraries 選項(xiàng),點(diǎn)擊「Finish」即可。在指定的目錄下可找到生成的 jar 包文件。

Java生成二維碼分享海報(bào)

10、運(yùn)行 jar 包,填寫必要信息后生成海報(bào)

如果電腦上安裝了 Java 的運(yùn)行環(huán)境,雙擊該 jar 包文件就可以運(yùn)行。運(yùn)行后的界面,如下圖所示。可以填寫中文、英文、海報(bào)封面路徑,然后點(diǎn)擊按鈕生成海報(bào)。

Java生成二維碼分享海報(bào)

PS:為了便于大家的學(xué)習(xí),我已經(jīng)將源碼放在了 GitHub 上,地址如下。

https://github.com/qinggee/poster/tree/jinshanciba

趕快去 star 吧!

上一篇:Java :接口和抽象類,傻傻分不清

下一篇:Java:優(yōu)雅地處理異常真是一門學(xué)問啊!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)站標(biāo)題:Java生成二維碼分享海報(bào)-創(chuàng)新互聯(lián)
URL標(biāo)題:http://chinadenli.net/article18/gdedp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站企業(yè)網(wǎng)站制作標(biāo)簽優(yōu)化建站公司外貿(mào)網(wǎng)站建設(shè)網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷型網(wǎng)站建設(shè)