Ooops
October 28, 2020, 05:15:47 AM

Author Topic: [bmx] SavePixmapDDS by JoshK [ 1+ years ago ]  (Read 1312 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] SavePixmapDDS by JoshK [ 1+ years ago ]
« on: June 29, 2017, 12:28:43 AM »
Title : SavePixmapDDS
Author : JoshK
Posted : 1+ years ago

Description : This routine will save a pixmap in .dds format.  The DXTC1, 3, and 5 formats are supported, as well as the uncompressed lossless format.  Optional mipmaps can be generated with wrapping interpolation, or the image can be clamped on either axes.  The mask correction flag will eliminate dark edges of masked images.  This is based on the original .bb code here:
<a href="http://blitzmax.com/codearcs/codearcs.php?code=1813" target="_blank">http://blitzmax.com/codearcs/codearcs.php?code=1813[/url]


Code :
Code: BlitzMax
  1. SuperStrict
  2.  
  3. Import brl.pixmap
  4. Import brl.bank
  5.  
  6. Const DDS_MIPMAPS:Int=1
  7. Const DDS_MASKCORRECTION:Int=2
  8. Const DDS_CLAMPMIPMAPSX:Int=4
  9. Const DDS_CLAMPMIPMAPSY:Int=8
  10.  
  11. Rem
  12. bbdoc:
  13. Description:
  14. This function saves a pixmap as a DDS file.
  15. Set the dxt mode with the format parameter 1. 3, Or 5 (Or 0 For uncompressed RGB only).
  16. The optional mipmaps flag can be set To 0 To save the first mipmap only.  The Default value is True.
  17. <p>Format:
  18. <br>0 - Uncompressed
  19. <br>1 - DXTC1 (RGB)
  20. <br>3 - DXTC3 (RGBA)
  21. <br>5 - DXTC5 (RGBA)
  22. <p>Flags:
  23. <br>DDS_MIPMAPS - generates mipmaps
  24. <br>DDS_MASKCORRECTION - eliminates dark edges on masked images
  25. <br>DDS_CLAMPMIPMAPSX - horizontally clamps mipmap generation
  26. <br>DDS_CLAMPMIPMAPSY - vertically clamps mipmap generation
  27. EndRem
  28. Function SavePixmapDDS:Int(pixmap:TPixmap,url:Object,format:Int=5,flags:Int=DDS_MIPMAPS)
  29.        
  30.         'Constants
  31.         Const pf_alphapix%=$00000001
  32.        
  33.         'dwFlags constants
  34.         Const DDSD_CAPS:Int=$00000001,DDSD_HEIGHT:Int=$00000002,DDSD_WIDTH:Int=$00000004
  35.         Const DDSD_PITCH:Int=$00000008,DDSD_PIXELFORMAT:Int=$00001000
  36.         Const DDSD_MIPMAPCOUNT:Int=$00020000,DDSD_LINEARSIZE:Int=$00080000
  37.         Const DDSD_DEPTH:Int=$00800000,DDPF_ALPHAPIXELS:Int=$00000001
  38.         Const DDPF_FOURCC:Int=$00000004,DDPF_RGB:Int=$00000040
  39.        
  40.         'dwCaps1 constants
  41.         Const DDSCAPS_COMPLEX:Int=$00000008,DDSCAPS_TEXTURE:Int=$00001000
  42.         Const DDSCAPS_MIPMAP:Int=$00400000
  43.        
  44.         'dwCaps2 constants
  45.         Const DDSCAPS2_CUBEMAP:Int=$00000200,DDSCAPS2_CUBEMAP_POSITIVEX:Int=$00000400
  46.         Const DDSCAPS2_CUBEMAP_NEGATIVEX:Int=$00000800
  47.         Const DDSCAPS2_CUBEMAP_POSITIVEY:Int=$00001000
  48.         Const DDSCAPS2_CUBEMAP_NEGATIVEY:Int=$00002000
  49.         Const DDSCAPS2_CUBEMAP_POSITIVEZ:Int=$00004000
  50.         Const DDSCAPS2_CUBEMAP_NEGATIVEZ:Int=$00008000,DDSCAPS2_VOLUME:Int=$00200000
  51.        
  52.         'Locals
  53.         Local stream:TStream
  54.         Local dwwidth:Int,dwheight:Int,flags1:Int,flags2:Int,caps1:Int,caps2:Int,bpp:Int,pitch:Int,sizebytes:Int,w:Int,h:Int,mipsize:Int
  55.         Local bsize:Int,bindex:Int,fourcc:Int,hdds:TBank
  56.         Local i:Int,x:Int,y:Int,offset:Int,mipoffset:Int,ix:Int,iy:Int,argb:Int
  57.         Local color:Int,color0:Int,color1:Int,color2:Int,color3:Int,color4:Int,color5:Int,color6:Int,color7:Int
  58.         Local d0:Int,d1:Int,d2:Int,d3:Int,d4:Int,d5:Int,d6:Int,d7:Int,texel:Int,a:Int
  59.         Local sclX:Float, sclY:Float   
  60.         Local width:Int=PixmapWidth(pixmap)
  61.         Local height:Int=PixmapHeight(pixmap)
  62.         Local pixmapbuf:TPixmap,c:Int
  63.         Local mips:Int
  64.         Local bytesC:Int
  65.         Local alphaispresent:Int=False,n:Int
  66.         Local mipmaps:Int,maskcorrection:Int
  67.        
  68.         'Options
  69.         If (DDS_MIPMAPS & flags) mipmaps=True
  70.         If (DDS_MASKCORRECTION & flags) maskcorrection=True
  71.        
  72.         'Mask correction for first mipmap
  73.         If maskcorrection
  74.                 pixmap=PixmapFilterMaskCorrection(pixmap)
  75.         EndIf
  76.        
  77.         'Open stream
  78.         stream=WriteStream(url)
  79.         If Not stream Return False
  80.        
  81.         'No format specified, so take a guess
  82.         If format=-1
  83.                 Select pixmap.format
  84.                         Case PF_A8,PF_RGBA8888,PF_BGRA8888
  85.                                 format=5
  86.                         Default
  87.                                 format=1
  88.                 EndSelect
  89.         EndIf
  90.        
  91.         Select format
  92.                 Case 0
  93.                         Select pixmap.format
  94.                                 Case PF_A8,PF_RGBA8888,PF_BGRA8888
  95.                                         alphaispresent=True
  96.                                 Default
  97.                                         alphaispresent=False
  98.                         EndSelect
  99.                 Case 2,3,4,5
  100.                         alphaispresent=True
  101.                 Default
  102.                         alphaispresent=False
  103.         EndSelect
  104.        
  105.         'Convert to RGBA
  106.         If pixmap.format<>PF_RGBA8888
  107.                 pixmap=ConvertPixmap(pixmap,PF_RGBA8888)
  108.         EndIf
  109.        
  110.         'Calculate mipmap count
  111.         If mipmaps
  112.                 mipmaps=Int(Log(Max(width,height))/Log(2)+1.0+0.5)
  113.         Else
  114.                 mipmaps=1
  115.         EndIf
  116.        
  117.         'Calculate DWORD-aligned width And height, multiple of 4
  118.         dwwidth=(width+3)/4*4
  119.         dwheight=(height+3)/4*4
  120.        
  121.         'Default flags For all formats
  122.         flags1=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT
  123.         caps1=DDSCAPS_TEXTURE
  124.        
  125.         'Weird hack
  126.         Local alphaimg:TPixmap
  127.  
  128.         If alphaispresent=True And format>1
  129.                 alphaimg=CreatePixmap(width,height,PF_RGB888)
  130.                 For x=0 To pixmap.width-1
  131.                         For y=0 To pixmap.height-1
  132.                                 color=ReadPixel(pixmap,x,y)
  133.                                 a=(color & $FF000000) Shr 24
  134.                                 WritePixel alphaimg,x,y,a+(a Shl 8)+(a Shl 16)'+(a Shl 24)
  135.                         Next
  136.                 Next  
  137.         EndIf
  138.        
  139.        
  140.         '================================================
  141.         'Calculate data size
  142.         '================================================
  143.        
  144.         'Uncompressed
  145.         If format=0
  146.                 flags1=flags1|DDSD_PITCH
  147.                 If alphaispresent
  148.                         flags2=DDPF_RGB|$00000001
  149.                         bpp=32
  150.                 Else
  151.                         flags2=DDPF_RGB
  152.                         bpp=24
  153.                 EndIf
  154.                
  155.                 'Determine Size of Bytes For each mipmap And add
  156.                 w=dwwidth
  157.                 h=dwheight
  158.                 For i=1 To mipmaps
  159.                         mipsize=Max(1,w)*(bpp/8) 'DWORD-aligned scanline
  160.                         sizebytes=sizebytes+mipsize*h
  161.                         w=Max(1,w/2)
  162.                         h=Max(1,h/2)
  163.                         If i=1 pitch=mipsize
  164.                 Next
  165.        
  166.         'Compressed
  167.         Else
  168.                
  169.                 flags1:|DDSD_LINEARSIZE
  170.                 flags2=DDPF_FOURCC
  171.                
  172.                 'Determine Size of Bytes For each mipmap And add
  173.                 If format>1
  174.                         bytesC=16
  175.                 Else
  176.                         bytesC=8
  177.                 EndIf
  178.                 w=dwwidth
  179.                 h=dwheight
  180.                 For i=1 To mipmaps
  181.                         mipsize=(Max(1,w/4)*Max(1,h/4))*bytesC
  182.                         sizebytes=sizebytes+mipsize
  183.                         w=Max(1,w/2)
  184.                         h=Max(1,h/2)
  185.                         'Linear size
  186.                         If i=1 pitch=mipsize
  187.                 Next
  188.                 'pitch=sizebytes
  189.                 bsize=2
  190.                 bindex=0
  191.                 If format>1
  192.                         bsize=4
  193.                         bindex=8 'block values
  194.                 EndIf
  195.                 If format=1 fourcc=MakeFourCC("D","X","T","1")
  196.                 If format=2 fourcc=MakeFourCC("D","X","T","2")
  197.                 If format=3 fourcc=MakeFourCC("D","X","T","3")
  198.                 If format=4 fourcc=MakeFourCC("D","X","T","4")
  199.                 If format=5 fourcc=MakeFourCC("D","X","T","5")
  200.                
  201.         EndIf
  202.        
  203.         '================================================
  204.         '
  205.         '================================================
  206.        
  207.         'Bank To store DDS
  208.         hdds=CreateBank(128+sizebytes)
  209.         For n=0 To hdds.size()-1
  210.                 hdds.PokeByte n,0
  211.         Next
  212.        
  213.         '============================================
  214.         'DDS File Header
  215.         '============================================
  216.        
  217.         'Magic Value, DWORD
  218.         PokeInt hdds,0,MakeFourCC("D","D","S"," ") 'dwMagic, "DDS "
  219.        
  220.         'Surface Format Header, DDSURFACEDESC2 structure
  221.         PokeInt hdds,4,124 'dwSize, SizeOf(DDSURFACEDESC2)
  222.         PokeInt hdds,8,flags1 'dwFlags, flags To indicate valid fields
  223.         PokeInt hdds,12,dwheight 'dwHeight, pixmap height in pixels
  224.         PokeInt hdds,16,dwwidth 'dwWidth, pixmap width in pixels
  225.         PokeInt hdds,20,pitch 'dwPitchOrLinearSize, pitch Or linear size
  226.         PokeInt hdds,24,0 'dwDepth, volume textures Not supported Until DX 8.0
  227.         PokeInt hdds,28,mipmaps 'dwMipMapCount, For items with mipmap levels
  228.         For i=1 To 11
  229.                 PokeInt hdds,(i*4)+28,0 'dwReserved[11]
  230.         Next
  231.        
  232.         'DDPIXELFORMAT structure
  233.         PokeInt hdds,76,32 'dwSize, SizeOf(DDPIXELFORMAT)
  234.         PokeInt hdds,80,flags2 'dwFlags, flags To indicate valid fields
  235.         PokeInt hdds,84,fourcc 'dwFourCC
  236.         PokeInt hdds,88,bpp 'dwRGBBitCount
  237.         PokeInt hdds,92,$00FF0000 'dwRBitMask
  238.         PokeInt hdds,96,$0000FF00 'dwGBitMask
  239.         PokeInt hdds,100,$000000FF 'dwBBitMask
  240.         PokeInt hdds,104,$FF000000 'dwRGBAlphaBitMask
  241.        
  242.         'DDCAPS2 structure
  243.         PokeInt hdds,108,caps1 'dwCaps1, flags To indicate valid fields
  244.         PokeInt hdds,112,caps2 'dwCaps2, flags To indicate valid fields
  245.         PokeInt hdds,116,0 'dwReserved
  246.         PokeInt hdds,120,0 'dwReserved
  247.         PokeInt hdds,124,0 'dwReserved
  248.         mipoffset=128 'Default Offset after Header
  249.        
  250.         '==================================================
  251.         'Save texture data
  252.         '==================================================
  253.        
  254.         '==================================================
  255.         'Uncompressed
  256.         '==================================================
  257.        
  258.         If format=0
  259.                 For mips=1 To mipmaps 'Loop of optional mipmap count   
  260.                         If mips>1
  261.                                 'Store offset
  262.                                 mipoffset=offset+pitch
  263.                                 'Half of dimension
  264.                                 w=Max(1,width/2)
  265.                                 h=Max(1,height/2)
  266.                                 sclX:Float=Float(w)/Float(width)
  267.                                 sclY:Float=Float(h)/Float(height)
  268.                                 pixmap=HalfSizePixmap(pixmap,maskcorrection)
  269.                                 width=w
  270.                                 height=h
  271.                                 pitch=width*(bpp/8)
  272.                         EndIf
  273.                        
  274.                         'Create Buffer
  275.                         For y=0 To height-1
  276.                                 offset=mipoffset+pitch*y 'Next DWORD-aligned scanline
  277.                                 For x=0 To width-1
  278.                                         argb=pixmap.ReadPixel(x,y)
  279.                                         PokeByte hdds,offset+(x*(bpp/8))+0,(argb & $000000FF)'b
  280.                                         PokeByte hdds,offset+(x*(bpp/8))+1,(argb & $0000FF00) Shr 8'g
  281.                                         PokeByte hdds,offset+(x*(bpp/8))+2,(argb & $00FF0000) Shr 16'r
  282.                                         If alphaispresent
  283.                                                 PokeByte hdds,offset+(x*(bpp/8))+3,(argb & $FF000000) Shr 24'a
  284.                                         EndIf
  285.                                 Next
  286.                         Next
  287.                 Next
  288.        
  289.         '==================================================
  290.         'Compressed
  291.         '==================================================
  292.        
  293.         Else 'Compressed
  294.  
  295.                 For mips=1 To mipmaps 'Loop of optional mipmap count  
  296.                         If mips>1
  297.                                 'Store offset
  298.                                 mipoffset=offset+dwwidth*bsize
  299.                                 'Half of dimension
  300.                                 w=Max(1,width/2) ; h=Max(1,height/2)
  301.                                 sclX#=Float(w)/Float(width) ; sclY#=Float(h)/Float(height)
  302.                                 pixmap=HalfSizePixmap(pixmap,maskcorrection)
  303.                                 'SavePixmapPNG pixmap,mips+".png"
  304.                                 'Scalepixmap pixmap,sclX#,sclY#
  305.                                 'If Not the same pixmap-handle scale the Alpha pixmap too
  306.                                 If alphaimg<>Null
  307.                                         alphaimg=HalfSizePixmap(alphaimg)'Scalepixmap alphaimg,sclX#,sclY#
  308.                                 EndIf
  309.                                 width=w
  310.                                 height=h
  311.                                 'Calculate DWORD-aligned width And height, multiple of 4
  312.                                 dwwidth=(width+3)/4*4
  313.                                 dwheight=(height+3)/4*4
  314.                         EndIf
  315.  
  316.                         'Create Buffer
  317.                         For y=0 To dwheight-1 Step 4
  318.                                 offset=mipoffset+Max(1,dwwidth/4)*(y*bsize) 'Next block-aligned scanline
  319.                                 For x=0 To dwwidth-1 Step 4
  320.                                        
  321.                                         Select format
  322.                                                
  323.                                                 Case 2,3'DXT2,DXT3
  324.                                                         'Find color in Alpha block And set each Alpha texel
  325.                                                         For iy=0 To 3
  326.                                                                 For ix=0 To 3
  327.                                                                         If x+ix<width And y+iy<height 'Not out of bounds
  328.                                                                                 argb=ReadPixel(alphaimg,ix+x,iy+y) 'Use Alpha map
  329.                                                                         Else
  330.                                                                                 argb=0 'Black
  331.                                                                         EndIf
  332.                                                                         i=ColorHighest(argb)/17.0+0.5
  333.                                                                         If i>15 i=15 'Alpha color 0..15
  334.                                                                         texel=PeekShort(hdds,offset+(x*bsize)+(iy*2))|(i Shl (ix*4))
  335.                                                                         PokeShort hdds,offset+(x*bsize)+(iy*2),texel 'wAlphaTexels[4]
  336.                                                                 Next
  337.                                                         Next
  338.                                                
  339.                                                 Case 4,5'DXT4,DXT5
  340.                                                         'Find highest And lowest colors in Alpha block
  341.                                                         color0=0  ; color1=$FFFFFFFF 'color0 highest
  342.                                                         For iy=0 To 3
  343.                                                                 For ix=0 To 3
  344.                                                                         If x+ix<width And y+iy<height 'Not out of bounds
  345.                                                                         argb=ReadPixel(alphaimg,ix+x,iy+y) 'Use Alpha map
  346.                                                                         If ColorHighest(argb)>ColorHighest(color0) color0=argb
  347.                                                                         If ColorHighest(argb)<ColorHighest(color1) color1=argb
  348.                                                                         EndIf
  349.                                                                 Next
  350.                                                         Next
  351.                                                         'Make sure color0 is the highest
  352.                                                         If color1>color0
  353.                                                                 i=color0
  354.                                                                 color0=color1
  355.                                                                 color1=i 'Switch order
  356.                                                         EndIf
  357.                                                         PokeByte hdds,offset+(x*bsize),ColorHighest(color0) 'bAlpha0
  358.                                                         PokeByte hdds,offset+(x*bsize)+1,ColorHighest(color1) 'bAlpha1
  359.                                                         'Set each Alpha texel in block To closest Alpha
  360.                                                         color0=ColorHighest(color0) ; color1=ColorHighest(color1)
  361.                                                         For iy=0 To 3
  362.                                                                 For ix=0 To 3
  363.                                                                         If x+ix<width And y+iy<height 'Not out of bounds
  364.                                                                                 argb=ReadPixel(alphaimg,ix+x,iy+y) 'Use Alpha map
  365.                                                                         Else
  366.                                                                                 argb=0 'black
  367.                                                                         EndIf
  368.                                                                         If color0>color1 '8-Alpha block
  369.                                                                                 color2=((6*color0)+color1)/7
  370.                                                                                 color3=((5*color0)+(2*color1))/7
  371.                                                                                 color4=((4*color0)+(3*color1))/7
  372.                                                                                 color5=((3*color0)+(4*color1))/7
  373.                                                                                 color6=((2*color0)+(5*color1))/7
  374.                                                                                 color7=(color0+(6*color1))/7
  375.                                                                         Else '6-Alpha block
  376.                                                                                 color2=((4*color0)+color1)/5
  377.                                                                                 color3=((3*color0)+(2*color1))/5
  378.                                                                                 color4=((2*color0)+(3*color1))/5
  379.                                                                                 color5=(color0+(4*color1))/5
  380.                                                                                 color6=0
  381.                                                                                 color7=255
  382.                                                                         EndIf
  383.                                                                         d0=Abs(color0-ColorHighest(argb)) 'Get differences
  384.                                                                         d1=Abs(color1-ColorHighest(argb))
  385.                                                                         d2=Abs(color2-ColorHighest(argb))
  386.                                                                         d3=Abs(color3-ColorHighest(argb))
  387.                                                                         d4=Abs(color4-ColorHighest(argb))
  388.                                                                         d5=Abs(color5-ColorHighest(argb))
  389.                                                                         d6=Abs(color6-ColorHighest(argb))
  390.                                                                         d7=Abs(color7-ColorHighest(argb))
  391.                                                                         i=0 ; If d1<d0 Then d0=d1 ; i=1 'Find closest color
  392.                                                                         If d2<d0 Then d0=d2 ; i=2
  393.                                                                         If d3<d0 Then d0=d3 ; i=3
  394.                                                                         If d4<d0 Then d0=d4 ; i=4
  395.                                                                         If d5<d0 Then d0=d5 ; i=5
  396.                                                                         If d6<d0 Then d0=d6 ; i=6
  397.                                                                         If d7<d0 Then d0=d7 ; i=7
  398.                                                                         If iy<2 'Upper 24bit-block
  399.                                                                                 texel=PeekInt(hdds,offset+(x*bsize)+2) & $00FFFFFF
  400.                                                                                 If iy=0 texel=texel|(i Shl (ix*3))
  401.                                                                                 If iy=1 texel=texel|(i Shl ((ix*3)+12))
  402.                                                                                 PokeInt hdds,offset+(x*bsize)+2,texel & $00FFFFFF
  403.                                                                                 Else 'Lower 24bit-block
  404.                                                                                 texel=PeekInt(hdds,offset+(x*bsize)+5) & $00FFFFFF
  405.                                                                                 If iy=2 texel=texel|(i Shl (ix*3))
  406.                                                                                 If iy=3 texel=texel|(i Shl ((ix*3)+12))
  407.                                                                                 PokeInt hdds,offset+(x*bsize)+5,texel & $00FFFFFF
  408.                                                                         EndIf
  409.                                                                 Next
  410.                                                         Next
  411.                                         EndSelect
  412.                                        
  413.                                         'Find highest And lowest colors in texel block
  414.                                         'Better algorithm might be To find the most common highest/lowest colors
  415.                                         color0=0 ; color1=$FFFFFFFF 'color0 highest
  416.                                         For iy=0 To 3
  417.                                                 For ix=0 To 3
  418.                                                         If x+ix<width And y+iy<height 'Not out of bounds
  419.                                                                 argb=ReadPixel(pixmap,ix+x,iy+y)
  420.                                                                 If ColorTotal(argb)>ColorTotal(color0) color0=argb
  421.                                                                 If ColorTotal(argb)<ColorTotal(color1) color1=argb
  422.                                                         EndIf
  423.                                                 Next
  424.                                         Next
  425.                                         'DebugLog argb
  426.                                         'Make sure color0 is the highest
  427.                                         If color1>color0 Then
  428.                                                 i=color0
  429.                                                 color0=color1
  430.                                                 color1=i 'Switch order
  431.                                         EndIf
  432.                                         'Switch order, color1 highest To indicate DXT1a
  433.                                         If format=1 And alphaimg<>Null 'DXT1a, using Alpha bit
  434.                                                 i=color0
  435.                                                 color0=color1
  436.                                                 color1=i
  437.                                         EndIf
  438.                                         'DebugLog (color0)+", "+(color1)
  439.                                         'DebugLog Color565(color0)+", "+Color565(color1)
  440.                                         PokeShort hdds,offset+(x*bsize)+bindex,Color565(color0) 'wColor0
  441.                                         PokeShort hdds,offset+(x*bsize)+bindex+2,Color565(color1) 'wColor1
  442.                                         'Set each texel in block To closest color
  443.                                         color0=ColorTotal(color0) ; color1=ColorTotal(color1)
  444.                                         For iy=0 To 3
  445.                                                 For ix=0 To 3
  446.                                                         If x+ix<width And y+iy<height 'Not out of bounds
  447.                                                                 argb=ReadPixel(pixmap,ix+x,iy+y)  
  448.                                                         Else
  449.                                                                 argb=0 'Black
  450.                                                         EndIf
  451.                
  452.                                                         If color0>color1 'Four-color block
  453.                                                                 color2=((2*color0)+color1)/3
  454.                                                                 color3=(color0+(2*color1))/3
  455.                                                         Else 'Three-color block
  456.                                                                 color2=(color0+color1)/2
  457.                                                                 color3=3*16 'Max transparent color
  458.                                                         EndIf
  459.                                                         d0=Abs(color0-ColorTotal(argb)) 'Get differences
  460.                                                         d1=Abs(color1-ColorTotal(argb))
  461.                                                         d2=Abs(color2-ColorTotal(argb))
  462.                                                         d3=Abs(color3-ColorTotal(argb))
  463.                                                         i=0 ; If d1<d0 Then d0=d1 ; i=1 'Find closest color
  464.                                                         If d2<d0 Then d0=d2 ; i=2
  465.                                                         If d3<d0 Then d0=d3 ; i=3
  466.                                                         If color0>color1 And Abs(color2-color3)<8
  467.                                                                 If i=3 i=2 'Close And wrong order so use color2
  468.                                                         EndIf
  469.                                                         If format=1 And alphaimg<>Null 'DXT1a, using Alpha bit
  470.                                                                 If i=3 i=2 'No color3 so use color2
  471.                                                         EndIf
  472.                                                         If x+ix>width-1 Or y+iy>height-1 'Out of bounds
  473.                                                                 'Find lowest color
  474.                                                                 If color0<color1
  475.                                                                         i=0
  476.                                                                 Else
  477.                                                                         i=1
  478.                                                                 EndIf
  479.                                                         EndIf
  480.                                                         texel=PeekByte(hdds,offset+(x*bsize)+bindex+4+iy)|(i Shl (ix*2))
  481.                                                         PokeByte hdds,offset+(x*bsize)+bindex+4+iy,texel 'bTexels[4]
  482.                                                 Next
  483.                                         Next
  484.                                        
  485.                                         'Find color in texel block And set each Alpha texel
  486.                                         If format=1 And alphaimg<>Null 'DXT1a, using Alpha bit
  487.                                                 For iy=0 To 3
  488.                                                         For ix=0 To 3
  489.                                                                 If x+ix<width And y+iy<height 'Not out of bounds
  490.                                                                         argb=ReadPixel(alphaimg,ix+x,iy+y) 'Use Alpha map
  491.                                                                         color3=3*16 'Max transparent color
  492.                                                                         If ColorTotal(argb)<color3 'Set Alpha texel
  493.                                                                                 texel=PeekByte(hdds,offset+(x*bsize)+bindex+4+iy) | (3 Shl (ix*2))
  494.                                                                                 PokeByte hdds,offset+(x*bsize)+bindex+4+iy,texel 'bTexels[4]
  495.                                                                         EndIf
  496.                                                                 EndIf      
  497.                                                         Next
  498.                                                 Next
  499.                                         EndIf
  500.                                 Next
  501.                         Next
  502.                 Next
  503.         EndIf
  504.  
  505.         stream.WriteBytes hdds.buf(),hdds.size()
  506.         stream.close()
  507.        
  508.         Return True
  509. EndFunction
  510.  
  511. Private
  512.  
  513. Function MakeFourCC:Int(c0$,c1$,c2$,c3$)
  514.         Return (Asc(c0$)+(Asc(c1$) Shl 8)+(Asc(c2$) Shl 16)+(Asc(c3$) Shl 24))
  515. EndFunction
  516.  
  517. Function ColorHighest:Int(argb:Int)
  518.         Local r:Int,g:Int,b:Int,a:Int
  519.         r=(argb & $00FF0000) Shr 16
  520.         g=(argb & $0000FF00) Shr 8
  521.         b=(argb & $000000FF)
  522.         If r>g a=r Else a=g
  523.         If b>a a=b
  524.         Return a
  525. EndFunction
  526.  
  527. Function ColorTotal:Int(argb:Int)
  528.         Local r:Int,g:Int,b:Int
  529.         r=(argb & $00FF0000) Shr 16
  530.         g=(argb & $0000FF00) Shr 8
  531.         b=(argb & $000000FF)
  532.         Return (r+g+b) '0..255*3
  533. EndFunction
  534.  
  535. Function Color565:Int(argb:Int)
  536.         Local r:Int,g:Int,b:Int
  537.         r=(argb & $00FF0000) Shr 16
  538.         r=Int((r*31.0/255.0+0.5)) Shl 11 'Bits 11..15
  539.         g=(argb & $0000FF00) Shr 8
  540.         g=Int((g*63.0/255.0+0.5)) Shl 5 'Bits 5..10
  541.         b=(argb & $000000FF)
  542.         b=Int(b*31/255.0+0.5) 'Bits 0..4
  543.         Return (r+g+b)
  544. EndFunction
  545.  
  546. Function ReadPixelA:Int(pixmap:TPixmap,x:Int,y:Int)
  547.         Local color:Int=pixmap.ReadPixel(x,y)
  548.         color=(color & $FF000000) Shr 24
  549.         Return RGBA(color,color,color,color)
  550. EndFunction
  551.  
  552. Function HalfSizePixmap:TPixmap(pixmap:TPixmap,flags:Int=0)
  553.         Local w:Int,h:Int,x:Int,y:Int,result:TPixmap
  554.         w=pixmap.width/2
  555.         h=pixmap.height/2
  556.         If w<1 w=1
  557.         If h<1 h=1
  558.         result=CreatePixmap(w,h,pixmap.format)
  559.         For x=0 To w-1
  560.                 For y=0 To h-1
  561.                         result.WritePixel(x,y,ReadPixel4(pixmap,x*2,y*2,flags))
  562.                 Next
  563.         Next
  564.         If (DDS_MASKCORRECTION & flags)
  565.                 result=PixmapFilterMaskCorrection(result)
  566.         EndIf
  567.         Return result
  568. EndFunction
  569.  
  570. Function RGBA:Int(r:Int,g:Int,b:Int,a:Int)
  571.         Return b+(g Shl 8)+(r Shl 16)+(a Shl 24)
  572. EndFunction
  573.  
  574. Function WrapReadPixel:Int(pixmap:TPixmap,x:Int,y:Int,flags:Int=0)
  575.         If (DDS_CLAMPMIPMAPSX & flags)
  576.                 If x<0 x=0
  577.                 If x>pixmap.width-1 x=pixmap.width-1
  578.         Else
  579.                 While x<0
  580.                         x=pixmap.width-x
  581.                 Wend
  582.                 While x>pixmap.width-1
  583.                         x=pixmap.width-x
  584.                 Wend
  585.         EndIf
  586.         If (DDS_CLAMPMIPMAPSY & flags)
  587.                 If y<0 y=0
  588.                 If y>pixmap.height-1 y=pixmap.height-1
  589.         Else
  590.                 While y<0
  591.                         y=pixmap.height-y
  592.                 Wend
  593.                 While y>pixmap.height-1
  594.                         y=pixmap.height-y
  595.                 Wend
  596.         EndIf
  597.         Return pixmap.ReadPixel(x,y)
  598. EndFunction
  599.  
  600. Function Alpha:Int(a:Int)
  601.         Return RGBA(a,a,a,a)
  602. EndFunction
  603.  
  604. Function PixmapFilterMaskCorrection:TPixmap(pixmap:TPixmap)
  605.         Local x:Int,y:Int,color:Int
  606.         Local result:TPixmap
  607.         Local a:Byte
  608.         Local channels:Byte[4]
  609.        
  610.         result=CreatePixmap(pixmap.width,pixmap.height,pixmap.format)
  611.         For x=0 To pixmap.width-1
  612.                 For y=0 To pixmap.height-1
  613.                         color=pixmap.ReadPixel(x,y)
  614.                         MemCopy channels,Varptr color,4
  615.                         If channels[3]<128
  616.                                 color=FindValidPixel(pixmap,x,y)
  617.                                 MemCopy channels,Varptr color,4
  618.                                 channels[3]=0
  619.                                 MemCopy Varptr color,channels,4
  620.                         EndIf
  621.                         result.WritePixel(x,y,color)
  622.                 Next
  623.         Next
  624.         Return result
  625.        
  626.         Function FindValidPixel:Int(pixmap:TPixmap,x:Int,y:Int)
  627.                 Local px:Int,py:Int
  628.                 Local color:Int
  629.                 Local channel:Byte[4]
  630.                 Local i:Int=1
  631.                 Local anythingfound:Int
  632.        
  633.                 Repeat
  634.                        
  635.                         anythingfound=False
  636.                
  637.                         px=x+i
  638.                         py=y
  639.                         If px<=pixmap.width-1
  640.                                 color=pixmap.ReadPixel(px,py)
  641.                                 MemCopy channel,Varptr color,4
  642.                                 If channel[3]>128 Return color
  643.                                 anythingfound=True
  644.                         EndIf
  645.                        
  646.                         px=x-i
  647.                         py=y
  648.                         If px=>0
  649.                                 color=pixmap.ReadPixel(px,py)
  650.                                 MemCopy channel,Varptr color,4
  651.                                 If channel[3]>128 Return color
  652.                                 anythingfound=True
  653.                         EndIf
  654.                        
  655.                         px=x
  656.                         py=y+i
  657.                         If py<=pixmap.height-1
  658.                                 color=pixmap.ReadPixel(px,py)
  659.                                 MemCopy channel,Varptr color,4
  660.                                 If channel[3]>128 Return color
  661.                                 anythingfound=True
  662.                         EndIf
  663.                        
  664.                         px=x
  665.                         py=y-i
  666.                         If py=>0
  667.                                 color=pixmap.ReadPixel(px,py)
  668.                                 MemCopy channel,Varptr color,4
  669.                                 If channel[3]>128 Return color
  670.                                 anythingfound=True
  671.                         EndIf
  672.                        
  673.                         If Not anythingfound Exit
  674.                         i:+1
  675.                 Forever
  676.                 Return RGBA(1,0,1,0)
  677.         EndFunction
  678.        
  679. EndFunction
  680.  
  681. Function ReadPixel4:Int(pixmap:TPixmap,x:Int,y:Int,flags:Int)
  682.         Local color:Int
  683.         Local channel:Byte[4,4]
  684.         Local r:Int,g:Int,b:Int,a:Int
  685.         Local Alpha:Float[4],alphasum:Float
  686.        
  687.         color=WrapReadPixel(pixmap,x+0,y+0,flags)
  688.         MemCopy Varptr channel[0,0],Varptr color,4
  689.         If channel[0,3]<128 Alpha[0]=0 Else Alpha[0]=1
  690.        
  691.         color=WrapReadPixel(pixmap,x+1,y+0,flags)
  692.         MemCopy Varptr channel[1,0],Varptr color,4
  693.         If channel[1,3]<128 Alpha[1]=0 Else Alpha[1]=1
  694.  
  695.         color=WrapReadPixel(pixmap,x+0,y+1,flags)
  696.         MemCopy Varptr channel[2,0],Varptr color,4
  697.         If channel[2,3]<128 Alpha[2]=0 Else Alpha[2]=1
  698.        
  699.         color=WrapReadPixel(pixmap,x+1,y+1,flags)
  700.         MemCopy Varptr channel[3,0],Varptr color,4
  701.         If channel[3,3]<128 Alpha[3]=0 Else Alpha[3]=1
  702.        
  703.         alphasum=Alpha[0]+Alpha[1]+Alpha[2]+Alpha[3]
  704.        
  705.         If (DDS_MASKCORRECTION & flags)
  706.                 If alphasum>0.0
  707.                         b=Int((Float(channel[0,0])*Alpha[0]+Float(channel[1,0])*Alpha[1]+Float(channel[2,0])*Alpha[2]+Float(channel[3,0])*Alpha[3])/alphasum)
  708.                         g=Int((Float(channel[0,1])*Alpha[0]+Float(channel[1,1])*Alpha[1]+Float(channel[2,1])*Alpha[2]+Float(channel[3,1])*Alpha[3])/alphasum)
  709.                         r=Int((Float(channel[0,2])*Alpha[0]+Float(channel[1,2])*Alpha[1]+Float(channel[2,2])*Alpha[2]+Float(channel[3,2])*Alpha[3])/alphasum)
  710.                         a=Int((Float(channel[0,3])*Alpha[0]+Float(channel[1,3])*Alpha[1]+Float(channel[2,3])*Alpha[2]+Float(channel[3,3])*Alpha[3])/alphasum)
  711.                 Else
  712.                         b=0
  713.                         g=0
  714.                         r=0
  715.                         a=0
  716.                 EndIf
  717.         Else
  718.                 b=Int((Float(channel[0,0])+Float(channel[1,0])+Float(channel[2,0])+Float(channel[3,0]))/4.0)
  719.                 g=Int((Float(channel[0,1])+Float(channel[1,1])+Float(channel[2,1])+Float(channel[3,1]))/4.0)
  720.                 r=Int((Float(channel[0,2])+Float(channel[1,2])+Float(channel[2,2])+Float(channel[3,2]))/4.0)
  721.                 a=Int((Float(channel[0,3])+Float(channel[1,3])+Float(channel[2,3])+Float(channel[3,3]))/4.0)
  722.         EndIf
  723.        
  724.         Return RGBA(r,g,b,a)
  725. EndFunction
  726.  
  727. Public


Comments :


Matty(Posted 1+ years ago)

 Looks good, would it also work in Blitz3d with some modifications of course.


JoshK(Posted 1+ years ago)

 The original code is on this forum and is for .bb.


JoshK(Posted 1+ years ago)

 Updated 4/5/2009.


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal