Ooops
November 28, 2020, 01:14:38 AM

Author Topic: [bb] SaveImageDDS function by markcw [ 1+ years ago ]  (Read 717 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bb] SaveImageDDS function by markcw [ 1+ years ago ]
« on: June 29, 2017, 12:28:41 AM »
Title : SaveImageDDS function
Author : markcw
Posted : 1+ years ago

Description : Code from my <a href="../Community/posts815a.html?topic=63126" target="_blank">SaveImageDDS thread[/url].

This function supports saving to dxt1, dxt3 and dxt5 as well as 24-bit uncompressed. It also seems to work for dxt2 and dxt4, although probably not quite right.

It uses an optional alpha image map to determine the alpha texels. This allows you to have full control over things. If you don't want to use an alpha map you can just omit the alpha parameter.

Updated by Tom C. to support mipmaps!


Code :
Code: BlitzBasic
  1. ;SaveImageDDS example code
  2.  
  3. Graphics3D 640,480,0,2 ;Setup the scene
  4. AppTitle "Save Image DDS"
  5. SetBuffer BackBuffer()
  6.  
  7. camera=CreateCamera()
  8. light=CreateLight()
  9. RotateEntity light,45,45,0
  10.  
  11. image=MakeTestImage(128,128) ;Create a test image
  12. ;image=LoadImage("test.bmp") ;Alternatively load a bmp
  13. ;image=LoadImage("test.png") ;Alternatively load a png
  14. ;image=LoadImage("test.jpg") ;Alternatively load a jpg
  15.  
  16. alpha=MakeTestAlpha(ImageWidth(image),ImageHeight(image)) ;A test alpha
  17.  
  18. filename$="test.dds" ;DDS Filename
  19. format=5 ;Set DDS format
  20. ;alpha=0 ;If we don't want an alpha channel set "alpha" to 0
  21. ok=SaveImageDDS(image,filename$,format,alpha)
  22.  
  23. cube=CreateCube() ;Create a cube to texture
  24. PositionEntity cube,0,0,4
  25. If format=1 Then flags=1+4 Else flags=1+2 ;Set either masked/alpha flags
  26. tex=LoadTexture(filename$,flags) ;Now load the new DDS file
  27. If format=1 Or format=3 Or format=5
  28.  EntityTexture cube,tex,0,0 ;Only texture cube if valid format
  29. EndIf
  30.  
  31. cube2=CreateCube() ;Create a cube behind the first cube
  32. PositionEntity cube2,0,2,8
  33.  
  34. While Not KeyHit(1) ;Main loop
  35.  RenderWorld()
  36.  
  37.  TurnEntity cube,0.4,0.3,0.2 ;Rotate the cubes
  38.  TurnEntity cube2,-0.4,-0.3,-0.2
  39.  
  40.  If space ;If space key was hit
  41.   DrawImage image,50,50 ;Draw image
  42.   If alpha DrawImage alpha,ImageWidth(image)+100,50 ;Draw alpha image
  43.  EndIf
  44.  If KeyHit(57) Then space=Not space ;Space key
  45.  
  46.  Text 0,0,"Hit space to show image and alpha maps"
  47.  Text 0,20,"ok="+ok+" file="+filename+" format="+format+" alpha="+alpha
  48.  
  49.  Flip
  50. Wend
  51.  
  52. Function MakeTestImage(width,height)
  53.  
  54.  Local image,x,y,rgb
  55.  image=CreateImage(width,height)
  56.  LockBuffer(ImageBuffer(image))
  57.  For y=0 To ImageHeight(image)-1
  58.   For x=0 To ImageWidth(image)-1
  59.    rgb=y+(y*256)+(x*256^2) ;Gradient color
  60.    WritePixelFast x,y,rgb,ImageBuffer(image)
  61.   Next
  62.  Next
  63.  UnlockBuffer(ImageBuffer(image))
  64.  SetBuffer ImageBuffer(image)
  65.  Color 255,255,255 : Oval 40,40,30,30
  66.  Color 0,0,0 : Text 50,50,"DXTC" : Color 255,255,255
  67.  SetBuffer BackBuffer()
  68.  Return image
  69.  
  70. End Function
  71.  
  72. Function MakeTestAlpha(width,height)
  73.  
  74.  Local alpha,x,y,rgb
  75.  alpha=CreateImage(width,height)
  76.  LockBuffer(ImageBuffer(alpha))
  77.  For y=0 To ImageHeight(alpha)-1
  78.   For x=0 To ImageWidth(alpha)-1
  79.    rgb=(y*2)+((y*2)*256)+((y*2)*256^2) ;Grayscale
  80.    If Not x Mod 8 Then rgb=$7F7F7F ;Grid lines
  81.    If Not y Mod 8 Then rgb=$7F7F7F
  82.    If Not x Mod 16 Then rgb=$FFFFFF
  83.    If Not y Mod 16 Then rgb=$FFFFFF
  84.    WritePixel x,y,rgb,ImageBuffer(alpha)
  85.   Next
  86.  Next
  87.  UnlockBuffer(ImageBuffer(alpha))
  88.  Return alpha
  89.  
  90. End Function
  91.  
  92. ;SaveImageDDS, by markcw on 13 Sep 06
  93. ;MipMap support, by Tom C. on 12 Jul 07
  94.  
  95. ;Description:
  96. ;This function works like SaveImage except it saves DDS files.
  97. ;Set the dxt mode with the format parameter 1-5 (or 0 for uncompressed RGB only)
  98. ;the alphaimg parameter is for an alpha image.
  99. ;If you omit it (or set it to 0) you get no alpha.
  100. ;Of course you can use the same image handle for alpha image
  101. ;the last optional parameter indicates a mipmap generation,
  102. ;0 for all possible mipmaps, 1 for only the main image (default)
  103. ;Return value is False if fails, True if succeeds.
  104.  
  105. Function SaveImageDDS(image,filename$,format,alphaimg=0,mipmaps=1)
  106.  ;image=image handle, filename$, format=optional compression format 0..5
  107.  ;alphaimg=optional alpha image handle, zero if no alpha required
  108.  ;mipmaps=count of mipmaps, if given the main picture will scaled down and saved to the file
  109.  ;Uses MakeEmptyAlpha, MAX, MakeFourCC, ColorHighest, ColorTotal, Color565
  110.  
  111.  Local width=ImageWidth(image)
  112.  Local height=ImageHeight(image)
  113.  Local imagebuf,alphabuf
  114.  
  115.  ;DXT3/5, if no alpha image then create empty white
  116.  If alphaimg=0 And format<>1 Then
  117.         alphaimg=MakeEmptyAlpha(width,height)
  118.         alphaimg_created=True
  119.  EndIf
  120.  
  121.  ;Determine mipmap count
  122.  If mipmaps=0 Then
  123.         c=MAX(width,height)
  124.         mipmaps=Log(c)/Log(2)+1
  125.  EndIf
  126.  
  127.  Local dwwidth,dwheight,flags1,flags2,caps1,caps2,bpp,pitch,sizebytes,w,h,mipsize
  128.  Local bsize,bindex,fourcc,hdds,i,x,y,offset,mipoffset,ix,iy,argb
  129.  Local color0,color1,color2,color3,color4,color5,color6,color7
  130.  Local d0,d1,d2,d3,d4,d5,d6,d7,texel,file
  131.  Local sclX#,sclY#
  132.  
  133.  ;dwFlags constants
  134.  Local DDSD_CAPS=$00000001,DDSD_HEIGHT=$00000002,DDSD_WIDTH=$00000004
  135.  Local DDSD_PITCH=$00000008,DDSD_PIXELFORMAT=$00001000
  136.  Local DDSD_MIPMAPCOUNT=$00020000,DDSD_LINEARSIZE=$00080000
  137.  Local DDSD_DEPTH=$00800000,DDPF_ALPHAPIXELS=$00000001
  138.  Local DDPF_FOURCC=$00000004,DDPF_RGB=$00000040
  139.  ;dwCaps1 constants
  140.  Local DDSCAPS_COMPLEX=$00000008,DDSCAPS_TEXTURE=$00001000
  141.  Local DDSCAPS_MIPMAP=$00400000
  142.  ;dwCaps2 constants
  143.  Local DDSCAPS2_CUBEMAP=$00000200,DDSCAPS2_CUBEMAP_POSITIVEX=$00000400
  144.  Local DDSCAPS2_CUBEMAP_NEGATIVEX=$00000800
  145.  Local DDSCAPS2_CUBEMAP_POSITIVEY=$00001000
  146.  Local DDSCAPS2_CUBEMAP_NEGATIVEY=$00002000
  147.  Local DDSCAPS2_CUBEMAP_POSITIVEZ=$00004000
  148.  Local DDSCAPS2_CUBEMAP_NEGATIVEZ=$00008000,DDSCAPS2_VOLUME=$00200000
  149.  
  150.  ;Calculate DWORD-aligned width and height, multiple of 4
  151.  dwwidth=(width+3)/4*4
  152.  dwheight=(height+3)/4*4
  153.  
  154.  ;Default flags for all formats
  155.  flags1=DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH Or DDSD_PIXELFORMAT
  156.  caps1=DDSCAPS_TEXTURE
  157.  
  158.  If format<=0 Or format>5 ;Uncompressed
  159.           flags1=flags1 Or DDSD_PITCH
  160.           flags2=DDPF_RGB
  161.           bpp=24
  162.           ;Determine Size of Bytes for each mipmap and add
  163.           w=dwwidth:h=dwheight
  164.           For i=1 To mipmaps
  165.                         mipsize=MAX(1,w)*(bpp/8) ;DWORD-aligned scanline
  166.                         sizebytes=sizebytes+mipsize*h
  167.                         w=MAX(1,w/2):h=MAX(1,h/2)
  168.                         ;pitch
  169.                         If i=1 Then pitch=mipsize
  170.           Next
  171.  Else ;Compressed
  172.           flags1=flags1 Or DDSD_LINEARSIZE
  173.           flags2=DDPF_FOURCC
  174.           ;Determine Size of Bytes for each mipmap and add
  175.           If format>1 Then bytesC=16 Else bytesC=8
  176.           w=dwwidth:h=dwheight
  177.           For i=1 To mipmaps
  178.                         mipsize=(MAX(1,w/4)*MAX(1,h/4))*bytesC
  179.                         sizebytes=sizebytes+mipsize
  180.                         w=MAX(1,w/2):h=MAX(1,h/2)
  181.                         ;Linear size
  182.                         If i=1 Then pitch=mipsize
  183.           Next
  184.           ;pitch=sizebytes
  185.           bsize=2 : bindex=0 : If format>1 Then bsize=4 : bindex=8 ;block values
  186.           If format=1 Then fourcc=MakeFourCC("D","X","T","1")
  187.           If format=2 Then fourcc=MakeFourCC("D","X","T","2")
  188.           If format=3 Then fourcc=MakeFourCC("D","X","T","3")
  189.           If format=4 Then fourcc=MakeFourCC("D","X","T","4")
  190.           If format=5 Then fourcc=MakeFourCC("D","X","T","5")
  191.  EndIf
  192.  
  193.  hdds=CreateBank(128+sizebytes) ;Bank to store DDS
  194.  
  195.  ;Magic Value, DWORD
  196.  PokeInt hdds,0,MakeFourCC("D","D","S"," ") ;dwMagic, "DDS "
  197.  ;Surface Format Header, DDSURFACEDESC2 structure
  198.  PokeInt hdds,4,124 ;dwSize, sizeof(DDSURFACEDESC2)
  199.  PokeInt hdds,8,flags1 ;dwFlags, flags to indicate valid fields
  200.  PokeInt hdds,12,dwheight ;dwHeight, image height in pixels
  201.  PokeInt hdds,16,dwwidth ;dwWidth, image width in pixels
  202.  PokeInt hdds,20,pitch ;dwPitchOrLinearSize, pitch or linear size
  203.  PokeInt hdds,24,0 ;dwDepth, volume textures not supported until DX 8.0
  204.  PokeInt hdds,28,mipmaps ;dwMipMapCount, for items with mipmap levels
  205.  For i=1 To 11
  206.         PokeInt hdds,(i*4)+28,0 ;dwReserved[11]
  207.  Next
  208.  ;DDPIXELFORMAT structure
  209.  PokeInt hdds,76,32 ;dwSize, sizeof(DDPIXELFORMAT)
  210.  PokeInt hdds,80,flags2 ;dwFlags, flags to indicate valid fields
  211.  PokeInt hdds,84,fourcc ;dwFourCC
  212.  PokeInt hdds,88,bpp ;dwRGBBitCount
  213.  PokeInt hdds,92,$00FF0000 ;dwRBitMask
  214.  PokeInt hdds,96,$0000FF00 ;dwGBitMask
  215.  PokeInt hdds,100,$000000FF ;dwBBitMask
  216.  PokeInt hdds,104,$FF000000 ;dwRGBAlphaBitMask
  217.  ;DDCAPS2 structure
  218.  PokeInt hdds,108,caps1 ;dwCaps1, flags to indicate valid fields
  219.  PokeInt hdds,112,caps2 ;dwCaps2, flags to indicate valid fields
  220.  For i=1 To 2
  221.   PokeInt hdds,(i*4)+112,0 ;dwReserved[2]
  222.  Next
  223.  PokeInt hdds,124,0 ;dwReserved2
  224.  mipoffset=128 ;default Offset after Header
  225.  ;Main Surface Data, BYTE bData1[] and Attached Surfaces Data for MIPMAPS
  226.  If format<=0 Or format>5 ;uncompressed, 24-bit
  227.         For mips=1 To mipmaps ;Loop of optional mipmap count   
  228.                 If mips>1 Then
  229.                         ;Store offset
  230.                         mipoffset=offset+pitch
  231.                         ;Half of dimension
  232.                         w=MAX(1,width/2):h=MAX(1,height/2)
  233.                         sclX#=Float#(w)/Float#(width):sclY#=Float#(h)/Float#(height)
  234.                         ScaleImage image,sclX#,sclY#
  235.                         width=w:height=h
  236.                         pitch=width*(bpp/8)
  237.                 EndIf
  238.                 ;Create Buffer
  239.                 imagebuf=ImageBuffer(image)
  240.                 LockBuffer(imagebuf)   
  241.                 For y=0 To height-1
  242.                         offset=mipoffset+pitch*y ;next DWORD-aligned scanline
  243.  
  244.                         For x=0 To width-1
  245.                         argb=ReadPixelFast(x,y,imagebuf)
  246.                         PokeByte hdds,offset+(x*3),argb And $000000FF ;b
  247.                         PokeByte hdds,offset+(x*3)+1,(argb And $0000FF00) Shr 8 ;g
  248.                         PokeByte hdds,offset+(x*3)+2,(argb And $00FF0000) Shr 16 ;r
  249.                         Next
  250.                 Next
  251.                 UnlockBuffer(imagebuf)
  252.         Next
  253.  Else ;Compressed
  254.   For mips=1 To mipmaps ;Loop of optional mipmap count 
  255.         If mips>1 Then
  256.                 ;Store offset
  257.                 mipoffset=offset+dwwidth*bsize
  258.                 ;Half of dimension
  259.                 w=MAX(1,width/2):h=MAX(1,height/2)
  260.                 sclX#=Float#(w)/Float#(width):sclY#=Float#(h)/Float#(height)
  261.                 ScaleImage image,sclX#,sclY#
  262.                 ;If not the same image-handle scale the alpha image too
  263.                 If image<>alphaimg And alphaimg>0 Then ScaleImage alphaimg,sclX#,sclY#
  264.                 width=w:height=h
  265.                 ;Calculate DWORD-aligned width and height, multiple of 4
  266.                 dwwidth=(width+3)/4*4:dwheight=(height+3)/4*4
  267.         EndIf
  268.  
  269.         ;Create Buffer
  270.         imagebuf=ImageBuffer(image)
  271.         If alphaimg Then alphabuf=ImageBuffer(alphaimg)
  272.         LockBuffer(imagebuf)
  273.         LockBuffer(alphabuf)
  274.         For y=0 To dwheight-1 Step 4
  275.            offset=mipoffset+MAX(1,dwwidth/4)*(y*bsize) ;Next block-aligned scanline
  276.            For x=0 To dwwidth-1 Step 4
  277.            If format=2 Or format=3 ;DXT2,DXT3
  278.                     ;Find color in alpha block and set each alpha texel
  279.                      For iy=0 To 3
  280.                       For ix=0 To 3
  281.                        If x+ix<width And y+iy<height ;Not out of bounds
  282.                                 argb=ReadPixelFast(ix+x,iy+y,alphabuf) ;Use alpha map
  283.                        Else
  284.                                         argb=0 ;Black
  285.                            EndIf
  286.                        i=ColorHighest(argb)/17 : If i>15 Then i=15 ;Alpha color 0..15
  287.                        texel=PeekShort(hdds,offset+(x*bsize)+(iy*2)) Or (i Shl ix*4)
  288.                        PokeShort hdds,offset+(x*bsize)+(iy*2),texel ;wAlphaTexels[4]
  289.                       Next
  290.                      Next
  291.             EndIf
  292.             If format=4 Or format=5 ;DXT4,DXT5
  293.                      ;Find highest and lowest colors in alpha block
  294.                      color0=0 : color1=$FFFFFFFF ;color0 highest
  295.                      For iy=0 To 3
  296.                                 For ix=0 To 3
  297.                                 If x+ix<width And y+iy<height ;Not out of bounds
  298.                                         argb=ReadPixelFast(ix+x,iy+y,alphabuf) ;Use alpha map
  299.                                                 If ColorHighest(argb)>ColorHighest(color0) Then color0=argb
  300.                                         If ColorHighest(argb)<ColorHighest(color1) Then color1=argb
  301.                                 EndIf
  302.                              Next
  303.                      Next
  304.                          ;Make sure color0 is the highest
  305.                          If color1>color0 Then
  306.                                 i=color0 : color0=color1 : color1=i ;Switch order
  307.                          EndIf
  308.                      PokeByte hdds,offset+(x*bsize),ColorHighest(color0) ;bAlpha0
  309.                      PokeByte hdds,offset+(x*bsize)+1,ColorHighest(color1) ;bAlpha1
  310.                      ;Set each alpha texel in block to closest alpha
  311.                      color0=ColorHighest(color0) : color1=ColorHighest(color1)
  312.                      For iy=0 To 3
  313.                               For ix=0 To 3
  314.                                        If x+ix<width And y+iy<height ;Not out of bounds
  315.                                         argb=ReadPixelFast(ix+x,iy+y,alphabuf) ;Use alpha map
  316.                                        Else
  317.                                                 argb=0 ;black
  318.                                        EndIf
  319.                                        If color0>color1 ;8-alpha block
  320.                                                 color2=((6*color0)+color1)/7
  321.                                                 color3=((5*color0)+(2*color1))/7
  322.                                                 color4=((4*color0)+(3*color1))/7
  323.                                                 color5=((3*color0)+(4*color1))/7
  324.                                                 color6=((2*color0)+(5*color1))/7
  325.                                                 color7=(color0+(6*color1))/7
  326.                                        Else ;6-alpha block
  327.                                                 color2=((4*color0)+color1)/5
  328.                                                 color3=((3*color0)+(2*color1))/5
  329.                                                 color4=((2*color0)+(3*color1))/5
  330.                                                 color5=(color0+(4*color1))/5
  331.                                                 color6=0
  332.                                                 color7=255
  333.                                        EndIf
  334.                                        d0=Abs(color0-ColorHighest(argb)) ;Get differences
  335.                                        d1=Abs(color1-ColorHighest(argb))
  336.                                        d2=Abs(color2-ColorHighest(argb))
  337.                                        d3=Abs(color3-ColorHighest(argb))
  338.                                        d4=Abs(color4-ColorHighest(argb))
  339.                                        d5=Abs(color5-ColorHighest(argb))
  340.                                        d6=Abs(color6-ColorHighest(argb))
  341.                                        d7=Abs(color7-ColorHighest(argb))
  342.                                        i=0 : If d1<d0 Then d0=d1 : i=1 ;Find closest color
  343.                                        If d2<d0 Then d0=d2 : i=2
  344.                                        If d3<d0 Then d0=d3 : i=3
  345.                                        If d4<d0 Then d0=d4 : i=4
  346.                                        If d5<d0 Then d0=d5 : i=5
  347.                                        If d6<d0 Then d0=d6 : i=6
  348.                                        If d7<d0 Then d0=d7 : i=7
  349.                                        If iy<2 ;Upper 24bit-block
  350.                                                 texel=PeekInt(hdds,offset+(x*bsize)+2) And $00FFFFFF
  351.                                                 If iy=0 Then texel=texel Or (i Shl (ix*3))
  352.                                                 If iy=1 Then texel=texel Or (i Shl ((ix*3)+12))
  353.                                                 PokeInt hdds,offset+(x*bsize)+2,texel And $00FFFFFF
  354.                                        Else ;Lower 24bit-block
  355.                                                 texel=PeekInt(hdds,offset+(x*bsize)+5) And $00FFFFFF
  356.                                                 If iy=2 Then texel=texel Or (i Shl (ix*3))
  357.                                                 If iy=3 Then texel=texel Or (i Shl ((ix*3)+12))
  358.                                                 PokeInt hdds,offset+(x*bsize)+5,texel And $00FFFFFF
  359.                                        EndIf
  360.                               Next
  361.                          Next
  362.             EndIf
  363.        
  364.                 ;Find highest and lowest colors in texel block
  365.             ;Better algorithm might be to find the most common highest/lowest colors
  366.             color0=0 : color1=$FFFFFFFF ;color0 highest
  367.             For iy=0 To 3
  368.                 For ix=0 To 3
  369.                         If x+ix<width And y+iy<height ;Not out of bounds
  370.                                 argb=ReadPixelFast(ix+x,iy+y,imagebuf)
  371.                                         If ColorTotal(argb)>ColorTotal(color0) Then color0=argb
  372.                                 If ColorTotal(argb)<ColorTotal(color1) Then color1=argb
  373.                         EndIf
  374.                 Next
  375.             Next
  376.                 ;Make sure color0 is the highest
  377.                 If color1>color0 Then
  378.                         i=color0 : color0=color1 : color1=i ;Switch order
  379.                 EndIf
  380.             ;Switch order, color1 highest to indicate DXT1a
  381.             If format=1 And alphaimg<>0 ;DXT1a, using alpha bit
  382.                         i=color0 : color0=color1 : color1=i
  383.                 EndIf
  384.             PokeShort hdds,offset+(x*bsize)+bindex,Color565(color0) ;wColor0
  385.             PokeShort hdds,offset+(x*bsize)+bindex+2,Color565(color1) ;wColor1
  386.             ;Set each texel in block to closest color
  387.             color0=ColorTotal(color0) : color1=ColorTotal(color1)
  388.             For iy=0 To 3
  389.                      For ix=0 To 3
  390.                               If x+ix<width And y+iy<height ;Not out of bounds
  391.                                 argb=ReadPixelFast(ix+x,iy+y,imagebuf) 
  392.                               Else
  393.                                         argb=0 ;Black
  394.                               EndIf
  395.                               If color0>color1 ;Four-color block
  396.                                         color2=((2*color0)+color1)/3
  397.                                         color3=(color0+(2*color1))/3
  398.                               Else ;Three-color block
  399.                                         color2=(color0+color1)/2
  400.                                         color3=3*16 ;Max transparent color
  401.                               EndIf
  402.                               d0=Abs(color0-ColorTotal(argb)) ;Get differences
  403.                               d1=Abs(color1-ColorTotal(argb))
  404.                               d2=Abs(color2-ColorTotal(argb))
  405.                               d3=Abs(color3-ColorTotal(argb))
  406.                               i=0 : If d1<d0 Then d0=d1 : i=1 ;Find closest color
  407.                               If d2<d0 Then d0=d2 : i=2
  408.                               If d3<d0 Then d0=d3 : i=3
  409.                               If color0>color1 And Abs(color2-color3)<8
  410.                                         If i=3 Then i=2 ;Close and wrong order so use color2
  411.                               EndIf
  412.                               If format=1 And alphaimg<>0 ;DXT1a, using alpha bit
  413.                                         If i=3 Then i=2 ;No color3 so use color2
  414.                               EndIf
  415.                               If x+ix>width-1 Or y+iy>height-1 ;Out of bounds
  416.                                         If color0<color1 Then i=0 Else i=1 ;Find lowest color
  417.                               EndIf
  418.                               texel=PeekByte(hdds,offset+(x*bsize)+bindex+4+iy) Or (i Shl ix*2)  
  419.                               PokeByte hdds,offset+(x*bsize)+bindex+4+iy,texel ;bTexels[4]
  420.                      Next
  421.             Next
  422.             ;Find color in texel block and set each alpha texel
  423.             If format=1 And alphaimg<>0 ;DXT1a, using alpha bit
  424.                      For iy=0 To 3
  425.                              For ix=0 To 3
  426.                                         If x+ix<width And y+iy<height ;Not out of bounds
  427.                                                 argb=ReadPixelFast(ix+x,iy+y,alphabuf) ;Use alpha map
  428.                                                 color3=3*16 ;Max transparent color
  429.                                                 If ColorTotal(argb)<color3 ;Set alpha texel
  430.                                                         texel=PeekByte(hdds,offset+(x*bsize)+bindex+4+iy) Or (3 Shl ix*2)
  431.                                                     PokeByte hdds,offset+(x*bsize)+bindex+4+iy,texel ;bTexels[4]
  432.                                                 EndIf
  433.                                         EndIf          
  434.                         Next
  435.                 Next
  436.                 EndIf
  437.           Next
  438.         Next
  439.         UnlockBuffer(imagebuf)
  440.         UnlockBuffer(alphabuf)
  441.   Next
  442.   ;Attached Surfaces Data, BYTE bData2[]
  443.   ;Complex
  444.  EndIf
  445.  
  446.  ;Write DDS bank to file
  447.  file=WriteFile(filename$)
  448.  If Not file FreeBank hdds : Return False ;Fail code
  449.  WriteBytes hdds,file,0,128+sizebytes
  450.  CloseFile file
  451.  FreeBank hdds
  452.  ;If an alpha image was created
  453.  If alphaimg_created=True Then FreeImage alphaimg
  454.  Return True ;Success code
  455.  
  456. End Function
  457.  
  458. Function MakeEmptyAlpha(width,height)
  459.  
  460.  Local alpha,x,y,rgb
  461.  alpha=CreateImage(width,height)
  462.  LockBuffer(ImageBuffer(alpha))
  463.  For y=0 To ImageHeight(alpha)-1
  464.           For x=0 To ImageWidth(alpha)-1
  465.                 rgb=$FFFFFF
  466.            WritePixel x,y,rgb,ImageBuffer(alpha)
  467.         Next
  468.  Next
  469.  UnlockBuffer(ImageBuffer(alpha))
  470.  Return alpha
  471.  
  472. End Function
  473.  
  474. Function MAX(a,b)
  475.  
  476.  If a=>b Then Return a Else Return b
  477.  
  478. End Function
  479.  
  480. Function MakeFourCC(c0$,c1$,c2$,c3$)
  481.  
  482.  Return (Asc(c0$)+(Asc(c1$) Shl 8)+(Asc(c2$) Shl 16)+(Asc(c3$) Shl 24))
  483.  
  484. End Function
  485.  
  486. Function ColorHighest(argb)
  487.  
  488.  Local r,g,b,a
  489.  r=(argb And $00FF0000) Shr 16
  490.  g=(argb And $0000FF00) Shr 8
  491.  b=(argb And $000000FF)
  492.  If r>g Then a=r Else a=g
  493.  If b>a Then a=b
  494.  Return a
  495.  
  496. End Function
  497.  
  498. Function ColorTotal(argb)
  499.  
  500.  Local r,g,b
  501.  r=(argb And $00FF0000) Shr 16
  502.  g=(argb And $0000FF00) Shr 8
  503.  b=(argb And $000000FF)
  504.  Return (r+g+b) ;0..255*3
  505.  
  506. End Function
  507.  
  508. Function Color565(argb)
  509.  
  510.  Local r,g,b
  511.  r=(argb And $00FF0000) Shr 16 : r=(r*31/255) Shl 11 ;Bits 11..15
  512.  g=(argb And $0000FF00) Shr 8 : g=(g*63/255) Shl 5 ;Bits 5..10
  513.  b=(argb And $000000FF) : b=b*31/255 ;Bits 0..4
  514.  Return (r+g+b)
  515.  
  516. End Function


Comments :


JoshK(Posted 1+ years ago)

 Sweet!


JoshK(Posted 1+ years ago)

 I converted the code to BlitzMax.  There seems to be a little color inaccuracy, compared to DDS files saved by ATI's Compressonator tool.  That tool includes some color weighting values that make no sense to me.  I think it must be part of a high-pass filter, but their exported DDS files more closely match the original image's colors:
Code: [Select]
Strict

Import brl.pixmap
Import brl.bank

'Local time=MilliSecs()
'SavePixmapDDS(LoadPixmap("bricks.bmp"),"poo.dds")
'Print "DDS Compressed in "+(MilliSecs()-time)+" msecs"
'OpenURL "poo.dds"

Rem
bbdoc:
Description:
This Function saves a pixmap as a DDS file.
Set the dxt mode with the format parameter 1. 3, or 5 (Or 0 For uncompressed RGB only).
The optional mipmaps flag can be set to 0 to save the first mipmap only.  The default value is True.
<p>Format:
<br>0 - Uncompressed
<br>1 - DXTC1 (RGB)
<br>3 - DXTC3 (RGBA)
<br>5 - DXTC5 (RGBA)
EndRem
Function SavePixmapDDS(pixmap:TPixmap,url:Object,format=-1,mipmaps=True)
Local stream:TStream=WriteStream(url)
If Not stream Return

'Choose format
If format=-1
If pixmap.format=PF_RGBA8888
format=5' DXTC5
Else
format=1' DXTC1 (no alpha)
EndIf
EndIf

pixmap=CopyPixmap(pixmap)
pixmap=ConvertPixmap(pixmap,PF_RGBA8888)

Local dwwidth,dwheight,flags1,flags2,caps1,caps2,bpp,pitch,sizebytes,w,h,mipsize
Local bsize,bindex,fourcc,hdds:TBank,i,x,y,offset,mipoffset,ix,iy,argb
Local color,color0,color1,color2,color3,color4,color5,color6,color7
Local d0,d1,d2,d3,d4,d5,d6,d7,texel,a
Local sclX#,sclY#
Local alphaimg:TPixmap=Null

Local width=PixmapWidth(pixmap)
Local height=PixmapHeight(pixmap)
Local pixmapbuf:TPixmap,alphabuf:TPixmap
Local alphaimg_created,c
Local mips

'DXT3/5, If no Alpha pixmap Then Create empty white
If alphaimg=Null And format<>1
alphaimg=CreatePixmap(width,height,PF_RGB888)
alphaimg_created=True
For x=0 To pixmap.width-1
For y=0 To pixmap.height-1
color=ReadPixel(pixmap,x,y)
a=(color & $FF000000) Shr 24
WritePixel alphaimg,x,y,a+(a Shl 8)+(a Shl 16)'+(a Shl 24)
Next
Next
EndIf

'Determine mipmap count
If mipmaps
c=Max(width,height)
mipmaps=Log(c)/Log(2)+1
Else
mipmaps=1
EndIf

Const pf_alphapix% = $00000001

'dwFlags constants
Const DDSD_CAPS=$00000001,DDSD_HEIGHT=$00000002,DDSD_WIDTH=$00000004
Const DDSD_PITCH=$00000008,DDSD_PIXELFORMAT=$00001000
Const DDSD_MIPMAPCOUNT=$00020000,DDSD_LINEARSIZE=$00080000
Const DDSD_DEPTH=$00800000,DDPF_ALPHAPIXELS=$00000001
Const DDPF_FOURCC=$00000004,DDPF_RGB=$00000040
'dwCaps1 constants
Const DDSCAPS_COMPLEX=$00000008,DDSCAPS_TEXTURE=$00001000
Const DDSCAPS_MIPMAP=$00400000
'dwCaps2 constants
Const DDSCAPS2_CUBEMAP=$00000200,DDSCAPS2_CUBEMAP_POSITIVEX=$00000400
Const DDSCAPS2_CUBEMAP_NEGATIVEX=$00000800
Const DDSCAPS2_CUBEMAP_POSITIVEY=$00001000
Const DDSCAPS2_CUBEMAP_NEGATIVEY=$00002000
Const DDSCAPS2_CUBEMAP_POSITIVEZ=$00004000
Const DDSCAPS2_CUBEMAP_NEGATIVEZ=$00008000,DDSCAPS2_VOLUME=$00200000
Local bytesC
'Calculate DWORD-aligned width And height, multiple of 4
dwwidth=(width+3)/4*4
dwheight=(height+3)/4*4

'Default flags For all formats
flags1=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
caps1=DDSCAPS_TEXTURE
'If alphaimg Notify 1 Else Notify 0
'Notify (pf_alphapix & DDSD_CAPS )

If format<=0 Or format>5 'Uncompressed
 flags1=flags1 | DDSD_PITCH
 flags2=DDPF_RGB
 bpp=24
 'Determine Size of Bytes For each mipmap And add
 w=dwwidth ; h=dwheight
 For i=1 To mipmaps
mipsize=Max(1,w)*(bpp/8) 'DWORD-aligned scanline
sizebytes=sizebytes+mipsize*h
w=Max(1,w/2) ; h=Max(1,h/2)
'pitch
If i=1 Then pitch=mipsize
 Next
Else 'Compressed
 flags1=flags1 | DDSD_LINEARSIZE
 flags2=DDPF_FOURCC
 'Determine Size of Bytes For each mipmap And add
 If format>1 Then bytesC=16 Else bytesC=8
 w=dwwidth ; h=dwheight
 For i=1 To mipmaps
mipsize=(Max(1,w/4)*Max(1,h/4))*bytesC
sizebytes=sizebytes+mipsize
w=Max(1,w/2) ; h=Max(1,h/2)
'Linear size
If i=1 Then pitch=mipsize
 Next
 'pitch=sizebytes
 bsize=2 ; bindex=0 ; If format>1 Then bsize=4 ; bindex=8 'block values
 If format=1 Then fourcc=MakeFourCC("D","X","T","1")
 If format=2 Then fourcc=MakeFourCC("D","X","T","2")
 If format=3 Then fourcc=MakeFourCC("D","X","T","3")
 If format=4 Then fourcc=MakeFourCC("D","X","T","4")
 If format=5 Then fourcc=MakeFourCC("D","X","T","5")
EndIf

hdds=CreateBank(128+sizebytes) 'Bank To store DDS
For Local n=0 To hdds.size()-1
hdds.PokeByte n,0
Next

'Magic Value, DWORD
'Notify MakeFourCC("D","D","S"," ")
PokeInt hdds,0,MakeFourCC("D","D","S"," ") 'dwMagic, "DDS "
'Surface Format Header, DDSURFACEDESC2 structure
PokeInt hdds,4,124 'dwSize, SizeOf(DDSURFACEDESC2)
PokeInt hdds,8,flags1 'dwFlags, flags To indicate valid fields
PokeInt hdds,12,dwheight 'dwHeight, pixmap height in pixels
PokeInt hdds,16,dwwidth 'dwWidth, pixmap width in pixels
PokeInt hdds,20,pitch 'dwPitchOrLinearSize, pitch Or linear size
PokeInt hdds,24,0 'dwDepth, volume textures Not supported Until DX 8.0
PokeInt hdds,28,mipmaps 'dwMipMapCount, For items with mipmap levels
For i=1 To 11
  PokeInt hdds,(i*4)+28,0 'dwReserved[11]
Next
'DDPIXELFORMAT structure
PokeInt hdds,76,32 'dwSize, SizeOf(DDPIXELFORMAT)
PokeInt hdds,80,flags2 'dwFlags, flags To indicate valid fields
PokeInt hdds,84,fourcc 'dwFourCC
PokeInt hdds,88,bpp 'dwRGBBitCount
PokeInt hdds,92,$00FF0000 'dwRBitMask
PokeInt hdds,96,$0000FF00 'dwGBitMask
PokeInt hdds,100,$000000FF 'dwBBitMask
PokeInt hdds,104,$FF000000 'dwRGBAlphaBitMask
'DDCAPS2 structure
PokeInt hdds,108,caps1 'dwCaps1, flags To indicate valid fields
PokeInt hdds,112,caps2 'dwCaps2, flags To indicate valid fields
For i=1 To 2
 PokeInt hdds,(i*4)+112,0 'dwReserved[2]
Next
PokeInt hdds,124,0 'dwReserved2
mipoffset=128 'Default Offset after Header
'Main Surface Data, Byte bData1[] And Attached Surfaces Data For MIPMAPS
If format<=0 Or format>5 'uncompressed, 24-bit
For mips=1 To mipmaps 'Loop of optional mipmap count
If mips>1 Then
'Store offset
mipoffset=offset+pitch
'Half of dimension
w=Max(1,width/2) ; h=Max(1,height/2)
sclX#=Float(w)/Float(width) ; sclY#=Float(h)/Float(height)
'Scalepixmap pixmap,sclX#,sclY#

pixmap=ResizePixmap(pixmap,w,h)

width=w ; height=h
pitch=width*(bpp/8)
EndIf
'Create Buffer
'pixmapbuf=pixmapBuffer(pixmap)
  'LockBuffer(pixmapbuf)
For y=0 To height-1
  offset=mipoffset+pitch*y 'Next DWORD-aligned scanline
  For x=0 To width-1
    argb=ReadPixel(pixmap,x,y)

    PokeByte hdds,offset+(x*3),argb & $000000FF 'b
    PokeByte hdds,offset+(x*3)+1,(argb & $0000FF00) Shr 8 'g
    PokeByte hdds,offset+(x*3)+2,(argb & $00FF0000) Shr 16 'r
  Next
  Next
  'UnlockBuffer(pixmapbuf)
Next
Else 'Compressed
 For mips=1 To mipmaps 'Loop of optional mipmap count
If mips>1 Then
'Store offset
mipoffset=offset+dwwidth*bsize
'Half of dimension
w=Max(1,width/2) ; h=Max(1,height/2)
sclX#=Float(w)/Float(width) ; sclY#=Float(h)/Float(height)
pixmap=ResizePixmap(pixmap,w,h)
'Scalepixmap pixmap,sclX#,sclY#
'If Not the same pixmap-handle scale the Alpha pixmap too
If pixmap<>alphaimg And alphaimg<>Null Then alphaimg=ResizePixmap(alphaimg,w,h)'Scalepixmap alphaimg,sclX#,sclY#
width=w ; height=h
'Calculate DWORD-aligned width And height, multiple of 4
dwwidth=(width+3)/4*4 ; dwheight=(height+3)/4*4
EndIf

'Create Buffer
'pixmapbuf=pixmapBuffer(pixmap)
If alphaimg Then alphabuf=alphaimg
'LockBuffer(pixmapbuf)
'LockBuffer(alphabuf)
For y=0 To dwheight-1 Step 4
  offset=mipoffset+Max(1,dwwidth/4)*(y*bsize) 'Next block-aligned scanline
  For x=0 To dwwidth-1 Step 4
  If format=2 Or format=3 'DXT2,DXT3
   'Find color in Alpha block And set each Alpha texel
    For iy=0 To 3
     For ix=0 To 3
      If x+ix<width And y+iy<height 'Not out of bounds
        argb=ReadPixel(alphabuf,ix+x,iy+y) 'Use Alpha map
      Else
  argb=0 'Black
  EndIf
      i=ColorHighest(argb)/17.0+0.5 ; If i>15 Then i=15 'Alpha color 0..15
      texel=PeekShort(hdds,offset+(x*bsize)+(iy*2)) | (i Shl (ix*4))
      PokeShort hdds,offset+(x*bsize)+(iy*2),texel 'wAlphaTexels[4]
     Next
    Next
   EndIf
   If format=4 Or format=5 'DXT4,DXT5
    'Find highest And lowest colors in Alpha block
    color0=0  ; color1=$FFFFFFFF 'color0 highest
    For iy=0 To 3
For ix=0 To 3
      If x+ix<width And y+iy<height 'Not out of bounds
        argb=ReadPixel(alphabuf,ix+x,iy+y) 'Use Alpha map
If ColorHighest(argb)>ColorHighest(color0) Then color0=argb
    If ColorHighest(argb)<ColorHighest(color1) Then color1=argb
      EndIf
    Next
    Next
'Make sure color0 is the highest
If color1>color0 Then
i=color0 ; color0=color1 ; color1=i 'Switch order
EndIf
    PokeByte hdds,offset+(x*bsize),ColorHighest(color0) 'bAlpha0
    PokeByte hdds,offset+(x*bsize)+1,ColorHighest(color1) 'bAlpha1
    'Set each Alpha texel in block To closest Alpha
    color0=ColorHighest(color0) ; color1=ColorHighest(color1)
    For iy=0 To 3
     For ix=0 To 3
      If x+ix<width And y+iy<height 'Not out of bounds
      argb=ReadPixel(alphabuf,ix+x,iy+y) 'Use Alpha map
      Else
        argb=0 'black
      EndIf
      If color0>color1 '8-Alpha block
       color2=((6*color0)+color1)/7
       color3=((5*color0)+(2*color1))/7
       color4=((4*color0)+(3*color1))/7
       color5=((3*color0)+(4*color1))/7
       color6=((2*color0)+(5*color1))/7
       color7=(color0+(6*color1))/7
      Else '6-Alpha block
       color2=((4*color0)+color1)/5
       color3=((3*color0)+(2*color1))/5
       color4=((2*color0)+(3*color1))/5
       color5=(color0+(4*color1))/5
       color6=0
       color7=255
      EndIf
      d0=Abs(color0-ColorHighest(argb)) 'Get differences
      d1=Abs(color1-ColorHighest(argb))
      d2=Abs(color2-ColorHighest(argb))
      d3=Abs(color3-ColorHighest(argb))
      d4=Abs(color4-ColorHighest(argb))
      d5=Abs(color5-ColorHighest(argb))
      d6=Abs(color6-ColorHighest(argb))
      d7=Abs(color7-ColorHighest(argb))
      i=0 ; If d1<d0 Then d0=d1 ; i=1 'Find closest color
      If d2<d0 Then d0=d2 ; i=2
      If d3<d0 Then d0=d3 ; i=3
      If d4<d0 Then d0=d4 ; i=4
      If d5<d0 Then d0=d5 ; i=5
      If d6<d0 Then d0=d6 ; i=6
      If d7<d0 Then d0=d7 ; i=7
      If iy<2 'Upper 24bit-block
       texel=PeekInt(hdds,offset+(x*bsize)+2) & $00FFFFFF
       If iy=0 Then texel=texel | (i Shl (ix*3))
       If iy=1 Then texel=texel | (i Shl ((ix*3)+12))
       PokeInt hdds,offset+(x*bsize)+2,texel & $00FFFFFF
      Else 'Lower 24bit-block
       texel=PeekInt(hdds,offset+(x*bsize)+5) & $00FFFFFF
       If iy=2 Then texel=texel | (i Shl (ix*3))
       If iy=3 Then texel=texel | (i Shl ((ix*3)+12))
       PokeInt hdds,offset+(x*bsize)+5,texel & $00FFFFFF
      EndIf
     Next
Next
   EndIf

'Find highest And lowest colors in texel block
   'Better algorithm might be To find the most common highest/lowest colors
   color0=0 ; color1=$FFFFFFFF 'color0 highest
   For iy=0 To 3
    For ix=0 To 3
      If x+ix<width And y+iy<height 'Not out of bounds
      argb=ReadPixel(pixmap,ix+x,iy+y)
'Notify argb
If ColorTotal(argb)>ColorTotal(color0) Then color0=argb
      If ColorTotal(argb)<ColorTotal(color1) Then color1=argb
      EndIf
    Next
   Next
'DebugLog argb
'Make sure color0 is the highest
If color1>color0 Then
i=color0 ; color0=color1 ; color1=i 'Switch order
EndIf
   'Switch order, color1 highest To indicate DXT1a
   If format=1 And alphaimg<>Null 'DXT1a, using Alpha bit
i=color0 ; color0=color1 ; color1=i
'Notify 1
EndIf
'DebugLog (color0)+", "+(color1)
'DebugLog Color565(color0)+", "+Color565(color1)
   PokeShort hdds,offset+(x*bsize)+bindex,Color565(color0) 'wColor0
   PokeShort hdds,offset+(x*bsize)+bindex+2,Color565(color1) 'wColor1
   'Set each texel in block To closest color
   color0=ColorTotal(color0) ; color1=ColorTotal(color1)
   For iy=0 To 3
    For ix=0 To 3
     If x+ix<width And y+iy<height 'Not out of bounds
      argb=ReadPixel(pixmap,ix+x,iy+y)
     Else
    argb=0 'Black
     EndIf

     If color0>color1 'Four-color block
      color2=((2*color0)+color1)/3
      color3=(color0+(2*color1))/3
     Else 'Three-color block
      color2=(color0+color1)/2
      color3=3*16 'Max transparent color
     EndIf
     d0=Abs(color0-ColorTotal(argb)) 'Get differences
     d1=Abs(color1-ColorTotal(argb))
     d2=Abs(color2-ColorTotal(argb))
     d3=Abs(color3-ColorTotal(argb))
     i=0 ; If d1<d0 Then d0=d1 ; i=1 'Find closest color
     If d2<d0 Then d0=d2 ; i=2
     If d3<d0 Then d0=d3 ; i=3
     If color0>color1 And Abs(color2-color3)<8
      If i=3 Then i=2 'Close And wrong order so use color2
     EndIf
     If format=1 And alphaimg<>Null 'DXT1a, using Alpha bit
      If i=3 Then i=2 'No color3 so use color2
     EndIf
     If x+ix>width-1 Or y+iy>height-1 'Out of bounds
      If color0<color1 Then i=0 Else i=1 'Find lowest color
     EndIf
     texel=PeekByte(hdds,offset+(x*bsize)+bindex+4+iy) | (i Shl (ix*2))
PokeByte hdds,offset+(x*bsize)+bindex+4+iy,texel 'bTexels[4]
'DebugLog ((offset+(x*bsize)+bindex+4+iy) | (i Shl (ix*2))) + ", "+texel
    Next
   Next
'WaitKey
   'Find color in texel block And set each Alpha texel
   If format=1 And alphaimg<>Null 'DXT1a, using Alpha bit
    For iy=0 To 3
    For ix=0 To 3
If x+ix<width And y+iy<height 'Not out of bounds
argb=ReadPixel(alphabuf,ix+x,iy+y) 'Use Alpha map
color3=3*16 'Max transparent color
If ColorTotal(argb)<color3 'Set Alpha texel
texel=PeekByte(hdds,offset+(x*bsize)+bindex+4+iy) | (3 Shl (ix*2))
   PokeByte hdds,offset+(x*bsize)+bindex+4+iy,texel 'bTexels[4]
EndIf
EndIf    
      Next
    Next
    EndIf
 Next
Next
 Next
EndIf
If hdds.size()<>128+sizebytes Notify 1
stream.WriteBytes hdds.buf(),hdds.size()'128+sizebytes
'For Local n=0 To hdds.size()-1
' Stream.WriteByte hdds.PeekByte(n)
'Next
stream.close()
Return 1
EndFunction

Private

Function MakeFourCC:Int(c0$,c1$,c2$,c3$)
Return (Asc(c0$)+(Asc(c1$) Shl 8)+(Asc(c2$) Shl 16)+(Asc(c3$) Shl 24))
EndFunction

Function ColorHighest:Int(argb)
Local r,g,b,a
r=(argb & $00FF0000) Shr 16
g=(argb & $0000FF00) Shr 8
b=(argb & $000000FF)
If r>g Then a=r Else a=g
If b>a Then a=b
Return a
EndFunction

Function ColorTotal:Int(argb)
Local r,g,b
r=(argb & $00FF0000) Shr 16
g=(argb & $0000FF00) Shr 8
b=(argb & $000000FF)
Return (r+g+b) '0..255*3
EndFunction

Function Color565:Int(argb)
Local r,g,b
r=(argb & $00FF0000) Shr 16 ; r=Int((r*31.0/255.0+0.5)) Shl 11 'Bits 11..15
g=(argb & $0000FF00) Shr 8 ; g=Int((g*63.0/255.0+0.5)) Shl 5 'Bits 5..10
b=(argb & $000000FF) ; b=Int(b*31/255.0+0.5) 'Bits 0..4
Return (r+g+b)
EndFunction

Public



markcw(Posted 1+ years ago)

 So the code works but the colors are a little off?I think that is due to my algorithm, so the Blitz3D version should do exactly the same thing. I wrote this code by reading the DX7 Programmer's Reference, there was no info about what algorithm to use so I came up with my own. If you can find the correct algorithm that ATI use then we could improve it, otherwise I have no idea what their algorithm is.


JoshK(Posted 1+ years ago)

 If I set the color weights in ATI's Compressonator to 0 the output looks just like yours.  So I think that is what makes the difference.  The default values are this:Red: 0.3086Green: 0.6094Blue: 0.082I have no idea how these are being used.  They looks like values to convert RGB to grayscale.


JoshK(Posted 1+ years ago)

 Ha!  It was just a rounding problem.  Your code is also about ten times faster than nvdxt.
Code: [Select]
Function Color565:Int(argb)
Local r,g,b
r=(argb & $00FF0000) Shr 16 ; r=Int((r*31.0/255.0+0.5)) Shl 11 'Bits 11..15
g=(argb & $0000FF00) Shr 8 ; g=Int((g*63.0/255.0+0.5)) Shl 5 'Bits 5..10
b=(argb & $000000FF) ; b=Int(b*31/255.0+0.5) 'Bits 0..4
Return (r+g+b)
EndFunction
The output is slightly grainy compared to NVidia and ATI tools, but it is hardly different.


markcw(Posted 1+ years ago)

 You fixed it? Great job! I am relieved. :)I had a look at color weighting and that seems to be the process of choosing the most used color in a block of pixels.I'm not sure but I think maybe Color565() should be dividing by 256.Yeah, the grainyness is probably due to the algorithm used.


JoshK(Posted 1+ years ago)

 I found it was necessary to clear the created bank, or errors would result after multiple saves.


JoshK(Posted 1+ years ago)

 There is an error in your calculation here, at least with BlitzMax integer handling:mipmaps=Log(c)/Log(2)+1It should be this:mipmaps=Int(Log(c)/Log(2)+1.0+0.5)The wrong mipmap count will be calculated with a texture of size 64, without this fix.


markcw(Posted 1+ years ago)

 Doesn't work in Blitz3D. The problem is that Int() behaves differently in BMax to B3D, in Max it floors the value whereas in B3D it rounds it to the nearest int. I'd actually consider this a bug in Max, but you could say it is a matter of preference.Edit: well looking at it again, Int() in Max is a type cast so it's not a bug but there's no function to do the equivalent, such as Round().


Perturbatio(Posted 1+ years ago)

 <div class="quote"> Edit: well looking at it again, Int() in Max is a type cast so it's not a bug but there's no function to do the equivalent, such as Round(). </div>Floor()?


markcw(Posted 1+ years ago)

 No, Int() in b3d isn't like Floor().With floor (or int type cast in max) 2.99=2, with int in b3d (or round in max) 2.99=3.Edit: in fact, Leadwerks' <a href="codearcs175d.html?code=2145" target="_blank">MathEx module[/url] has a Round().


_PJ_(Posted 1+ years ago)

 
Code: [Select]
Round%(fFoat#)=Abs(Floor#(Float#+(Sgn(fFloat#))*0.5)))
Woudn't this do the trick? [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal