Bitmap Dosyalarının Genel Yapısı

PC hakkındaki genel bilgi ve ipucu paylaşım alanıdır.
Cevapla
Kullanıcı avatarı
trwe
Terabyte3
Terabyte3
Mesajlar: 4895
Kayıt: 25 Eyl 2013, 13:38
cinsiyet: Erkek
Konum: Düzce/Akçakoca

Bitmap Dosyalarının Genel Yapısı

Mesaj gönderen trwe » 19 Eki 2013, 13:34

Bitmap Dosyalarının Genel Yapısı
------------------------------------------------------------------------------------

Bitmap resim doyası genel olarak üç bölümden oluşur, bunlar;

1- Bitmap File Header (Dosya başlığı)
2- Bitmap Info Header (Resim bilgi başlığı)
3- Color map (Renk haritası)

Resime Ayrılan Veri Alanı:

29x29 pixel ve 256 renk bilgisine sahip bir resim için şu hesap yapılmaktadır.Öncelikle resmin satır genişliği hesaplanır. Yani bir satır için ne kadar veri alanı gerektiği tespit edilir. 256 renk bilgisi COLORMAP denilen alanda saklanır ve bu tip resim dosyaları 8 bit olarak bilinmektedir.

Bu hesap için aşağıdaki fonksiyon kullanılabilir.

Kod: Tümünü seç

Private Funtion GetRowSize(ByVal nWidth As Integer, ByVal nBitCount As Integer) As Long
    GetRowSize = 4 * (((nBitCount / 8) * nWidth + 3) \ 4)
End Function
Buna göre 29x29 pixel boyutlarında bir resim için ayrılan veri alanı;

VeriAlanı = GetRowSize(29, 8) * 29 = 928 byte'tir

Bitmap File Header:

Bitmap file header yapısı aşağıdaki gibidir (14 byte boyutunda).

Kod: Tümünü seç

Private Type BITMAPFILEHEADER
    bfType As Integer
    bfSize As Long
    bfReserved1 As Integer
    bfReserved2 As Integer
    bfOffBits As Long
End Type
Bu Koddakiler Özetlenirse;

bfType: 'B' ve 'M' harfleri olan 19778 degerini geri döndürür. (Bitmap dosya tipi için)
bfSize: Dosya boyutu (byte cinsinden)
bfReserved1: Boş
bfReserved2: Boş
bfOffBits: Bitmap file header'ın bittiği, Bitmap info header'ın başladığı değeri işaret eder

Örnek:

Herhangi bir bilgisayarın C: kök sürücünde ;

256 renk biti ile örneklenmiş ve 160x120 pixel boyutlarındaki bir dosyayının incelenmesi;

Kod: Tümünü seç

Private Const FileName As String = "C:\test.bmp"
Dim bfh As BITMAPFILEHEADER
'VB 6.0 da Standart open yöntemi ile dosyayı açınız.
Open FileName For Binary Access Read As #1
' Get komutu ile 14 byte uzunluğundaki BITMAPFILEHEADER bilgisini
'... değişkenimize aktarıyoruz.
Get #1, ,bfh
' ve son olarak dosyayı kapatınız.
Close #1

Kod: Tümünü seç

' BITMAPFILEHEADER içindeki bilgileri Debug penceresine yazdırınız.
Debug.Print "bfType: " & bfh.bfType
Debug.Print "bfSize: " & bfh.bfSize
Debug.Print "bfReserved1: " & bfh.bfReserved1
Debug.Print "bfReserved2: " & bfh.bfReserved2
Debug.Print "bfOffBits: " & bfh.bfOffBits
Çıktı, aşağıdaki gibidir.

bfType: 19778
bfSize: 20278
bfReserved1: 0
bfReserved2: 0
bfOffBits: 1078

Kısaca sonucu açıklarsak;

* bfType: 19778 değerini döndürdü, yani dosya bitmap (BM) tipindedir.B harfinin Asci kodu 66, M hafinin ise 77 dir. Basit bir hesapla bu değerlerin integer karşılığı "bfType = 'M' * 256 + 'B'" yani "bfType = 77 * 256 + 66" dir.

* bfSize: 20278 değerini döndürdü, yani bu değeri kendimiz hesaplarsak.

bfSize = Len(BITMAPFILEHEADER) + Len(BITMAPINFOHEADER) + Len(COLORMAP) + Len(IMAGESIZE)
şeklindedir.

Bu hesap sırasında bahsetmediğimiz COLORMAP ve BITMAPINFOHEADER bilgileri var.İlerleyen konularda bu bilgiler verilecektir. Neticede COLORMAP hesabı şu şekilde yapılır.Yukarıdaki örnekte tanımdladığımız (Dim bfh As BITMAPFILEHEADER) bfh kullanılarak;

Len(COLORMAP) = bfh.bfOffBits - Len(bfh) - Len(BITMAPINFOHEADER) = 1078 - 14 - 40 = 1024 byte olacaktır.

Sonuç olarak bfSize değeri;

bfSize = 14 + 40 + 1024 + GetRowSize(160, 8) * 120

bfSize = 14 + 40 + 1024 + 160 * 120 = 20278

GetRowSize(160, 8) sonucunun 160 olması sizi yanıltmasın çünkü bu değer BitCount değerine bağlı olarak farklı sonuçlar döndürür. Mesela 29*29 pixel boyutlardaki bir resim için BitCount değerinin 24 olduğu düşünülürse; mantık dahilinde;

bfSize = 29 * 29 * (BitCount / 8) = 841 * (3) = 2523 olması beklenilir.

Fakat asıl değer;

bfSize = GetRowSize(Width, BitCount) * Height

bfSize = GetRowSize(29, 24) * 29 = 2552 olacaktır.

Çıkan sonuç daima 4'e tam olarak bölünmektedir. (4 byte değerinde RGB ve Alpha)

* bfOffBits: 1078 değerini döndürdü.

Yani
bfOffBits = Len(BITMAPFILEHEADER) + Len(BITMAPINFOHEADER) + Len(COLORMAP)

bfOffBits = 14 + 40 + (256 * 4) (256 renk değeri için)

Bitmap Info Header

Bitmap Info Header 40 byte lık bir alan kaplar. Yığın yapısı aşağıdaki gibidir.

Kod: Tümünü seç

Private Type BITMAPINFOHEADER
    biSize           As Long          ' Size of info header
    biWidth          As Long          ' Width of image
    biHeight         As Long          ' Height of image
    biPlanes         As Integer       ' Number of color planes
    biBitCount       As Integer       ' Number of bits per pixel
    biCompression    As Long          ' Type of compression to use
    biSizeImage      As Long          ' Size of image data
    biXPelsPerMeter  As Long          ' X pixels per meter
    biYPelsPerMeter  As Long          ' Y pixels per meter
    biClrUsed        As Long          ' Number of colors used
    biClrImportant   As Long          ' Number of important colors
End Type
* bfSize: BITMAPINFOHEADER yığınının kapladığı alan yani 40 byte değeri.
* biWidth: Resmin genişliği (pixel cinsinden)
* biHeight: Resmin yüksekliği (pixel cinsinden)
* biPlanes: Renk planı (genellikle 1 dir)
* biBitCount: 1 pixel için ayrılan veri alanı (1, 4, 8, 16, 24, 32 gibi)
* biCompression: Resim bilgisinin sıkıştırılmış veya sıkıştırılmamış olduğu bilgisi.
Genel olarak biCompression değeri
BI_RGB = 0, BI_RLE8 = 1, BI_RLE4 = 2, BI_BITFIELDS = 3 geğerlerinden biri olur.
Tabi burada anlatılmayan farklı sıkıştırma tekniklerinden biri de olabilir. Fakat
şu an sadece bu değerleri size aktaracağım.
BI_RGB: Resimde herhangi bir sıkıştırma olmadığı bilgisidir. Resim verisi olduğu
saklanır.
BI_RLE8: 8 bit uzunluk hesabına göre sıkıştırma
BI_RLE4: 4 bit uzunluk hesabına göre sıkıştırma
BI_BITFIELDS: RGB resim bilgisinin RGB maskeleme bilgisiyle sıkıştırıldığı vs...
* biSizeImage: Resim için ayrılan veri alanı değeridir. Bu değer yukarıda anlatılan
biSizeImage = GetRowSize(Width, BitCount) * Height sonucuna göre hesaplanır.
* biXPelsPerMeter: Metre başına pixel genişliği
* biYPelsPerMeter: Metre başına pixel yüksekliği
* biClrUsed: Sayı renklerin kullanıldığı
* biClrImportant: Sayı önemli renkleri

Yukarıdaki kodu yeni bilgilerle tekrar düzenlersek;

Kod: Tümünü seç

Option Explicit

'Colormap entry structure
Private Type RGBQUAD
    rgbBlue     As Byte      ' Blue value
    rgbGreen    As Byte      ' Green value
    rgbRed      As Byte      ' Red value
    rgbReserved As Byte      ' Reserved
End Type

'BMP file header structure
Private Type BITMAPFILEHEADER
    bfType          As Integer       ' Magic number for file
'   bfType          As String * 2    ' Magic number for file (veya kullanılabilir)
    bfSize          As Long          ' Size of file
    bfReserved1     As Integer       ' Reserved
    bfReserved2     As Integer       ' ...
    bfOffBits       As Long          ' Offset to bitmap data
End Type

'BMP file info structure
Private Type BITMAPINFOHEADER
    biSize           As Long          ' Size of info header
    biWidth          As Long          ' Width of image
    biHeight         As Long          ' Height of image
    biPlanes         As Integer       ' Number of color planes
    biBitCount       As Integer       ' Number of bits per pixel
    biCompression    As Long          ' Type of compression to use
    biSizeImage      As Long          ' Size of image data
    biXPelsPerMeter  As Long          ' X pixels per meter
    biYPelsPerMeter  As Long          ' Y pixels per meter
    biClrUsed        As Long          ' Number of colors used
    biClrImportant   As Long          ' Number of important colors
End Type

'Bitmap information structure
Private Type BITMAPINFO_24
    bmiHeader       As BITMAPINFOHEADER  ' Image header
    bmiColors()     As RGBQUAD           ' Image colormap
End Type
Private Const FileName As String = "C:\test.bmp"

Private Sub Form_Load()
    Dim bfh As BITMAPFILEHEADER
    Dim bih As BITMAPINFOHEADER

    'VB 6.0 da Standart open yöntemi ile dosyayı açıyoruz.
    Open FileName For Binary Access Read As #1
    ' Get komutu ile 14 byte uzunluğundaki BITMAPFILEHEADER bilgisini
    '... değişkenimize aktarıyoruz.
    Get #1, ,bfh
    ' Get komutu ile 40 byte uzunluğundaki BITMAPINFOHEADER bilgisini
    '... değişkenimize aktarıyoruz.
    Get #1, ,bih   
    ' ve son olarak dosyayı kapatıyoruz.
    Close #1
    With bih
        Debug.Print "biSize: " & .biSize
        Debug.Print "biWidth: " & .biWidth
        Debug.Print "biHeight: " & .biHeight
        Debug.Print "biPlanes: " & .biPlanes
        Debug.Print "biBitCount: " & .biBitCount
        Debug.Print "biCompression: " & .biCompression
        Debug.Print "biSizeImage: " & .biSizeImage
        Debug.Print "biXPelsPerMeter: " & .biXPelsPerMeter
        Debug.Print "biYPelsPerMeter: " & .biYPelsPerMeter
        Debug.Print "biClrUsed: " & .biClrUsed
        Debug.Print "biClrImportant: " & .biClrImportant
    End With
End Sub
Çıktı, aşağıdaki gibidir.

biSize: 40
biWidth: 160
biHeight: 120
biPlanes: 1
biBitCount: 8
biCompression: 0
biSizeImage: 19200
biXPelsPerMeter: 2835
biYPelsPerMeter: 2835
biClrUsed: 0
biClrImportant: 0

Color Map

Kod: Tümünü seç

Private Sub Form_Load()
    Dim bfh As BITMAPFILEHEADER
    Dim bih As BITMAPINFOHEADER
    Dim cmAry() As RGBQUAD
    Dim nColorSize As Long

    'VB 6.0 da Standart open yöntemi ile dosyayı açıyoruz.
    Open FileName For Binary Access Read As #1
    ' Get komutu ile 14 byte uzunluğundaki BITMAPFILEHEADER bilgisini
    '... değişkenimize aktarıyoruz.
    Get #1, ,bfh
    ' Get komutu ile 40 byte uzunluğundaki BITMAPINFOHEADER bilgisini
    '... değişkenimize aktarıyoruz.
    Get #1, ,bih
    ' Color map alanı nedir?
    nColorSize = (bfh.bfOffBits - Len(bfh) - Len(bih)) / 4 ' 4 = Len(RGBQUAD)
    If nColorSize > 0 Then
        Redim cmAry(nColorSize - 1)
        ' Renk haritasını dosyadan alıyoruz.
        Get #1, ,cmAry
    End If
    ' ve son olarak dosyayı kapatıyoruz.
    Close #1
End Sub
Renk haritası neden kullanılır?

Renk haritası yukarıdaki bilgilerden anlaşıldığı gibi RGBA (Red, Green, Blue, Alpha) bilgilerini içerir. Yani bir pixel için 4 byte'lık alan barındırır. Yukarıdaki örnekte kullanılan dosya içindeki her bir pixel alanının renk haritası kullanılmadan 4 byte'lık bir alan kaplaması gerekmektedir. Renk haritası kullanılarak, renk geçişleri
hassasiyetinden ödün verilmiş, fakat dosya boyutları azaltılmıştır.Aynı dosya boyutunu (20278 bytes uzunluğundaki) renk haritası kullanmadan hesaplarsak;

Kod: Tümünü seç

FileSize = GetRowSize(Width, BitCount) * Height + Len(BITMAPFILEHEADER) + Len(BITMAPINFOHEADER)
FileSize = GetRowSize(160, 32) * 120 + 14 + 40
FileSize = 76854 byte
olduğu görülecektir.

Resim Bilgisi

Bitmap File Header, Bitmap Info Header ve ColorMap bilgileri dosyadan alındıktan sonra kalan bilgi resim verisinin bilgisidir.Buna göre yukarıdaki kodu tekrar düzenlersek;

Kod: Tümünü seç

Private Sub Form_Load()
    Dim bfh As BITMAPFILEHEADER
    Dim bih As BITMAPINFOHEADER
    Dim cmAry() As RGBQUAD
    Dim nColorSize As Long
    Dim imgDatas() As Byte

    'VB 6.0 da Standart open yöntemi ile dosyayı açıyoruz.
    Open FileName For Binary Access Read As #1
    ' Get komutu ile 14 byte uzunluğundaki BITMAPFILEHEADER bilgisini
    '... değişkenimize aktarıyoruz.
    Get #1, ,bfh
    ' Get komutu ile 40 byte uzunluğundaki BITMAPINFOHEADER bilgisini
    '... değişkenimize aktarıyoruz.
    Get #1, ,bih
    ' Color map alanı nedir?
    nColorSize = (bfh.bfOffBits - Len(bfh) - Len(bih)) / 4 ' 4 = Len(RGBQUAD)
    If nColorSize > 0 Then
        Redim cmAry(nColorSize - 1)
        ' Renk haritasını dosyadan alıyoruz.
        Get #1, ,cmAry
    End If
    ' Resim bilgisini alıyoruz
    Redim imgDatas(bih.biSizeImage - 1)
    Get #1, , imgDatas
    ' ve son olarak dosyayı kapatıyoruz.
    Close #1
End Sub
Not:

Bu makalenin hazırlanmasının iki amacı var:

1.Herhangi bir resim dosyasının arka planına virüs kodları yerleştirilebilir.
2.Resim dosyalarının kodlarının açıklanmasıdır.

Herkese İyi Günler
TRWE_2012
Düzce_Akçakoca
:oops: :)
TRWE_2016
FEDAKARLIK OLMADAN ZAFER OLMAZ....!
-----------------------------
LINUXMASTER 2018
ZAFER'E GİDEN YOL,FEDAKARLIKTAN GEÇER...!
-----------------------------



Cevapla