3

現在、ほとんどのコーディングに Notepad++ を使用しています。ただし、カスタマイズのためにアイコンを変更したいと思います。

そこで、 Resource Hackerで.exe を開き、アイコンの場所を確認しました。それらはビットマップ形式のようですが、透明性があるため奇妙であり、私が知っている「ビットマップ」(BMヘッダー、「Windows ビットマップ」) 形式に置き換えることはできません (アイコンは表示されません)。

では、これらのファイルはどの形式で、どのように作成すればよいのでしょうか?

ビットマップのサンプルは、Notepad++ リポジトリにあります。
newFile http://sourceforge.net/p/notepad-plus/code/735/tree/trunk/PowerEditor/src/icons/newFile.bmp?format=raw openFile http ://sourceforge.net/p/notepad-plus/code/735/tree/trunk/PowerEditor/src/icons/openFile.bmp?format=生保存ファイル http://sourceforge.net/p/notepad-plus/code /735/tree/trunk/PowerEditor/src/icons/saveFile.bmp?format=raw saveAll http://sourceforge.net/p/notepad-plus/code/735/tree/trunk/PowerEditor/src/icons/saveAll .bmp?format=raw closeFile http://sourceforge.net/p/notepad-plus/code/735/tree/trunk/PowerEditor/src/icons/closeFile.bmp?format=raw closeAll http://sourceforge.net /p/notepad-plus/code/735/tree/trunk/PowerEditor/src/icons/closeAll.bmp?format=raw

ご覧のとおり、グレーのマットがあり、アルファ チャネルが非標準的な方法でフォーマットに保存されていると思われます。(または、バイナリ透過性を持ち、透過性を#C0C0C0意味します)。

また、かなり大きく、表現される各ピクセルあたり 5 バイトを超えます (!)。

上記の最初のビットマップのヘッダーは次のようになります。

六角ワークショップ

何か案が?これがどのような形式であるかを知るだけで十分です。

4

2 に答える 2

3

これは 8BPP (ピクセルあたり 8 ビット) のインデックス付きビットマップです。「BM」の後には、52 バイトのヘッダー、256 色のパレット、およびインデックス付きのピクセル データがあります。各色は BGR_ 形式の 4 バイトです (4 番目のバイトは使用されません。アルファ チャネルの場合は、00 ではなく FF が表示されます)。

インデックス付きピクセル データは 0x436 から始まります。簡単です。1 バイトがパレット内の 1 つのインデックスを表します。たとえば、最初の数バイトは 07 07 18 18 です。0x07 は、そのピクセルがパレットの 8 番目の色、#C0C0C0 を使用するようにします。0x18 は、そのピクセルがパレットの 25 番目の色、#CECECE を使用するようにします。

ご想像のとおり、透過性が処理されていると思います。透明なピクセルがある場所ならどこでも 07 が表示され、パレット内の対応する色は #C0C0C0 です。

ピクセルデータは上下逆に保存されることに注意してください。つまり、オフセット 0x436 の最初の 16 バイトは、ピクセルの一番下の行を表します。

ここで詳しく説明されています: http://en.wikipedia.org/wiki/BMP_file_format#File_structure

編集: それらを生成する方法については、お気に入りの画像編集ソフトウェアを使用して、画像を 256 色のビットマップ (または 8BPP ビットマップのいずれか利用可能なもの) としてエクスポートするように依頼してください。描画後に保存すると、Microsoft Paint が色を壊してしまうので、実際に描画する前に保存してください。

于 2012-12-12T01:36:04.053 に答える
0

ジェフが指摘したことはすべて正しく、受け入れられた答えであり続けます。ただし、他の誰かが NP++ を微調整したい場合に備えて、8 ビットのインデックス付きビットマップを (リソース ハッカーなどを介して) NP++ で使用できるものに変換するために使用できる小さなコンバーターを作成しました。

これは Javascript でコーディングされており、Chrome でのみテストされており、コードはひどくずさんです: JsFiddle

それを使用するには、お気に入りのプログラムで 8 ビット 16x16 のインデックス付きビットマップを作成し、その中にドラッグ アンド ドロップします。デバッグの詳細が出力され、互換性のあるビットマップを「ダウンロード」できるようにリンクが表示されます (ただし、これはすべて HTML5 のクライアント側で行われます)。

編集: SO は、関連するコードをここに投稿せずに JsFiddle へのリンクを貼り付けたと不平を言っているので、投稿します。これは、完全に自己完結型の HTML です。

<!DOCTYPE html>
<html>
    <head>
        <title>Endoblast</title>
        <style>
            html { background: #F8F8F8; }
            #drop-zone {
                position: fixed;
                left: 0;
                right: 0;
                bottom: 0;
                top: 0;
                border: 4px dashed #DDD;
                z-index: -1;
            }
            #result { font: 12px Consolas; padding-bottom: 240px; }
            .color { margin-right: -7px; position: relative; cursor: default; }
            .color > .top, .color > .bottom { position: absolute; left: 0; right: 0; height: 2px; }
            .color > .top    { position: absolute; top:    0; background: rgba(255, 255, 255, 0.2); }
            .color > .bottom { position: absolute; bottom: 0; background: rgba(  0,   0,   0, 0.05); }
        </style>
    </head>
    <body>
        <div id="drop-zone"></div>
        <p id="result"></p>
        <script>

            if (window.File && window.FileReader && window.FileList && window.Blob) {

                function Readr(bytes) {

                    var data = bytes;

                    var offset = 0;

                    this.nextStr = function(amount) {

                        var result = []

                        while (amount--) result.push(data[offset++]);

                        return toStr(result);

                    }

                    this.nextInt = function(amount) {

                        if (amount == 1 || !amount) return data[offset++];

                        if (amount == 2) return toInt16(data[offset++], data[offset++]);

                        if (amount == 4) return toInt32(data[offset++], data[offset++], data[offset++], data[offset++]);

                        return next(amount);

                    }

                    var next = this.next = function(amount) {

                        var result = []

                        while (amount--) result.push(data[offset++]);

                        return result;

                    }

                }

                function Color(r, g, b) {

                    this.r = r;
                    this.g = g;
                    this.b = b;

                }

                function toStr(bytes) {
                    var result = '';
                    for (var i = 0; i < bytes.length; i++) result += String.fromCharCode(bytes[i]);
                    return result;
                }

                function toInt16(b1, b2) { return (b1 << 0) + (b2 << 8); }

                function toInt32(b1, b2, b3, b4) { return (b1 << 0) + (b2 << 8) + (b3 << 16) + (b4 << 24); }

                function fromInt16(int16) {

                    return [
                         int16 & parseInt('00FF', 16),
                        (int16 & parseInt('FF00', 16)) >> 8
                    ];

                }

                function fromInt32(int32) {

                    return [
                         int32 & parseInt('000000FF', 16),
                        (int32 & parseInt('0000FF00', 16)) >> 8,
                        (int32 & parseInt('00FF0000', 16)) >> 16,
                        (int32 & parseInt('FF000000', 16)) >> 24
                    ];

                }

                function log(text) { document.getElementById('result').innerHTML += text + '\n<br/>'; }

                function logHtml(html) { document.getElementById('result').innerHTML += html + '<br/>'; }

                var bitCounts = {
                    '1': '1-bit',
                    '2': '2-bit',
                    '4': '4-bit',
                    '8': '8-bit',
                    '16': '16-bit',
                    '24': '24-bit',
                    '32': '32-bit'
                };

                var compressions = {
                    '0': 'RGB (uncompressed)'
                };

                function handleFileSelect(evt) {

                    evt.stopPropagation();
                    evt.preventDefault();

                    var files = evt.dataTransfer.files; // FileList object.

                    var reader = new FileReader();

                    reader.onload = function (event) {

                        var b = [].slice.call(new Uint8Array(event.target.result));

                        var r = new Readr(b);

                        if (r.nextStr(2) == 'BM')
                            log('BM header found.');
                        else
                            return log('File is not a BMP.');

                        var fileSize = r.nextInt(4);

                        log('File size: ' + fileSize + ' Bytes.');

                        var reserved = r.next(4)

                        var offset = r.nextInt(4);

                        log('Image data offset: ' + offset + ' Bytes.');
                        log('Image data size: ' + (fileSize - offset) + ' Bytes.');

                        var headerSize = r.nextInt(4);

                        log('DIB header size: ' + headerSize + ' Bytes.');

                        var header = r.next(headerSize - 4);

                        var hr = new Readr(header);

                        var width = hr.nextInt(4);
                        var height = hr.nextInt(4);

                        log('Image width: ' + width + 'px.');
                        log('Image height: ' + height + 'px.');

                        var planes = hr.nextInt(2);

                        log('Color planes: ' + planes + '.');

                        var bitCount = bitCounts[hr.nextInt(2)] || 'unknown';
                        var compression = compressions[hr.nextInt(4)] || 'unknown';

                        log('Bit depth: ' + bitCount + '.');
                        log('Compression: ' + compression + '.');

                        var pixelCount = hr.nextInt(4);

                        log('Pixel count: ' + pixelCount + '.');

                        var yPPM = hr.nextInt(4);
                        var xPPM = hr.nextInt(4);

                        var colorTableSize = hr.nextInt(4);

                        log('Color table size: ' + colorTableSize + '.');

                        var importantColors = hr.nextInt(4);

                        log('Important colors in color table: ' + importantColors + '.');

                        var colorTable = r.next(colorTableSize * 4);

                        var cr = new Readr(colorTable);

                        var colors = [];

                        for (var i = 0; i < colorTableSize; i++) {

                            var B = cr.nextInt(),
                                G = cr.nextInt(),
                                R = cr.nextInt(),
                                _ = cr.nextInt();

                            colors.push(new Color(R, G, B));

                        }

                        function createColorCell(r, g, b, desc) {

                            var title = 'title="' + desc + ': rgb(' + r + ', ' + g + ', '  + b + ')"'

                            return '<span class="color" ' + title + ' style="background:rgb(' + r + ',' + g + ',' + b + ')">'
                                 + '<span class="top"></span><span class="bottom"></span>&nbsp;&nbsp;</span> ';

                        }

                        var cells = '';

                        for (var i = 0; i < colors.length; i++) {

                            var c = colors[i];

                            cells += createColorCell(c.r, c.g, c.b, 'Color at index ' + i + ' in the color table');

                        }

                        if (colorTableSize) logHtml('Colors in the color table: ' + cells); else return log('No color table.');

                        log('Bitmap data, mapped to the color table is shown below.');

                        var bitmapCells = '';

                        var bitmapRows = [];

                        var indexes = [];

                        for (var y = height; y > 0; y--) {

                            for (var x = 0; x < width; x++) {

                                var index = r.nextInt();

                                indexes.push(index);

                                var color = colors[index];

                                var desc = 'Pixel x' + x + ', y' + y + ', mapped to index ' + index + ' in the color table, '
                                         + 'which has colors rgb(' + color.r + ', ' + color.g + ', ' + color.g + ')';

                                bitmapCells += createColorCell(color.r, color.g, color.b, desc);

                            }

                            bitmapRows.push(bitmapCells);
                            bitmapCells = '';

                        }

                        for (var row = height - 1; row > -1; row--) {

                            logHtml(bitmapRows[row]);

                        }

                        var fixedData = new ArrayBuffer(1334);

                        var fixed = new Uint8Array(fixedData);

                        var fixedOffset = 0;

                        function s8(b) { fixed[fixedOffset++] = b; }

                        function s16(i16) {
                            var bytes = fromInt16(i16);
                            s8(bytes[0]);
                            s8(bytes[1]);
                        }

                        function s32(i32) {
                            var bytes = fromInt32(i32);
                            s8(bytes[0]);
                            s8(bytes[1]);
                            s8(bytes[2]);
                            s8(bytes[3]);
                        }

                        // Now we build a fixed up bitmap.

                        s16(19778); // header.
                        s32(1334); // file size.
                        s32(0); // reserved.
                        s32(1078); // DIB data offset.
                        s32(40); // DIB header size.
                        s32(16); // width.
                        s32(16); // height.
                        s16(1); // planes.
                        s16(8); // bit depth.
                        s32(0); // compression.
                        s32(256); // image size.
                        s32(0); // Xpels.
                        s32(0); // Ypels.
                        s32(256); // Colors used.
                        s32(256); // Important colors.

                        for (var i = 0; i < 1024; i++) {

                            var c = colorTable[i];

                            if (typeof c !== 'undefined')
                                s8(colorTable[i])
                            else
                                s8(((i % 4) == 3) ? 0 : 255);

                        }

                        for (var i = 0; i < 256; i++) s8(indexes[i]);

                        window.URL = window.webkitURL || window.URL;
                        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
                        var file = new window.BlobBuilder();

                        file.append(fixed);

                        var a = document.createElement('a');
                        a.href = window.URL.createObjectURL(file.getBlob('image/bmp'));
                        a.download = 'fixed.bmp';
                        a.textContent = 'Download Notepad++ compatible bitmap';
                        document.getElementById('result').appendChild(a);

                    };

                    reader.readAsArrayBuffer(files[0]);

                }

                function handleDragOver(evt) {
                    evt.stopPropagation();
                    evt.preventDefault();
                    evt.dataTransfer.dropEffect = 'copy';
                }

                var dropZone = document.getElementById('drop-zone');
                dropZone.addEventListener('dragover', handleDragOver, false);
                dropZone.addEventListener('drop', handleFileSelect, false);

            } else {

                alert('The File APIs are not fully supported in this browser.');

            }

        </script>
    </body>
</html>
于 2012-12-13T00:51:43.980 に答える