To convert the black wave to the red signal.

Taking forward Jesse Craig's answer and dukeling's comment of spotting a switch between increasing and decreasing does yield a solution, at least in simple cases where there is no noise.
E.g. with this input signal

if you calculate the differences between consecutive values of y (the code below is in R, so is operating on vectors)
diffs = y[2:length(y)] - y[1:length(y)-1]
then the signs of the differences
dir = sign(diffs)
assuming that no values are equal (we have no zeros in diffs), you can spot a direction change by looking for where the signs are different
dir_change = dir[2:length(dir)] != dir[1:length(dir)-1]
# no change of direction for first two positions
dir_change = c(FALSE, FALSE, dir_change)
This identifies the maxima and minima, (where dir_change is TRUE)

and the square wave can be calculated as Jesse Craig suggested, by taking the midpoints between the maxima and minima.
So far so good. I wasn't sure if the OP's signal included noise. Assuming that it did, I tried a few techniques to try to identify maxima and minima with noise present, but I found it pretty hard (I've spent at least 10x as long trying to get an algorithm that is robust to noise as I did on the above code). I tried a moving average, and some simple thresholding, but I couldn't get either technique to work straightforwardly. This seems to confirm it's not trivial to deal with noise! I'd be interested if anyone could comment (or I could search for or ask an SO question on this).
Edit there is a nice summary of peak detection methods in this answer.
You need to use a local search technique like Hill Climbing to identify all the local minimums and maximums. That will give you all the horizontals lines in your square wave. Then find the mid point (value of X for the mean value of Y) between adjacent local maximums and minimums and that will tell you where the edges (vertical lines) in your square wave are found.