その漫画自炊オタクはImageJマクロに恋をする

プログラミングを用いた、自炊漫画の画像処理

実用版!ノンブル領域を削除し, コントラスト調整, 解像度変更も一括で行えるMacro

 

f:id:yu3xx:20200624015007j:plain

 

選択したフォルダ内の全画像の、「ノンブル領域の削除」、「コントラスト調整」、「解像度変更」を一括で行えるマクロです。

  

 

//NombreCut_UsingROI.txt
//ContrastAdjust (As necessary)
//SetResolution (As necessary)
//number==0 -> error


//Clear ROI Manager
roiCount=roiManager("count");
if(roiCount>0){
	roiManager("Deselect");
	roiManager("Delete");
}

//ROI setting ODD(1,3,5,7,...)
waitForUser("ODD(1,3,5,7,...)","Open a [ODD number] file and set [ROI] using rectangle tool, then click [OK].");
roiManager("Add");
close();

//ROI setting EVEN(2,4,6,8,...)
waitForUser("EVEN(2,4,6,8,...)","Open a [EVEN number] file and set [ROI] using rectangle tool, then click [OK].");
roiManager("Add");
close();


//Do something for selected folder
showMessage("Select Open Folder");
openDir=getDirectory("Choose a Directory");
print("Processing :",openDir);
selectWindow("Log");
showMessage("Select Save Folder");
saveDir=getDirectory("Choose a Directory");
print("Save to :",saveDir);
selectWindow("Log");
list=getFileList(openDir);
wait(1000);

//Whether or not to adjust contrast and set resolution
Dialog.create("Processing setting");
items = newArray("No", "Yes");
Dialog.addRadioButtonGroup("Do you adjust the contrast?", items, 1, 2, "No");
Dialog.addRadioButtonGroup("Do you change the resolution?", items, 1, 2, "No");
Dialog.show;
ansContr=Dialog.getRadioButton();
ansReso=Dialog.getRadioButton();
if(ansContr == "Yes") flagContr = 1;
else flagContr = 0;
if(ansReso == "Yes") flagReso = 1;
else flagReso = 0;

//Enter parameter
Dialog.create("Processing Setting");
if (flagContr == 1) Dialog.addNumber("min (0-255)",0);
if (flagContr == 1) Dialog.addNumber("Max (0-255)",255);
if (flagReso == 1) Dialog.addNumber("axis x matrixSize (400dpi... 1600-1800)",0);
items = newArray("JPEG", "PNG");
Dialog.addRadioButtonGroup("Output format", items, 1, 2, "JPEG");
Dialog.show;
if (flagContr == 1) min = Dialog.getNumber();
if (flagContr == 1) max = Dialog.getNumber();
if (flagReso == 1) reso = Dialog.getNumber();
output = Dialog.getRadioButton();

//JPEG,PNG quality setting(jpeg=90,gif=-1)
quality=90;
run("Input/Output...", "jpeg=quality gif=-1 file=.csv save_column save_row");


//operation
startTime=whatTimeNow();
setBatchMode(true);

for (i=0; i<list.length;i++){
	operation();
}
roiManager("Deselect");
roiManager("Delete");

//fin
finishTime=whatTimeNow();
if (flagContr == 1) print("min=",min,", Max=",max);
if (output == "JPEG") print("JPEG quality=",quality);
print("Start Time .... ",startTime);
print("FinishTime ... ",finishTime);
print("oshimai");
beep();


//-----------------------------------------------------------------------------
//Define operation
function operation(){

	open(openDir+list[i]);

	//Progress.the second decimal place by 10000/100
	print(i+1,"/",list.length,"...Progress=",floor((i+1)/list.length*10000)/100,"%");
	
	name = getTitle;
	dotIndex = indexOf(name, ".");
	title=substring(name,0,dotIndex);
	underBar=lastIndexOf(title,"_");
	trueTitle=substring(title,0,underBar);
	number=substring(title,underBar+1);
	number=parseInt(number);
	
	//ODD(1,3,5,7,...)
	if(number%2==1){
		roiManager("Select", 0);
		run("Crop");
	}
	//EVEN(2,4,6,8,...)
	if(number%2==0){
		roiManager("Select", 1);
		run("Crop");
	}
	
	//Processing for GrayScale Images
	depth=bitDepth();
	if (depth==8) {
		//ContrastAdjust (As necessary)
		if (flagContr == 1) setMinAndMax(min, max);
		if (flagContr == 1) run("Apply LUT");
	}

	//SetResolution (As necessary)
	if (flagReso == 1) run("Size...", "width=reso constrain average interpolation=Bicubic");
	
	if (output == "JPEG") newname = title+".jpg";
	else if (output == "PNG") newname = title+".png";	

	rename(newname);

	if (output == "JPEG") saveAs("Jpeg", saveDir+newname);
	else if (output == "PNG") saveAs("PNG", saveDir+newname);
	
	close(newname);
}

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//Define function whatTimeNow

function whatTimeNow(){
	getDateAndTime(year,month,dayOfWeek,dayOfMonth,hour,minute,second,msec);
	stringTime = "string";
	strYear = ""+year;
	month = month+1;
	if(month < 10){
		strMonth = "0"+month;
	}else{
		strMonth = ""+month;
	}
	if(dayOfMonth < 10){
		strDayOfMonth = "0"+dayOfMonth;
	}else{
		strDayOfMonth = ""+dayOfMonth;
	}
	if(hour < 10){
		strHour = "0"+hour;
	}else{
		strHour = ""+hour;
	}
	if(minute < 10){
		strMinute = "0"+minute;
	}else{
		strMinute = ""+minute;
	}
	if(second < 10){
		strSecond = "0"+second;
	}else{
		strSecond = ""+second;
	}
	stringTime = strYear+"/"+strMonth+"/"+strDayOfMonth+"_"+strHour+":"+strMinute+":"+strSecond;
	return stringTime;
}

//-----------------------------------------------------------------------------

 ※コントラスト調整と解像度変更は (As Necessary) として「//」で無効にしています。こちらも一緒に行いたい場合は、該当部位の「//」を外してください。

 2020.04.05 追記 コントラスト調整・解像度変更の有無、書き出しフォーマットをダイアログから選択出来るように修正しました。コード書き換えなしで使用出来ます。

 

使い方

① マクロ「NombreCut_UsingROI.txt」を起動させる。

②メッセージに従い「奇数ナンバー」のファイルをDrag&Drop等で開き、ROIを設定する。

ファイル名が奇数ナンバーです。実際の本のページではありませんので注意!)

②メッセージに従い「偶数ナンバー」のファイルをDrag&Drop等で開き、ROIを設定する。

(同じくファイル名が偶数ナンバーです。)

③ 処理したいFolder (Open Folder)と保存先フォルダ (Save Folder)を選択。

④ 必要に応じて、minMax、解像度(x軸)を入力。

⑤ 終了まで待つだけ。

 

 

ROIの設定

主に文庫本などのノンブル領域の余白などにROIを設定し、トリミングします。もちろん漫画でもOKです。

「偶数ナンバー」の設定時には、ROI Managerに保存された「奇数ナンバー」のROIを選択・呼び出しすると、サイズが同じになるので調整しやすいです。

f:id:yu3xx:20200316070347p:plain

 

 

「カラー表紙」や「見開き地図」などのページも問答無用でトリミングされる設定なので、そのようなページは「元データ」や「別処理したデータ」と差し替えてください。

 

マクロの起動方法

①ImageJ上部タブの[Plugins]→[New]→[Macro]で起動したエディタに、記事の一番上のコードをコピペしてtxtファイル(NombreCut_UsingROI.txt)を作成・保存する。 

 

②保存したファイルをImageJフォルダ内の[plugins]フォルダにしまう。

このとき、[plugins]フォルダの中に新たに適当な名前のフォルダを作って、その中にしまってもOKです。ここでは仮に「自炊」というフォルダにtxtファイルを突っ込んだとします。

 

③一度ImageJを再起動すると、マクロがインストールされ、起動準備OK。

 

④上部タブ[Plugins]→[自炊]→[NombreCut UsingROI]でマクロが実行されます。

 

 

 

imagej-jisui.hatenablog.com

 

 

 

 

ライセンスなんかは一切無いので、ぜひぜひ自由に使ってみてください!

 

imagej-jisui.hatenablog.com