News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

BMP color table in OpenGL

Started by gelatine1, October 20, 2015, 08:21:59 PM

Previous topic - Next topic

gelatine1

Hello
I am currently working with bitmap files (.BMP) to be used in an OpenGL program. The first bitmaps I used had the standard BGR format but now I have a .bmp file that uses 8 bits per pixel. I've been reading on wikipedia about the bmp file format (https://en.wikipedia.org/wiki/BMP_file_format#Color_table). In this specific file each index xy (x and y are from 0 to F so together they're 1 byte) becomes a color xy,xy,xy.
Now I have been trying to use this in my program and I found 2 functions that should be useful but I don't really understand how to use the parameters. glPixelTasferf and glPixelMapfv (https://msdn.microsoft.com/en-us/library/windows/desktop/ee872059(v=vs.85).aspx and https://msdn.microsoft.com/en-us/library/windows/desktop/ee872056(v=vs.85).aspx).

In my program I open up the file as follows:


LoadBMP proc Filename:DWORD ;Filename is a pointer to the file name.
cmp Filename,0
jnz @F
xor eax,eax
ret
@@:
invoke CreateFile,Filename,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
mov fhandle,eax
invoke CreateFileMapping,fhandle,0,PAGE_READONLY,0,0,0
mov hmap,eax
invoke MapViewOfFile,eax,FILE_MAP_READ,0,0,0
mov fmap,eax

;add ERROR CHECKING (note to myself...)
ret
LoadBMP endp

UnLoadBMP proc
invoke UnmapViewOfFile,fmap
invoke CloseHandle,hmap
invoke CloseHandle,fhandle
ret
UnLoadBMP endp

LoadGLTextures proc
LOCAL TextureImage:DWORD ; is a pointer to a texture image
LOCAL status:DWORD
LOCAL fileoffset:DWORD

invoke LoadBMP,addr filename
cmp eax,0
jz @F
mov [TextureImage],eax
mov esi,[eax+10] ; get offset of the bmp data
mov fileoffset,esi

;these functions don't really matter for this question
mov status,1
invoke glGenTextures,3,addr texture
invoke glBindTexture,GL_TEXTURE_2D,addr texture
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST

;this function is the important one for this question
mov esi,[TextureImage]
mov edi,esi
add edi,[fileoffset]
invoke glTexImage2D,GL_TEXTURE_2D,0,3,[esi+18],[esi+22],0,GL_BGR_EXT,GL_UNSIGNED_BYTE,edi

@@:
cmp status,0
jz @F
invoke UnLoadBMP
@@:
mov eax,status
ret
LoadGLTextures endp


also in the glTexImage2D proc the GL_BGR_EXT param should be changed to GL_COLOR_INDEX.

So is there anyone who could explain me or show me an example on how to use this color table for the glTexImage2D function ?
the bmp is in the attachment.

thanks in advance

Siekmanski

Here is an example how to load BMP JPEG GIF EMF WMF ICO pictures in memory and create textures in opengl.

;* Siekmanski (c) 2005 - laad jpg, bmp, gif, ico etc.

.const
; IPicture guid
IID_IPicture TEXTEQU <{07bf80980h,0bf32h,0101ah,{08bh,0bbh,000h,0aah,000h,030h,00ch,0abh}}>
HIMETRIC_INCH equ 2540

; ------------------------------------------------------
; Macros

RGB MACRO rood,groen,blauw
EXITM %((blauw shl 16) or (groen shl 8) or (rood))
ENDM

RGBA MACRO rood,groen,blauw,alpha
EXITM %((alpha shl 24) or (blauw shl 16) or (groen shl 8) or (rood))
ENDM


; IPicture interface
_vtIPicture MACRO CastName:REQ
_vtIUnknown CastName
&CastName&_get_Handle    comethod2  ?
&CastName&_get_hPal    comethod2  ?
&CastName&_get_Type    comethod2  ?
&CastName&_get_Width    comethod2  ?
&CastName&_get_Height    comethod2  ?
&CastName&_Render    comethod11 ?
&CastName&_set_hPal    comethod2  ?
&CastName&_get_CurDC    comethod2  ?
&CastName&_SelectPicture    comethod4  ?
&CastName&_get_KeepOriginalFormat  comethod2  ?
&CastName&_put_KeepOriginalFormat  comethod2  ?
&CastName&_PictureChanged    comethod1  ?
&CastName&_SaveAsFile    comethod4  ?
&CastName&_get_Attributes    comethod2  ?
ENDM

IPicture struct
_vtIPicture IPicture
IPicture ends


.data?

IP_Data dd ?
IP_Width dd ?
IP_Height dd ?

.code

Load_File proc Filename:DWORD
   LOCAL   hFile,dwLength,dwReadbytes,pPTR:DWORD

   invoke  CreateFile,Filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
   inc    eax
   jz    Error
   dec    eax
   mov    hFile,eax
   invoke  GetFileSize,hFile,NULL
   inc    eax
   jz    Error
   dec    eax
   mov    dwLength,eax

   Alloc_mem   pPTR,dwLength
   test    eax,eax
   jz    Error

   invoke  ReadFile,hFile,pPTR,dwLength,addr dwReadbytes,NULL
   test    eax,eax
   jz    Error
   invoke  CloseHandle,hFile
   mov    eax,pPTR
   mov    ecx,dwLength
Error:
   ret
Load_File endp

Find_PowerOf2 proc Value:dword
mov eax,MaxTextureSize
cmp Value,eax
jae Max_TextureSize ; Not bigger than Max of gfxcard
fld FLT4(0.30102999) ; 1/log2(10)
fild Value ; <- Pic Width or Height
fyl2x ; Log(Value) = Log2(Value) * (1/log2(10))
fmul FLT4(3.32192809488736234787031942948) ; Powerof2 = Log (Value) * (1/log(2))
fadd FLT4(0.5) ; round to highest Powerof2 (257 -> 512)
fistp Value
mov eax,1
mov ecx,Value ; shift with Powerof2
shl eax,cl ; -> New Pic Width or Height (Powerof2)
Max_TextureSize:
ret
Find_PowerOf2 endp


Load_Bitmap proc  uses esi edi PictureName:DWORD,BitmapID:DWORD,PowerOf2:DWORD
local PictureBuffer:dword
local RsrcData:dword
local RsrcSize:dword
local hRsrc:dword
local pStream:dword
local IBitmap:dword
local pPicture:dword
local hdcTemp:HDC
local binfo:BITMAPINFO
local IPicWidth:dword
local IPicHeight:dword

   invoke  FindResource,NULL,PictureName,TEXT_("PICTURE")
   test    eax,eax
   jz    Find_Picture ; No picture in the resource, so look somewhere else
   mov    hRsrc,eax

   invoke  SizeofResource,NULL,eax
   mov    RsrcSize,eax

   Alloc_mem   PictureBuffer,eax
   test    eax,eax
   jz    Err_PIC_Load

   invoke  LoadResource,NULL,hRsrc
   invoke  LockResource,eax
   mov    RsrcData,eax

   mov    esi,RsrcData
   mov    edi,PictureBuffer
   mov    ecx,RsrcSize
   cld
   rep    movsb

   jmp    Loading_pic

Find_Picture:
   invoke  Load_File,PictureName
   test    eax,eax
   jz    Err_PIC_Load
   mov    PictureBuffer,eax

Loading_pic:
   invoke  CreateStreamOnHGlobal,PictureBuffer,TRUE,addr pStream
   cmp    eax,S_OK
   jne    Err_PIC_CStream

   invoke  OleLoadPicture,pStream,NULL,TRUE,GUID_ADDR(IID_IPicture),addr pPicture
   cmp    eax,S_OK
   jne Err_PIC_Stream

   invoke  GetDC,NULL
   push    eax
   invoke  CreateCompatibleDC,eax
   mov    hdcTemp,eax
   pop    eax
   invoke  DeleteDC,eax

   ; Get IPicture width and height
   coinvoke pPicture,IPicture,get_Width,addr IPicWidth
   coinvoke pPicture,IPicture,get_Height,addr IPicHeight

   ; Convert to pixels
   invoke  GetDeviceCaps,hdcTemp,LOGPIXELSX
   invoke  MulDiv,IPicWidth,eax,HIMETRIC_INCH
   mov    IP_Width,eax
   invoke  GetDeviceCaps,hdcTemp,LOGPIXELSY
   invoke  MulDiv,IPicHeight,eax,HIMETRIC_INCH
   mov    IP_Height,eax

   .if PowerOf2
invoke  Find_PowerOf2,IP_Width
mov IP_Width,eax
invoke  Find_PowerOf2,IP_Height
mov IP_Height,eax
   .endif

   invoke  RtlZeroMemory,addr binfo.bmiHeader,sizeof BITMAPINFOHEADER

   mov    binfo.bmiHeader.biSize,sizeof BITMAPINFOHEADER
   mov    binfo.bmiHeader.biBitCount,32 ; we want only 32 bit
   mov    eax,IP_Width
   mov    binfo.bmiHeader.biWidth,eax
   mov    eax,IP_Height
   mov    binfo.bmiHeader.biHeight,eax
   mov    binfo.bmiHeader.biCompression,BI_RGB
   mov    binfo.bmiHeader.biPlanes,1

   ; we do a "CreateDIBSection" so we have access to the pixel-data and change whatever we want......
   invoke  CreateDIBSection,hdcTemp,addr binfo,DIB_RGB_COLORS,addr IP_Data,NULL,0
   test    eax,eax
   jz    Err_PIC_DIB
   mov    IBitmap,eax

   invoke  SelectObject,hdcTemp,IBitmap
   test    eax,eax
   jz    Err_PIC_Render

   mov    eax,IPicHeight
   neg    eax
   coinvoke pPicture,IPicture,Render,hdcTemp,0,0,IP_Width,IP_Height,0,IPicHeight,IPicWidth,eax,0
   cmp    eax,S_OK
   jne    Err_PIC_Render

   mov    ecx,BitmapID
   mov    eax,IBitmap
   mov    [ecx],eax

   invoke  DeleteDC,hdcTemp
   SAFE_RELEASE pPicture
   SAFE_RELEASE pStream
   mov eax,TRUE
   ret
Err_PIC_Render:
   invoke  DeleteObject,IBitmap
Err_PIC_DIB:
   invoke  DeleteDC,hdcTemp
   SAFE_RELEASE pPicture
Err_PIC_Stream:
   SAFE_RELEASE pStream
   mov eax,FALSE
   ret
Err_PIC_CStream:
   Delete_mem PictureBuffer
Err_PIC_Load:
   mov eax,FALSE
   ret
Load_Bitmap endp


Load_Texture proc TextureName:DWORD,TextureID:DWORD,InternalFormat:DWORD,Format:DWORD,ColorKey:DWORD
LOCAL Texture_Data:DWORD
LOCAL TextureTemp:DWORD
LOCAL Bitmap:DWORD

invoke Load_Bitmap,TextureName,addr Bitmap,TRUE
test eax,eax
jz Texture_Error

mov eax,IP_Width
imul eax,IP_Height
push eax
shl eax,2
Alloc_mem Texture_Data,eax
pop ecx
test eax,eax
jz Texture_Error

mov esi,IP_Data
mov edi,Texture_Data
CopyPixels:
lodsd
shl eax,8
bswap eax
mov edx,ColorKey ; -1 = no alpha
test edx,edx
js NoAlpha
cmp edx,eax
jne NoAlpha
mov eax,0ff000000h
NoAlpha:
xor eax,0ff000000h
stosd
loop CopyPixels

invoke DeleteObject,Bitmap

invoke glGenTextures,1,addr TextureTemp
.if TextureTemp != 0
invoke glBindTexture,GL_TEXTURE_2D,TextureTemp
invoke glEnable,GL_TEXTURE_2D
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST
invoke glTexImage2D,GL_TEXTURE_2D,0,InternalFormat,IP_Width,IP_Height,0,Format,GL_UNSIGNED_BYTE,Texture_Data
invoke glDisable,GL_TEXTURE_2D
.endif
Delete_mem Texture_Data
mov eax,TextureTemp
mov ecx,TextureID
mov [ecx],eax
mov eax,TRUE
ret

Texture_Error:
invoke MessageBox,0,TEXT_("Can't load Texture file"),TEXT_("Siekmanski antwoordt:.."),MB_ICONSTOP
.if (Bitmap)
invoke DeleteObject,Bitmap
.endif
mov eax,FALSE
ret
Load_Texture endp

Delete_Texture proc TextureID:DWORD
invoke glDeleteTextures,1,addr TextureID
ret
Delete_Texture endp

DrawQuad2D proc Xpos:REAL4,Ypos:REAL4,QuadWidth:REAL4,QuadHeight:REAL4,QuadDepth:REAL4,TextureID:DWORD
invoke glPushMatrix
invoke glTranslatef,Xpos,Ypos,QuadDepth
invoke glEnable,GL_TEXTURE_2D
invoke glBindTexture,GL_TEXTURE_2D,TextureID
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR ; // Linear Filtered
invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR ; // Linear Filtered

invoke glBegin,GL_QUADS
invoke glTexCoord2f,FLT4(0.0),FLT4(1.0)
invoke glVertex3f,FLT4(0.0),FLT4(0.0),QuadDepth
invoke glTexCoord2f,FLT4(0.0),FLT4(0.0)
invoke glVertex3f,FLT4(0.0),QuadHeight,QuadDepth
invoke glTexCoord2f,FLT4(1.0),FLT4(0.0)
invoke glVertex3f,QuadWidth,QuadHeight,QuadDepth
invoke glTexCoord2f,FLT4(1.0),FLT4(1.0)
invoke glVertex3f,QuadWidth,FLT4(0.0),QuadDepth
invoke glEnd
invoke glDisable,GL_TEXTURE_2D
invoke glPopMatrix
ret
DrawQuad2D endp


Complete example,
Creative coders use backward thinking techniques as a strategy.

gelatine1

I suppose I shouldn't use the same IID?  ;) I'm not very familiar with Com though so I hope I won't need it too much to understand your code?

dedndave

i don't know about OpenGL, but if you have a DIB HBITMAP handle,
you should be able to use GetDIBColorTable and SetDIBColorTable

https://msdn.microsoft.com/en-us/library/dd144878%28v=vs.85%29.aspx
https://msdn.microsoft.com/en-us/library/dd162972%28v=vs.85%29.aspx

TouEnMasm


There is a sample using glu in the masm32 package.
Can be of real help.
Fa is a musical note to play with CL

gelatine1

Quote from: ToutEnMasm on October 21, 2015, 02:18:17 AM

There is a sample using glu in the masm32 package.
Can be of real help.

What's the name of that example ? Because I don't really see it..

Quote from: dedndave on October 21, 2015, 01:16:25 AM
i don't know about OpenGL, but if you have a DIB HBITMAP handle,
you should be able to use GetDIBColorTable and SetDIBColorTable

https://msdn.microsoft.com/en-us/library/dd144878%28v=vs.85%29.aspx
https://msdn.microsoft.com/en-us/library/dd162972%28v=vs.85%29.aspx

So how exactly would I use those ? I tried this code below but I got the feeling it's not really working... and I was wondering what exactly do I get when calling GetDIBColorTable ? Does it simply fill in the same color table array that's already specified in the .bmp file ?


.data
filename db "D:\dev\asm\OpenGL\Real8\Star.bmp",0

.data?
handle dd ?
hdcb dd ?
colortable RGBQUAD 256 dup(<>)
htemp dd ?

.code
start:
invoke LoadImage,0,addr filename,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION
mov handle,eax
invoke GetDC,0
invoke CreateCompatibleDC,eax
mov hdcb,eax
invoke SelectObject,hdcb,handle
mov htemp,eax
invoke GetDIBColorTable,hdcb,0,256,addr colortable

invoke SelectObject,hdcb,htemp
invoke DeleteDC,hdcb
invoke DeleteObject,handle
end start


I think I need a function that interprets the given Bitmap data and its color table specified in the DIB header and then translate it to some data in 24 or 32 bit format. Or maybe just some functions that tell opengl to interpret my bitmap like that.

dedndave

i'm not sure that LoadImage with CREATEDIBSECTION creates a "real" DIB section
i've had problems with that before - i was not able to write the DIB to a file
what i did to fix it was to LoadImage without CREATEDIBSECTION
i then used CreateDIBSection and BitBlt to copy from the bitmap to the DIB
i was then able to copy from the DIB to file

GetDIBColorTable is straightforward, but it does require a DIB secion

TouEnMasm


The sample is this one

invoke glPixelTransferf,GL_RED_SCALE,2.14 ;2.14 arbitrary value of type REAL4
invoke glPixelMapfv,GL_PIXEL_MAP_I_TO_G,mapsize,pointer on map

The first function is easy to use,you have all constants in the include files.
Take care of the map size on the second,msdn will help in that.
Fa is a musical note to play with CL

Farabi

Hi,

You`ll need to convert the bitmap pixel on the fly. You might want to see "Donkey Graphic Lib" in order to do this. Unfortunately I did not get my laptop with me. I might be able to help you with this.
http://farabidatacenter.url.ph/MySoftware/
My 3D Game Engine Demo.

Contact me at Whatsapp: 6283818314165