html前端顯示tiff

0 問題的提出

項目中使用到了傳真(Fax)功能,而傳真收到的文件一般都是tif格式的。

我們需要把這樣的tif文件展示在前端。

後端會從某處下載這個tif文件,可以用字節數組表示這個文件。

1. 思路

思路1:修改擴展名。把tif修改爲jpg,png之類的擴展名

失敗,修改後直接用Chrome都無法正常展示。顯示一個小方格,即便是放大很多,也還是顯示不出圖片。

思路2:講byte[]返回Base64編碼字符串。

我們知道:<img>標籤的src可以使用Base64編碼字符串來顯示圖片。那麼我們直接返回tif的Base64字符串,然後指定其類型爲image/jpg會怎樣呢?

失敗,無論修改爲image/jpg還是image/tig等其它類型,其顯示結果都和直接修改擴展名在chrome下的顯示結果一樣。

<img src="data:image/jpg;base64,XXXXXXBase64StringXXXXX" />

思路3:用Java把tif轉換爲jpg

在調查中發現,Java有JAI可以實現將tif轉換爲jpg格式。代碼比較簡單:

import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;

import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;

public class Test {
	public static void main(String[] args) throws Exception {
		/* tif轉換到jpg格式 */
		String input = "D:/1.tif";
		String output = "D:/1.jpg";
		RenderedOp src = JAI.create("fileload", input);
		OutputStream os = new FileOutputStream(output);
		// ImageEncodeParam接口有JPEGEncodeParam,BMPXXX,PNGXXX,TIFFXXX實現類
		JPEGEncodeParam param = new JPEGEncodeParam();
		// 指定格式類型,jpg 屬於 JPEG 類型
		ImageEncoder enc = ImageCodec.createImageEncoder("JPEG", os, param);
		enc.encode(src);
		os.close();
	}
}

放棄,並不是這個方法不可用,而是JAI的包在Maven倉庫中找不到。

項目中使用的是客戶方私服,想要加個jar進去比較困難。

思路4:Java把tif轉換爲pdf

項目中已經使用了iText 2.1.7,那麼把tif直接作爲圖片放在pdf文件中是不是就可以了呢?

package com.example.async;

import java.io.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
import com.lowagie.text.pdf.codec.*;

public class TiffToPDF {

	public static void main(String[] args) {
		if (args.length < 1) {
			System.out.println("Usage: Tiff2Pdf file1.tif [file2.tif  fileN.tif]");
			System.exit(1);
		}

		String tiff, pdf;
		for (int i = 0; i < args.length; i++) {
			tiff = args[i];
			pdf = tiff.substring(0, tiff.lastIndexOf('.') + 1) + "pdf";
			Document document = new Document(PageSize.LETTER, 0, 0, 0, 0);
			int pages = 0, comps = 0;
			try {
				PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdf));
				document.open();
				PdfContentByte cb = writer.getDirectContent();
				RandomAccessFileOrArray ra = null;
				try {
					ra = new RandomAccessFileOrArray(tiff);
					comps = TiffImage.getNumberOfPages(ra);
				} catch (Throwable e) {
					System.out.println("Exception in " + tiff + " " + e.getMessage());
					continue;
				}

				System.out.println("Processing: " + tiff);
				for (int c = 0; c < comps; ++c) {
					try {
						Image img = TiffImage.getTiffImage(ra, c + 1);
						if (img != null) {
							System.out.println("page " + (c + 1));
							img.scalePercent(7200f / img.getDpiX(), 7200f / img.getDpiY());
							document.setPageSize(new Rectangle(img.getScaledWidth(), img.getScaledHeight()));
							img.setAbsolutePosition(0, 0);
							cb.addImage(img);
							document.newPage();
							++pages;
						}
					} catch (Throwable e) {
						System.out.println("Exception " + tiff + " page " + (c + 1) + " " + e.getMessage());
					}
				}
				ra.close();
				document.close();
			} catch (Throwable e) {
				e.printStackTrace();
			}
			System.out.println("done...");
		}
	}
}

上面的代碼存在兩個問題:

1. 一直沒法調整tif圖片在pdf文件的大小,無法讓圖片填滿整個pdf。預期至少是水平方面填滿,垂直方向按比例拉伸。

2. 部分tif處理會報異常:java.lang.RuntimeException: Scanline must begin with EOL code word. 撒(主要是說tif文件可能是invalid或者corrupt了,可以通過指定recoverFromImageError參數來讀取無效的tiff,但是似乎2.1.7版本並沒有這個參數)。

思路5:使用JavaScript:tiff.js來顯示tif

在後續的調查中發現,有個tiff.js可以實現對tiff圖片的預覽展示。

注意:除了tiff.js,其在GitHub上還說了兩個其它方案:

https://github.com/photopea/UTIF.js

https://github.com/image-js/tiff

tiff.js用法非常簡單,在引入tiff.min.js後,使用如下代碼即可顯示tif:

// 1.發送請求獲取arraybuffer
// 2.使用Tiff轉換爲canvas並顯示
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open('GET', "url/of/a/tiff/image/file.tiff");
xhr.onload = function (e) {
  var tiff = new Tiff({buffer: xhr.response});
  var canvas = tiff.toCanvas();
  document.body.append(canvas);
};
xhr.send();

上面使用原生的XMLHttpRequest去獲取tif文件的arraybuffer,我們項目中使用的是接口返回的byte[](Jackson返回的時候會對byte[]轉換爲Base64返回),後端代碼如下所示:

@Controller
@RequestMapping("/tif")
public class TifController {

	@GetMapping("/download")
	@ResponseBody
	public Map<String, Object> downloadTif() {
		String fileName = "1.tif";
		String filePath = "D:" + File.separator + fileName;
		File file = new File(filePath);

		Map<String, Object> result = new HashMap<String, Object>();
		result.put("fileName", fileName);
		try {
			// Jackson會對byte[]會編碼爲Base64字符串,所以前端需要解碼
			result.put("fileContent", FileUtils.readFileToByteArray(file));
		} catch (IOException e) {
			// TODO exception handle
		}
		result.put("filelLength", file.length());
		return result;
	}

}

前端AngularJS展示的代碼調整如下:

$scope.showTif = function() {
    $http({
        method: 'GET',
        responseType: 'json',
        url: '/tif/download'
    }).then(function successCallback(response) {
        var buffer = $scope.decodeBase64(response.data.fileContent);
        var tiff = new Tiff({
            buffer : buffer
        });
        var canvas = tiff.toCanvas();
        var width = tiff.width();
        var height = tiff.height();
        if (canvas) {
            $('#output').empty().append(canvas);
        }  
    }, function errorCallback(response) {
        console.log("error...");
    });
}

$scope.decodeBase64 = function(base64Str) {
    var bString = atob(base64Str);
    var len = bString.length;
    var arr = new Uint8Array(len);
    while (len--) {
        arr[len] = bString.charCodeAt(len);
    }
    return arr;
}

詳細代碼見附件,示例訪問地址:

http://localhost:8080/tiff-demo-upload-tiff.html

http://localhost:8080/angularjs-show-tif.html

源代碼:https://download.csdn.net/download/u012383839/11830615

參考

1. [前端img標籤顯示 base64格式的圖片](https://blog.csdn.net/kukudehui/article/details/80409522)

2. [JAVA 實現jpg/tif/bmp 等圖片之間格式得互相轉換](https://www.iteye.com/blog/yangpanwww-1127787)

3. [java實現 tiff圖片 轉 JPG圖片(完美解決)](https://blog.csdn.net/mufeng633/article/details/83380510)

4. [java使用itextpdf將圖片轉換成pdf時DPI的問題](https://blog.csdn.net/lizhengyu891231/article/details/81052594)

5. [Tiff to PDF in Java (itext)](https://blog.csdn.net/zzh87615/article/details/5839790)

6. [Exception: Scanline must begin with EOL code word](https://stackoverflow.com/questions/29787388/exception-when-converting-tiff-file-to-pdf-file-with-itext

7. [Github tiff.js] (https://github.com/seikichi/tiff.js)

8. [GitHub:使用tiff.js上傳tif並展示的例子](http://seikichi.github.io/tiff.js/upload.html

9. [Spring Boot直接訪問靜態html頁面](https://blog.csdn.net/csdn_liumh/article/details/81939664

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章