KDP(電子出版)のメモ 急急如律令

Amazon Kindleダイレクト・パブリッシングでの電子出版や電子書籍の作成販売について、文章やイラストの作成や編集方法について書いています。

android向けに書き換えて 複数ファイルを変換 convertFiles

あなた:

android向けに書き換えて

 /** 複数ファイルを変換
     * @param dstPath srcFileがキャッシュで入力ファイルを同じ場所に出力先指定をする場合 */
    private void convertFiles(File[] srcFiles, File dstPath) throws Exception {
        if (srcFiles.length == 0 ) return;

        convertCanceled = false;

        ////////////////////////////////////////////////////////////////
        //Appletのパラメータを取得
        ////////////////////////////////////////////////////////////////
        //画面サイズと画像リサイズ
        int resizeW = 0;
        if (jCheckResizeW.isSelected()) try { resizeW = Integer.parseInt(jTextResizeNumW.getText()); } catch (Exception ignored) {}
        int resizeH = 0;
        if (jCheckResizeH.isSelected()) try { resizeH = Integer.parseInt(jTextResizeNumH.getText()); } catch (Exception ignored) {}
        //int pixels = 0;
        //if (jCheckPixel.isSelected()) try { pixels = Integer.parseInt(jTextPixelW.getText())*Integer.parseInt(jTextPixelH.getText()); } catch (Exception e) {}
        int dispW = Integer.parseInt(jTextDispW.getText());
        int dispH = Integer.parseInt(jTextDispH.getText());
        this.coverW = Integer.parseInt(this.jTextCoverW.getText());
        this.coverH = Integer.parseInt(this.jTextCoverH.getText());
        int singlePageSizeW = Integer.parseInt(jTextSinglePageSizeW.getText());
        int singlePageSizeH = Integer.parseInt(jTextSinglePageSizeH.getText());
        int singlePageWidth = Integer.parseInt(jTextSinglePageWidth.getText());

        float imageScale = 0;
        if (jCheckImageScale.isSelected()) try { imageScale = Float.parseFloat(jTextImageScale.getText()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
        int imageFloatType = 0; //0=無効 1=上 2=下
        int imageFloatW = 0;
        int imageFloatH = 0;
        if (jCheckImageFloat.isSelected()) {
            imageFloatType = this.jComboImageFloatType.getSelectedIndex()+1;
            try { imageFloatW =Integer.parseInt(jTextImageFloatW.getText()); } catch (Exception e) {
                throw new RuntimeException(e);
            }
            try { imageFloatH =Integer.parseInt(jTextImageFloatH.getText()); } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        float jpegQualty = 0.8f; try { jpegQualty = Integer.parseInt(jTextJpegQuality.getText())/100f; } catch (Exception e) {
            throw new RuntimeException(e);
        }
        float gamma = 1.0f; if (jCheckGamma.isSelected()) try { gamma = Float.parseFloat(jTextGammaValue.getText()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
        int autoMarginLimitH = 0;
        int autoMarginLimitV = 0;
        int autoMarginWhiteLevel = 0;
        float autoMarginPadding = 0;
        int autoMarginNombre = 0;
        float autoMarginNombreSize = 0.03f;
        if (jCheckAutoMargin.isSelected()) {
            autoMarginLimitH =Integer.parseInt(jTextAutoMarginLimitH.getText());
            try { autoMarginLimitV =Integer.parseInt(jTextAutoMarginLimitV.getText()); } catch (Exception e) {
                throw new RuntimeException(e);
            }
            try { autoMarginWhiteLevel =Integer.parseInt(jTextAutoMarginWhiteLevel.getText()); } catch (Exception e) {
                throw new RuntimeException(e);
            }
            try { autoMarginPadding =Float.parseFloat(jTextAutoMarginPadding.getText()); } catch (Exception e) {
                throw new RuntimeException(e);
            }
            autoMarginNombre = jComboAutoMarginNombre.getSelectedIndex();
            try { autoMarginNombreSize =Float.parseFloat(jTextAutoMarginNombreSize.getText())*0.01f; } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        int rorateAngle = 0; if (jComboRotateImage.getSelectedIndex() == 1) rorateAngle = 90; else if (jComboRotateImage.getSelectedIndex() == 2) rorateAngle = -90;

        int imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_ASPECT;
        if (jRadioImageSizeType1.isSelected()) imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_AUTO;
        //else if (jRadioImageSizeType2.isSelected()) imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_HEIGHT;

        //int imageFitType = SectionInfo.IMAGE_SIZE_TYPE_ASPECT;
        //if (jRadioImageFitType2.isSelected()) imageFitType = SectionInfo.IMAGE_SIZE_TYPE_HEIGHT;

        this.epub3Writer.setImageParam(dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth,
                imageSizeType, jCheckFitImage.isSelected(), jCheckSvgImage.isSelected(), rorateAngle,
                imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQualty, gamma, autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding, autoMarginNombre, autoMarginNombreSize);
        this.epub3ImageWriter.setImageParam(dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth,
                imageSizeType, jCheckFitImage.isSelected(), jCheckSvgImage.isSelected(), rorateAngle,
                imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQualty, gamma, autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding, autoMarginNombre, autoMarginNombreSize);
        //目次階層化設定
        this.epub3Writer.setTocParam(jCheckNavNest.isSelected(), jCheckNcxNest.isSelected());

        //スタイル設定
        String[] pageMargin = new String[4];
        String pageMarginUnit = jRadioPageMarginUnit0.isSelected()?"em":"%";
        for (int i=0; i<pageMargin.length; i++) {
            pageMargin[i] = jTextPageMargins[i].getText()+pageMarginUnit;
        }
        String[] bodyMargin = new String[4];
        String bodyMarginUnit = jRadioBodyMarginUnit0.isSelected()?"em":"%";
        for (int i=0; i<bodyMargin.length; i++) {
            bodyMargin[i] = jTextBodyMargins[i].getText()+bodyMarginUnit;
        }
        float lineHeight = 1.8f;
        try { lineHeight = Float.parseFloat(jComboLineHeight.getEditor().getItem().toString()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
        int fontSize = 100;
        try { fontSize = (int)Float.parseFloat(jComboFontSize.getEditor().getItem().toString()); } catch (Exception e) {
            throw new RuntimeException(e);
        }

        int dakutenType = jRadioDakutenType0.isSelected() ? 0 : (jRadioDakutenType1.isSelected() ? 1 : 2);

        this.epub3Writer.setStyles(pageMargin, bodyMargin, lineHeight, fontSize, jCheckBoldUseGothic.isSelected(), jCheckGothicUseBold.isSelected());

        try {
            //挿絵なし
            this.aozoraConverter.setNoIllust(jCheckNoIllust.isSelected());
            //栞用ID出力
            this.aozoraConverter.setWithMarkId(this.jCheckMarkId.isSelected());
            //変換オプション設定
            this.aozoraConverter.setAutoYoko(this.jCheckAutoYoko.isSelected(), this.jCheckAutoYokoNum1.isSelected(), this.jCheckAutoYokoNum3.isSelected(), this.jCheckAutoEQ1.isSelected());
            //文字出力設定
            this.aozoraConverter.setCharOutput(dakutenType, jCheckIvsBMP.isSelected(), jCheckIvsSSP.isSelected());
            //全角スペースの禁則
            this.aozoraConverter.setSpaceHyphenation(this.jRadioSpaceHyp0.isSelected()?0:(this.jRadioSpaceHyp1.isSelected()?1:2));
            //注記のルビ表示
            this.aozoraConverter.setChukiRuby(this.jRadioChukiRuby1.isSelected(), this.jRadioChukiRuby2.isSelected());
            //コメント
            this.aozoraConverter.setCommentPrint(this.jCheckCommentPrint.isSelected(), this.jCheckCommentConvert.isSelected());

            //float表示
            this.aozoraConverter.setImageFloat(this.jCheckImageFloatPage.isSelected(), this.jCheckImageFloatBlock.isSelected());

            //空行除去
            int removeEmptyLine = jComboxRemoveEmptyLine.getSelectedIndex();
            int maxEmptyLine = jComboxMaxEmptyLine.getSelectedIndex();
            this.aozoraConverter.setRemoveEmptyLine(removeEmptyLine, maxEmptyLine);

            //行頭字下げ
            this.aozoraConverter.setForceIndent(this.jCheckForceIndent.isSelected());

            //強制改ページ
            if (jCheckPageBreak.isSelected()) {
                try {
                    int forcePageBreakSize = 0;
                    int forcePageBreakEmpty = 0;
                    int forcePageBreakEmptySize = 0;
                    int forcePageBreakChapter = 0;
                    int forcePageBreakChapterSize = 0;
                    forcePageBreakSize = Integer.parseInt(jTextPageBreakSize.getText().trim()) * 1024;
                    if (jCheckPageBreakEmpty.isSelected()) {
                        forcePageBreakEmpty = Integer.parseInt(Objects.requireNonNull(jComboxPageBreakEmptyLine.getSelectedItem()).toString());
                        forcePageBreakEmptySize = Integer.parseInt(jTextPageBreakEmptySize.getText().trim()) * 1024;
                    } if (jCheckPageBreakChapter.isSelected()) {
                        forcePageBreakChapter = 1;
                        forcePageBreakChapterSize = Integer.parseInt(jTextPageBreakChapterSize.getText().trim()) * 1024;
                    }
                    //Converterに設定
                    this.aozoraConverter.setForcePageBreak(forcePageBreakSize, forcePageBreakEmpty, forcePageBreakEmptySize, forcePageBreakChapter, forcePageBreakChapterSize);
                } catch (Exception e) {
                    LogAppender.println("強制改ページパラメータ読み込みエラー");
                }
            }

            //目次設定
            int maxLength = 64;
            try { maxLength = Integer.parseInt((jTextMaxChapterNameLength.getText())); } catch (Exception e) {
                throw new RuntimeException(e);
            }

            this.aozoraConverter.setChapterLevel(maxLength, jCheckChapterExclude.isSelected(), jCheckChapterUseNextLine.isSelected(), jCheckChapterSection.isSelected(),
                    jCheckChapterH.isSelected(), jCheckChapterH1.isSelected(), jCheckChapterH2.isSelected(), jCheckChapterH3.isSelected(), jCheckSameLineChapter.isSelected(),
                    jCheckChapterName.isSelected(),
                    jCheckChapterNumOnly.isSelected(), jCheckChapterNumTitle.isSelected(), jCheckChapterNumParen.isSelected(), jCheckChapterNumParenTitle.isSelected(),
                    jCheckChapterPattern.isSelected()?jComboChapterPattern.getEditor().getItem().toString().trim():"");


            ////////////////////////////////////////////////////////////////
            //すべてのファイルの変換実行
            ////////////////////////////////////////////////////////////////

            this._convertFiles(srcFiles, dstPath);

            if (convertCanceled) {
                this.jProgressBar.setStringPainted(false);
                this.jProgressBar.setValue(0);
            }

        } catch (Exception e) {
            LogAppender.append("エラーが発生しました : ");
            LogAppender.println(e.getMessage());
            throw new RuntimeException(e);
        }
        ////////////////////////////////
        System.gc();

    }

ChatGPT:

この convertFiles メソッドは、Swing の UI コンポーネントを参照しながら、画像変換とEPUB生成のパラメータを取得し、複数ファイルの変換処理を行うものです。これを Android 向けに移植するには、以下の変更が必要です:

  1. Swing UI 部分の置き換え → Android の Preference や EditText, CheckBox, Spinner 等に変換。
  2. ログ出力 → System.out や Log に変換。
  3. 例外処理 → Android の文脈に合わせて Toast 表示や Log.e() に変換可。
  4. 進捗バー → ProgressBar に置き換え。
  5. UIスレッドとバックグラウンド処理 → Handler や Coroutine, Thread, AsyncTask 等で分離。

Swing UI 部分の置き換え → Android の Preference や EditText, CheckBox, Spinner 等に変換。

ログ出力 → System.out や Log に変換。

例外処理 → Android の文脈に合わせて Toast 表示や Log.e() に変換可。

進捗バー → ProgressBar に置き換え。

UIスレッドとバックグラウンド処理 → Handler や Coroutine, Thread, AsyncTask 等で分離。

Javaで書く場合はfindViewById等を使って同様に対応可能です。

fun convertFiles(context: Context, srcFiles: Array<File>, dstPath: File) {
    if (srcFiles.isEmpty()) return

    var convertCanceled = false

    // UIから設定取得
    val resizeW = getIntFromEditText(R.id.resizeWidthEditText)
    val resizeH = getIntFromEditText(R.id.resizeHeightEditText)
    val dispW = getIntFromEditText(R.id.displayWidthEditText)
    val dispH = getIntFromEditText(R.id.displayHeightEditText)
    val coverW = getIntFromEditText(R.id.coverWidthEditText)
    val coverH = getIntFromEditText(R.id.coverHeightEditText)

    val singlePageSizeW = getIntFromEditText(R.id.singlePageSizeWidthEditText)
    val singlePageSizeH = getIntFromEditText(R.id.singlePageSizeHeightEditText)
    val singlePageWidth = getIntFromEditText(R.id.singlePageWidthEditText)

    val imageScale = getFloatFromEditText(R.id.imageScaleEditText)
    val jpegQuality = getFloatFromEditText(R.id.jpegQualityEditText) / 100f
    val gamma = if (isChecked(R.id.gammaCheckBox)) getFloatFromEditText(R.id.gammaValueEditText) else 1.0f

    val imageFloatType = when (getSelectedIndex(R.id.imageFloatSpinner)) {
        0 -> 0
        1 -> 1
        else -> 2
    }

    val imageFloatW = getIntFromEditText(R.id.imageFloatWidthEditText)
    val imageFloatH = getIntFromEditText(R.id.imageFloatHeightEditText)

    // EPUB 書き出しパラメータなども同様に取得

    try {
        // 設定のセット
        epub3Writer.setImageParam(...)
        epub3ImageWriter.setImageParam(...)
        aozoraConverter.setNoIllust(...)
        aozoraConverter.setCharOutput(...)
        aozoraConverter.setForcePageBreak(...)

        // 実際の変換処理
        _convertFiles(srcFiles, dstPath)

        if (convertCanceled) {
            val progressBar = findViewById<ProgressBar>(R.id.progressBar)
            progressBar.progress = 0
        }

    } catch (e: Exception) {
        Log.e("Converter", "エラー: ${e.message}")
        Toast.makeText(context, "変換中にエラーが発生しました", Toast.LENGTH_LONG).show()
    }
}
fun getIntFromEditText(resId: Int): Int {
    return try {
        findViewById<EditText>(resId).text.toString().toInt()
    } catch (e: Exception) { 0 }
}

fun getFloatFromEditText(resId: Int): Float {
    return try {
        findViewById<EditText>(resId).text.toString().toFloat()
    } catch (e: Exception) { 0f }
}

fun isChecked(resId: Int): Boolean {
    return findViewById<CheckBox>(resId).isChecked
}

fun getSelectedIndex(resId: Int): Int {
    return findViewById<Spinner>(resId).selectedItemPosition
}

もしご希望があれば、Java版に完全変換したコードや、convertFiles() に必要なレイアウトXMLの構造例も出せます!

どうします?Javaで続けたい?Kotlinで整理したほうが楽なところもあるけど、どっちがいい?

あなた:

Javaでpreferenceから取得するとする

ChatGPT:

了解です!では、JavaでPreferenceから設定値を取得して、convertFiles()メソッドに活用する形で整理していきます。

AndroidのPreferenceFragmentCompatなどで保存された値は、SharedPreferencesから取得できます。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
public void convertFiles(Context context, File[] srcFiles, File dstPath) {
    if (srcFiles == null || srcFiles.length == 0) return;

    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

    // 数値系の設定
    int resizeW = prefs.getInt("resize_width", 0);
    int resizeH = prefs.getInt("resize_height", 0);
    int dispW = prefs.getInt("display_width", 0);
    int dispH = prefs.getInt("display_height", 0);
    int coverW = prefs.getInt("cover_width", 0);
    int coverH = prefs.getInt("cover_height", 0);
    int singlePageSizeW = prefs.getInt("single_page_size_width", 0);
    int singlePageSizeH = prefs.getInt("single_page_size_height", 0);
    int singlePageWidth = prefs.getInt("single_page_width", 0);

    float imageScale = prefs.getFloat("image_scale", 1.0f);
    float jpegQuality = prefs.getFloat("jpeg_quality", 0.8f);
    float gamma = prefs.getBoolean("enable_gamma", false) ?
                  prefs.getFloat("gamma_value", 1.0f) : 1.0f;

    // 画像回り込み設定(例: 0=なし, 1=強制, 2=自動)
    int imageFloatType = Integer.parseInt(prefs.getString("image_float_type", "0"));
    int imageFloatW = prefs.getInt("image_float_width", 0);
    int imageFloatH = prefs.getInt("image_float_height", 0);

    // 他の設定も同様に取得

    try {
        // 設定を各変換クラスにセット
        epub3Writer.setImageParam(imageScale, jpegQuality, gamma);
        epub3ImageWriter.setImageParam(resizeW, resizeH, dispW, dispH);
        aozoraConverter.setForcePageBreak(prefs.getBoolean("force_page_break", false));
        aozoraConverter.setCharOutput(prefs.getBoolean("char_output", false));
        aozoraConverter.setNoIllust(prefs.getBoolean("no_illust", false));

        _convertFiles(srcFiles, dstPath);

    } catch (Exception e) {
        Log.e("Converter", "変換中にエラー: " + e.getMessage(), e);
        Toast.makeText(context, "変換エラー: " + e.getMessage(), Toast.LENGTH_LONG).show();
    }
}

これらのキー(例: "resize_width" や "image_float_type")は、preferences.xml や PreferenceFragmentCompat で設定しておく必要があります。

<EditTextPreference
    android:key="resize_width"
    android:title="Resize Width"
    android:inputType="number"
    android:defaultValue="800" />

<ListPreference
    android:key="image_float_type"
    android:title="画像回り込み"
    android:entries="@array/image_float_entries"
    android:entryValues="@array/image_float_values"
    android:defaultValue="0" />

必要なら:

  • preferences.xml のテンプレート
  • PreferenceFragmentCompat の実装例
  • PreferenceActivity での呼び出し方 などもまとめて用意できます!

preferences.xml のテンプレート

PreferenceFragmentCompat の実装例

PreferenceActivity での呼び出し方 などもまとめて用意できます!

続きをどうする?上記の設定UIの部分見たい?それともこの convertFiles をさらに整理したい?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

     ////////////////////////////////////////////////////////////////
        //Appletのパラメータを取得
        ////////////////////////////////////////////////////////////////
        //画面サイズと画像リサイズ
        int resizeW = 0;
        if (jCheckResizeW.isSelected()) try { resizeW = Integer.parseInt(jTextResizeNumW.getText()); } catch (Exception ignored) {}
        int resizeH = 0;
        if (jCheckResizeH.isSelected()) try { resizeH = Integer.parseInt(jTextResizeNumH.getText()); } catch (Exception ignored) {}
        //int pixels = 0;
        //if (jCheckPixel.isSelected()) try { pixels = Integer.parseInt(jTextPixelW.getText())*Integer.parseInt(jTextPixelH.getText()); } catch (Exception e) {}
        int dispW = Integer.parseInt(jTextDispW.getText());
        int dispH = Integer.parseInt(jTextDispH.getText());
        this.coverW = Integer.parseInt(this.jTextCoverW.getText());
        this.coverH = Integer.parseInt(this.jTextCoverH.getText());
        int singlePageSizeW = Integer.parseInt(jTextSinglePageSizeW.getText());
        int singlePageSizeH = Integer.parseInt(jTextSinglePageSizeH.getText());
        int singlePageWidth = Integer.parseInt(jTextSinglePageWidth.getText());

ChatGPT:

このSwingベースのコードを Android 向けに書き換えて Java の Preference(SharedPreferences)から取得するようにする場合、以下のようになります。

// Preferenceから設定値を取得する
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

// 画面サイズと画像リサイズ
int resizeW = 0;
if (prefs.getBoolean("resizeW_enabled", false)) {
    try {
        resizeW = Integer.parseInt(prefs.getString("resizeW_value", "0"));
    } catch (Exception ignored) {}
}

int resizeH = 0;
if (prefs.getBoolean("resizeH_enabled", false)) {
    try {
        resizeH = Integer.parseInt(prefs.getString("resizeH_value", "0"));
    } catch (Exception ignored) {}
}

// 表示サイズ
int dispW = 0;
try {
    dispW = Integer.parseInt(prefs.getString("dispW", "0"));
} catch (Exception ignored) {}

int dispH = 0;
try {
    dispH = Integer.parseInt(prefs.getString("dispH", "0"));
} catch (Exception ignored) {}

// カバー画像サイズ
int coverW = 0;
try {
    coverW = Integer.parseInt(prefs.getString("coverW", "0"));
} catch (Exception ignored) {}

int coverH = 0;
try {
    coverH = Integer.parseInt(prefs.getString("coverH", "0"));
} catch (Exception ignored) {}

// 単ページ化サイズと幅
int singlePageSizeW = 0;
try {
    singlePageSizeW = Integer.parseInt(prefs.getString("singlePageSizeW", "0"));
} catch (Exception ignored) {}

int singlePageSizeH = 0;
try {
    singlePageSizeH = Integer.parseInt(prefs.getString("singlePageSizeH", "0"));
} catch (Exception ignored) {}

int singlePageWidth = 0;
try {
    singlePageWidth = Integer.parseInt(prefs.getString("singlePageWidth", "0"));
} catch (Exception ignored) {}
機能 Boolean キー String キー
横幅リサイズ使用 resizeW_enabled resizeW_value
縦幅リサイズ使用 resizeH_enabled resizeH_value
表示サイズ(横) dispW
表示サイズ(縦) dispH
カバー画像サイズ(横) coverW
カバー画像サイズ(縦) coverH
単ページサイズ(横) singlePageSizeW
単ページサイズ(縦) singlePageSizeH
単ページの幅 singlePageWidth

もし PreferenceScreen のXMLや SettingsFragment のコードも必要でしたら、それも用意できますよ!要りますか?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

    float imageScale = 0;
    if (jCheckImageScale.isSelected()) try { imageScale = Float.parseFloat(jTextImageScale.getText()); } catch (Exception e) {
        throw new RuntimeException(e);
    }
    int imageFloatType = 0; //0=無効 1=上 2=下
    int imageFloatW = 0;
    int imageFloatH = 0;
    if (jCheckImageFloat.isSelected()) {
        imageFloatType = this.jComboImageFloatType.getSelectedIndex()+1;
        try { imageFloatW =Integer.parseInt(jTextImageFloatW.getText()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try { imageFloatH =Integer.parseInt(jTextImageFloatH.getText()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    float jpegQualty = 0.8f; try { jpegQualty = Integer.parseInt(jTextJpegQuality.getText())/100f; } catch (Exception e) {
        throw new RuntimeException(e);
    }
    float gamma = 1.0f; if (jCheckGamma.isSelected()) try { gamma = Float.parseFloat(jTextGammaValue.getText()); } catch (Exception e) {
        throw new RuntimeException(e);
    }

ChatGPT:

このSwingベースのコードを Android 向けに書き換え、SharedPreferences から値を取得する形にすると、以下のようになります。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

// 画像スケールの取得
float imageScale = 0;
if (prefs.getBoolean("imageScale_enabled", false)) {
    try {
        imageScale = Float.parseFloat(prefs.getString("imageScale_value", "0"));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

// 画像の回り込み設定(float設定)
int imageFloatType = 0; // 0=無効, 1=上, 2=下
int imageFloatW = 0;
int imageFloatH = 0;

if (prefs.getBoolean("imageFloat_enabled", false)) {
    imageFloatType = prefs.getInt("imageFloatType", 0); // 1 or 2 を直接保存する

    try {
        imageFloatW = Integer.parseInt(prefs.getString("imageFloatW", "0"));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    try {
        imageFloatH = Integer.parseInt(prefs.getString("imageFloatH", "0"));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

// JPEGクオリティの取得(0.0f〜1.0f)
float jpegQuality = 0.8f;
try {
    jpegQuality = Integer.parseInt(prefs.getString("jpegQuality", "80")) / 100f;
} catch (Exception e) {
    throw new RuntimeException(e);
}

// ガンマ値の取得
float gamma = 1.0f;
if (prefs.getBoolean("gamma_enabled", false)) {
    try {
        gamma = Float.parseFloat(prefs.getString("gamma_value", "1.0"));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
機能名 Boolean キー String/Int キー 備考
画像スケール imageScale_enabled imageScale_value 例: 1.2など
回り込み設定ON/OFF imageFloat_enabled
回り込みの位置 imageFloatType 1=上, 2=下
回り込み横幅 imageFloatW
回り込み縦幅 imageFloatH
JPEG品質(整数%) jpegQuality 例: 80 で 0.8f になる
ガンマ補正ON/OFF gamma_enabled gamma_value 例: 1.0, 0.9 など

PreferenceScreen の XML や、SettingsFragment での設定画面コードもご希望であれば、続けて作成できますよ。必要ですか?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

    int autoMarginLimitH = 0;
    int autoMarginLimitV = 0;
    int autoMarginWhiteLevel = 0;
    float autoMarginPadding = 0;
    int autoMarginNombre = 0;
    float autoMarginNombreSize = 0.03f;
    if (jCheckAutoMargin.isSelected()) {
        autoMarginLimitH =Integer.parseInt(jTextAutoMarginLimitH.getText());
        try { autoMarginLimitV =Integer.parseInt(jTextAutoMarginLimitV.getText()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try { autoMarginWhiteLevel =Integer.parseInt(jTextAutoMarginWhiteLevel.getText()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try { autoMarginPadding =Float.parseFloat(jTextAutoMarginPadding.getText()); } catch (Exception e) {
            throw new RuntimeException(e);
        }
        autoMarginNombre = jComboAutoMarginNombre.getSelectedIndex();
        try { autoMarginNombreSize =Float.parseFloat(jTextAutoMarginNombreSize.getText())*0.01f; } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    int rorateAngle = 0; if (jComboRotateImage.getSelectedIndex() == 1) rorateAngle = 90; else if (jComboRotateImage.getSelectedIndex() == 2) rorateAngle = -90;

    int imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_ASPECT;
    if (jRadioImageSizeType1.isSelected()) imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_AUTO;
    //else if (jRadioImageSizeType2.isSelected()) imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_HEIGHT;

    //int imageFitType = SectionInfo.IMAGE_SIZE_TYPE_ASPECT;
    //if (jRadioImageFitType2.isSelected()) imageFitType = SectionInfo.IMAGE_SIZE_TYPE_HEIGHT;

    this.epub3Writer.setImageParam(dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth,
            imageSizeType, jCheckFitImage.isSelected(), jCheckSvgImage.isSelected(), rorateAngle,
            imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQualty, gamma, autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding, autoMarginNombre, autoMarginNombreSize);
    this.epub3ImageWriter.setImageParam(dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth,
            imageSizeType, jCheckFitImage.isSelected(), jCheckSvgImage.isSelected(), rorateAngle,
            imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQualty, gamma, autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding, autoMarginNombre, autoMarginNombreSize);

ChatGPT:

以下は、上記のSwingコードを Android 向けに Java + SharedPreferences に書き換えた例です。各値は Preference に保存されている前提で、例外処理を含みつつ変換しています。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

// 自動マージン設定(有効な場合のみ取得)
int autoMarginLimitH = 0;
int autoMarginLimitV = 0;
int autoMarginWhiteLevel = 0;
float autoMarginPadding = 0;
int autoMarginNombre = 0;
float autoMarginNombreSize = 0.03f;

if (prefs.getBoolean("autoMargin_enabled", false)) {
    try {
        autoMarginLimitH = Integer.parseInt(prefs.getString("autoMarginLimitH", "0"));
        autoMarginLimitV = Integer.parseInt(prefs.getString("autoMarginLimitV", "0"));
        autoMarginWhiteLevel = Integer.parseInt(prefs.getString("autoMarginWhiteLevel", "0"));
        autoMarginPadding = Float.parseFloat(prefs.getString("autoMarginPadding", "0"));
        autoMarginNombre = prefs.getInt("autoMarginNombre", 0);
        autoMarginNombreSize = Float.parseFloat(prefs.getString("autoMarginNombreSize", "3")) * 0.01f;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

// 回転角度(選択肢 0=なし, 1=右, 2=左)
int rotateAngle = 0;
int rotateIndex = prefs.getInt("rotateImage", 0); // 0, 1, 2
if (rotateIndex == 1) rotateAngle = 90;
else if (rotateIndex == 2) rotateAngle = -90;

// 画像サイズタイプ(0=ASPECT, 1=AUTO)
int imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_ASPECT;
if (prefs.getBoolean("imageSizeType_auto", false)) {
    imageSizeType = SectionInfo.IMAGE_SIZE_TYPE_AUTO;
}

// フィット・SVG画像のフラグ
boolean fitImage = prefs.getBoolean("fitImage", false);
boolean svgImage = prefs.getBoolean("svgImage", false);

// 最終的な設定値をセット
this.epub3Writer.setImageParam(
    dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth,
    imageSizeType, fitImage, svgImage, rotateAngle,
    imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQuality, gamma,
    autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding,
    autoMarginNombre, autoMarginNombreSize
);

this.epub3ImageWriter.setImageParam(
    dispW, dispH, coverW, coverH, resizeW, resizeH, singlePageSizeW, singlePageSizeH, singlePageWidth,
    imageSizeType, fitImage, svgImage, rotateAngle,
    imageScale, imageFloatType, imageFloatW, imageFloatH, jpegQuality, gamma,
    autoMarginLimitH, autoMarginLimitV, autoMarginWhiteLevel, autoMarginPadding,
    autoMarginNombre, autoMarginNombreSize
);
機能 キー 備考
自動マージン使用 autoMargin_enabled boolean チェックボックス
横方向マージン制限 autoMarginLimitH string 例: "30"
縦方向マージン制限 autoMarginLimitV string
白レベル autoMarginWhiteLevel string
パディング比率 autoMarginPadding string 例: "0.05"
ノンブル位置(選択インデックス) autoMarginNombre int 0=なし、1=上、2=下など
ノンブルサイズ(%) autoMarginNombreSize string 例: "3" → 0.03f
画像回転 rotateImage int 0=回転なし, 1=右90°, 2=左90°
画像サイズタイプ imageSizeType_auto boolean true = AUTO
画像フィット fitImage boolean チェックボックス
SVG画像使用 svgImage boolean チェックボックス

もしこれに基づく PreferenceFragmentCompat の設定画面(XML含む) や 選択肢設定(ListPreferenceやDropDown) の実装が必要であれば、それもすぐ作成できます。どうしますか?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

    //目次階層化設定
    this.epub3Writer.setTocParam(jCheckNavNest.isSelected(), jCheckNcxNest.isSelected());

    //スタイル設定
    String[] pageMargin = new String[4];
    String pageMarginUnit = jRadioPageMarginUnit0.isSelected()?"em":"%";
    for (int i=0; i<pageMargin.length; i++) {
        pageMargin[i] = jTextPageMargins[i].getText()+pageMarginUnit;
    }
    String[] bodyMargin = new String[4];
    String bodyMarginUnit = jRadioBodyMarginUnit0.isSelected()?"em":"%";
    for (int i=0; i<bodyMargin.length; i++) {
        bodyMargin[i] = jTextBodyMargins[i].getText()+bodyMarginUnit;
    }
    float lineHeight = 1.8f;
    try { lineHeight = Float.parseFloat(jComboLineHeight.getEditor().getItem().toString()); } catch (Exception e) {
        throw new RuntimeException(e);
    }
    int fontSize = 100;
    try { fontSize = (int)Float.parseFloat(jComboFontSize.getEditor().getItem().toString()); } catch (Exception e) {
        throw new RuntimeException(e);
    }

    int dakutenType = jRadioDakutenType0.isSelected() ? 0 : (jRadioDakutenType1.isSelected() ? 1 : 2);

    this.epub3Writer.setStyles(pageMargin, bodyMargin, lineHeight, fontSize, jCheckBoldUseGothic.isSelected(), jCheckGothicUseBold.isSelected());

ChatGPT:

以下は、提示された Swing コードを Android 向けに Java + SharedPreferences を使って書き換えた実装です。設定画面から取得するスタイル設定・目次設定などを含めています。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

// 目次階層化設定(ナビゲーションとNCXのネスト)
boolean navNest = prefs.getBoolean("toc_nav_nest", false);
boolean ncxNest = prefs.getBoolean("toc_ncx_nest", false);
this.epub3Writer.setTocParam(navNest, ncxNest);

// スタイル設定
String[] pageMargin = new String[4];
String pageMarginUnit = prefs.getString("pageMargin_unit", "em"); // "em" or "%"
for (int i = 0; i < 4; i++) {
    pageMargin[i] = prefs.getString("pageMargin" + i, "0") + pageMarginUnit;
}

String[] bodyMargin = new String[4];
String bodyMarginUnit = prefs.getString("bodyMargin_unit", "em"); // "em" or "%"
for (int i = 0; i < 4; i++) {
    bodyMargin[i] = prefs.getString("bodyMargin" + i, "0") + bodyMarginUnit;
}

// 行間
float lineHeight = 1.8f;
try {
    lineHeight = Float.parseFloat(prefs.getString("lineHeight", "1.8"));
} catch (Exception e) {
    throw new RuntimeException(e);
}

// フォントサイズ
int fontSize = 100;
try {
    fontSize = (int) Float.parseFloat(prefs.getString("fontSize", "100"));
} catch (Exception e) {
    throw new RuntimeException(e);
}

// 濁点結合タイプ(0=結合, 1=分離, 2=自動)
int dakutenType = prefs.getInt("dakuten_type", 0);

// ゴシック・ボールド設定
boolean boldUseGothic = prefs.getBoolean("bold_use_gothic", false);
boolean gothicUseBold = prefs.getBoolean("gothic_use_bold", false);

// 設定を適用
this.epub3Writer.setStyles(pageMargin, bodyMargin, lineHeight, fontSize, boldUseGothic, gothicUseBold);
項目 キー 備考
ナビ階層化 toc_nav_nest boolean チェックボックス
NCX階層化 toc_ncx_nest boolean チェックボックス
ページマージン単位 pageMargin_unit string "em" または "%"
ページマージン数値 pageMargin0 ~ pageMargin3 string 各辺のマージン数値
本文マージン単位 bodyMargin_unit string 同上
本文マージン数値 bodyMargin0 ~ bodyMargin3 string 同上
行間 lineHeight string 例: "1.8"
フォントサイズ fontSize string 例: "100"
濁点結合タイプ dakuten_type int 0=結合, 1=分離, 2=自動
ゴシック化 bold_use_gothic boolean チェックボックス
ボールド化 gothic_use_bold boolean チェックボックス
  • SharedPreferences の getString(...) は EditTextPreference に対応しています。
  • ラジオボタン相当のものは ListPreference(文字列型)や DropDownPreference で int 変換。
  • PreferenceFragmentCompat と preferences.xml を定義することで、これらを GUI から編集可能になります。

SharedPreferences の getString(...) は EditTextPreference に対応しています。

ラジオボタン相当のものは ListPreference(文字列型)や DropDownPreference で int 変換。

PreferenceFragmentCompat と preferences.xml を定義することで、これらを GUI から編集可能になります。

ご希望があれば、これに対応する preferences.xml や PreferenceFragmentCompat の実装テンプレートもお出しできます。必要ですか?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

    try {
        //挿絵なし
        this.aozoraConverter.setNoIllust(jCheckNoIllust.isSelected());
        //栞用ID出力
        this.aozoraConverter.setWithMarkId(this.jCheckMarkId.isSelected());
        //変換オプション設定
        this.aozoraConverter.setAutoYoko(this.jCheckAutoYoko.isSelected(), this.jCheckAutoYokoNum1.isSelected(), this.jCheckAutoYokoNum3.isSelected(), this.jCheckAutoEQ1.isSelected());
        //文字出力設定
        this.aozoraConverter.setCharOutput(dakutenType, jCheckIvsBMP.isSelected(), jCheckIvsSSP.isSelected());
        //全角スペースの禁則
        this.aozoraConverter.setSpaceHyphenation(this.jRadioSpaceHyp0.isSelected()?0:(this.jRadioSpaceHyp1.isSelected()?1:2));
        //注記のルビ表示
        this.aozoraConverter.setChukiRuby(this.jRadioChukiRuby1.isSelected(), this.jRadioChukiRuby2.isSelected());
        //コメント
        this.aozoraConverter.setCommentPrint(this.jCheckCommentPrint.isSelected(), this.jCheckCommentConvert.isSelected());

        //float表示
        this.aozoraConverter.setImageFloat(this.jCheckImageFloatPage.isSelected(), this.jCheckImageFloatBlock.isSelected());

        //空行除去
        int removeEmptyLine = jComboxRemoveEmptyLine.getSelectedIndex();
        int maxEmptyLine = jComboxMaxEmptyLine.getSelectedIndex();
        this.aozoraConverter.setRemoveEmptyLine(removeEmptyLine, maxEmptyLine);

        //行頭字下げ
        this.aozoraConverter.setForceIndent(this.jCheckForceIndent.isSelected());

        //強制改ページ
        if (jCheckPageBreak.isSelected()) {
            try {
                int forcePageBreakSize = 0;
                int forcePageBreakEmpty = 0;
                int forcePageBreakEmptySize = 0;
                int forcePageBreakChapter = 0;
                int forcePageBreakChapterSize = 0;
                forcePageBreakSize = Integer.parseInt(jTextPageBreakSize.getText().trim()) * 1024;
                if (jCheckPageBreakEmpty.isSelected()) {
                    forcePageBreakEmpty = Integer.parseInt(Objects.requireNonNull(jComboxPageBreakEmptyLine.getSelectedItem()).toString());
                    forcePageBreakEmptySize = Integer.parseInt(jTextPageBreakEmptySize.getText().trim()) * 1024;
                } if (jCheckPageBreakChapter.isSelected()) {
                    forcePageBreakChapter = 1;
                    forcePageBreakChapterSize = Integer.parseInt(jTextPageBreakChapterSize.getText().trim()) * 1024;
                }
                //Converterに設定
                this.aozoraConverter.setForcePageBreak(forcePageBreakSize, forcePageBreakEmpty, forcePageBreakEmptySize, forcePageBreakChapter, forcePageBreakChapterSize);
            } catch (Exception e) {
                LogAppender.println("強制改ページパラメータ読み込みエラー");
            }
        }

ChatGPT:

以下は、上記の Swing UI コードを Android 用に書き換えた Java コード で、SharedPreferences を使って設定を取得し、AozoraConverter に反映する形式です。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

try {
    // 挿絵なし
    this.aozoraConverter.setNoIllust(prefs.getBoolean("no_illust", false));

    // 栞用ID出力
    this.aozoraConverter.setWithMarkId(prefs.getBoolean("with_mark_id", false));

    // 変換オプション設定(横書き等)
    boolean autoYoko = prefs.getBoolean("auto_yoko", false);
    boolean autoYokoNum1 = prefs.getBoolean("auto_yoko_num1", false);
    boolean autoYokoNum3 = prefs.getBoolean("auto_yoko_num3", false);
    boolean autoEQ1 = prefs.getBoolean("auto_yoko_eq1", false);
    this.aozoraConverter.setAutoYoko(autoYoko, autoYokoNum1, autoYokoNum3, autoEQ1);

    // 文字出力設定
    boolean ivsBmp = prefs.getBoolean("ivs_bmp", false);
    boolean ivsSsp = prefs.getBoolean("ivs_ssp", false);
    int dakutenType = prefs.getInt("dakuten_type", 0); // 既出項目
    this.aozoraConverter.setCharOutput(dakutenType, ivsBmp, ivsSsp);

    // 全角スペースの禁則設定(0, 1, 2)
    int spaceHyphenation = prefs.getInt("space_hyphenation", 0);
    this.aozoraConverter.setSpaceHyphenation(spaceHyphenation);

    // 注記のルビ表示(引数は boolean, boolean)
    boolean chukiRuby1 = prefs.getBoolean("chuki_ruby1", false);
    boolean chukiRuby2 = prefs.getBoolean("chuki_ruby2", false);
    this.aozoraConverter.setChukiRuby(chukiRuby1, chukiRuby2);

    // コメント設定
    boolean commentPrint = prefs.getBoolean("comment_print", false);
    boolean commentConvert = prefs.getBoolean("comment_convert", false);
    this.aozoraConverter.setCommentPrint(commentPrint, commentConvert);

    // float 表示設定
    boolean imageFloatPage = prefs.getBoolean("image_float_page", false);
    boolean imageFloatBlock = prefs.getBoolean("image_float_block", false);
    this.aozoraConverter.setImageFloat(imageFloatPage, imageFloatBlock);

    // 空行除去設定
    int removeEmptyLine = prefs.getInt("remove_empty_line", 0);
    int maxEmptyLine = prefs.getInt("max_empty_line", 0);
    this.aozoraConverter.setRemoveEmptyLine(removeEmptyLine, maxEmptyLine);

    // 行頭字下げ
    this.aozoraConverter.setForceIndent(prefs.getBoolean("force_indent", false));

    // 強制改ページ
    if (prefs.getBoolean("page_break_enabled", false)) {
        try {
            int forcePageBreakSize = Integer.parseInt(prefs.getString("page_break_size_kb", "0")) * 1024;

            int forcePageBreakEmpty = 0;
            int forcePageBreakEmptySize = 0;
            if (prefs.getBoolean("page_break_empty_enabled", false)) {
                forcePageBreakEmpty = Integer.parseInt(prefs.getString("page_break_empty_line_count", "0"));
                forcePageBreakEmptySize = Integer.parseInt(prefs.getString("page_break_empty_size_kb", "0")) * 1024;
            }

            int forcePageBreakChapter = 0;
            int forcePageBreakChapterSize = 0;
            if (prefs.getBoolean("page_break_chapter_enabled", false)) {
                forcePageBreakChapter = 1;
                forcePageBreakChapterSize = Integer.parseInt(prefs.getString("page_break_chapter_size_kb", "0")) * 1024;
            }

            this.aozoraConverter.setForcePageBreak(
                forcePageBreakSize,
                forcePageBreakEmpty,
                forcePageBreakEmptySize,
                forcePageBreakChapter,
                forcePageBreakChapterSize
            );
        } catch (Exception e) {
            Log.e("Aozora", "強制改ページパラメータ読み込みエラー", e);
        }
    }

} catch (Exception e) {
    Log.e("Aozora", "設定の読み込み中にエラーが発生しました", e);
}
項目 キー名
挿絵なし no_illust boolean
栞用ID出力 with_mark_id boolean
自動横書き変換 auto_yoko boolean
横書き:1桁数字 auto_yoko_num1 boolean
横書き:3桁数字 auto_yoko_num3 boolean
横書き:記号= auto_yoko_eq1 boolean
IVS BMP 出力 ivs_bmp boolean
IVS SSP 出力 ivs_ssp boolean
濁点タイプ dakuten_type int
全角スペース禁則 space_hyphenation int
注記ルビ(青空方式) chuki_ruby1 boolean
注記ルビ(電書協方式) chuki_ruby2 boolean
コメント出力 comment_print boolean
コメント変換 comment_convert boolean
挿絵 float 表示ページ内 image_float_page boolean
挿絵 float 表示ブロック内 image_float_block boolean
空行除去タイプ remove_empty_line int
空行の最大数 max_empty_line int
行頭字下げ force_indent boolean
改ページ有効 page_break_enabled boolean
改ページ条件(全体サイズ) page_break_size_kb string
空行による改ページ有効 page_break_empty_enabled boolean
空行数 page_break_empty_line_count string
空行改ページサイズ page_break_empty_size_kb string
章改ページ有効 page_break_chapter_enabled boolean
章改ページサイズ page_break_chapter_size_kb string

この形式に対応する preferences.xml をご希望でしたら、続けて生成します!必要ですか?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

        //目次設定
        int maxLength = 64;
        try { maxLength = Integer.parseInt((jTextMaxChapterNameLength.getText())); } catch (Exception e) {
            throw new RuntimeException(e);
        }

        this.aozoraConverter.setChapterLevel(maxLength, jCheckChapterExclude.isSelected(), jCheckChapterUseNextLine.isSelected(), jCheckChapterSection.isSelected(),
                jCheckChapterH.isSelected(), jCheckChapterH1.isSelected(), jCheckChapterH2.isSelected(), jCheckChapterH3.isSelected(), jCheckSameLineChapter.isSelected(),
                jCheckChapterName.isSelected(),
                jCheckChapterNumOnly.isSelected(), jCheckChapterNumTitle.isSelected(), jCheckChapterNumParen.isSelected(), jCheckChapterNumParenTitle.isSelected(),
                jCheckChapterPattern.isSelected()?jComboChapterPattern.getEditor().getItem().toString().trim():"");


        ////////////////////////////////////////////////////////////////
        //すべてのファイルの変換実行
        ////////////////////////////////////////////////////////////////

        this._convertFiles(srcFiles, dstPath);

        if (convertCanceled) {
            this.jProgressBar.setStringPainted(false);
            this.jProgressBar.setValue(0);
        }

    } catch (Exception e) {
        LogAppender.append("エラーが発生しました : ");
        LogAppender.println(e.getMessage());
        throw new RuntimeException(e);
    }
    ////////////////////////////////
    System.gc();

ChatGPT:

以下は、提示された Swing ベースのコードを Android 向けに書き換え、SharedPreferences を使って目次設定の各種パラメータを取得する形にした Java コードです。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

try {
    // 目次設定:最大章タイトル長さ(例: 64)
    int maxLength = 64;
    try {
        maxLength = Integer.parseInt(prefs.getString("max_chapter_name_length", "64"));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    // チェックボックス系の取得
    boolean chapterExclude = prefs.getBoolean("chapter_exclude", false);
    boolean chapterUseNextLine = prefs.getBoolean("chapter_use_next_line", false);
    boolean chapterSection = prefs.getBoolean("chapter_section", false);
    boolean chapterH = prefs.getBoolean("chapter_h", false);
    boolean chapterH1 = prefs.getBoolean("chapter_h1", false);
    boolean chapterH2 = prefs.getBoolean("chapter_h2", false);
    boolean chapterH3 = prefs.getBoolean("chapter_h3", false);
    boolean sameLineChapter = prefs.getBoolean("same_line_chapter", false);
    boolean chapterName = prefs.getBoolean("chapter_name", false);
    boolean chapterNumOnly = prefs.getBoolean("chapter_num_only", false);
    boolean chapterNumTitle = prefs.getBoolean("chapter_num_title", false);
    boolean chapterNumParen = prefs.getBoolean("chapter_num_paren", false);
    boolean chapterNumParenTitle = prefs.getBoolean("chapter_num_paren_title", false);

    // パターン(空文字の可能性あり)
    String chapterPattern = "";
    if (prefs.getBoolean("chapter_pattern_enabled", false)) {
        chapterPattern = prefs.getString("chapter_pattern", "").trim();
    }

    // 設定を反映
    this.aozoraConverter.setChapterLevel(
        maxLength,
        chapterExclude,
        chapterUseNextLine,
        chapterSection,
        chapterH,
        chapterH1,
        chapterH2,
        chapterH3,
        sameLineChapter,
        chapterName,
        chapterNumOnly,
        chapterNumTitle,
        chapterNumParen,
        chapterNumParenTitle,
        chapterPattern
    );

    ////////////////////////////////////////////////////////////////
    // すべてのファイルの変換実行
    ////////////////////////////////////////////////////////////////

    this._convertFiles(srcFiles, dstPath);

    if (convertCanceled) {
        // 進捗バーの処理(Androidでは ProgressBar を非表示にする等に置き換え)
        progressBar.setIndeterminate(false);
        progressBar.setProgress(0);
    }

} catch (Exception e) {
    Log.e("Aozora", "エラーが発生しました : " + e.getMessage(), e);
    throw new RuntimeException(e);
} finally {
    System.gc(); // 必要性が薄いが Swing 互換のために残す
}
項目 キー名
最大章タイトル長 max_chapter_name_length string
除外 chapter_exclude boolean
次の行を使用 chapter_use_next_line boolean
section を使う chapter_section boolean
<h*> を使う(共通) chapter_h boolean

を使う

chapter_h1 boolean

を使う

chapter_h2 boolean

を使う

chapter_h3 boolean
同一行に出力 same_line_chapter boolean
タイトルを出力 chapter_name boolean
数字のみ chapter_num_only boolean
数字+タイトル chapter_num_title boolean
数字(括弧付き) chapter_num_paren boolean
数字(括弧)+タイトル chapter_num_paren_title boolean
正規表現パターン使用 chapter_pattern_enabled boolean
パターン文字列 chapter_pattern string

必要であれば、これらに対応する Android の PreferenceScreen XML も生成できます!欲しいですか?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

    try {
        //挿絵なし
        this.aozoraConverter.setNoIllust(jCheckNoIllust.isSelected());
        //栞用ID出力
        this.aozoraConverter.setWithMarkId(this.jCheckMarkId.isSelected());
        //変換オプション設定
        this.aozoraConverter.setAutoYoko(this.jCheckAutoYoko.isSelected(), this.jCheckAutoYokoNum1.isSelected(), this.jCheckAutoYokoNum3.isSelected(), this.jCheckAutoEQ1.isSelected());
        //文字出力設定
        this.aozoraConverter.setCharOutput(dakutenType, jCheckIvsBMP.isSelected(), jCheckIvsSSP.isSelected());
        //全角スペースの禁則
        this.aozoraConverter.setSpaceHyphenation(this.jRadioSpaceHyp0.isSelected()?0:(this.jRadioSpaceHyp1.isSelected()?1:2));
        //注記のルビ表示
        this.aozoraConverter.setChukiRuby(this.jRadioChukiRuby1.isSelected(), this.jRadioChukiRuby2.isSelected());
        //コメント
        this.aozoraConverter.setCommentPrint(this.jCheckCommentPrint.isSelected(), this.jCheckCommentConvert.isSelected());

        //float表示
        this.aozoraConverter.setImageFloat(this.jCheckImageFloatPage.isSelected(), this.jCheckImageFloatBlock.isSelected());

        //空行除去
        int removeEmptyLine = jComboxRemoveEmptyLine.getSelectedIndex();
        int maxEmptyLine = jComboxMaxEmptyLine.getSelectedIndex();
        this.aozoraConverter.setRemoveEmptyLine(removeEmptyLine, maxEmptyLine);

        //行頭字下げ
        this.aozoraConverter.setForceIndent(this.jCheckForceIndent.isSelected());

        //強制改ページ
        if (jCheckPageBreak.isSelected()) {
            try {
                int forcePageBreakSize = 0;
                int forcePageBreakEmpty = 0;
                int forcePageBreakEmptySize = 0;
                int forcePageBreakChapter = 0;
                int forcePageBreakChapterSize = 0;
                forcePageBreakSize = Integer.parseInt(jTextPageBreakSize.getText().trim()) * 1024;
                if (jCheckPageBreakEmpty.isSelected()) {
                    forcePageBreakEmpty = Integer.parseInt(Objects.requireNonNull(jComboxPageBreakEmptyLine.getSelectedItem()).toString());
                    forcePageBreakEmptySize = Integer.parseInt(jTextPageBreakEmptySize.getText().trim()) * 1024;
                } if (jCheckPageBreakChapter.isSelected()) {
                    forcePageBreakChapter = 1;
                    forcePageBreakChapterSize = Integer.parseInt(jTextPageBreakChapterSize.getText().trim()) * 1024;
                }
                //Converterに設定
                this.aozoraConverter.setForcePageBreak(forcePageBreakSize, forcePageBreakEmpty, forcePageBreakEmptySize, forcePageBreakChapter, forcePageBreakChapterSize);
            } catch (Exception e) {
                LogAppender.println("強制改ページパラメータ読み込みエラー");
            }
        }
        //目次設定
        int maxLength = 64;
        try { maxLength = Integer.parseInt((jTextMaxChapterNameLength.getText())); } catch (Exception e) {
            throw new RuntimeException(e);
        }

        this.aozoraConverter.setChapterLevel(maxLength, jCheckChapterExclude.isSelected(), jCheckChapterUseNextLine.isSelected(), jCheckChapterSection.isSelected(),
                jCheckChapterH.isSelected(), jCheckChapterH1.isSelected(), jCheckChapterH2.isSelected(), jCheckChapterH3.isSelected(), jCheckSameLineChapter.isSelected(),
                jCheckChapterName.isSelected(),
                jCheckChapterNumOnly.isSelected(), jCheckChapterNumTitle.isSelected(), jCheckChapterNumParen.isSelected(), jCheckChapterNumParenTitle.isSelected(),
                jCheckChapterPattern.isSelected()?jComboChapterPattern.getEditor().getItem().toString().trim():"");


        ////////////////////////////////////////////////////////////////
        //すべてのファイルの変換実行
        ////////////////////////////////////////////////////////////////

        this._convertFiles(srcFiles, dstPath);

        if (convertCanceled) {
            this.jProgressBar.setStringPainted(false);
            this.jProgressBar.setValue(0);
        }

    } catch (Exception e) {
        LogAppender.append("エラーが発生しました : ");
        LogAppender.println(e.getMessage());
        throw new RuntimeException(e);
    }
    ////////////////////////////////
    System.gc();

}

ChatGPT:

以下は、提示された Swing ベースの変換処理ロジック全体を Android 向けに書き換えた Java コードです。SharedPreferences から設定値を取得し、それぞれの変換オプションへ適用する形になっています。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

try {
    // 挿絵なし
    this.aozoraConverter.setNoIllust(prefs.getBoolean("no_illust", false));

    // 栞用ID出力
    this.aozoraConverter.setWithMarkId(prefs.getBoolean("with_mark_id", false));

    // 変換オプション設定(自動横組み)
    boolean autoYoko = prefs.getBoolean("auto_yoko", false);
    boolean autoYokoNum1 = prefs.getBoolean("auto_yoko_num1", false);
    boolean autoYokoNum3 = prefs.getBoolean("auto_yoko_num3", false);
    boolean autoEQ1 = prefs.getBoolean("auto_eq1", false);
    this.aozoraConverter.setAutoYoko(autoYoko, autoYokoNum1, autoYokoNum3, autoEQ1);

    // 文字出力設定
    int dakutenType = Integer.parseInt(prefs.getString("dakuten_type", "0"));
    boolean ivsBMP = prefs.getBoolean("ivs_bmp", false);
    boolean ivsSSP = prefs.getBoolean("ivs_ssp", false);
    this.aozoraConverter.setCharOutput(dakutenType, ivsBMP, ivsSSP);

    // 全角スペースの禁則
    int spaceHyphenation = Integer.parseInt(prefs.getString("space_hyphenation", "0"));
    this.aozoraConverter.setSpaceHyphenation(spaceHyphenation);

    // 注記のルビ表示
    boolean chukiRuby1 = prefs.getBoolean("chuki_ruby_1", false);
    boolean chukiRuby2 = prefs.getBoolean("chuki_ruby_2", false);
    this.aozoraConverter.setChukiRuby(chukiRuby1, chukiRuby2);

    // コメント変換
    boolean commentPrint = prefs.getBoolean("comment_print", false);
    boolean commentConvert = prefs.getBoolean("comment_convert", false);
    this.aozoraConverter.setCommentPrint(commentPrint, commentConvert);

    // float 表示
    boolean floatPage = prefs.getBoolean("image_float_page", false);
    boolean floatBlock = prefs.getBoolean("image_float_block", false);
    this.aozoraConverter.setImageFloat(floatPage, floatBlock);

    // 空行除去
    int removeEmptyLine = Integer.parseInt(prefs.getString("remove_empty_line", "0"));
    int maxEmptyLine = Integer.parseInt(prefs.getString("max_empty_line", "0"));
    this.aozoraConverter.setRemoveEmptyLine(removeEmptyLine, maxEmptyLine);

    // 行頭字下げ
    this.aozoraConverter.setForceIndent(prefs.getBoolean("force_indent", false));

    // 強制改ページ
    if (prefs.getBoolean("page_break_enabled", false)) {
        try {
            int forcePageBreakSize = Integer.parseInt(prefs.getString("page_break_size_kb", "0")) * 1024;
            int forcePageBreakEmpty = 0;
            int forcePageBreakEmptySize = 0;
            int forcePageBreakChapter = 0;
            int forcePageBreakChapterSize = 0;

            if (prefs.getBoolean("page_break_empty_enabled", false)) {
                forcePageBreakEmpty = Integer.parseInt(prefs.getString("page_break_empty_line", "0"));
                forcePageBreakEmptySize = Integer.parseInt(prefs.getString("page_break_empty_size_kb", "0")) * 1024;
            }

            if (prefs.getBoolean("page_break_chapter_enabled", false)) {
                forcePageBreakChapter = 1;
                forcePageBreakChapterSize = Integer.parseInt(prefs.getString("page_break_chapter_size_kb", "0")) * 1024;
            }

            this.aozoraConverter.setForcePageBreak(
                forcePageBreakSize,
                forcePageBreakEmpty,
                forcePageBreakEmptySize,
                forcePageBreakChapter,
                forcePageBreakChapterSize
            );

        } catch (Exception e) {
            Log.e("Aozora", "強制改ページパラメータ読み込みエラー", e);
        }
    }

    // 目次設定
    int maxLength = 64;
    try {
        maxLength = Integer.parseInt(prefs.getString("max_chapter_name_length", "64"));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    this.aozoraConverter.setChapterLevel(
        maxLength,
        prefs.getBoolean("chapter_exclude", false),
        prefs.getBoolean("chapter_use_next_line", false),
        prefs.getBoolean("chapter_section", false),
        prefs.getBoolean("chapter_h", false),
        prefs.getBoolean("chapter_h1", false),
        prefs.getBoolean("chapter_h2", false),
        prefs.getBoolean("chapter_h3", false),
        prefs.getBoolean("same_line_chapter", false),
        prefs.getBoolean("chapter_name", false),
        prefs.getBoolean("chapter_num_only", false),
        prefs.getBoolean("chapter_num_title", false),
        prefs.getBoolean("chapter_num_paren", false),
        prefs.getBoolean("chapter_num_paren_title", false),
        prefs.getBoolean("chapter_pattern_enabled", false)
            ? prefs.getString("chapter_pattern", "").trim()
            : ""
    );

    ////////////////////////////////////
    // すべてのファイルの変換実行
    ////////////////////////////////////
    this._convertFiles(srcFiles, dstPath);

    if (convertCanceled) {
        progressBar.setIndeterminate(false);
        progressBar.setProgress(0);
    }

} catch (Exception e) {
    Log.e("Aozora", "エラーが発生しました : " + e.getMessage(), e);
    throw new RuntimeException(e);
} finally {
    System.gc(); // Android では明示的なGCは基本不要ですが、互換用に残してあります
}
機能カテゴリ キー名の例
挿絵なし no_illust boolean
栞ID with_mark_id boolean
自動横組み auto_yoko, auto_yoko_num1 boolean
文字出力 dakuten_type, ivs_bmp string, boolean
改ページ page_break_size_kb string
空行除去 remove_empty_line string
目次関連 max_chapter_name_length string
その他 comment_print, chapter_h2 boolean

必要であれば、この SharedPreferences 設定に対応した Android Preference XML も作成できます!作成しておきましょうか?

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

private void convertFile(File srcFile, File dstPath)
{
    //拡張子
    String ext = srcFile.getName();
    ext = ext.substring(ext.lastIndexOf('.')+1).toLowerCase();


    //zipならzip内のテキストを検索
    int txtCount = 1;
    boolean imageOnly = false;
    LogAppender.append("------ ");
    switch (ext) {
        case "zip", "txtz" -> {
            try {
                txtCount = AozoraEpub3.countZipText(srcFile);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if (txtCount == 0) {
                txtCount = 1;
                imageOnly = true;
            }
        }
        case "rar" -> {
            try {
                txtCount = AozoraEpub3.countRarText(srcFile);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if (txtCount == 0) {
                txtCount = 1;
                imageOnly = true;
            }
        }
        case "cbz" -> imageOnly = true;
        case "txt" -> LogAppender.println();
    }
    if (this.convertCanceled){
        LogAppender.println("変換処理を中止しました : "+srcFile.getAbsolutePath());
        return;
    }

    //キャッシュパスのファイルならエンコードを変換時のみUTF-8にする
    String encType = (String)jComboEncType.getSelectedItem();
    if (this.isCacheFile(srcFile)) jComboEncType.setSelectedItem("UTF-8");
    try {
        for (int i=0; i<txtCount; i++) {
            convertFile(srcFile, dstPath, ext, i, imageOnly);
            if (convertCanceled) return;
        }
    } finally {
        //設定を戻す
        jComboEncType.setSelectedItem(encType);
    }

}

ChatGPT:

以下は、あなたの提示した Swing ベースの convertFile(File srcFile, File dstPath) メソッドを Android 向けに書き換えた Java コードです。SharedPreferences からエンコード設定を取得する形に修正し、jComboEncType の代替処理も反映しています。

private void convertFile(File srcFile, File dstPath, Context context) {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

    // 拡張子取得
    String ext = srcFile.getName();
    ext = ext.substring(ext.lastIndexOf('.') + 1).toLowerCase();

    // zip なら zip 内のテキストを検索
    int txtCount = 1;
    boolean imageOnly = false;
    LogAppender.append("------ ");
    switch (ext) {
        case "zip":
        case "txtz":
            try {
                txtCount = AozoraEpub3.countZipText(srcFile);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if (txtCount == 0) {
                txtCount = 1;
                imageOnly = true;
            }
            break;
        case "rar":
            try {
                txtCount = AozoraEpub3.countRarText(srcFile);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if (txtCount == 0) {
                txtCount = 1;
                imageOnly = true;
            }
            break;
        case "cbz":
            imageOnly = true;
            break;
        case "txt":
            LogAppender.println();
            break;
    }

    if (this.convertCanceled) {
        LogAppender.println("変換処理を中止しました : " + srcFile.getAbsolutePath());
        return;
    }

    // SharedPreferences から現在のエンコード取得
    String encType = prefs.getString("encoding_type", "UTF-8");

    // キャッシュファイルなら一時的に UTF-8 に変更
    String originalEncType = encType;
    if (this.isCacheFile(srcFile)) {
        encType = "UTF-8";
    }

    // エンコードを Converter に設定(必要なら)
    this.aozoraConverter.setEncoding(encType);

    try {
        for (int i = 0; i < txtCount; i++) {
            convertFile(srcFile, dstPath, ext, i, imageOnly, context);
            if (convertCanceled) return;
        }
    } finally {
        // 元のエンコードに戻す(必要なら)
        this.aozoraConverter.setEncoding(originalEncType);
    }
}

この関数内で呼び出している convertFile(srcFile, dstPath, ext, i, imageOnly, context); の処理も、同様に Android 用にしていると仮定しています。必要であればそちらも提供できます。

キー名 内容
encoding_type テキストのエンコード String
  • convertFile(File, File, String, int, boolean, Context) の Android 実装版の提供
  • isCacheFile(File) の Android 向けロジック確認
  • PreferenceFragmentCompat 用 XML の生成

convertFile(File, File, String, int, boolean, Context) の Android 実装版の提供

isCacheFile(File) の Android 向けロジック確認

PreferenceFragmentCompat 用 XML の生成

必要なものがあれば教えてください!

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

/** キャッシュパスを以下のファイルならtrue */
private boolean isCacheFile(File file)
{
    try {
        return file.getCanonicalPath().startsWith(this.getCachePath().getCanonicalPath());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    //return false;
}

ChatGPT:

以下は、あなたの提示した isCacheFile(File file) メソッドを Android 向けに書き換えた Java コードです。

Android ではアプリのキャッシュディレクトリは context.getCacheDir() で取得できます。これに書き換えた形がこちら:

private boolean isCacheFile(File file, Context context) {
    try {
        File cacheDir = context.getCacheDir(); // Android のキャッシュパス
        return file.getCanonicalPath().startsWith(cacheDir.getCanonicalPath());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
if (isCacheFile(srcFile, context)) {
    encType = "UTF-8";
}
  • Android では getCacheDir() がアプリ専用の /data/data//cache/ ディレクトリを返します。
  • getCanonicalPath() を使うことでシンボリックリンクや相対パスを正規化して比較できます。

Android では getCacheDir() がアプリ専用の /data/data/<package>/cache/ ディレクトリを返します。

getCanonicalPath() を使うことでシンボリックリンクや相対パスを正規化して比較できます。

必要であれば、他の File パス(例: external cache、files、downloads)に対応したロジックも提供できます。何か追加でやりたいことがあれば教えてください!

あなた:

android向けに書き換えて、Javaでpreferenceから取得するとする

/** 内部用変換関数 Appletの設定を引数に渡す
 * @param srcFile 変換するファイル txt,zip,cbz,(rar,cbr)
 * @param dstPath 出力先パス
 * @param txtIdx Zip内テキストファイルの位置
 */
private void convertFile(File srcFile, File dstPath, String ext, int txtIdx, boolean imageOnly)
{
    //パラメータ設定
    if (!"txt".equals(ext) && !"txtz".equals(ext) && !"zip".equals(ext) && !"cbz".equals(ext) && !"rar".equals(ext) ) {
        if (!"png".equals(ext) && !"jpg".equals(ext) && !"jpeg".equals(ext) && !"gif".equals(ext)) {
            LogAppender.println("txt, txtz, zip, cbz rar 以外は変換できません");
        }
        return;
    }
    }

ChatGPT:

Android 向けに書き換え、Java の SharedPreferences から設定を取得する構成に対応した形で、提示された convertFile(...) 関数を整理します。

  • Context context が渡されている(またはクラス内で保持)
  • SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); で取得
  • すでに設定値(エンコード、オプションなど)は Preference に保存済み

Context context が渡されている(またはクラス内で保持)

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); で取得

すでに設定値(エンコード、オプションなど)は Preference に保存済み

private void convertFile(File srcFile, File dstPath, String ext, int txtIdx, boolean imageOnly, Context context) {
    // 対応している拡張子以外は変換しない
    if (!ext.equals("txt") && !ext.equals("txtz") && !ext.equals("zip") &&
        !ext.equals("cbz") && !ext.equals("rar") &&
        !ext.equals("png") && !ext.equals("jpg") && !ext.equals("jpeg") && !ext.equals("gif")) {
        LogAppender.println("txt, txtz, zip, cbz, rar 以外は変換できません");
        return;
    }

    // SharedPreferences から設定値を取得(例:エンコード設定)
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    String encoding = prefs.getString("encoding_type", "UTF-8");

    // キャッシュファイルの場合はエンコードを強制的にUTF-8に
    if (isCacheFile(srcFile, context)) {
        encoding = "UTF-8";
    }

    // 実際の変換処理を呼び出す(ここで encoding を使うなら引数に渡すなど)
    try {
        // 例:変換処理メソッドの呼び出し
        actualConversion(srcFile, dstPath, ext, txtIdx, imageOnly, encoding, context);
    } catch (Exception e) {
        LogAppender.println("変換中にエラーが発生しました: " + e.getMessage());
    }
}
private boolean isCacheFile(File file, Context context) {
    try {
        File cacheDir = context.getCacheDir();
        return file.getCanonicalPath().startsWith(cacheDir.getCanonicalPath());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
  • SharedPreferences を通じて UI からの設定を Preference 画面に保存し、それをこの関数内で読み込むようにするのがポイント。
  • actualConversion(...) は本体の変換処理。そこに必要な設定値をすべて引数で渡すように設計するとテストしやすくなります。

SharedPreferences を通じて UI からの設定を Preference 画面に保存し、それをこの関数内で読み込むようにするのがポイント。

actualConversion(...) は本体の変換処理。そこに必要な設定値をすべて引数で渡すように設計するとテストしやすくなります。

この関数で使う encoding や変換オプション(ルビの表示、禁則処理など)をすべて SharedPreferences から読み込むようにすれば、完全に Swing 依存を排除できます。必要に応じて、他の設定値取得部分も prefs.getBoolean(...) や prefs.getInt(...) で書き換えていきましょうか?