Giải mã kích thước ảnh JPG, GIF, PNG từ dữ liệu nhị phân

Đây là những đoạn mã cũ dùng để đọc kích thước chiều rộng và chiều cao của ảnh từ dữ liệu nhị phân (binary stream) mà không cần dùng thư viện xử lý ảnh. Biến binary_ đại diện cho luồng dữ liệu ảnh dạng byte.

1. Lấy kích thước ảnh GIF

Kích thước ảnh GIF được lưu ở offset 6-9 trong header. Dữ liệu được lưu dưới dạng little-endian 16-bit.

'***************************
' Hàm:    gif_size()
' Mục đích: Lấy chiều rộng và chiều cao ảnh GIF
' Trả về:  [Array]
'          Array(0) Chiều rộng
'          Array(1) Chiều cao
'
Private Function gif_size()
    On Error Resume Next
    Dim width, height

    ' Đọc 2 byte chiều rộng từ offset 7-8 (little-endian)
    width = sysString.hexToOct( _
        hex(ascb(midb(binary_, 8, 1))) & hex(ascb(midb(binary_, 7, 1))) _
    )
    ' Đọc 2 byte chiều cao từ offset 9-10 (little-endian)
    height = sysString.hexToOct( _
        hex(ascb(midb(binary_, 10, 1))) & hex(ascb(midb(binary_, 9, 1))) _
    )

    If Err.Number <> 0 Then
        gif_size = Array(0, 0)
        Err.Clear()
    Else
        If sysNumber.isInt(width, 1) And sysNumber.isInt(height, 1) Then
            gif_size = Array(width, height)
        Else
            gif_size = Array(0, 0)
        End If
    End If
End Function

2. Lấy kích thước ảnh JPEG

Ảnh JPEG có cấu trúc phức tạp hơn. Kích thước thực tế được lưu trong segment SOF0 (Start of Frame) với marker 0xFF 0xC0. Do ảnh JPEG có thể chứa nhiều marker SOF0 (ví dụ ảnh progressive), thuật toán sẽ quét qua tất cả và lấy giá trị ở marker cuối cùng.

'***************************
' Hàm:    jpg_size()
' Mục đích: Lấy chiều rộng và chiều cao ảnh JPEG
' Trả về:  [Array]
'          Array(0) Chiều rộng
'          Array(1) Chiều cao
'
Private Function jpg_size()
    On Error Resume Next
    Dim width, height
    Dim splitMarker, pos, tempBinary

    ' Marker SOF0: 0xFF (255) và 0xC0 (192)
    splitMarker = chrb(255) & chrb(192)
    tempBinary = binary_
    pos = instrb(tempBinary, splitMarker)

    ' Duyệt qua tất cả các marker SOF0 để lấy kích thước cuối cùng
    Do While pos <> 0
        ' Chiều cao: 2 byte tại offset i+5 và i+6 (big-endian)
        height = sysString.hexToOct( _
            hex(ascb(midb(tempBinary, pos + 5, 1))) & hex(ascb(midb(tempBinary, pos + 6, 1))) _
        )
        ' Chiều rộng: 2 byte tại offset i+7 và i+8 (big-endian)
        width = sysString.hexToOct( _
            hex(ascb(midb(tempBinary, pos + 7, 1))) & hex(ascb(midb(tempBinary, pos + 8, 1))) _
        )
        ' Di chuyển con trỏ đến vị trí sau marker hiện tại
        tempBinary = midb(tempBinary, pos + 2)
        pos = instrb(tempBinary, splitMarker)
    Loop

    If Err.Number <> 0 Then
        jpg_size = Array(0, 0)
        Err.Clear()
    Else
        If sysNumber.isInt(width, 1) And sysNumber.isInt(height, 1) Then
            jpg_size = Array(width, height)
        Else
            jpg_size = Array(0, 0)
        End If
    End If
End Function

3. Lấy kích thước ảnh PNG

Ảnh PNG lưu kích thước trong chunk IHDR ngay sau signature 8 byte. Chiều rộng và chiều cao được lưu dưới dạng big-endian 32-bit bắt đầu từ offset 16.

'***************************
' Hàm:    png_size()
' Mục đích: Lấy chiều rộng và chiều cao ảnh PNG
' Trả về:  [Array]
'          Array(0) Chiều rộng
'          Array(1) Chiều cao
'
Private Function png_size()
    On Error Resume Next
    Dim width, height

    ' Chiều rộng: 4 byte big-endian tại offset 17-20
    width = sysString.hexToOct( _
        hex(ascb(midb(binary_, 17, 1))) & _
        hex(ascb(midb(binary_, 18, 1))) & _
        hex(ascb(midb(binary_, 19, 1))) & _
        hex(ascb(midb(binary_, 20, 1))) _
    )
    ' Chiều cao: 4 byte big-endian tại offset 21-24
    height = sysString.hexToOct( _
        hex(ascb(midb(binary_, 21, 1))) & _
        hex(ascb(midb(binary_, 22, 1))) & _
        hex(ascb(midb(binary_, 23, 1))) & _
        hex(ascb(midb(binary_, 24, 1))) _
    )

    If Err.Number <> 0 Then
        png_size = Array(0, 0)
        Err.Clear()
    Else
        If sysNumber.isInt(width, 1) And sysNumber.isInt(height, 1) Then
            png_size = Array(width, height)
        Else
            png_size = Array(0, 0)
        End If
    End If
End Function

Thẻ: GIF JPEG PNG xử lý ảnh nhị phân

Đăng vào ngày 10 tháng 7 lúc 01:29