Page 1 of 1

TGA Image Encoder - hit a snag

Posted: Wed Nov 01, 2006 6:46 pm
by localmotion34
So i mostly have a TGA image encoder written, however when writing bytes to memory corresponding to the bitmap data, the image appears upside down. Also, i am having trouble with getting/setting the alpha channel.

here is the code, and any help would be appreciated.

Code: Select all



UseTIFFImageDecoder() 
UseJPEGImageDecoder() 
UseTGAImageDecoder() 
UsePNGImageDecoder() 


Procedure EncodeTGA(hBitmap.l,Outputfile$)
  
  GetObject_(hBitmap, SizeOf(BITMAP), BM.BITMAP)
  bitcount = BM\bmBitsPixel
  width=BM\bmWidth
  height=BM\bmHeight
  Debug width
  Debug height
  Debug bitcount 
  extrabytesperrow = (4 - (width * bitcount / 8) % 4) % 4
  sizeheaders = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER)
  sizeimage = (width * bitcount / 8 + extrabytesperrow) * height
  Debug sizeimage 
  *bitmap = AllocateMemory(sizeheaders + sizeimage) 
  
  *bitmapfile.BITMAPFILEHEADER = *bitmap
  *bitmapfile\bfType = Asc("B") + Asc("M") << 8
  *bitmapfile\bfSize = sizeheaders +sizeimage
  *bitmapfile\bfOffBits = sizeheaders 
  *bitmapinfo.BITMAPINFOHEADER = *bitmap + SizeOf(BITMAPFILEHEADER)
  *bitmapinfo\biSize = SizeOf(BITMAPINFOHEADER)
  *bitmapinfo\biWidth = width
  *bitmapinfo\biHeight = height
  *bitmapinfo\biPlanes = 1
  *bitmapinfo\biBitCount = bitcount
  *bitmapinfo\biCompression = 0
  *bitmapinfo\biSizeImage = sizeimage
  
  *bitmapdata = *bitmap + sizeheaders
  
  *bitmapdatapos = *bitmapdata
  hdc = GetDC_(#Null)
  GetDIBits_(hdc, hBitmap, 0, height, *bitmap+sizeheaders, *bitmapinfo, #DIB_RGB_COLORS	)
  ; Start writing the image
  If CreateFile(0,Outputfile$)
    For tmp=1 To 12
      Read Header
      WriteByte(0,Header)
    Next    
    
    ;Write Header
    WriteWord(0,width)
    WriteWord(0,height)    
    WriteByte(0,bitcount)
    WriteByte(0,32)
    
    For j= 0 To height - 1  ; j = 0 corresponds to bottom of image  ;;;HUH?
      For i = 0 To width - 1
        WriteByte(0,PeekB(*bitmapdatapos)) ; Blue
        WriteByte(0,PeekB(*bitmapdatapos + 1)) ; Green
        WriteByte(0,PeekB(*bitmapdatapos + 2)) ; Red
        ; If bitcount=32 ;Add Alpha channel bit
          ; If PeekB(*bitmapdatapos + 3)=0
            ; WriteByte(0,0)
          ; Else
            ; WriteByte(0,255)
          ; EndIf
        ; EndIf 
        *bitmapdatapos + bitcount / 8
      Next
      *bitmapdatapos + extrabytesperrow
    Next
  EndIf 
  
EndProcedure 
  
Pattern$ = "All Supported Formats|*.bmp;*.jpg;*.png;*.tif"
Filename.s = OpenFileRequester("Choose An Image File To Open","",Pattern$,0)
If Filename
  bitmap.l=LoadImage(100,Filename)
  EncodeTGA(bitmap,"K:\testing.tga")
EndIf

  
DataSection
Data.l 0,0,2,0,0,0,0,16,0,0,0,0
EndDataSection

Posted: Wed Nov 01, 2006 7:05 pm
by srod
For the upside down part, try switching

Code: Select all

*bitmapinfo\biHeight = height 
for

Code: Select all

*bitmapinfo\biHeight = -height 

Just an initial thought.

Posted: Wed Nov 01, 2006 7:13 pm
by localmotion34
You Da man!

never would have thought of that. It seems the Alpha channel is working now with most images, so i am going to tailbite this after making the right encoder code like Ec_Choni's example.

Posted: Wed Nov 01, 2006 7:16 pm
by srod
localmotion34 wrote:never would have thought of that...
I've come across this before. The default is a 'bottom up' bitmap. By making the *bitmapinfo\biHeight negative, you are in effect specifiying a 'top down' bitmap.

This will be a useful encoder.

Posted: Wed Nov 01, 2006 8:07 pm
by localmotion34
here is the procedure that works for encoding TGA files. i am still not sure of how to get the transparent color of say a PNG image you load and want to save to TGA with transparency.

Code: Select all

Procedure EncodeTGA(Outputfile$,hBitmap)
  If GetObject_(hBitmap, SizeOf(BITMAP), BM.BITMAP)
    bitcount = BM\bmBitsPixel
    width=BM\bmWidth
    height=BM\bmHeight
    extrabytesperrow = (4 - (width * bitcount / 8) % 4) % 4
    sizeheaders = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER)
    sizeimage = (width * bitcount / 8 + extrabytesperrow) * height
    *bitmap = AllocateMemory(sizeheaders + sizeimage) 
    
    *bitmapfile.BITMAPFILEHEADER = *bitmap
    *bitmapfile\bfType = Asc("B") + Asc("M") << 8
    *bitmapfile\bfSize = sizeheaders +sizeimage
    *bitmapfile\bfOffBits = sizeheaders 
    *bitmapinfo.BITMAPINFOHEADER = *bitmap + SizeOf(BITMAPFILEHEADER)
    *bitmapinfo\biSize = SizeOf(BITMAPINFOHEADER)
    *bitmapinfo\biWidth = width
    *bitmapinfo\biHeight = -height
    *bitmapinfo\biPlanes = 1
    *bitmapinfo\biBitCount = bitcount
    *bitmapinfo\biCompression = 0
    *bitmapinfo\biSizeImage = sizeimage
    
    *bitmapdata = *bitmap + sizeheaders
    
    *bitmapdatapos = *bitmapdata
    hdc = GetDC_(#Null)
    GetDIBits_(hdc, hBitmap, 0, height, *bitmap+sizeheaders, *bitmapinfo, #DIB_RGB_COLORS	)
    ReleaseDC_(0,hdc)
    
    ; Start writing the image
    If CreateFile(0,Outputfile$)
      For tmp=1 To 12
        Read Header
        WriteByte(0,Header)
      Next    
      
      ;Write Header
      WriteWord(0,width)
      WriteWord(0,height)    
      WriteByte(0,bitcount)
      WriteByte(0,32)
      
      For j= 0 To height - 1  ; j = 0 corresponds to bottom of image
        For i = 0 To width - 1
          WriteByte(0,PeekB(*bitmapdatapos)) ; Blue
          WriteByte(0,PeekB(*bitmapdatapos + 1)) ; Green
          WriteByte(0,PeekB(*bitmapdatapos + 2)) ; Red
          If bitcount=32 ;Add Alpha channel bit
            If PeekB(*bitmapdatapos + 3)=0
              WriteByte(0,0)
            Else
              WriteByte(0,255)
            EndIf
          EndIf 
          *bitmapdatapos + bitcount / 8
        Next
        *bitmapdatapos + extrabytesperrow
      Next
      If FreeMemory(*bitmap):EndIf 
      If FreeMemory(*bitmapdata):EndIf 
      If FreeMemory(*bitmapfile):EndIf 
      If FreeMemory(*bitmapinfo):EndIf 
      closefile(0)
      ProcedureReturn #True
    Else
      ProcedureReturn #False 
    EndIf 
  Else
    MessageRequester("Error", "Not A Valid hbitmap Or Could Not Be Decoded In Memory",#PB_MessageRequester_Ok)
    ProcedureReturn #False 
  EndIf 
EndProcedure 
i tried making an image plugin with tailbite, however, i am way confused as to the *Buffer parameter in the Encode() procedure that needs to be passed. i cant return a valid hbitmap from the pointer. so here in the procedure that does the encoding.