[SOLVED]FOR loop problem in drawing event

W

Wraithious

Guest
Hi, I'm having a horrible time trying to get this FOR loop to work correctly, I will explain it first.
What it's supposed to do:
takes segments from an image and draws them in order 1 time to make a complete new image while background_showcolour=false, then a picture is taken of the image, assigned to a sprite, then an object has it's sprite changed to the new picture and background_showcolour is set back to true.

How it's set up:
user loads picture, the processor object is created and in it's create event breaks up the picture into 50 x 50 chunks max size (2500 pixels) and records how many chunks (segments), the starting x,y of each segment, the width and height of each segment, and the area of each segment.
the user presses enter, enter sets starting point of picture and sets alarm.
Alarm gets and evaluates each pixel in the image segment by segment, after each segment is processed the alarm lets the step event take a step which updates the progress bar, then if there are more segments sets the alarm again, repeats until all segments are done.
This is where the drawing event is now activated with the for loop i've spent 3 days trying to get to work correctly,
The for loop variables explained:

brk- the number of segments in the image
array colorize[ brk-1 ] - if all segments have been processed (brk -1 because arrays start at 0)
o- itterator value
h- total number of pixels in the complete image
g- incremental variable for x positions in the current segment
l- incremental variable for y positions in the current segment
colorsmake[ ] - array holding every pixel's color in the complete image
drwatx[ ] - array variable for the starting x position of the current segment
drwaty[ ] - array variable for the starting y position of the current segment
iii- variable to define which segment we are currently drawing, starts as 0 and ends at brk-1
v[ ] - width of the current segment in pixels
w[ ] - height of the current segment in pixels

The Loop code in the drawing event:
Code:
///Colorize effect
if(global.effect=8 && global.snshop=1 && colorize[brk-1]=1)//if true draw the image
{
    for(o=0;o<h;o+=1;)
    {
        draw_point_colour(g,l,colsmake[o]);
        g+=1;
        if(g=drwatx[iii]+v[iii] && l<drwaty[iii]+w[iii])
        {
            g=drwatx[iii];
            l+=1;
        }
        if(g=drwatx[iii]+v[iii] && l=drwaty[iii]+w[iii] && iii<brk)
        {
            iii+=1;
            g=drwatx[iii];
            l=drwaty[iii];
        }
    }
}
If the picture is 50 x 50 pixels or smaller it works perfectly, but if it's larger This is what I get at best for a result:
forloopdisaster.png
The picture on the right is the result, I broke it up (left pic) to try and see what was going on, and it looks like the for loop is not deligating the segments correctly, in fact, each time the loop ends a segment it cuts off the top row of the 2nd segment, top 2 rows of the 3rd, then switches and cuts off the last 3 rows of the 4th, last 4 rows of the 5th, etc till the last segment, as you can also see the missing segments are there and evenly fragmented through the entire image!! what is going on here?! Please if anyone can help with what I'm doing wrong that would be awesome, if you need more code I can provide it but I know from checking the other codes that feed this loop they are all correct.
 

TheouAegis

Member
Ah the joys of working with multiple iterators. By the way, do you need the 'o' for loop? I mean, g and l are already covering each pixel per segment and iii is covering each segment, so it seems like o is redundantly needless. Then again, I'm just eyeballing it and trying to make sense of it. These kinds of loops gave me a headache when trying to work on my NDS file decryptor.
 

Alvare

Member
It cuts off the wrong height on each segment from a sprite larger than 50px. Pretty weird. So it works 100% correctly when having 49px? V is width and w is height. And it progressively cuts off part of the next ones.. Seems to me that the number of segments aren't correctly divided over the amount of pixels.
I think I'm gonna need more information than the for loop.
 
Last edited:
W

Wraithious

Guest
By the way, do you need the 'o' for loop
Hmmm, you hava a point there, o does have to increment by 1, every time g increments, but i could maybe use a while loop instead

So it works 100% correctly when having 49px?
Yes, even if it's 50 x 50, i'll post more code when i get to my computer

Ok, I'll post the codes in the order of execution-
in the create event of the processor object colbnw:
Code:
create event-
a=0;b=0;c=0;d=0;g=0;h=0;i=0;ii=0;iii=0;j=0;k=0;l=0;m=0;n=0;o=0;p=0;s=0;t=0;u=0;brk=0;bwatch=0;donz=0;canbreak=0;wkg=0;cbit=1;colsr=0;colsg=0;colsb=0;
colspicked=noone;global.instruct="Loading...";sbw1="";//initializes non array variables (yep, here's pretty much the rest of the alphabet lol)
if(instance_exists(picture1))
{j=(picture1.bbox_right+1)-picture1.bbox_left;
k=(picture1.bbox_bottom+1)-picture1.bbox_top;
h=(j*k);
s=j mod 50;//if last x segment in row is less than 50 pixels
t=k mod 50;//if last y segment in last row is less than 50 pixels
c=(ceil(j/50));//determins how many segments in x plane
d=(ceil(k/50));//determins how many segments in y plane
brk=c*d;
for(i=0;i<h+1;i+=1){colsmake[i]=0;}//now we can initialize the arrays
for(i=0;i<=brk+1;i+=1)
{v[i]=0;//width in pixels of segments
w[i]=0;//height in pixels of segments
z[i]=0;//area of segments
drwatx[i]=0;//start x of segments
drwaty[i]=0;//start y of segments
colorize[i]=0;}//variable for later use in the drawing event
if(h<=2500)// if picture is less than or equals 50 x 50
{
    drwatx[0]=picture1.bbox_left;
    drwaty[0]=picture1.bbox_top;
    v[0]=j;
    w[0]=k;
    z[bwatch]=h;
}
if(h>2500)//WHILE LOOP executes if picture is greater than 50 by 50 pixels
{
        while(a<c && b<d-1)
        {
        if(a<c)
            {
            drwatx[ii]=picture1.bbox_left+(a*50);
        if s=0 v[ii]=50;
        if s !=0 && a<c-1 v[ii]=50;
        if s !=0 && a=c-1 v[ii]=s;
            drwaty[ii]=picture1.bbox_top+(b*50);
            w[ii]=50;
            z[ii]=v[ii]*w[ii];
            a+=1;
            ii+=1;
            }
        if(a=c)
            {
            b+=1;
            a=0;
        }
    }
    while(a<c && b=d-1)
        {
            drwatx[ii]=picture1.bbox_left+(a*50);
        if s=0 v[ii]=50;
        if s !=0 && a<c-1 v[ii]=50;
        if s !=0 && a=c-1 v[ii]=s;
            drwaty[ii]=picture1.bbox_top+(b*50);
        if t=0 w[ii]=50;
        if t !=0 w[ii]=t;
            z[ii]=v[ii]*w[ii];
            a+=1;
            ii+=1;
        }
    }
}
press enter event:
Code:
wkg=1;bwatch=0;donz=0;global.cent=0;m=drwatx[bwatch];n=drwaty[bwatch];e=0;iii=0;
background_showcolour=false;alarm[0]=1;global.instruct="Rendering..#   0%";
Alarm[0] event:
Code:
for(u=0;u<(z[bwatch]);u+=1;)
{colspicked=surface_getpixel(application_surface,m,n);//gets every pixel color
colsr=colspicked & 255;colsg=(colspicked >> 8)& 255;colsb=(colspicked >> 16)& 255;//splits colors to rgb
p=colsr+colsg+colsb;//determins brightness of color
if p<=255 cbit=1;if p>255 && p<=510 cbit=2;if p>510 cbit=3;//1=dark,2=medium,3=light//gives 3 results light,medium and dark
if(global.palrgb=1)//applies desired effect on each pixel
{if cbit=1 colsmake[(u+donz)]=make_colour_rgb(255,colsg,colsb);
if cbit=2 colsmake[(u+donz)]=make_colour_rgb(colsr,255,colsb);
if cbit=3 colsmake[(u+donz)]=make_colour_rgb(colsr,colsg,255);}
if(global.palrgb=2)
{if cbit=1 colsmake[(u+donz)]=make_colour_rgb(255,colsg,colsb);
if cbit=2 colsmake[(u+donz)]=make_colour_rgb(colsr,colsg,255);
if cbit=3 colsmake[(u+donz)]=make_colour_rgb(colsr,255,colsb);}
if(global.palrgb=3)
{if cbit=1 colsmake[(u+donz)]=make_colour_rgb(colsr,255,colsb);
if cbit=2 colsmake[(u+donz)]=make_colour_rgb(255,colsg,colsb);
if cbit=3 colsmake[(u+donz)]=make_colour_rgb(colsr,colsg,255);}
if(global.palrgb=4)
{if cbit=1 colsmake[(u+donz)]=make_colour_rgb(colsr,255,colsb);
if cbit=2 colsmake[(u+donz)]=make_colour_rgb(colsr,colsg,255);
if cbit=3 colsmake[(u+donz)]=make_colour_rgb(255,colsg,colsb);}
if(global.palrgb=5)
{if cbit=1 colsmake[(u+donz)]=make_colour_rgb(colsr,colsg,255);
if cbit=2 colsmake[(u+donz)]=make_colour_rgb(colsr,255,colsb);
if cbit=3 colsmake[(u+donz)]=make_colour_rgb(255,colsg,colsb);}
if(global.palrgb=6)
{if cbit=1 colsmake[(u+donz)]=make_colour_rgb(colsr,colsg,255);
if cbit=2 colsmake[(u+donz)]=make_colour_rgb(255,colsg,colsb);
if cbit=3 colsmake[(u+donz)]=make_colour_rgb(colsr,255,colsb);}
if(m<drwatx[bwatch]+v[bwatch]){m+=1;}
if(m=drwatx[bwatch]+v[bwatch] && n=drwaty[bwatch]+w[bwatch]){m=drwatx[bwatch];}
if(m=drwatx[bwatch]+v[bwatch] && n<drwaty[bwatch]+w[bwatch]){m=drwatx[bwatch];n+=1}
if(u>=z[bwatch]-1){canbreak=1;colorize[bwatch]=1;}//if segment is done canbreak is 1 and the step event can take a step and update the progress % bar
}
Step event:
Code:
if(canbreak=1)
{canbreak=0;
if(bwatch>=brk-1)
{global.instruct="Finished!";
global.cent=95;//keeps the progress bar from going past desires boarder
global.inc1+=1;
g=drwatx[0];l=drwaty[0];//sets starting point in first segment for draw event
alarm[2]=1;wkg=0;global.snshop=1;global.lock2=1;//sets up the variables for the result image to be taken and saved in other alarms
}
if(bwatch<brk-1)//if there are more segments run alarm[0] again
{donz+=z[(bwatch)];bwatch+=1;//donz are # of pixels completed, bwatch tells us which segment we are on
m=drwatx[bwatch];n=drwaty[bwatch];//resets x,y start position for next segment
global.cent=round((95/(h/donz)));//updates progress % bar
global.instruct="Rendering-#   "+string((global.cent+5))+"%";
alarm[0]=1;}
}
 
Last edited by a moderator:
W

Wraithious

Guest
I think I'm gonna need more information than the for loop.
Ok even better I made a small project, you can download the gmz here:
EDIT: DELETED this gmz, new project link is below v v
 
Last edited by a moderator:
W

Wraithious

Guest
So I've made a couple of changes but nothing has made any difference, this video shows that when rendering a b&w pic larger than 50x50 pixels the result pic is somewhat scrambled, but a 50x50 pic works perfectly. you can skip to about 2 minuites as when screen recording it takes twice as long to render, also you can see in the video i dragged the 2 result pics on the originals and alpha'd them out so you can clearly see the problem:


Also here's a small updated .gmz of the project, nothing seems to make any difference but I tested and tested different variables using the draw event and everything seems to be working correctly, I'm pretty sure it has to be the for loop in the drawing event throwing me off somehow, if anyone can check out the .gmz and tell me what I'm doing wrong, I'm going crazy with this : (

https://drive.google.com/open?id=0B4uEFC9Ii8BnaXRGTEJPb0dzWVU

This is the current for loop in the draw event for object colbnw:
Code:
///Colorize effect
if(global.snshop=1 && colorize[brk-1]=1)
{
    for(o=0;o<h;o+=1;)
    {
        draw_point_colour(g,l,colsmake[o]);
        g+=1;       
        if(g=drwatx[iii]+v[iii] && l<drwaty[iii]+w[iii])
        {
            g=drwatx[iii];
            l+=1;
        }
        if(g=drwatx[iii]+v[iii] && l=drwaty[iii]+w[iii] && iii<brk)
        {
            iii+=1;
            g=drwatx[iii];
            l=drwaty[iii];
        }
    }
}
 
Last edited by a moderator:
W

Wraithious

Guest
So I have scrapped that whole idea (scrap idea #3 lol) and spent a couple of days learning about buffers and surfaces and that solved my problem!!! it's 10x faster and looks much better, thank you to @Tizzio of whom I found a nice example on the old forum and modified the living **** out of it and it works beautifully!!!
Basically in a create event you create and put a sprite onto a surface, create a fixed buffer with arguments width and height of desired sprite and create a second surface and put sprite on it, then use a
var n=0;
for(var yy=0;yy<h;yy++){
for(var xx=0;xx<w;xx++){
var col=buffer_read(buf,buffer_u32);
var a=(col >> 24) & 255;
var r=(col >> 16) & 255;
var g=(col >> 8) & 255;
var b=col & 255;
draw_set_alpha(a);
draw_set_color(make_colour_rgb(r,g,b));
draw_point(xx,yy);
n++;
}
}
, then in a GUI drawing event to draw the second surface, itterate through all the pixels with
xx=0;
yy=0;
n=0;
for(yy=0;yy<h;yy++)
{
for(xx=0;xx<w;xx++)
{
whole_picture(xx,yy);
n++;
}
}
, and call the buffer script
var pix=buffer_peek(buf,(argument0+argument1*surface_get_width(sur2))*4,buffer_u32);
var a=(pix >> 24) & 255;
var r=(pix >> 16) & 255;
var g=(pix >> 8) & 255;
var b=pix & 255;
p=r+g+b;
if p<=255 cbit=1;if p>255 && p<=510 cbit=2;if p>510 cbit=3;
draw_set_alpha(a);
if(global.palrgb=0)
{draw_set_color(make_colour_rgb(r, g, b));
}
if(global.palrgb=1)
{if cbit=1 draw_set_color(make_colour_rgb(global.trim,g,b));
if cbit=2 draw_set_color(make_colour_rgb(r,global.trim,b));
if cbit=3 draw_set_color(make_colour_rgb(r,g,global.trim));}
if(global.palrgb=2)
{if cbit=1 draw_set_color(make_colour_rgb(global.trim,g,b));
if cbit=2 draw_set_color(make_colour_rgb(r,g,global.trim));
if cbit=3 draw_set_color(make_colour_rgb(r,global.trim,b));}
if(global.palrgb=3)
{if cbit=1 draw_set_color(make_colour_rgb(r,global.trim,b));
if cbit=2 draw_set_color(make_colour_rgb(global.trim,g,b));
if cbit=3 draw_set_color(make_colour_rgb(r,g,global.trim));}
if(global.palrgb=4)
{if cbit=1 draw_set_color(make_colour_rgb(r,global.trim,b));
if cbit=2 draw_set_color(make_colour_rgb(r,g,global.trim));
if cbit=3 draw_set_color(make_colour_rgb(global.trim,g,b));}
if(global.palrgb=5)
{if cbit=1 draw_set_color(make_colour_rgb(r,g,global.trim));
if cbit=2 draw_set_color(make_colour_rgb(r,global.trim,b));
if cbit=3 draw_set_color(make_colour_rgb(global.trim,g,b));}
if(global.palrgb=6)
{if cbit=1 draw_set_color(make_colour_rgb(r,g,global.trim));
if cbit=2 draw_set_color(make_colour_rgb(global.trim,g,b));
if cbit=3 draw_set_color(make_colour_rgb(r,global.trim,b));}
draw_point(x+w+5+xx,y+yy);
every itteration. I even added a trim effect for the right and left arrows to decrease or increase the dominant color for each pallet scheme!

I still had to use for loops but even tho they are nested they are MUCH simpler than the creature double feature for loop I was trying to get to work haha
 
Top