アンドロイドアプリのUIを作る
EPUB生成まではできたが次は画像、外字フォント、表紙がちゃんと読み込めるかをテストする。 今のファイル読み込みは、zipとtxtに制限しているので画像の読み込みがzip内にある場合に制限されている。表紙を別にSAFで読み込むかが、挿絵も一緒に読み込むかを悩んでいる。 txtとzipで本文をよみこむ型像はそのディレクトリ内を探索していた。だけどandroidではディレクトリ内を探索するには許可が必要なので、内部ファイルにコピーしてから処理している都合上画像の探索が内部ファイルにないといけない。
UIをConstraintLayoutかLinearLayoutにするかを考えていた。項目数が少ないと並べるだけでいいが増えると画面外にはみ出さないように縦に並べるほうが楽な気がした。 アンドロイドアプリのUIデザイン、画面表示の項目数
- 表紙画像ファイルの読み込み
- 挿絵ファイルの読み込み
- 本文ファイルの読み込み
- 設定を開く
- textview
あなた:
次の要素のアンドロイドアプリのUIを作って
表紙画像ファイルの読み込み 挿絵ファイルの読み込み 本文ファイルの読み込み 設定を開く textview
ChatGPT:
アンドロイドアプリのUIレイアウトをXMLで作成すると、以下のようになります。これは、表紙画像、挿絵、本文ファイルの読み込みボタン、設定を開くボタン、本文を表示する TextView を含んだシンプルなUIデザインです。
あなた:
kotlinじゃなくてjavaにして
ChatGPT:
Javaで実装する場合、以下のようになります。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <!-- 表紙画像 --> <ImageView android:id="@+id/coverImageView" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop" android:background="@android:color/darker_gray" /> <!-- 表紙画像ファイルの読み込みボタン --> <Button android:id="@+id/loadCoverButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="表紙画像を読み込む" /> <!-- 挿絵画像 --> <ImageView android:id="@+id/illustrationImageView" android:layout_width="match_parent" android:layout_height="150dp" android:scaleType="centerInside" android:background="@android:color/darker_gray" /> <!-- 挿絵ファイルの読み込みボタン --> <Button android:id="@+id/loadIllustrationButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="挿絵を読み込む" /> <!-- 本文ファイルの読み込みボタン --> <Button android:id="@+id/loadTextButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="本文を読み込む" /> <!-- 本文表示エリア --> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="本文がここに表示されます" android:padding="8dp" android:background="@android:color/white" android:textSize="16sp" /> <!-- 設定を開くボタン --> <Button android:id="@+id/openSettingsButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="設定を開く" /> </LinearLayout>
package com.example.myapp; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.provider.OpenableColumns; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import java.io.InputStream; import java.util.Objects; public class MainActivity extends AppCompatActivity { private ImageView coverImageView; private ImageView illustrationImageView; private TextView textView; private final ActivityResultLauncher<String> imagePicker = registerForActivityResult( new ActivityResultContracts.GetContent(), uri -> { if (uri != null) { displayImage(uri, coverImageView); } }); private final ActivityResultLauncher<String> illustrationPicker = registerForActivityResult( new ActivityResultContracts.GetContent(), uri -> { if (uri != null) { displayImage(uri, illustrationImageView); } }); private final ActivityResultLauncher<String> textPicker = registerForActivityResult( new ActivityResultContracts.GetContent(), uri -> { if (uri != null) { displayText(uri); } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); coverImageView = findViewById(R.id.coverImageView); illustrationImageView = findViewById(R.id.illustrationImageView); textView = findViewById(R.id.textView); Button loadCoverButton = findViewById(R.id.loadCoverButton); Button loadIllustrationButton = findViewById(R.id.loadIllustrationButton); Button loadTextButton = findViewById(R.id.loadTextButton); Button openSettingsButton = findViewById(R.id.openSettingsButton); loadCoverButton.setOnClickListener(view -> imagePicker.launch("image/*")); loadIllustrationButton.setOnClickListener(view -> illustrationPicker.launch("image/*")); loadTextButton.setOnClickListener(view -> textPicker.launch("text/plain")); openSettingsButton.setOnClickListener(view -> { Intent intent = new Intent(MainActivity.this, SettingsActivity.class); startActivity(intent); }); } private void displayImage(Uri uri, ImageView imageView) { try { InputStream inputStream = getContentResolver().openInputStream(uri); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); imageView.setImageBitmap(bitmap); } catch (Exception e) { e.printStackTrace(); } } private void displayText(Uri uri) { try { InputStream inputStream = getContentResolver().openInputStream(uri); String text = new String(Objects.requireNonNull(inputStream).readAllBytes()); textView.setText(text); } catch (Exception e) { textView.setText("ファイルを読み込めませんでした"); e.printStackTrace(); } } }
package com.example.myapp; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; public class SettingsActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="設定画面" android:textSize="20sp" /> </LinearLayout>
- 画像の選択
ActivityResultContracts.GetContent() を使い、ユーザーがギャラリーから画像を選択できるようにする。
displayImage() で選択した画像を ImageView に表示。 2. ActivityResultContracts.GetContent() を使い、ユーザーがギャラリーから画像を選択できるようにする。 3. displayImage() で選択した画像を ImageView に表示。 4. 本文ファイルの読み込み
.txt ファイルを選択すると、displayText() で TextView に表示。 5. .txt ファイルを選択すると、displayText() で TextView に表示。 6. 設定画面の開閉
openSettingsButton を押すと SettingsActivity へ遷移。 7. openSettingsButton を押すと SettingsActivity へ遷移。
画像の選択
- ActivityResultContracts.GetContent() を使い、ユーザーがギャラリーから画像を選択できるようにする。
- displayImage() で選択した画像を ImageView に表示。
ActivityResultContracts.GetContent() を使い、ユーザーがギャラリーから画像を選択できるようにする。
displayImage() で選択した画像を ImageView に表示。
本文ファイルの読み込み
- .txt ファイルを選択すると、displayText() で TextView に表示。
.txt ファイルを選択すると、displayText() で TextView に表示。
設定画面の開閉
- openSettingsButton を押すと SettingsActivity へ遷移。
openSettingsButton を押すと SettingsActivity へ遷移。
- registerForActivityResult は、AndroidXの ActivityResultContracts を使用する最新の方法です。
- 画像やテキストファイルを適切に読み込めるよう、適切なエラーハンドリングを追加しています。
registerForActivityResult は、AndroidXの ActivityResultContracts を使用する最新の方法です。
画像やテキストファイルを適切に読み込めるよう、適切なエラーハンドリングを追加しています。
これでJava版のUIが完成しました!このコードを使って、画像やテキストを読み込むアプリを作成できます。 ファイルを指定して読み込むとEPUBを出力するまで止まらない。propertiesはpreferenceにしたい。コンソール版をベースにしているので、変換前確認がない。変換前確認するためには途中で、データを確認するページを作る必要がある。
以前の画面設定でEPUB生成まで。
package io.github.kyukyunyorituryo.practice; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.widget.TextView; import androidx.activity.EdgeToEdge; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.github.junrar.exception.RarException; import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.Objects; import java.util.Properties; import io.github.kyukyunyorituryo.practice.util.Detector; import io.github.kyukyunyorituryo.practice.converter.AozoraEpub3Converter; import io.github.kyukyunyorituryo.practice.image.ImageInfoReader; import io.github.kyukyunyorituryo.practice.info.BookInfo; import io.github.kyukyunyorituryo.practice.info.SectionInfo; import io.github.kyukyunyorituryo.practice.util.Detector; import io.github.kyukyunyorituryo.practice.util.LogAppender; import io.github.kyukyunyorituryo.practice.writer.Epub3ImageWriter; import io.github.kyukyunyorituryo.practice.writer.Epub3Writer; public class MainActivity extends AppCompatActivity { private Properties props; private static final int READ_REQUEST_CODE = 1; private File srcFile; @SuppressLint("SetTextI18n") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(v -> { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); String[] mimeTypes ={ "text/plain", "application/zip"}; intent.setType("*/*").putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes); Intent chooserIntent = Intent.createChooser(intent, "ファイルの選択"); _launcherSelectFile.launch(chooserIntent); }); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); //プロパティーの読み込み props = new Properties(); InputStream isini; try { isini = this.getAssets().open("AozoraEpub3.ini"); props.load(isini); } catch (IOException e) { e.printStackTrace(); } } ActivityResultLauncher<Intent> _launcherSelectFile = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { Charset cs; if (result.getResultCode() == RESULT_OK) { Intent resultData = result.getData(); if (resultData != null) { Uri uri = resultData.getData(); String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME}; String path = null; Cursor cursor = this.getContentResolver().query(uri, projection, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { path = cursor.getString(0); } cursor.close(); Context context = getApplicationContext(); srcFile = new File(context.getFilesDir(), path); System.out.println("filename:" + path); System.out.println("filename:" + srcFile.getPath()); } try { InputStream inputStream = getContentResolver().openInputStream(uri); String ext = srcFile.getName(); ext = ext.substring(ext.lastIndexOf('.') + 1).toLowerCase(); if(ext.equals("txt")){ cs= Charset.forName(Detector.getCharset(inputStream)); System.out.println("charset:" + cs); } Files.copy(inputStream, srcFile.toPath(), REPLACE_EXISTING); } catch (IOException e) { e.printStackTrace(); } } } /** ePub3出力クラス */ Epub3Writer epub3Writer; /** ePub3画像出力クラス */ Epub3ImageWriter epub3ImageWriter; /** 出力先パス */ File dstPath = null; //ePub出力クラス初期化 epub3Writer = new Epub3Writer(this); epub3ImageWriter = new Epub3ImageWriter(this); int titleIndex = 0; //try { titleIndex = Integer.parseInt(props.getProperty("TitleType")); } catch (Exception e) {}//表題 //コマンドラインオプション以外 boolean coverPage = "1".equals(props.getProperty("CoverPage"));//表紙追加 int titlePage = BookInfo.TITLE_NONE; if ("1".equals(props.getProperty("TitlePageWrite"))) { try { titlePage =Integer.parseInt(props.getProperty("TitlePage")); } catch (Exception e) {} } boolean withMarkId = "1".equals(props.getProperty("MarkId")); //boolean gaiji32 = "1".equals(props.getProperty("Gaiji32")); boolean commentPrint = "1".equals(props.getProperty("CommentPrint")); boolean commentConvert = "1".equals(props.getProperty("CommentConvert")); boolean autoYoko = "1".equals(props.getProperty("AutoYoko")); boolean autoYokoNum1 = "1".equals(props.getProperty("AutoYokoNum1")); boolean autoYokoNum3 = "1".equals(props.getProperty("AutoYokoNum3")); boolean autoYokoEQ1 = "1".equals(props.getProperty("AutoYokoEQ1")); int spaceHyp = 0; try { spaceHyp = Integer.parseInt(props.getProperty("SpaceHyphenation")); } catch (Exception e) {} boolean tocPage = "1".equals(props.getProperty("TocPage"));//目次追加 boolean tocVertical = "1".equals(props.getProperty("TocVertical"));//目次縦書き boolean coverPageToc = "1".equals(props.getProperty("CoverPageToc")); int removeEmptyLine = 0; try { removeEmptyLine = Integer.parseInt(props.getProperty("RemoveEmptyLine")); } catch (Exception e) {} int maxEmptyLine = 0; try { maxEmptyLine = Integer.parseInt(props.getProperty("MaxEmptyLine")); } catch (Exception e) {} //画面サイズと画像リサイズ int dispW = 600; try { dispW =Integer.parseInt(props.getProperty("DispW")); } catch (Exception e) {} int dispH = 800; try { dispH =Integer.parseInt(props.getProperty("DispH")); } catch (Exception e) {} int coverW = 600; try { coverW = Integer.parseInt(props.getProperty("CoverW")); } catch (Exception e) {} int coverH = 800; try { coverH = Integer.parseInt(props.getProperty("CoverH")); } catch (Exception e) {} int resizeW = 0; if ("1".equals(props.getProperty("ResizeW"))) try { resizeW = Integer.parseInt(props.getProperty("ResizeNumW")); } catch (Exception e) {} int resizeH = 0; if ("1".equals(props.getProperty("ResizeH"))) try { resizeH = Integer.parseInt(props.getProperty("ResizeNumH")); } catch (Exception e) {} int singlePageSizeW = 480; try { singlePageSizeW = Integer.parseInt(props.getProperty("SinglePageSizeW")); } catch (Exception e) {} int singlePageSizeH = 640; try { singlePageSizeH = Integer.parseInt(props.getProperty("SinglePageSizeH")); } catch (Exception e) {} int singlePageWidth = 600; try { singlePageWidth = Integer.parseInt(props.getProperty("SinglePageWidth")); } catch (Exception e) {} float imageScale = 1; try { imageScale = Float.parseFloat(props.getProperty("ImageScale")); } catch (Exception e) {} int imageFloatType = 0; try { imageFloatType = Integer.parseInt(props.getProperty("ImageFloatType")); } catch (Exception e) {} int imageFloatW = 0; try { imageFloatW = Integer.parseInt(props.getProperty("ImageFloatW")); } catch (Exception e) {} int imageFloatH = 0; try { imageFloatH = Integer.parseInt(props.getProperty("ImageFloatH")); } catch (Exception e) {} int imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_HEIGHT; try { imageSizeType = Integer.parseInt(props.getProperty("ImageSizeType")); } catch (Exception e) {} boolean fitImage = "1".equals(props.getProperty("FitImage")); boolean svgImage = "1".equals(props.getProperty("SvgImage")); int rotateImage = 0; if ("1".equals(props.getProperty("RotateImage"))) rotateImage = 90; else if ("2".equals(props.getProperty("RotateImage"))) rotateImage = -90; float jpegQualty = 0.8f; try { jpegQualty = Integer.parseInt(props.getProperty("JpegQuality"))/100f; } catch (Exception e) {} float gamma = 1.0f; if ( "1".equals(props.getProperty("Gamma"))) try { gamma = Float.parseFloat(props.getProperty("GammaValue")); } catch (Exception e) {} int autoMarginLimitH = 0; int autoMarginLimitV = 0; int autoMarginWhiteLevel = 80; float autoMarginPadding = 0; int autoMarginNombre = 0; float nobreSize = 0.03f; if ("1".equals(props.getProperty("AutoMargin"))) { try { autoMarginLimitH = Integer.parseInt(props.getProperty("AutoMarginLimitH")); } catch (Exception e) {} try { autoMarginLimitV = Integer.parseInt(props.getProperty("AutoMarginLimitV")); } catch (Exception e) {} try { autoMarginWhiteLevel = Integer.parseInt(props.getProperty("AutoMarginWhiteLevel")); } catch (Exception e) {} try { autoMarginPadding = Float.parseFloat(props.getProperty("AutoMarginPadding")); } catch (Exception e) {} try { autoMarginNombre = Integer.parseInt(props.getProperty("AutoMarginNombre")); } catch (Exception e) {} try { autoMarginPadding = Float.parseFloat(props.getProperty("AutoMarginNombreSize")); } catch (Exception e) {} } epub3Writer.setImageParam(dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth, imageSizeType, fitImage, svgImage, rotateImage, imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQualty, gamma, autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding, autoMarginNombre, nobreSize); epub3ImageWriter.setImageParam(dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth, imageSizeType, fitImage, svgImage, rotateImage, imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQualty, gamma, autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding, autoMarginNombre, nobreSize); //目次階層化設定 epub3Writer.setTocParam("1".equals(props.getProperty("NavNest")), "1".equals(props.getProperty("NcxNest"))); //スタイル設定 String[] pageMargin = {}; try { pageMargin = props.getProperty("PageMargin").split(","); } catch (Exception e) {} if (pageMargin.length != 4) pageMargin = new String[]{"0", "0", "0", "0"}; else { String pageMarginUnit = props.getProperty("PageMarginUnit"); for (int i=0; i<4; i++) { pageMargin[i] += pageMarginUnit; } } String[] bodyMargin = {}; try { bodyMargin = props.getProperty("BodyMargin").split(","); } catch (Exception e) {} if (bodyMargin.length != 4) bodyMargin = new String[]{"0", "0", "0", "0"}; else { String bodyMarginUnit = props.getProperty("BodyMarginUnit"); for (int i=0; i<4; i++) { bodyMargin[i] += bodyMarginUnit; } } float lineHeight = 1.8f; try { lineHeight = Float.parseFloat(props.getProperty("LineHeight")); } catch (Exception e) {} int fontSize = 100; try { fontSize = Integer.parseInt(props.getProperty("FontSize")); } catch (Exception e) {} boolean boldUseGothic = "1".equals(props.getProperty("BoldUseGothic")); boolean gothicUseBold = "1".equals(props.getProperty("gothicUseBold")); epub3Writer.setStyles(pageMargin, bodyMargin, lineHeight, fontSize, boldUseGothic, gothicUseBold); //自動改ページ int forcePageBreakSize = 0; int forcePageBreakEmpty = 0; int forcePageBreakEmptySize = 0; int forcePageBreakChapter = 0; int forcePageBreakChapterSize = 0; if ("1".equals(props.getProperty("PageBreak"))) { try { try { forcePageBreakSize = Integer.parseInt(props.getProperty("PageBreakSize")) * 1024; } catch (Exception e) {} if ("1".equals(props.getProperty("PageBreakEmpty"))) { try { forcePageBreakEmpty = Integer.parseInt(props.getProperty("PageBreakEmptyLine")); } catch (Exception e) {} try { forcePageBreakEmptySize = Integer.parseInt(props.getProperty("PageBreakEmptySize")) * 1024; } catch (Exception e) {} } if ("1".equals(props.getProperty("PageBreakChapter"))) { forcePageBreakChapter = 1; try { forcePageBreakChapterSize = Integer.parseInt(props.getProperty("PageBreakChapterSize")) * 1024; } catch (Exception e) {} } } catch (Exception e) {} } int maxLength = 64; try { maxLength = Integer.parseInt((props.getProperty("ChapterNameLength"))); } catch (Exception e) {} boolean insertTitleToc = "1".equals(props.getProperty("TitleToc")); boolean chapterExclude = "1".equals(props.getProperty("ChapterExclude")); boolean chapterUseNextLine = "1".equals(props.getProperty("ChapterUseNextLine")); boolean chapterSection = !props.containsKey("ChapterSection")||"1".equals(props.getProperty("ChapterSection")); boolean chapterH = "1".equals(props.getProperty("ChapterH")); boolean chapterH1 = "1".equals(props.getProperty("ChapterH1")); boolean chapterH2 = "1".equals(props.getProperty("ChapterH2")); boolean chapterH3 = "1".equals(props.getProperty("ChapterH3")); boolean sameLineChapter = "1".equals(props.getProperty("SameLineChapter")); boolean chapterName = "1".equals(props.getProperty("ChapterName")); boolean chapterNumOnly = "1".equals(props.getProperty("ChapterNumOnly")); boolean chapterNumTitle = "1".equals(props.getProperty("ChapterNumTitle")); boolean chapterNumParen = "1".equals(props.getProperty("ChapterNumParen")); boolean chapterNumParenTitle = "1".equals(props.getProperty("hapterNumParenTitle")); String chapterPattern = ""; if ("1".equals(props.getProperty("ChapterPattern"))) chapterPattern = props.getProperty("ChapterPatternText"); //オプション指定を反映 boolean useFileName = false;//表題に入力ファイル名利用 String coverFileName = null; String encType = "AUTO";//文字コードの初期設定を空に String outExt = ".epub"; boolean autoFileName = true; //ファイル名を表題に利用 boolean vertical = true; String targetDevice = null; //変換クラス生成とパラメータ設定 AozoraEpub3Converter aozoraConverter = null; try { aozoraConverter = new AozoraEpub3Converter(epub3Writer, this); } catch (IOException e) { e.printStackTrace(); } //挿絵なし aozoraConverter.setNoIllust("1".equals(props.getProperty("NoIllust"))); //栞用span出力 aozoraConverter.setWithMarkId(withMarkId); //変換オプション設定 aozoraConverter.setAutoYoko(autoYoko, autoYokoNum1, autoYokoNum3, autoYokoEQ1); //文字出力設定 int dakutenType = 0; try { dakutenType = Integer.parseInt(props.getProperty("DakutenType")); } catch (Exception e) {} boolean printIvsBMP = "1".equals(props.getProperty("IvsBMP")); boolean printIvsSSP = "1".equals(props.getProperty("IvsSSP")); aozoraConverter.setCharOutput(dakutenType, printIvsBMP, printIvsSSP); //全角スペースの禁則 aozoraConverter.setSpaceHyphenation(spaceHyp); //コメント aozoraConverter.setCommentPrint(commentPrint, commentConvert); aozoraConverter.setRemoveEmptyLine(removeEmptyLine, maxEmptyLine); //強制改ページ aozoraConverter.setForcePageBreak(forcePageBreakSize, forcePageBreakEmpty, forcePageBreakEmptySize, forcePageBreakChapter, forcePageBreakChapterSize); //目次設定 aozoraConverter.setChapterLevel(maxLength, chapterExclude, chapterUseNextLine, chapterSection, chapterH, chapterH1, chapterH2, chapterH3, sameLineChapter, chapterName, chapterNumOnly, chapterNumTitle, chapterNumParen, chapterNumParenTitle, chapterPattern); //////////////////////////////// //各ファイルを変換処理 //////////////////////////////// // for (String fileName : fileNames) { LogAppender.println("--------"); //File srcFile = new File(fileName); if(srcFile == null || !srcFile.isFile()) { LogAppender.error("file not exist. " + srcFile.getAbsolutePath()); // continue; } String ext = srcFile.getName(); ext = ext.substring(ext.lastIndexOf('.') + 1).toLowerCase(); int coverImageIndex = -1; if(coverFileName != null) { if("0".equals(coverFileName)) { coverImageIndex = 0; coverFileName = ""; } else if("1".equals(coverFileName)) { coverFileName = AozoraEpub3.getSameCoverFileName(srcFile); //入力ファイルと同じ名前+.jpg/.png } } //zipならzip内のテキストを検索 int txtCount = 1; boolean imageOnly = false; boolean isFile = "txt".equals(ext); if("zip".equals(ext) || "txtz".equals(ext)) { try { txtCount = AozoraEpub3.countZipText(srcFile); } catch (IOException e) { e.printStackTrace(); } if(txtCount == 0) { txtCount = 1; imageOnly = true; } } else if("rar".equals(ext)) { try { txtCount = AozoraEpub3.countRarText(srcFile); } catch (IOException | RarException e) { e.printStackTrace(); } if(txtCount == 0) { txtCount = 1; imageOnly = true; } } else if("cbz".equals(ext)) { imageOnly = true; } for(int txtIdx = 0; txtIdx < txtCount; txtIdx++) { ImageInfoReader imageInfoReader = new ImageInfoReader(isFile, srcFile); BookInfo bookInfo = null; //文字コード判別 String encauto; try { encauto=AozoraEpub3.getTextCharset(srcFile, ext, imageInfoReader, txtIdx); } catch (IOException e) { throw new RuntimeException(e); } catch (RarException e) { throw new RuntimeException(e); } if (Objects.equals(encauto, "SHIFT_JIS"))encauto="MS932"; if (encType.equals("AUTO")) encType =encauto; if(!imageOnly) { bookInfo = AozoraEpub3.getBookInfo(srcFile, ext, txtIdx, imageInfoReader, aozoraConverter, encType, BookInfo.TitleType.indexOf(titleIndex), false); bookInfo.vertical = vertical; bookInfo.insertTocPage = tocPage; bookInfo.setTocVertical(tocVertical); bookInfo.insertTitleToc = insertTitleToc; aozoraConverter.vertical = vertical; //表題ページ bookInfo.titlePageType = titlePage; } //表題の見出しが非表示で行が追加されていたら削除 if(!bookInfo.insertTitleToc && bookInfo.titleLine >= 0) { bookInfo.removeChapterLineInfo(bookInfo.titleLine); } Epub3Writer writer = epub3Writer; if(!isFile) { if(imageOnly) { LogAppender.println("画像のみのePubファイルを生成します"); //画像出力用のBookInfo生成 bookInfo = new BookInfo(srcFile); bookInfo.imageOnly = true; //Writerを画像出力用派生クラスに入れ替え writer = epub3ImageWriter; } //先頭からの場合で指定行数以降なら表紙無し if("".equals(coverFileName)) { try { int maxCoverLine = Integer.parseInt(props.getProperty("MaxCoverLine")); if(maxCoverLine > 0 && bookInfo.firstImageLineNum >= maxCoverLine) { coverImageIndex = -1; coverFileName = null; } } catch (Exception e) {} } //表紙設定 bookInfo.insertCoverPageToc = coverPageToc; bookInfo.insertCoverPage = coverPage; bookInfo.coverImageIndex = coverImageIndex; if(coverFileName != null && !coverFileName.startsWith("http")) { File coverFile = new File(coverFileName); if(!coverFile.exists()) { coverFileName = srcFile.getParent() + "/" + coverFileName; if(!new File(coverFileName).exists()) { coverFileName = null; LogAppender.println("[WARN] 表紙画像ファイルが見つかりません : " + coverFile.getAbsolutePath()); } } } bookInfo.coverFileName = coverFileName; String[] titleCreator = BookInfo.getFileTitleCreator(srcFile.getName()); if(titleCreator != null) { if(useFileName) { if(titleCreator[0] != null && titleCreator[0].trim().length() > 0) bookInfo.title = titleCreator[0]; if(titleCreator[1] != null && titleCreator[1].trim().length() > 0) bookInfo.creator = titleCreator[1]; } else { //テキストから取得できていない場合 if(bookInfo.title == null || bookInfo.title.length() == 0) bookInfo.title = titleCreator[0] == null ? "" : titleCreator[0]; if(bookInfo.creator == null || bookInfo.creator.length() == 0) bookInfo.creator = titleCreator[1] == null ? "" : titleCreator[1]; } } File outFile = AozoraEpub3.getOutFile(srcFile, dstPath, bookInfo, autoFileName, outExt); AozoraEpub3.convertFile(srcFile, ext, outFile, aozoraConverter, writer, encType, bookInfo, imageInfoReader, txtIdx); } } }); }