It looks like you're new here. If you want to get involved, click one of these buttons!
I am working on on a program that colorizes grayscale images with color gradients.
The first hurdle was to create good color gradients.
Why? What's wrong with normal gradients?
The problem with normal color gradients like in photoshop or illustrator, is that they make linear transitions from one color stop to the next. In your artwork or photo that shows up as oversaturated stripes. I would find myself manually adding more color stops to the gradient to make the transitions more gradual. That is a tedious process. You can also use the duo tone system, but that is even more cumbersome.
This program tackles the problem with a different approach.
The classic color gradients can be seen as a 3D polygon through the rgb color cube. Starting from the black point drawing straight lines to the color stops to end at the white point. A grayscale gradient would be a straight diagonal line from black to white.
This program changes the polygon into a Bézier curve at starts at the black point, but then curves around the gray diagonal in the middle.
The program takes three colors, a pure color, a shade and highlight as input and uses them as attractor points. Non of the attractor colors are actually one the curve, but they sequential pull the curve away from the gray center line.
The next issue was to compensate for luminosity. Colors have dramatically different luminosity compared to there rgb values, so I had to find a way to redistribute the color stops according to their perceived lightness.
This is my first Codea program after many years of not coding and I'm still on a steep learning curve.
Feel free to point out where my code is clunky or old school.
For instance the colorize function changes the test image pixel by pixel. Is there a way to replace that function with a shader?
I also have a few other questions, but first I'll post the code and show you what it does.
Comments
Hmm, how do I paste my code into a post?
Ah, got it.
Here is a video.
a shader can absolutely do this for you, as I'm sure someone will demonstrate..but nice work anyway
Here's an example of a colour gradient shader:
http://codea.io/talk/discussion/6772/multiple-step-colour-gradient-shader
It just uses the GLES smoothstep function, which I believe is a hermite curve, so not smooth enough for your needs I imagine. It wouldn't be too hard to throw a different algorithm into the fragment shader though.
Thanks @Ignatz! I think I figured it out with your ebook.
Just made my first fragment shader.
The trick is to feed it the color range image as a second texture and use it as a lookup table for the first.
Thanks for putting me on the trail of the smoothstep function and the hermite curve, @yojimbo2000. That will come in handy in situations where I want to force the curve through anchor points. I didn't have an algorithm for that.
More to experiment.
@tyxs - that's great, well done!
Have fun! =D>
All done. Now all time critical functions have been replaced by shaders.
Changing the parameter colors immediately changes the image.
Awesome! That certainly is a very smooth gradient, looks gorgeous. Putting your own images in is a lot of fun.
I have no idea how the maths works! I'm curious about your background. Is this for a pro imaging application?
If you're interested in curves that go through control points, I also have a GLES version of the Catmull-Rom curve.
A couple of thoughts. Does the gradient range map need to be built every cycle? You could perhaps add a callback to the color pickers so that it just gets built when the colors are changed? Also, the
range
gradient image could just be 1 pixel wide, couldn't it?@yojimbo Thanks! I've been a hobby programmer for years, but totally out of shape these days. I used to make stuff in basic and had formal training in Pascal.
I'm also a hobby artist. In real life I do other stuff. This experiment in Codea is born out of frustration with all painting and sketching programs. I have a latent ambition to launch a drawing app, but let's be realistic. I'm chewing on every line of code in my limited spare time. Codea doesn't even have direct access to the photo album. If I can make an awesome drawing tool on the iPad for my own use, I'm a happy coder and artist.
So the frustration that fuels this program is the way that all drawing programs deal with color. They don't offer a logical way to colorize gray drawings or photos. Have you ever tried to colorize a black and white photo in Photoshop? It's a struggle and there are no simple guidelines. And the results are usually disappointing. It's not that I don't know how to do it. I know several ways to color a picture in Photoshop. I'm just not satisfied with any of the available solutions.
So this Codea experiment is to test some of my ideas how to do it better.
One of the problems Is that the rgb color system doesn't take a colors luminosity into account. Luminosity is the perceived lightness of a color. In the rgb color system red, green and blue build up to white in 255 equal steps. But in our visual system, they don't contribute to the luminosity of white in equal amounts. Blue only adds a fraction of light to a color and green adds the most. Green and red together, making yellow come very close to white. So when you change a gray pixel into a color, you actually change the luminosity of that pixel dramatically.
My idea is to make drawing or imaging tools that allow you to change a color and at he same time keep the luminosity unchanged unless the user wants to change it. I think this program is a good start and I'm very pleased to lean about the shader possibilities this weekend!
My next step will be to allow the user to paint on the image with this gradient. So that you can color different areas with different gradients.
Another idea is to create a painting tool where you pick a color range instead of just one color. And paint a picture from scratch.
Curves that force through control points will be useful for another idea that I have in mind, but I'll get back to you when I come to that.
The range image should probably not be built up in the draw function every time. But I haven't figure out how to structured my events properly, and they don't slow down the program noticeably, so for now... Good idea to put it in a callback function. But I might as well start thinking about a user interface.
And yes, one pixel wide should do it, but I wondered if the edges don't blur? And a height of a 1000 is probably more then necessary as well.
Making progress. Just a idea of where I'm heading.

Looks good! How many pixels is that canvas?
Normal iPad screen size. I havent bothered showing screen edges yet. But it scales and rotates with pinch gesture.