ジェフが指摘したことはすべて正しく、受け入れられた答えであり続けます。ただし、他の誰かが 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> </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>