flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [fasmg] PNG file generation from pixel data

Author
Thread Post new topic Reply to topic
bitRAKE



Joined: 21 Jul 2003
Posts: 4042
Location: vpcmpistri
bitRAKE 13 Apr 2022, 20:55
Code:
include 'unPNG.inc'

PNG.ALPHA       := 0    ; change to run second test
PNG.WIDTH       := 256
PNG.HEIGHT      := 256

virtual at 0
PNG.DATA::
        repeat PNG.HEIGHT,y:0
                repeat PNG.WIDTH,x:0
                        if PNG.ALPHA
                                db x,y,128,(x+y) shr 1 ; RGBA test
                        else
                                db x,y,128 ; RGB test
                        end if
                end repeat
        end repeat
end virtual    
unPNG.inc
Code:
; PNG.ALPHA     : indicate if pixel data is 24-bit (RGB) or 32-bit (RGBA)
; PNG.WIDTH     : > 0 and < 16383
; PNG.HEIGHT    : > 0
; PNG.DATA      : an address space defining pixel data

if ~ definite PNG ; once
PNG := 1

virtual at 0
crc32:: ; the little table
dd 0,0x1DB71064,0x3B6E20C8,0x26D930AC,0x76DC4190,0x6B6B51F4,0x4DB26158,0x5005713C,0xEDB88320,0xF00F9344,0xD6D6A3E8,0xCB61B38C,0x9B64C2B0,0x86D3D2D4,0xA00AE278,0xBDBDF21C
end virtual

namespace PNG

macro Chunk type*,ddata&
        local dstart,dend,CRC
        dd (dend - dstart - 4) bswap 4
        dstart:
                db type
                assert ($ - dstart) = 4 ; chunk id is four bytes
                match ,ddata
                else
                        db ddata
                end match
        dend:
        CRC = 0xFFFFFFFF
        repeat $ - dstart
                load b:1 from dstart+%-1
                CRC = CRC xor b
                load t:4 from crc32:(CRC and 15) shl 2
                CRC = (CRC shr 4) xor t
                load t:4 from crc32:(CRC and 15) shl 2
                CRC = (CRC shr 4) xor t
        end repeat
        dd (CRC xor 0xFFFFFFFF) bswap 4
end macro


format binary as 'png'
db 89h,'PNG',13,10,26,10

virtual at 0
        dd WIDTH bswap 4
        dd HEIGHT bswap 4
        assert ALPHA and 1 = ALPHA ; 0 or 1
        ; Depth=8, Color=True color with/without alpha
        ; Compression=Deflate, Filter=No, Interlace=No
        db 8,2+(ALPHA shl 2),0,0,0
        load dat:$ from 0
end virtual
Chunk 'IHDR',dat

virtual at 0
        ; for Adler-32 checksum of uncompressed data:
        s1 = 1 ; sum of all bytes mod 65521
        s2 = 0 ; sum of all s1 mod 65521

        if ALPHA
                pitch = 4 * WIDTH
        else
                pitch = 3 * WIDTH
        end if

        db 78h,1 ; deflate data, blocked by horizontal lines
        repeat HEIGHT,h:0
                if % = %%
                        db 1
                else
                        db 0
                end if
                dw pitch+1, 0xFFFF xor (pitch+1)
                load dat:pitch from DATA:pitch*h
idata.h:
                db 0
                db dat
                repeat pitch+1
                        load b:1 from idata.h + % - 1
                        s1 = (s1 + b) mod 65521
                        s2 = (s2 + s1) mod 65521
                end repeat
        end repeat
        dd ((s2 shl 16) or s1) bswap 4
        load dat:$ from 0
end virtual
Chunk 'IDAT',dat

Chunk 'IEND'

end namespace ; PNG

end if ; PNG    
This produces an uncompressed image file that in most cases some post processing with OptiPNG or pngcrush is desired.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 13 Apr 2022, 20:55
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4042
Location: vpcmpistri
bitRAKE 14 Apr 2022, 07:15
Logistic Map
Code:
PNG.ALPHA       := 0    ; change to run second test
PNG.WIDTH       := 256*3
PNG.HEIGHT      := 256

virtual ;at 0
PNG.DATA::
        ; start with black canvas
        if PNG.ALPHA
                dd PNG.HEIGHT*PNG.WIDTH dup ?
        else
                db PNG.HEIGHT*PNG.WIDTH dup (?,?,?)
        end if

db -1 ; force size?

        LogMap  (1 shl 32),(4 shl 32)
end virtual

struc GET x*,y*
        if PNG.ALPHA
                load .:4 from PNG.DATA:4*(x + y*PNG.WIDTH)
        else
                load .:3 from PNG.DATA:3*(x + y*PNG.WIDTH)
        end if
end struc
struc SET x*,y*
        if PNG.ALPHA
                store .:4 at PNG.DATA:4*(x + y*PNG.WIDTH)
        else
                store .:3 at PNG.DATA:3*(x + y*PNG.WIDTH)
        end if
end struc

; y coordinate always mapped to range (0,1)
; 0 < λ_min < λ_max < 4 shl S
macro LogMap λ_min*, λ_max*, S:32
        local Δλ,ΔFn,λ,Fn,x,y,c
        Δλ    := (λ_max - λ_min)/PNG.WIDTH
        ΔFn    := ((1 shl S)+(PNG.HEIGHT - 1))/PNG.HEIGHT

        λ = λ_min
        repeat PNG.WIDTH,x:0
                c = 0
                Fn = 1 shl (S-1) ; 0.5
                while c and $FF <> $FF
                        Fn = (λ * ((Fn * ((1 shl S) - Fn)) shr S)) shr S
                        y = Fn/ΔFn
                        c GET x,y
                        c = c + 0x010101
                        c SET x,y
                end while
                λ = λ + Δλ
        end repeat
end macro

include 'unPNG.inc'    
Edit: fix the rounding to prevent overflow in the inner loop. Greater precision creates much smoother images. Dropping down to 16-bit can produce rougher images quite fast.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup


Last edited by bitRAKE on 14 Apr 2022, 10:35; edited 1 time in total
Post 14 Apr 2022, 07:15
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4042
Location: vpcmpistri
bitRAKE 14 Apr 2022, 08:28
changed the pixel get/set routines to rein in (not reign in, lol) memory usage:
Code:
calminstruction (pixel) GET x*, y*
        compute size, 3+PNG.ALPHA
        compute offset, size * (x + y*PNG.WIDTH)
        arrange command, =load pixel:size =from =PNG.=DATA:offset
        assemble command
end calminstruction
calminstruction (pixel) SET x*, y*
        compute size, 3+PNG.ALPHA
        compute offset, size * (x + y*PNG.WIDTH)
        arrange command, =store pixel:size =at =PNG.=DATA:offset
        assemble command
end calminstruction    


Some larger images posted on github.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 14 Apr 2022, 08:28
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.