2012-12-12 33 views
3

我使用記事本++來完成我目前大部分的編碼。不過,我想改變它的圖標,只是爲了定製的緣故。Notepad ++用於其圖標的位圖格式(所以我可以更改它們)?

所以我所做的就是用Resource Hacker打開.exe文件,看看圖標在哪裏。它們似乎是位圖格式,這很奇怪,因爲它們具有透明度,並且用我知道的任何「位圖」(BM標頭,「Windows位圖」)格式替換它們都不起作用(圖標未顯示)。

所以我想問一下,這些文件的格式是什麼,我怎樣才能生成它們?

位圖的樣品可以在Notepad++ repository發現:
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=raw saveFile 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個字節(!)。

這是第一個位圖的頭怎麼以上內容:

Hex Workshop

任何想法?只要知道這是什麼格式就足夠了。

回答

3

這是一個8BPP(每像素8位)索引位圖。在「BM」之後,有一個52字節的標題,一個256色的調色板和索引的像素數據。每種顏色都是4字節,採用BGR_格式(不使用第四個字節;如果是alpha通道,則會看到FF而不是00)。

索引的像素數據從0x436開始。很簡單:一個字節代表調色板中的一個索引。例如,前幾個字節是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將破壞顏色,所以在實際繪製任何東西之前保存它。

+0

謝謝您的詳細解答:)但是,我似乎無法通過任何方式生成這樣的文件。在Photoshop中導出該文件的8位索引BMP會產生一個440字節的文件,而原始的文件有1334字節(如果我將其替換爲資源,它不會被NP ++正確識別)。這是爲什麼? –

+0

沒關係,你是對的,在閱讀了一下之後,我現在看到在palete中有一個非常大的填充量,其值是所有FF FF FF(白色)像素的形式,Notepad ++將無法加載圖像,除非它們包含這樣的填充。我不知道爲什麼會這樣,但它是,而且最重要的是,你是正確的,所以+1和✓:) –

0

傑夫指出的所有內容都是正確的,並將繼續成爲公認的答案。但是,如果其他人可能想要調整NP ++,我已經制作了一個小型轉換器,您可以使用它將任何8位索引位圖轉換爲您可以在NP ++中使用的位圖(通過資源黑客或類似方法)。

其編碼在Javascript中,僅使用Chrome測試,代碼是非常草率的:JsFiddle

要使用它,創建一個在您最喜歡的節目索引位8位16×16,它拖放到那個東西。它會輸出一些調試細節並給你一個鏈接,所以你可以「下載」一個兼容的位圖(但所有這些都發生在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> 
相關問題