목차

TIFF 프리뷰 이미지 뷰어 가이드

예시

템플릿 위치: /HTML5/OSS/tiff_preview

템플릿 파일

화면 스크립트

/**
 * 이미지 파일 오브젝트, 추후 로컬 저장시나 처리할때 사용한다.
 * 2022.07.06 이미지 페이지 단위로 인쇄하게 처리
 */
this.objTiffFile = null;

// 화면 로드 이벤트
function screen_on_load()
{
	// tiff.min.js 라이브러리 로드
	this.loadTiffLib();

	// TIFF 이미지 URL 설정
	this.fld_text_multi.settext("./ext/media/multipage.tif");
}

/**
 * tiff.min.js 라이브러리 로드
 */
function loadTiffLib()
{
	// TIFF 이미지 처리용 라이브러리 로드 (프로젝트 환경에 따라 경로를 달라질 수 있음)
	// 템플릿이 저장된 디렉토리의 tiff.min.js 파일을 활용하세요.
	// https://github.com/seikichi/tiff.js/blob/master/README.md
	screen.loadjs("./ext/lib/tiff.min.js");

	// 초기 설정
	// When you load large tiff file, you will see the error message "Cannot enlarge memory arrays in asm.js"
	// in such case, please call 'Tiff.initialize({TOTAL_MEMORY: ... })' before you create a Tiff instance
	Tiff.initialize({ TOTAL_MEMORY: 16777216 * 10 });
}

/**
 * URL을 File 객체로 변경해서 리턴한다. (promise 객체)
 * @param {string} AUrl 이미지를 가져올 URL
 * @returns {promise} 이미지를 File Object로 생성해서 리턴한다.
 */
function getFileFromURL(image_url) {
	var sFileName, xhr;

	// 이미지를 가져오기 위한 XMLHttpRequest 오브젝트 생성
	xhr = new XMLHttpRequest();

	// 이미지 URL에서 파일 이름 추출
	sFileName = image_url.split("/").pop();

	return new Promise(function (resolv, reject) {
		// ASYNC 방식으로 XMLHttpRequest open 함수 호출
		xhr.open("GET", image_url, true);

		// 수신 데이터 형식을 BLOB 형식으로 지정
		xhr.responseType = "blob";

		// 정상 수신 이벤트 처리 함수
		xhr.onload = function (event) {
			// 파일을 정상적으로 가져왔다.
			resolv(new File([event.target.response], sFileName));
		};

		// 오류 수신 이벤트 처리 함수
		xhr.onerror = function (event) {
			// 파일을 제대로 못가져왔다.
			reject();
		};

		// XMLHttpRequest send 함수 호출
		xhr.send();
	});
}

/**
 * Tiff File오브젝트를 이용해서 이미지를 그리기 처리한다.
 * @param {File} ATiffFileObj 처리할 Tiff파일오브젝트
 */
function getDataURITiffFromFile(ATiffFileObj)
{
	var _this;

	_this = this;

	// 화면 Protect 처리
	screen.setscreenprotect(true, 30);

	// Tiff 이미지 데이터 정보 보관용 데이터셋 초기화
	this.xdImage.init();

	return new Promise(function (resolv, reject) {
		var reader = new FileReader();
		reader.onload = function (e) {
			var buffer = e.target.result;
			var tiffImage = new Tiff({ buffer: buffer });
			var intImageCount = tiffImage.countDirectory();

			// 이미지 갯수만큼 Loop를 돌면서 데이터 셋(xdImage)에 값 설정
			for (i = 0; i < intImageCount; i++) {
				tiffImage.setDirectory(i);
				_this.xdImage.addrow(false);
				_this.xdImage.setdata(i, 0, tiffImage.toDataURL(), false);
				_this.xdImage.setdata(i, 1, (i + 1).toString(10), false);
				_this.xdImage.setdata(i, 2, tiffImage.width(), false);
				_this.xdImage.setdata(i, 3, tiffImage.height(), false);
			}

			// 데이터세 이벤트 발생하여 컴포넌트에 반영
			_this.xdImage.fireevent();

			// Tiff 이미지 오브젝트 닫기
			tiffImage.close();

			//
			_this.lvImageLists.setselecteditem(0, true);
			_this.lvImageLists.setfocus();
			resolv();
		}.bind(_this);

		reader.readAsArrayBuffer(ATiffFileObj);
	});
}

// "웹이미지로드" 버튼 이벤트, 웹에서 다운로드해서 이미지 표시
function btn_load_imagemulti_on_mouseup(objInst)
{
	var _this;

	_this = this;

	// URL을 File 객체로 변경해서 리턴한다. (promise 객체)
	getFileFromURL(this.fld_text_multi.gettext()).then(function (AObjTiffFile) {
		_this.objTiffFile = AObjTiffFile;

		_this.getDataURITiffFromFile(AObjTiffFile).then(function () {
			screen.setscreenprotect(false);

			_this.FitLeftImageSize();

			console.log("로드 완료");
		});
	}.bind(this)).catch(function () {
		screen.alert("파일 다운로드 실패");
	});
}

// "로컬파일일기" 버튼 이벤트, 사용자 PC에서 파일을 선택하여 이미지 표시
function btnSelectTiffFIle_on_mousedown(objInst) {
	// File 오브젝트를 이용하여 파일 선택 상자 표시
	// 파일 선택시 파일 컴포넌트의 on_selectfiles 이벤트에 지정된 아래의 "objFile_on_selectfiles" 함수 호출됨
	this.objFile.selectfiles("image/tiff", false);
}

// 좌측 리스트뷰 아이템내 이미지 썸네일을 보여주기 위한
// 작은 이미지에 대한 fit 처리한다. (아래 로직은 IE에서 작동하지 않는다.)
function FitLeftImageSize() {
	// 좌측 리스트뷰 아이템내 이미지 썸네일을 보여주기 위한
	// 작은 이미지에 대한 fit 처리한다. (아래 로직은 IE에서 작동하지 않는다.)
	for (var i = 0; i < this.imgSmall.length; i++) {
		// fit 처리
		// The CSS object-fit property is used to specify
		// how an <img> or <video> should be resized to fit its container.
		// contain - The image keeps its aspect ratio, but is resized to fit within the given dimension
		$(this.imgSmall[i].getdom().children[0]).css('object-fit', 'contain');
	}
}

// 파일 컴포넌트 파일 선택 이벤트, 선택된 파일에 대한 이미지를 처리한다.
function objFile_on_selectfiles(objInst, arrFiles) {
	var _this;

	_this = this;

	if (arrFiles != null) {
		// 파일 오브젝트를 objTiffFile 전역 변수에 저장
		this.objTiffFile = arrFiles[0];

		// 파일 오브젝트를 이용하여 이미지 표시 처리
		this.getDataURITiffFromFile(arrFiles[0]).then(function () {
			screen.setscreenprotect(false);

			_this.FitLeftImageSize();

			console.log("로드 완료");
		});
	}
}

// 리스트뷰 아이템 키 처리를 위한 필드의 키 이벤트 처리
function fldFocus_on_prekeydown(objInst, index, keycode, bctrldown, bshiftdown, baltdown, bnumpadkey) {
	// 위로, 아래로 화살에 따른 처리한다.
	if (keycode == 40) {
		if (index < (this.lvImageLists.getitemcount() - 1)) { this.lvImageLists.setselecteditem(index + 1, true); }
	}
	else if (keycode == 38) {
		if (index > 0) { this.lvImageLists.setselecteditem(index - 1, true); }
	}
	return 0;
}

// 리스트뷰 아이템 변경 이벤트
function lvImageLists_on_itemchange(objInst, nPrevIndex, nCurrIndex) {
	// 기존에 선택된 아이템의 배경용 사각형의 배경색 투명 처리
	if (nPrevIndex != -1) { this.rectBack[nPrevIndex].settransparent(true); }

	// this.imgFullView.setwidth(this.imgSmall[nCurrIndex].getimagewidth());
	// this.imgFullView.setheight(this.imgSmall[nCurrIndex].getimageheight());

	// 오른쪽 이미지 전체 표시용 이미지 컴포넌트 크기 지정
	this.imgFullView.setwidth(this.xdImage.getdata(nCurrIndex, 2));
	this.imgFullView.setheight(this.xdImage.getdata(nCurrIndex, 3));

	// 선택된 아이템의 배경용 사각형의 배경색 불투명
	this.rectBack[nCurrIndex].settransparent(false);

	// 리스트뷰 아이템네 키 처리를 위해서 이미지 뒤에 숨겨진 필드에 포커싱
	this.fldFocus[nCurrIndex].setfocus();
}

// 리스트뷰 아이템 클릭 이벤트
function lvImageLists_on_itemclick(objInst, nItemIndex, objChildInst) {
	// 리스트뷰 아이템네 키 처리를 위해서 이미지 뒤에 숨겨진 필드에 포커싱
	if (nItemIndex >= 0) { this.fldFocus[nItemIndex].setfocus(); }
}

// "인쇄" 버튼 이벤트
function btnPrint_on_mouseup(objInst)
{
	var arrHtml = [];

	arrHtml.push("<html>");

	// 2022.07.06 인쇄 관련 CSS 추가처리
	arrHtml.push("<style>");

	/* 2022.07.06 페이지 여백을 없앨려면은 아래 부분 주석 해체처리
	arrHtml.push("@page {");
	arrHtml.push("  margin: 0mm 0mm 0mm 0mm;");
	arrHtml.push("}");
	*/

	arrHtml.push(".imgData {");
	arrHtml.push("  object-fit: contain;");
	arrHtml.push("  width: 100%;");
	// arrHtml.push("  height: 100%;");
	arrHtml.push("  display: block;");
	arrHtml.push("}");

	arrHtml.push("@media print{");
	arrHtml.push("  .imgData {");
	arrHtml.push("    page-break-after: always;");
	arrHtml.push("  }");
	arrHtml.push("}");

	arrHtml.push("</style>");
	// 2022.07.06 인쇄 관련 CSS 추가처리 끝

	// HTML 로드시 인쇄 함수 호출 지정
	arrHtml.push("<body onload='window.print()'>");

	// 이미지 DOM 추가
	for (var i = 0; i < this.xdImage.getrowcount(); i++) {
		// 2022.07.06 인쇄 처리용 class 지정처리
		arrHtml.push('<img src="' + this.xdImage.getdata(i, 0) + '" class="imgData">');
		// 2022.07.06 인쇄 처리용 class 지정처리 끝
	}

	arrHtml.push("</body>");
	arrHtml.push("</html>");

	this.webPrint.sethtml(arrHtml.join("\r\n"));
}

// "로컬 저장" 버튼 이벤트
function btnSaveFile_on_mouseup(objInst)
{
	if (this.objTiffFile == null) {
		screen.alert("이미지가 없습니다.");
		return;
	}

	screen.savefile(this.objTiffFile);
}