Page 1 of 1

LoadPix Function

Posted: Tue Jun 12, 2007 4:46 am
by localmotion34
Finally!! I wrote a decoder COMPLETELY on my own. Can you feel it? huh? can you? Can't you tell i am excited?

I started PBXImage so I could learn image formats and image manipulation, but I always hit a snag. Haqibaba, seemingly a master at images, bailed me out with his amazing knowledge. Now, I have turned a new corner.

Alias/Wavefront .PIX format is now available for PB users. Kind of an newer-old format, HOWEVER, with my new knowledge, SGI graphics and their textures and bitmapped formats are a short ways away (hopefully). Knowing how to decode this format could possibly lead to decoding their multilayered image/texture format, which are stellar for game creation.

Please report any bugs. XNview can save .PIX, so you can test all kinds of bitmap conversion to .PIX with this loader.

Code: Select all



Structure APIXHEADER
  ;;;NO Magic number!!!!!!!!!!!!
  width.w;   	        /* Width of image in pixels */
  height.w;           /* Height of image in pixels */
  XOffset.w;          /* X of lower left corner of image */ NOT USED
  YOffset.w;          /* Y of lower left corner of image */ NOT USED
  bpp.w                ; ALWAYS 24
EndStructure

Macro SwapWord(val)
  (((val >> 8) & $00FF) | ((val << 8) & $FF00))
EndMacro

Procedure.l Endian(val.l)
  !MOV Eax,dword[p.v_val]
  !BSWAP Eax
  ProcedureReturn
EndProcedure


Procedure LoadPix(filename.s)
  
  file=ReadFile(#PB_Any,filename)
  If file
    ;really simple header
    *PIX.APIXHEADER=AllocateMemory(SizeOf(APIXHEADER))
    ReadData(file,*PIX.APIXHEADER,SizeOf(APIXHEADER))
    width=SwapWord(*PIX\width)
    height=SwapWord(*PIX\height)
    bpp= SwapWord(*PIX\bpp)
    If bpp =24
    pitch=(((width*bpp)+31)/32)*4 ;DWORD-aligned width
    bhsize=SizeOf(BITMAPINFOHEADER) ;DIB info header size
    ncolors=0 
    
    ;create the bitmap structure
    hDIB=AllocateMemory(bhsize+(ncolors*4)+(pitch*height))
    Protected bmpinfo.BITMAPINFOHEADER
    With bmpinfo
      \biSize=SizeOf(BITMAPINFOHEADER) ;Size of struct
      \biWidth=width ;Bitmap width
      \biHeight=-height ;Bitmap height, bitmap is top down
      \biPlanes=1 ;Single plane
      \biBitCount=24 ;Bit depth
      \biCompression=#BI_RGB ;No compression
      \biSizeImage=0
      \biXPelsPerMeter=0
      \biYPelsPerMeter=0
      \biClrUsed=0
      \biClrImportant=0
    EndWith
    
    Bits=hDIB+SizeOf(BITMAPINFOHEADER) ;Pointer to bits
    For a=0 To height-1
      LineBytesRead=0
      
      While LineBytesRead<pitch-2
        If Not Eof(file); protect ourselves from overflow
        lng.l=Endian(ReadLong(file)); byte order is reversed in .PIX
        Blue.b=PeekB(@lng) &255;blue
        Green.b=PeekB(@lng+1) &255 ;green
        Red.b= PeekB(@lng+2)&255 ;red
        runcnt.b= PeekB(@lng+3);&255;runcount
        For b=0 To (runcnt&$FF)-1
          ;PokeL(Bits+LineBytesRead+3+(a*pitch),RGB(Red,Green,Blue)) ;i think this also works - but not as good
          PokeB(Bits+LineBytesRead+(a*pitch),Red)
          PokeB(Bits+LineBytesRead+1+(a*pitch),Green)
          PokeB(Bits+LineBytesRead+2+(a*pitch),Blue)
          LineBytesRead=LineBytesRead+3
        Next
      Else
        Break 
      EndIf 
      Wend   
    Next 
    CloseFile(file)
Else
    ProcedureReturn -1
  EndIf
  
  ;Create the DDB bitmap
  hdc=GetDC_(#Null)
  hBitmap=CreateDIBitmap_(hdc,bmpinfo,#CBM_INIT,Bits,bmpinfo,#DIB_RGB_COLORS)
  FreeMemory(*PIX.APIXHEADER)
  FreeMemory(hDIB)
  ProcedureReturn hBitmap  
Else
  ProcedureReturn -1
EndIf 
EndProcedure


If OpenWindow(0,0,0,670,620,"Load PIX",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  ButtonGadget(0, 10, 10,80,20,"Open File")
  ImageGadget(1, 10, 50, 300,300,0,#PB_Image_Border)
EndIf
  
Repeat
  Select  WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Pattern$="All Supported Formats|*.pix"
          filename.s=OpenFileRequester("Choose An Image File To Open","",Pattern$,0)
          If filename
            hBitmap=LoadPix(filename.s)
            SendMessage_(GadgetID(1), #STM_SETIMAGE,#IMAGE_BITMAP,hBitmap)
          EndIf
      EndSelect
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver