Jpg /Png export

Blitz3D Forums/Blitz3D Programming/Jpg /Png export

D4NM4N(Posted 2005) [#1]
Does anyone know if any patent exists for writing these files, also anyone know of some code that does it?


Wayne(Posted 2005) [#2]
jpg patent expires oct 2006
png patent free


Banshee(Posted 2005) [#3]
There are some file exporters in the code archives i'm pretty sure I saw png the other day but i'm not 100% sure it might have been tga.

There used to be a free .dll by Guy Savorie to export .jpg images, but he had a personal situation and disapeared from the indie scene a few years ago and i've lost the .dll myself, I think a few of my online friends from another programming community might well have it still if you really need it, i'll try to track it down.


jfk EO-11110(Posted 2005) [#4]
http://www.blitzcoder.com/cgi-bin/showcase/showcase_showentry.pl?id=snarty09252003024804&comments=no


VP(Posted 2005) [#5]
If anyone wants a PNG exporter written purely in Blitz, I could probably sort that out this weekend.

Anyone interested?


D4NM4N(Posted 2005) [#6]
@all Thanks
@JFK Looks promising ill check it out now!
@vinylpusher MeMeMe!


VP(Posted 2005) [#7]
Ok, I'll take Andre LaMothe's Targa exporter in C++ and change it to a PNG exporter in Blitz. How hard can it be?

Should be a laugh.


John Blackledge(Posted 2005) [#8]
vinylpusher, me too! Please!


VP(Posted 2005) [#9]
The beginnings of the exporter are included below. I've got a real stinking cold right now so I'm not exactly on top form. Please excuse any stupid errors!

I didn't realise quite how complex PNG is. I've got to implement LZ77 compression and CRC32 creation just to get a very basic PNG file created. This is something I will start doing tomorrow (if I get out of bed at all).

pngexporter.bb
;------------------------------------------------------------------------------

; Native Blitz 3D PNG exporter

; Version 0.01

; Copyright 2005 Stefan Holmes.

; You may use this file freely so long as the text "PNG exporter by Stefan
; Holmes" appears either in your application's 'help, about' or in the main
; documentation.

;------------------------------------------------------------------------------

Function pngExport(file$,img%)

    ;--------------------------------------------------------------------------
    ;
    ; ARGUMENTS:
    ;
    ; file$     : Full path and name of the file to be saved.
    ;
    ; image%    : Valid Blitz 3D image handle.
    ;--------------------------------------------------------------------------
    ;
    ; RETURNS:
    ;
    ; Not 0 : Success.
    ;
    ; 0     : Failure.
    ;--------------------------------------------------------------------------

    DeleteFile file$ 
    fh% = WriteFile(file$) : If fh%=0 Then Return 0

    Restore pngExporter_sig
    For i=1 To 8
        Read d%
        WriteByte(fh%,d%)
    Next

    ; IHDR chunk.
    pngExporterStartChunk(fh%,13,"IHDR")
    pngExporterWriteInt(fh%,ImageWidth(img%))   ; Width                 4 bytes
    pngExporterWriteInt(fh%,ImageHeight(img%))  ; Height                4 bytes
    WriteByte(fh%,8)                            ; Bitdepth              1 byte
    WriteByte(fh%,2)                            ; Colour type           1 byte
    WriteByte(fh%,0)                            ; Compression method    1 byte
    WriteByte(fh%,0)                            ; Filter method         1 byte
    WriteByte(fh%,0)                            ; Interlace method      1 byte  

    ; IEND chunk.
    pngExporterStartChunk(fh%,0,"IEND")
    WriteInt(fh%,0)


    CloseFile fh%

    Return fh%
    
End Function
.pngExporter_sig
Data  137,80,78,71,13,10,26,10


Function pngExporterStartChunk(filehandle%,length%,chunk$)
    pngExporterWriteInt(filehandle%,length%)
    pngExporterWriteStr(filehandle%,chunk$)
End Function


Function pngExporterWriteInt(filehandle%,value%)
    ; Taken from Starfox a.k.a David Dawkin's WriteMotorolaInt function
    ; available at http://www.blitzbasic.com/codearcs/codearcs.php?code=674
    ; Thanks, Starfox.
    WriteByte(filehandle%, value% Shr 24 And $FF)
    WriteByte(filehandle%, value% Shr 16 And $FF)
    WriteByte(filehandle%, value% Shr 8 And $FF)
    WriteByte(filehandle%, value% And $FF)
End Function 


Function pngExporterWriteStr(filehandle%,strng$)
    For i% = 1 To Len(strng$)
        WriteByte( filehandle%, Asc( Mid(strng$,i%,1) ) )
    Next
End Function
tester.bb
;------------------------------------------------------------------------------

; Test program for "Native Blitz 3D PNG exporter"

; Version 0.01

; Copyright 2005 Stefan Holmes.

; This code is 'public domain' without limitation or condition.

;------------------------------------------------------------------------------

Include "pngexporter.bb"

;------------------------------------------------------------------------------

img%=LoadImage("kodim20.png")

If img%>0
    Graphics ImageWidth(img%)+16,ImageHeight(img%)+22,32,2
    img%=LoadImage("kodim20.png")

    DrawImage img%,8,17
    Color 255,255,255
    Rect 7,16,GraphicsWidth()-14,GraphicsHeight()-20,False
    Color 0,0,0

    txt("Exporting PNG...")
    err%=pngExport("a_out.png",img%)

    If err%>0
        Txt("PNG saved.")
    Else
        txt("Error when saving.")
    EndIf 
    
Else
    Print "Unable to load image; exiting."
    Delay 4000
    End 
EndIf

Function txt(txt$)
    Color 0,0,0
    Rect 0,0,GraphicsWidth(),16
    Color 255,255,255
    Text 0,0,txt$
End Function

Here is the kodim20.png test image I'm using.


VP(Posted 2005) [#10]
Slightly updated version.

Still doesn't do anything useful, but I'm getting there. I might not have any more time today to work on it today, got some IRL stuff to do which takes priority :-/

EDIT: Fixed stupid CRC32 bug. should now generate correct CRC.
;------------------------------------------------------------------------------

; Native Blitz 3D PNG exporter

; Version 0.02

; Copyright 2005 Stefan Holmes.

; You may use this file freely so long as the text "PNG exporter by Stefan
; Holmes" appears either in your application's 'help, about' or in the main
; documentation.

;------------------------------------------------------------------------------

Function pngExport(file$,img%)
    ;==========================================================================
    ; DESCRIPTION
    ;
    ; Exports an image as a PNG file without recourse to an external DLL.
    ;
    ; Inspired by a request for such a function originally made by Daniel
    ; Harvey (D-Grafix) and seconded by John Blackledge.
    ; http://www.blitzbasic.com/Community/posts.php?topic=52394
    ;--------------------------------------------------------------------------
    ; PARAMETERS
    ;
    ; file$ : Full path and name of the file to be saved.
    ;
    ; img%  : Valid Blitz 3D image handle.
    ;--------------------------------------------------------------------------
    ; RETURNS
    ;
    ; >0    : Size of the written file.
    ;
    ; 0     : Failed to write file.
    ;==========================================================================

    DeleteFile file$ 
    fh% = WriteFile(file$) : If fh%=0 Then Return 0
    
    crc32bank%=pngExporterInitCRC32()

    imgwidth%=ImageWidth(img%)
    imgheight%=ImageHeight(img%)
    
    ;--------------------------------------------------------------------------
    ; PNG signature.
    WriteByte(fh%,137):WriteByte(fh%,80):WriteByte(fh%,78):WriteByte(fh%,71)
    WriteByte(fh%,13):WriteByte(fh%,10):WriteByte(fh%,26):WriteByte(fh%,10)
    ;--------------------------------------------------------------------------

    
    ;--------------------------------------------------------------------------
    ; IHDR chunk.
    pngExporterStartChunk(fh%,13,"IHDR")
    pngExporterWriteInt(fh%,imgwidth%)      ; Width                 4 bytes
    pngExporterWriteInt(fh%,imgheight%)     ; Height                4 bytes
    WriteByte(fh%,8)                        ; Bitdepth              1 byte
    WriteByte(fh%,2)                        ; Colour type           1 byte
    WriteByte(fh%,0)                        ; Compression method    1 byte
    WriteByte(fh%,0)                        ; Filter method         1 byte
    WriteByte(fh%,0)                        ; Interlace method      1 byte  
    ;--------------------------------------------------------------------------
    

    ;--------------------------------------------------------------------------
    ; Convert pixels to data stored in a bank.
    
    imgbank%=CreateBank( (imgwidth% * imgheight%) * 3 )
    imgwidth%=imgwidth%-1 : imgheight%=imgheight%-1
    
    SetBuffer ImageBuffer(img%)
    LockBuffer
    i%=0
    For y%=0 To imgheight%
        For x%=0 To imgwidth%
            ; There is no doubt a better way to do this, but it works.
            ; Taken from the BMax desaturation fader by Marc van den Dikkenberg
            ; (xlsior).
            ; http://www.blitzbasic.com/codearcs/codearcs.php?code=1282
            pixel%=ReadPixelFast(x%,y%)
            PokeByte imgbank%,i%,(pixel% And $00FF0000) Shr 16
            PokeByte imgbank%,i%+1,(pixel% And $FF00) Shr 8
            PokeByte imgbank%,i%+2,(pixel% And $FF)
            i%=i%+3
        Next
    Next 
    UnlockBuffer

    SetBuffer FrontBuffer()
    
    ; Calculate the CRC32 needed for the IDAT chunk
    crc%=pngExporterCalcCRC32(crc32bank%,imgbank%)

    ;--------------------------------------------------------------------------


    ;--------------------------------------------------------------------------
    ; IEND chunk.
    pngExporterStartChunk(fh%,0,"IEND")
    WriteInt(fh%,0)
    ;--------------------------------------------------------------------------

    FreeBank crc32bank%
    FreeBank imgbank%
    CloseFile fh%

    Return FileSize(file$)
    
End Function


Function pngExporterStartChunk(filehandle%,length%,chunk$)
    pngExporterWriteInt(filehandle%,length%)
    pngExporterWriteStr(filehandle%,chunk$)
End Function

;------------------------------------------------------------------------------
; File functions adapted from the LightWave exporter by David Dawkin (starfox).
; http://www.blitzbasic.com/codearcs/codearcs.php?code=674
;------------------------------------------------------------------------------
Function pngExporterWriteInt(filehandle%,value%)
    WriteByte(filehandle%, value% Shr 24 And $FF)
    WriteByte(filehandle%, value% Shr 16 And $FF)
    WriteByte(filehandle%, value% Shr 8 And $FF)
    WriteByte(filehandle%, value% And $FF)
End Function 


Function pngExporterWriteStr(filehandle%,strng$)
    ;==========================================================================
    ; DESCRIPTION
    ;
    ; Writes a string literal to a file with no preceeding or trailing data.
    ;--------------------------------------------------------------------------
    ; ARGUMENTS
    ;
    ; filehandle%   : Self explanatory.
    ;
    ; strng$        : String to be outputted to the file.
    ;==========================================================================

    For i% = 1 To Len(strng$)
        WriteByte( filehandle%, Asc( Mid(strng$,i%,1) ) )
    Next
End Function

;------------------------------------------------------------------------------
; CRC32 functions adapted from Recursive CRC32 Builder by Odin Jensen (ozak).
; http://www.blitzbasic.com/codearcs/codearcs.php?code=1457
;------------------------------------------------------------------------------
Function pngExporterInitCRC32%()
    ;==========================================================================
    ; DESCRIPTION
    ;
    ; Precomputes the CRC32 lookup table and stores it in a bank.
    ;--------------------------------------------------------------------------
    ; RETURNS
    ;
    ; Handle to a 256 byte bank containing a CRC32 lookup table or 0 if failed.
    ;==========================================================================

    bank%=CreateBank(256*4)

    If bank%
        For i%=0 To 255
            value%=i%

            For j%=0 To 7
                If (value% And $1) Then
                    value%=(value% Shr 1) Xor $EDB88320
                Else
                    value%=(value% Shr 1)
                EndIf
            Next
        
            PokeInt bank%,i%*4,value%
        Next
    End If 

    Return bank%
  
End Function

Function pngExporterCalcCRC32%(crcbank%,databank%)
    ;==========================================================================
    ; DESCRIPTION
    ;
    ; Computes the CRC32 value for data stored in a bank.
    ;--------------------------------------------------------------------------
    ; PARAMETERS
    ;
    ; crcbank%  : Handle to a bank containing precomputed CRC32 lookup data.
    ;
    ; databank% : Handle to a bank containing the data you wish a CRC32 value
    ;           : to be computed for.
    ;--------------------------------------------------------------------------
    ; RETURNS
    ;
    ; 32 bit CRC for the data held in the bank.
    ;==========================================================================

    crc%=$FFFFFFFF
    length%=BankSize(databank%)-1
  
    For i%=0 To length%
        byte%=PeekByte(databank%,i%)
        crc%=(crc% Shr 8) Xor (PeekInt(crcbank%,(byte% Xor (crc% And $ff))*4))
    Next
    
    Return ~crc%
    
End Function



VP(Posted 2005) [#11]
Folks, I have a quandry. I've got to implement zlib compression in order to encode an image as a PNG. Whilst I am already doing a fair amount of wheel re-inventing by writing a PNG exporter natively in Blitz, should I really re-invent (part of) zlib in order to proceed?

If I do press ahead and implement the zlib part in Blitz, I would appreciate a little help from someone a little more gifted ;) (i.e. someone else write the zlib compression function).


VP(Posted 2005) [#12]
*bump*

Nobody showing much interest here... you guys still alive?


John Pickford(Posted 2005) [#13]
I'm here. I'll give the code a try when I have a moment.


D4NM4N(Posted 2005) [#14]
Thanx all


markcw(Posted 2005) [#15]
hey vinylpusher, this is kind of generous of ya!

anyway seems nobodys interested, but me, i could put trying to write the zlib stuff on my 'mental to-do shelf' for a while and you should pop this into code archives, seems quite good, you know.

So ehh, i get round to it later (i'm busy writing stuff for my game at the moment) but this is kinda fun, if you like image file format stuff that is. personally, i only got as far as the bmp stuff, then all those compression formats kinda put me off, you know. but ehh, seems like there is adequate documentation for png... sooo that would be useful. maybe... anyway, cheers.


VP(Posted 2005) [#16]
somethingfunky: Dude, I really appreciate any support you can give. Even pseudocode or a link to useful zlib info would be received with thanks.

John Pickford: Thanks, I would be happy to receive criticism and advice on moving this forward. Any code you can come up with would also be marvellous ;)

All: be advised, the CRC calculation is wrong-o. PNG requires the CRC be calculated for the whole chunk (header and data) and not just the data. I'm only CRC'ing the data at the moment. Will be fixed this weekend.


markcw(Posted 2005) [#17]
wellll, in that case me goes to bookmark library and whips out...

http://www.libpng.org/pub/png/spec/iso/

i think you'll prolly know this one already, but you sound like maybe, you don't. now for the zlib page its...

http://www.gzip.org/zlib/rfc-zlib.html

pretty obvious though as the links there on the first page anyway. good luck, this would be a nice thing to have anyway wouldn't it! i'll be looking into it later in the month anyway, so there you go, a little help goes a long way, they say. :)


VP(Posted 2005) [#18]
muk: Thanks, I've got the PNG spec printed out already ;)

I had a quick scan of the zlib stuff already. It scared me off but I'll have to revisit it I'm sure.


To implement PNG you need zlib, to implement zlib you need Adler-32. All in all, a real PITA and laborious conversion to any other language (Blitz included). At least the Adler-32 function has a C example, which is nice and easy to convert.


ImaginaryHuman(Posted 2005) [#19]
I suggest you look on the internet and find sites which explain how the zlid compression works, rather than trying to figure it out by looking at computer sourcecode, which might not really represent the algorithm very well. It's probably simpler than it appears.


VP(Posted 2005) [#20]
It sounds simple. I can understand the theory behind it. Compression theory hasn't changed since I read an article about it back when Amigas were more powerful than PC's.

I will get around to doing it. I just need to have a few hours uninterrupted creative time :)


octothorpe(Posted 2005) [#21]
It hurt my eyes too - too much optimization! Perhaps the RFC referred to in the zlib FAQ would be helpful to you?

http://www.zlib.net/zlib_faq.html#faq30

Also

http://www.zlib.net/feldspar.html

Although these articles are geared towards developers wanting to deflate things rather than inflate them, they do describe the format of zlib-compressed data, which may be helpful in understanding how to compress.

I don't mean to throw pins at your bubble, but there is a zlib DLL. Might there be a libpng DLL too?


VP(Posted 2005) [#22]
Thanks octo, I've already had a read of those articles. Deflating is what is needed for the PNG exporter ;)

There most likely is a DLL for this, but where's the challenge in using a DLL? :D