image saving algorithm

Just starting out? Need help? Post your questions and find answers here.
SeregaZ
Enthusiast
Enthusiast
Posts: 628
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

image saving algorithm

Post by SeregaZ »

i am trying to make some grafic editor for game for Sega Mega Drive - Dune.

Image

too many glithc... but not a editor :)


so, it have image in array:

Code: Select all

Enumeration
  #File
EndEnumeration
 
Structure colorarraystr
  Array Y.u(0)
EndStructure
 
markx = 16
marky = 16
 
Global Dim X.colorarraystr(markx)
For i = 0 To markx
  ReDim X(i)\Y(marky)
Next
 
; write data
X(0)\Y(0) = 1
X(10)\Y(0) = 1
X(0)\Y(10) = 1
 
                      If CreateFile(#File, "D:\test")
                        x = 0
                        y = 0
                        xlim = 8
                  
                        Repeat
                          
                          ; make variable for write
                          first = X(x)\Y(y)
                          x = x + 1
                          second = X(x)\Y(y)
                          x = x + 1
                          Number = first << 4
                          Number + second
                    
                          WriteAsciiCharacter(#File, Number)
                          
                          ; catch end of file
                          If x = markx And y = marky-1
                            Break
                          EndIf
                          
                          ; write file from up to down blocks 8х8
                          If x = xlim
                            x = xlim - 8
                            y = y + 1
                            If y = marky
                              y = 0
                              x = xlim
                              xlim = xlim + 8
                            EndIf
                          EndIf
                    
                        ForEver                        
                        
                        CloseFile(#File)
                      EndIf
for this example final file is have 128 bytes. 4 tyles - blocks 8x8 pixels. but for this example only 3 tyles have "data". last one - 4 have all empty colors 0 for all 64 pixels (8x8). how to make some algorithm for save only that data, where lays data.

Image

for this 3 cases it will be 96 bytes file, 96 bytes, 64 bytes. becouse Sega Mega Drive have a small quantity of tyles. every image must be optimized.
infratec
Always Here
Always Here
Posts: 7644
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: image saving algorithm

Post by infratec »

Hm...

for me it's not exactly clear how your codes fits to pixel arrays.
I think if you explain it a bit better ...
SeregaZ
Enthusiast
Enthusiast
Posts: 628
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: image saving algorithm

Post by SeregaZ »

array can have value from 0 to 15 - numbers of colors. colors themselves lays in another place.

i think to write not in a file, but memory. and then make some summ of every bytes in 32 bytes length data (tyle size). and make some additional array. this additional array will have size 16 (4x4 tyles is maximum size, that can have image).
then just add this summ into this array according his tyle number. then start cycle with step -1 from end to begining of this additional array. when it get any value exept 0 - is will marker for end of file. then i will write into file data from memory with size, what i am get with this "marker for end of file". code is not ready :) it is just idea in my head.
SeregaZ
Enthusiast
Enthusiast
Posts: 628
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: image saving algorithm

Post by SeregaZ »

Code: Select all

Enumeration
  #File
EndEnumeration
 
Structure colorarraystr
  Array Y.u(0)
EndStructure
 
markx = 16
marky = 16
 
Global Dim X.colorarraystr(markx)
For i = 0 To markx
  ReDim X(i)\Y(marky)
Next

Global Dim TyleArray(16)
Global *MemForSaveImage = AllocateMemory(512)
 
; write data
X(0)\Y(0)  = 1 ; tyle N1 area
X(10)\Y(0) = 1 ; tyle N3 area
X(0)\Y(10) = 1 ; tyle N2 area
;X(15)\Y(9) = 1 ; tyle N4 area
 
                      ;If CreateFile(#File, "D:\test")
                        x = 0
                        y = 0
                        xlim = 8
                        
                        limitfortyle = 32
                        tylenumber   = 1
                        tikmem       = 0
                        
                        ; reset array
                        Dim TyleArray(16)
                  
                        Repeat
                          
                          ; make variable for write
                          first = X(x)\Y(y)
                          x = x + 1
                          second = X(x)\Y(y)
                          x = x + 1
                          Number = first << 4
                          Number + second
                          
                          TyleArray(tylenumber) + Number
                          
                          limitfortyle - 1
                          If limitfortyle = 0                            
                            limitfortyle = 32
                            tylenumber + 1
                          EndIf
                          
                          PokeA(*MemForSaveImage+tikmem, Number)
                          tikmem + 1                    
                          ;WriteAsciiCharacter(#File, Number)
                          
                          ; catch end of file
                          If x = markx And y = marky-1
                            Break
                          EndIf
                          
                          ; write file from up to down blocks 8х8
                          If x = xlim
                            x = xlim - 8
                            y = y + 1
                            If y = marky
                              y = 0
                              x = xlim
                              xlim = xlim + 8
                            EndIf
                          EndIf
                    
                        ForEver                        
                        
                        ;CloseFile(#File)
                      ;EndIf
                        
                      For i = 16 To 1 Step -1
                        If TyleArray(i)
                          Debug "size for WriteData is " + Str(i*32)
                          Break
                        EndIf
                      Next
                      
:P
SeregaZ
Enthusiast
Enthusiast
Posts: 628
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: image saving algorithm

Post by SeregaZ »

same problem, but with colors.

i have image as array with colors num and palette array, with RGB. all work fine... until i am need to move main image. when i move this image - i will need rewrite array-image. i think to use Point(x, y) for get colors and write it into array... BUT! what if palette will have 2 same colors? original array will have some 1, 1, 1, 2, 2 colors. but after move image and Point(x, y) - it will have 1, 1, 1, 1, 1 - this 2 index for color will be eat.

any way to save all indexes, even image will have 2 same colors in a palette?

start drag and drop over image and move box to some place.

Code: Select all

Enumeration
  #Window
  #GraficCont1MainCanvas
  #GraficTempRImage3
EndEnumeration

; array-image structure
Structure CoordY
  Y.a[144]
EndStructure
Dim X.CoordY(144)
; data
X(50)\Y[50] = 1
X(50)\Y[51] = 1
X(50)\Y[52] = 1
X(50)\Y[53] = 1
X(51)\Y[50] = 1
X(51)\Y[51] = 1
X(51)\Y[52] = 1
X(51)\Y[53] = 1
X(52)\Y[50] = 2
X(52)\Y[51] = 2
X(52)\Y[52] = 2
X(52)\Y[53] = 2
X(53)\Y[50] = 2
X(53)\Y[51] = 2
X(53)\Y[52] = 2
X(53)\Y[53] = 2

; palette
Dim Pal.l(3)
Pal(0) = 0
Pal(1) = RGB(200, 0, 0)
Pal(2) = RGB(200, 0, 0)

CreateImage(#GraficTempRImage3, 576, 576)
If StartDrawing(ImageOutput(#GraficTempRImage3))
  For x = 0 To 143
    For y = 0 To 143
      Box(x*4, y*4, 4, 4, Pal(X(x)\Y[y])) ; becouse image is *4 from original
    Next
  Next
  StopDrawing()
EndIf

If OpenWindow(#Window, 100, 200, 600, 600, "", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)

  CanvasGadget(#GraficCont1MainCanvas, 5, 5, 576, 576)
  SetGadgetAttribute(#GraficCont1MainCanvas, #PB_Canvas_Image, ImageID(#GraficTempRImage3)) 

  Repeat
    Event = WaitWindowEvent()
    
    Select Event
      Case #PB_Event_Gadget
        EvGadget = EventGadget()
        Select EvGadget
          Case #GraficCont1MainCanvas
            MHMainX = GetGadgetAttribute(#GraficCont1MainCanvas, #PB_Canvas_MouseX)
            MHMainY = GetGadgetAttribute(#GraficCont1MainCanvas, #PB_Canvas_MouseY)
            
            Select EventType()
                
              Case #PB_EventType_LeftButtonDown
                    ; start dragndrop
                    MHDragndrop = 1
                    
                    ; get starting coordinates
                    MHStartX = MHMainX
                    MHStartY = MHMainY
                    
                    MHOrigX = 0
                    MHOrigY = 0
                    
                    ;Debug "its start"                    
                    
              Case #PB_EventType_LeftButtonUp
                    ; end of drangndrop
                    MHDragndrop = 0
                    ; paint with grab
                    If StartDrawing(ImageOutput(#GraficTempRImage3))                  
                      DrawImage(GetGadgetAttribute(#GraficCont1MainCanvas, #PB_Canvas_Image), 0, 0, 576, 576)                  
                      StopDrawing()
                    EndIf
                    ;Debug "end dragndrop"
                    
              Case #PB_EventType_MouseMove
                    ; work only if dragndrop starts
                    If MHDragndrop
                      
                      ; get new coordinates
                      MHMoveX = MHMainX
                      MHMoveY = MHMainY
                      
                      ; get shift
                      MHCurrX = (MHStartX - MHMoveX) / 4
                      MHCurrY = (MHStartY - MHMoveY) / 4
                      ; if that shift exists
                      If MHCurrX Or MHCurrY

                        MHStartX = MHMoveX
                        MHStartY = MHMoveY
                        
                        MHOrigX - MHCurrX * 4
                        MHOrigY - MHCurrY * 4
                                                
                        If StartDrawing(CanvasOutput(#GraficCont1MainCanvas))
                          Box(0, 0, 576, 576, 0)
                          ; main image
                          DrawImage(ImageID(#GraficTempRImage3), MHOrigX, MHOrigY)
                          ; get colors from Point(x, y) and rewrite image-array???
                          ; it is suks!
                          StopDrawing()
                        EndIf
                      
                      EndIf                      
                      ;Debug "mouse move"
                    EndIf
                    
            EndSelect
        EndSelect  
    
      Case #PB_Event_CloseWindow
        GraficQuit = 1

    EndSelect    

  Until GraficQuit = 1 
  
EndIf
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: image saving algorithm

Post by djes »

You should create procedures to make these operations when needed and test different solutions with as many procedures as you want. The output should be on an image, not directly on the canvas, because they are more flexible in terms of size and drawing operations. Canvas is cool, but should be seen as a final rendering destination.

You can also create a second array with the needed result. Why don't you use a two dimensional array?
User avatar
Franky666
User
User
Posts: 17
Joined: Wed Jan 09, 2008 10:43 pm
Location: Germany

Re: image saving algorithm

Post by Franky666 »

It is hard to me to understand what you want exactly. So I might miss the topic. :mrgreen:
for this example final file is have 128 bytes. 4 tyles - blocks 8x8 pixels. but for this example only 3 tyles have "data". last one - 4 have all empty colors 0 for all 64 pixels (8x8). how to make some algorithm for save only that data, where lays data.
If that is for retro console, don't save the empty tiles to minimize ROM size. If it is for PC, it doesn't really matter, if you write a few wasting zeros at that file size. (a single cluster of the filesystem has 4 or more kb in most cases and there is no difference if the file is 1, 256 or 4096 bytes of size.)

To prevent wasting, check if a tile is empty. If so, just don't write to the file at all. Let the corresponding file reading algorithm read tile by tile until it reaches the EOF. Or better: specify a small header that contains the information, how many tiles are in the file and which tile index they are for (so if #2 is empty, the #3 keeps #3). If the files are is still too big, try some basic row-based RLE algorithm (4x black, then 2x green, then 5x blue...).
what if palette will have 2 same colors?
Then these don't differ in the final rendered image anymore. The information from which palette entry the color came is getting lost during converting the indexed tiles to RGB. There is no much you can do to prevent that.

What is the reason to have two equal palette entries? And for your internal logic that shouldn't be an issue if you work with only the raw vales (0-15), where the two entries are still different. Use the palette only for color mapping at final rendering (without converting back the resulting output image to palette index arrays!). :wink:
SeregaZ
Enthusiast
Enthusiast
Posts: 628
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: image saving algorithm

Post by SeregaZ »

Franky666, with tyle saving is solved :) try to comment some of string in my code:

Code: Select all

X(0)\Y(0)  = 1 ; tyle N1 area
X(10)\Y(0) = 1 ; tyle N3 area
X(0)\Y(10) = 1 ; tyle N2 area
;X(15)\Y(9) = 1 ; tyle N4 area
and you will see changing final size for save. this for example only 1 pixel is exists.

about clusters on HDD - for windows it probably not matter, but our game compiler read this as file. so if file have 128 bytes and last part is 0 - compiler will add to game all. so that is why i am recount size of file according pixels. it will save a lot of resourses for game.
Image


about 2 same colors - problem is 0 color index is transparent in that 16 table colors. but this 0 can have same color as another slot. for image render not matter... but i try to make image editor. if i will move image on canvas and read all colors with Point(x, y) in new position - all same colors - it was black - will be all transparent. that is why i need some kind of array-shift procedure... i didnt catch it in my head yet.
Image
SeregaZ
Enthusiast
Enthusiast
Posts: 628
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: image saving algorithm

Post by SeregaZ »

probably i need to set restrict for purple color. i mean denide to change any colors from 1 to 15 for purple. and when read palette procedure starts - read 0 always as purple. it will probably save that 2 colors problem. but what if users before it by manualy set this purple in one of colors? :evil:
SeregaZ
Enthusiast
Enthusiast
Posts: 628
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: image saving algorithm

Post by SeregaZ »

probably it can be some kind if this:

Code: Select all

; array-image structure
Structure CoordY
  Y.a[20]
EndStructure
Global Dim X.CoordY(20)
; data
X(10)\Y[10] = 1
X(10)\Y[11] = 1
X(10)\Y[12] = 1
X(10)\Y[13] = 1
X(11)\Y[10] = 1
X(11)\Y[11] = 1
X(11)\Y[12] = 1
X(11)\Y[13] = 1
X(12)\Y[10] = 2
X(12)\Y[11] = 2
X(12)\Y[12] = 2
X(12)\Y[13] = 2
X(13)\Y[10] = 2
X(13)\Y[11] = 2
X(13)\Y[12] = 2
X(13)\Y[13] = 2

; palette
Dim Pal.l(3)
Pal(0) = 0
Pal(1) = RGB(200, 0, 0)
Pal(2) = RGB(200, 0, 0)

Dim X2.CoordY(20)

Procedure DebugArray()
For x = 0 To 19
  tmp$ = ""
  For y = 0 To 19
    tmp$ + Str(X(x)\Y[y]) + " "
  Next
  Debug tmp$
Next
Debug ""
Debug ""
EndProcedure

DebugArray()

shiftx = 5
shifty = 2

If shiftx >= 0 And shifty >= 0
  For x = 0 To 19 
    If x + shiftx < 19
      For y = 0 To 19
        If y + shifty < 19
          X2(x)\Y[y] = X(x + shiftx)\Y[y + shifty]
        EndIf
      Next
    EndIf
  Next  
EndIf

CopyArray(X2(), X())

DebugArray()
but effect is a little not that i thought :) +5 for x and +2 - it must be move to right and down, but debug shows it move left and up :) and a lot of cases for shiftx >= 0 And shifty >= 0. very dirty. i am not like that.
Post Reply