lộn ngược là do bản chất nó vốn thế ^^
Chứng tỏ là bạn chưa hiểu rõ
hết về cấu trúc tập tin BMP.
Không phải bản chất nó thế. Nếu gọi là bản chất thì BMP có 2 bản chất.
Có 2 cách ghi các dòng bai mầu trong tập tin BMP.
Cách 1. Thường dùng nhất, để hình dung ta tạm cho là trong 99,99% các trường hợp.
Trong trường hợp này
biHeight trong cấu trúc
BitmapInfoHeader được thiết lập là số
DƯƠNG. Hàm ý là gốc tọa độ là góc dưới bên trái của màn hình -
lower left corner (trục y hướng lên trên), và các dòng bai mầu được ghi trong tập tin BMP theo thứ tự: trước tiên ghi dòng cuối cùng, sau đó là dòng trước dòng cuối cùng, ..., dòng sau dòng đầu, dòng đầu. Đó chính là
bottom-up DIB.
Tập tin BMP của bạn ở dạng này:
biHeight = 183 = B7 (hex) - DƯƠNG. Trong tập tin BMP của bạn đó là 4 bai từ bai 22 tới bai 25 (offset tính từ 0) - trên bảng tính là B23:B26. Giá trị Long (VBA) - DWORD (Windows) &H000000B7 = 183 chính là số dòng trong bitmap của bạn (400 x 183).
Cách 2.
biHeight là số ÂM, gốc tọa độ là góc trên bên trái (
upper left corner - trục y hướng xuống dưới), các dòng bai mầu được ghi theo thứ tự ngược lại, tức: trước tiên dòng đầu, tiếp theo dòng sau dòng đầu, ..., dòng trước cuối, dòng cuối (
top-down).
Do tập tin của bạn thuộc cách 1 (các dòng bai mầu được ghi trong BMP theo
bottom-up) nên khi đọc ra để ghi vào sheet bạn phải ghi theo thứ tự: ghi dòng bai mầu đầu tiên đọc từ tập tin BMP (dòng cuối cùng của ảnh) vào vd. dòng 183 của sheet, dòng thứ 2 đọc từ tập tin BMP (dòng trước cuối của ảnh) vào dòng 182 của sheet, ...., dòng trước cuối đọc từ tập tin BMP (dòng 2 của ảnh) vào dòng 2 của sheet, dòng cuối cùng đọc từ tập tin BMP (dòng đầu của ảnh) vào dòng 1 của sheet. Lúc đó ảnh sẽ không bị ngược.
Lưu ý:
Về đọc các dòng bai mầu từ tập tin BMP.
Trong trường hợp tổng quát khi tạo tập tin BMP 24 bit thì mỗi pixel được biểu diễn bởi 3 bai liên tiếp (các thành phần B, G, R của pixel - xem hình 2). Như vậy với BMP có
w pixel theo hàng ngang thì mỗi dòng bai mầu được biểu diễn bằng 3*
w bai. Nhưng nếu 3*w không là bội của 4 thì 1, 2 hoặc 3 bai 0 sẽ được thêm vào cuối mỗi dòng bai mầu (xem hình 2) để sao cho mỗi dòng bai mầu có số bai là bội của 4. Vd.
w = 11 thì không phải 3*11 = 33 bai sẽ được ghi vào mỗi dòng mầu
khi tạo BMP. Lúc đó sẽ được ghi 33 bai mầu của dòng + 3 bai 0:
Vd. với
bottom-up:
<33 bai màu của dòng cuối><3 bai 0><33 bai mầu của dòng trước cuối><3 bai 0> ... <33 bai mầu của dòng đầu tiên><3 bai 0>
Trong trường hợp trên để chấm mầu trên sheet thì khi đọc ra các bai cho từng dòng thì chỉ đọc 33 bai (3*
biWidth), và trước khi đọc dòng mới thì phải nhẩy bỏ qua 3 bai 0.
Trong trường hợp của bạn
w = 400. Mỗi dòng mầu được biểu diễn bằng 3*400 = 1200 bai. 1200 là bội của 4 nên
khi tập tin BMP được tạo thì không có bai 0 nào được thêm, được chèn giữa các dòng mầu. Vì thế đọc và lấy các bai như bạn là được. Nhưng trong trường hợp tổng quát phải đọc ra
biWidth để kiểm tra xem 3*
biWidth có là bội của 4 không. Nếu không thì tính được số bai 0 được thêm vào mỗi dòng bai mầu. Và khi đọc ra để chấm mầu trên sheet thì phải bỏ qua các bai 0 này - đọc ra 3*
biHeight bai -> bỏ qua các bai 0 nếu có -> đọc tiếp 3*
biHeight bai -> bỏ qua các bai 0 nếu có ...
Đấy là nói về format 24 bit. Còn với các format khác thì khi đọc ra bai còn phải thực hiện thao tác bit để biết được pixel (x, y) có mầu thế nào.