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

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

ACOファイルを編集するプログラムがなかったのでChatGPTに作らせた

 配色データ(拡張子.aco)があるのだけど、編集できるソフトがadobeのものが多くて、読み込みにしか対応していないことがある。 ChatGPTに「以下のC#コードをJavascriptで書き直して下さい。」の下に下記サイトのサンプルコードを乗せただけ。

qiita.com

そうしたら、acoファイルを読み込んで表示するプログラムが出力された。 「編集結果を保存できるように書き換えて」 ChatGPT「編集結果を保存できるようにするために、ユーザーが編集した色のデータをJSONファイルとしてダウンロードできる機能を追加します。以下はそのための改良版です。」 「jsonではなくACOファイルとして保存するように変更して。」 そしたらACOファイルを編集するプログラムができた。

UIを整えたり項目を増やしたり減らし、HTMLの色コードを読み込ませたりすると完成になりそう。

使用方法 ブラウザでファイルを開く:

index.htmlファイルをブラウザで開きます。 ACOファイルのインポート:

「*.aco」ファイルをインポートするために、ファイル入力ボックスにACOファイルをドラッグ&ドロップするか、クリックしてファイルを選択します。 「Import」ボタンが有効になるので、クリックしてACOファイルを読み込みます。 色の編集:

インポートされた色がリストで表示されます。 各色のカラーピッカーを使用して色を変更できます。色を変更すると、そのRGB値もラベルに表示されます。 ACOファイルの保存:

色の編集が完了したら、「Save」ボタンをクリックしてACOファイルを保存します。 ブラウザがファイルをダウンロードし、新しいACOファイルが保存されます。 注意点 このコードは、ブラウザのFile APIを使用しているため、ローカルファイルシステムへのアクセスを必要とします。一部のブラウザや環境では動作しない場合があります。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Aco Importer</title>
    <style>
        .color-box {
            display: flex;
            align-items: center;
            margin: 10px 0;
        }
        .color-box input[type="color"] {
            margin-right: 10px;
        }
    </style>
</head>
<body>
    <h1>Aco Importer</h1>
    <input type="file" id="fileInput" accept=".aco">
    <button id="importButton" disabled>Import</button>
    <button id="saveButton" disabled>Save</button>
    <div id="colorList"></div>

    <script src="acoImporter.js"></script>
</body>
</html>
document.addEventListener('DOMContentLoaded', () => {
    const fileInput = document.getElementById('fileInput');
    const importButton = document.getElementById('importButton');
    const saveButton = document.getElementById('saveButton');
    const colorList = document.getElementById('colorList');

    let colors = null;

    fileInput.addEventListener('change', () => {
        if (fileInput.files.length > 0) {
            importButton.disabled = false;
        } else {
            importButton.disabled = true;
            saveButton.disabled = true;
        }
    });

    importButton.addEventListener('click', () => {
        const file = fileInput.files[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = function(event) {
                const arrayBuffer = event.target.result;
                colors = getColors(new Uint8Array(arrayBuffer));
                displayColors(colors);
                saveButton.disabled = false;
            };
            reader.readAsArrayBuffer(file);
        }
    });

    saveButton.addEventListener('click', () => {
        if (colors) {
            const acoData = createAcoFile(colors);
            download('colors.aco', acoData);
        }
    });

    function displayColors(colors) {
        colorList.innerHTML = '';
        colors.forEach(color => {
            const colorBox = document.createElement('div');
            colorBox.classList.add('color-box');

            const colorInput = document.createElement('input');
            colorInput.type = 'color';
            colorInput.value = rgbToHex(color.R, color.G, color.B);
            colorInput.addEventListener('input', (event) => {
                const hex = event.target.value;
                const rgb = hexToRgb(hex);
                color.R = rgb.r;
                color.G = rgb.g;
                color.B = rgb.b;
                color.Color = `rgba(${color.R}, ${color.G}, ${color.B}, 1)`;
            });

            const label = document.createElement('label');
            label.textContent = rgbToHex(color.R, color.G, color.B);

            colorBox.appendChild(colorInput);
            colorBox.appendChild(label);
            colorList.appendChild(colorBox);
        });
    }

    function getColors(array) {
        const colors = [];
        const colorCount = array[3];
        let pos = 6;
        for (let i = 0; i < colorCount; i++) {
            const R = array[pos];
            const G = array[pos + 2];
            const B = array[pos + 4];
            const color = {
                R,
                G,
                B,
                Color: `rgba(${R}, ${G}, ${B}, 1)`
            };
            colors.push(color);
            pos += 10;
        }
        return colors;
    }

    function rgbToHex(r, g, b) {
        return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
    }

    function hexToRgb(hex) {
        const bigint = parseInt(hex.slice(1), 16);
        return {
            r: (bigint >> 16) & 255,
            g: (bigint >> 8) & 255,
            b: bigint & 255
        };
    }

    function createAcoFile(colors) {
        const buffer = new ArrayBuffer(4 + colors.length * 10);
        const view = new DataView(buffer);
        view.setUint16(0, 0); // version
        view.setUint16(2, colors.length); // color count

        let pos = 4;
        colors.forEach(color => {
            view.setUint16(pos, 0); // color space (0 = RGB)
            view.setUint16(pos + 2, color.R * 256); // R
            view.setUint16(pos + 4, color.G * 256); // G
            view.setUint16(pos + 6, color.B * 256); // B
            view.setUint16(pos + 8, 0); // padding
            pos += 10;
        });

        return new Blob([buffer], { type: 'application/octet-stream' });
    }

    function download(filename, data) {
        const element = document.createElement('a');
        element.href = URL.createObjectURL(data);
        element.download = filename;

        document.body.appendChild(element);
        element.click();
        document.body.removeChild(element);
    }
});

問題は出力されたファイルが、acoの仕様に沿っていないことだ。 qiita.com

7月11日から7月17日までキンドル新刊ピックアップ

7月11日発売の本

疾患別看護過程ポケットブック

疾患別看護過程ポケットブック

  • メディカル・ケア・サービス
Amazon

7月11日発売のそのほかの本kyukyunyorituryo.github.io

7月12日発売の本

7月12日発売のそのほかの本kyukyunyorituryo.github.io

7月13日発売の本

7月13日発売のそのほかの本kyukyunyorituryo.github.io

7月14日発売の本

7月14日発売のそのほかの本kyukyunyorituryo.github.io

7月15日発売の本

7月15日発売のそのほかの本kyukyunyorituryo.github.io

7月16日発売の本

7月16日発売のそのほかの本kyukyunyorituryo.github.io

7月17日発売の本

7月17日発売のそのほかの本kyukyunyorituryo.github.io

新刊紹介サイトのGatsbyJSへ移行

新刊を探すのにどういうのがいいのか。次の要素で絞り込むことを考えた。

  • 先月、今月、来月以降
  • マンガ、小説、ライトノベル、その他
  • 出版社ごとKADOKAWA、講談社、秋田書店、白泉社、集英社、徳間書店、小学館
  • 検索 タイトル カテゴリー 出版社 日付

kyukyunyorituryo.github.io

 新刊チェックというサイトを作っていたが、bootstrap4ベースでサイト構造が古めだったので新しくGatsbyJSに書き換えることにした。最近はreactに慣れてきてUIの編集がし易いなと思っている。

古いサイトの問題点はhtmlの生成とjsonの生成とで2重に時間がかかっていたのと、全体の更新を一気にできなかったので、古いデータと新しいデータの整合性が取れなかった。

  • GatsbyJSの問題点はサイトのデータ数が増えるとレンダリングが増える。
  • 新しいデータ管理の方法はjsonとページを一対になる管理をしている。
  • jsonファイルを消せば古いページを削除できる。

  • npm updateをするだけで使用しているライブラリが更新されるので楽。

  • reactのライブラリが豊富なので機能追加が楽。
  • react componentを作ればコピー&ペーストするだけで他のサイトにも適応が可能。
  • seoを強くするのが楽

GatsbyJSの作ったコードをスターターとして公開しようと思う。

7月4日から7月10日までキンドル新刊ピックアップ

7月4日発売の本

7月4日発売のそのほかの本kyukyunyorituryo.github.io

7月5日発売の本

イルカと生きる

イルカと生きる

Amazon

7月5日発売のそのほかの本kyukyunyorituryo.github.io

7月6日発売の本

7月6日発売のそのほかの本kyukyunyorituryo.github.io

7月7日発売の本

7月7日発売のそのほかの本kyukyunyorituryo.github.io

7月8日発売の本

7月8日発売のそのほかの本kyukyunyorituryo.github.io

7月9日発売の本

7月9日発売のそのほかの本kyukyunyorituryo.github.io

7月10日発売の本

7月10日発売のそのほかの本kyukyunyorituryo.github.io

6月27日から7月3日までキンドル新刊ピックアップ

6月27日発売の本

6月27日発売のそのほかの本

kyukyunyorituryo.github.io

6月28日発売の本

6月28日発売のそのほかの本kyukyunyorituryo.github.io

6月29日発売の本

6月29日発売のそのほかの本kyukyunyorituryo.github.io

6月30日発売の本

6月30日発売のそのほかの本kyukyunyorituryo.github.io

7月1日発売の本

7月1日発売のそのほかの本kyukyunyorituryo.github.io

7月2日発売の本

7月2日発売のそのほかの本kyukyunyorituryo.github.io

7月3日発売の本

7月3日発売のそのほかの本kyukyunyorituryo.github.io