I've looked for a while, but I wonder what the best way is to make a 2-dimensional rectangular gradient using a given color at each corner and interpolating the colors in the rest of the rectangle in the desired color space (like RGB, HSV, LAB, LUV, or HCL); I mean you see images like this......all the time, but I haven't found anything more workable than simply making gradients for two of the edges, and then based on the color values at each point of each edge, making gradients across the rectangle.(I've tried some questionable R code I found on StackOverflow, and a GIMP script called "2D Gradients," and an old "custom wallpaper" app that only did RGB interpolation, but I haven't found anything that easily makes images like the one above.)Maybe chroma.js is a better idea: http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/I'm also going to see whether Processing will work better: http://hclcolor.com/It's too bad that Inkscape doesn't implement "diffusion curves" because that more general idea would work too: http://wiki.inkscape.org/wiki/index.php/Diffusion_CurvesBTW that image was used in a Wikipedia article about why color TV signals can be understood by the ol' black-and-white: https://en.wikipedia.org/wiki/YUV
3/9/2013 1:36:33 AM
If you can interpolate in one dimension to make the edge gradient, what's keeping you from handling the 2D interpolation? This is a pretty easy task assuming you know how the color spaces work.
3/9/2013 8:19:38 AM
I was hoping there would be some way to make a gradient involving four colors at the corners of a rectangle that was as easy as the ways offered by typical image-editing programs to make gradients involving just two colors, like something I hadn't found yet, rather than something I'd have to whip up myself.
3/9/2013 12:10:16 PM
This is the second strange color gradient post you've made, its weird
3/9/2013 2:23:41 PM
^^you're basically making two linear two-color gradients. Then you're making multiple linear two color gradients connecting those two lines.
3/9/2013 4:41:24 PM
^I already said that in the OP, and I was hoping someone had automated the process of making all those gradients.[Edited on March 9, 2013 at 6:19 PM. Reason : ^^The "first one" you're thinking of was not about gradients but about individual colors.
3/9/2013 6:18:33 PM
what kind of "automation" are you looking for? You could easily write a Photoshop script to do it.
3/9/2013 9:02:46 PM
The kind of automation is an interface in which you just specify the colors at the four corners and the dimensions of the rectangle and out pops the gradient; I know I could code such a thing (I'm actually thinking about doing it with the HTML5 canvas) but wondered whether it had already been done.
3/9/2013 9:11:25 PM
k I tried using canvas and couldn't even get it to work for some reason...I might get back to that and even try out dat chroma.js: http://vis4.net/labs/185but I did figure out how to do almost what I wanted in R, using the following code to make the image below (the inverse of the image above, flipped so that lighter shades are still at the top)...
color.bar <- function(tpal,bpal,min,wid=100,hgt=wid,max=-min){ tlut=tpal(wid) blut=bpal(wid) scale = (hgt-1)/(max-min) dev.new(width=wid,height=hgt) plot(c(0,wid),c(min,max),type='n',bty='n',xaxt='n',xlab='',yaxt='n',ylab='') for(j in 1:wid){ lut=colorRampPalette(c(tlut[j],blut[j]),space="Lab")(hgt) for(k in 1:(hgt-1)){ y=(k-1)/scale+min rect(j-1,y,j,y+1/scale,col=lut[k],border=NA) } }}tpal=colorRampPalette(c("#AAFFF9","#BFC6FF"),space="Lab")bpal=colorRampPalette(c("#004055","#090040"),space="Lab")color.bar(tpal,bpal,1,200)
3/10/2013 3:43:57 AM
I'm still confused what you're looking for...are you asking for an algorithm, an application, or a website?What size images do you want? Is this for an on-going purpose? Is it a one-time thing? Is it curiosity? You don't appear to care about language, but you don't want to have to use an image editing app either...
3/11/2013 1:09:03 AM
I'm asking for a way, as easily as possible, to do something like this, whether it's already done on some website, packaged into a (preferably free) application, or described by an algorithm (which I could probably implement but would prefer not to have to), and it is indeed a curiosity.It's not an ongoing thing, and ideally it would create images of an arbitrary size; I don't get where you thought I "don't want to have to use an image editing app either" because I would actually love to see such a thing implemented in an image editor (I even tried a script in The GIMP that usually either gave me random rainbows or solid blocks of color).I think I'll further modify this R code I came up with (heavily modified itself from something I found on the Internets) to manually interpolate HSV color values, but I was hoping there was something more elegant than using brute force and essentially an O(n^2) algorithm (I mean the more general "Diffusion Curves" idea I could understand being that inefficient, but I'd think there would be a more elegant solution in this special case).
3/11/2013 1:28:52 AM
Here's my implementation in Matlab:
%RGB, range: 0-1colorInput1=[1 0 0];colorInput2=[0.5 0.5 0.2];colorInput3=[0.2 0.5 0.2];colorInput4=[1 0 0.2];%output size, plot with imshowoutputDim=[250 250];%output preallocationoutPut=NaN(outputDim(1),outputDim(2),3);%schematic illustrating how inputs translate to corners% 1 2%% 3 4%Linear interpolate values for each color components for top and bottom edgesR_1_2=linspace(colorInput1(1),colorInput2(1),outputDim(1));G_1_2=linspace(colorInput1(2),colorInput2(2),outputDim(1));B_1_2=linspace(colorInput1(3),colorInput2(3),outputDim(1));R_3_4=linspace(colorInput3(1),colorInput4(1),outputDim(1));G_3_4=linspace(colorInput3(2),colorInput4(2),outputDim(1));B_3_4=linspace(colorInput3(3),colorInput4(3),outputDim(1));%use loop to handle interpolation for each pair of edge pointsfor i=1:outputDim(2) outPut(:,i,1)=linspace(R_1_2(i),R_3_4(i),outputDim(2)); outPut(:,i,2)=linspace(G_1_2(i),G_3_4(i),outputDim(2)); outPut(:,i,3)=linspace(B_1_2(i),B_3_4(i),outputDim(2));end
3/11/2013 6:28:24 PM
Another method that's slower but provides a proper distance weighted interpolation:
colorInput1=[1 1 0.7];colorInput2=[1 0 1];colorInput3=[0 1 0];colorInput4=[0 1 1];outputDim=[1250 1250];x=[1 1 outputDim(1) outputDim(1)];y=[1 outputDim(2) 1 outputDim(2)];zr=[colorInput1(1) colorInput2(1) colorInput3(1) colorInput4(1)];zg=[colorInput1(2) colorInput2(2) colorInput3(2) colorInput4(2)];zb=[colorInput1(3) colorInput2(3) colorInput3(3) colorInput4(3)];[xq,yq] = meshgrid(1:outputDim(1),1:outputDim(2));vqr = griddata(x,y,zr,xq,yq);vqg = griddata(x,y,zg,xq,yq);vqb = griddata(x,y,zb,xq,yq);outPut=cat(3,vqr,vqg,vqb);
3/11/2013 7:49:16 PM
I hope this works in GNU Octave lol
3/11/2013 8:05:59 PM
It should.
3/11/2013 8:27:40 PM
This is much faster than that last bit of code I posted I remember that since this is effectively interpolating with a Cartesian grid, the interp2 function is orders of magnitude faster than the griddata of TriScatteredInterp functions:
colorInput1=[1 0.1 0];colorInput2=[1 0 1];colorInput3=[0 1 0];colorInput4=[0 0.1 1];outputDim=[1250 1250];x=[1 1; outputDim(1) outputDim(1)];y=[1 outputDim(2); 1 outputDim(2)];zr=[colorInput1(1) colorInput2(1); colorInput3(1) colorInput4(1)];zg=[colorInput1(2) colorInput2(2); colorInput3(2) colorInput4(2)];zb=[colorInput1(3) colorInput2(3); colorInput3(3) colorInput4(3)];[xq,yq] = meshgrid(1:outputDim(1),1:outputDim(2));vqr = interp2(y,x,zr,xq,yq);vqg = interp2(y,x,zg,xq,yq);vqb = interp2(y,x,zb,xq,yq);outPut=cat(3,vqr,vqg,vqb);
3/11/2013 10:17:24 PM
I'm guessing that your example uses vermilion, magenta, green, and blue, but I wonder whether there are any stability problems caused by, say, using four colors with 1 or 0 in all components, or possibly in having a gradient that goes through white (as the R documentation said would be problematic if I used CIELAB space, recommending RGB gradients if they would go through white).
3/11/2013 11:19:43 PM
The way I've done my interpolation, you can't pass through white since the color spaces is rgb. There should be zero issues for valid rgb colors. Using other color spaces raises some interesting issues. If you convert to rgb and do the interpolation in that color space you have to worry about colors that don't map from one space to another. If you do the same interpolation in the native color space, then you may have to change the interpolation technique sine some color spaces are cylindrical or spherical or just map colors in odd ways. It's an interesting problem. It's a similar challenge to a function I wrote to create color maps with constantly shifting hues that increase linearly in luminosity. The goal there was to create a color map that degraded to grayscale without banding and to aid colorblind readers of technical figures.
3/11/2013 11:48:51 PM
^^^ seems to break when using non-square dimensions.
3/12/2013 1:10:45 AM
changed these 2 lines:x=[1 1; outputDim(2) outputDim(2)];y=[1 outputDim(1); 1 outputDim(1)];
3/12/2013 1:51:23 AM
I still haven't tried out the Matlab code, but I did roll my own solution for HSV-based four-corner gradients and although I've only gotten it to work if the gradients don't cross the 0-hue plane, it doesn't really look much different for the range I've tried and only really looks different (albeit with an artifact at yellow that the CIELAB-based gradients lack) if it involves a massive difference in hue.Also, as might be imagined, if all four corners have high saturation but wildly differing hues, the gradients will zoom around the outside of HSV space rather than going through grey as an RGB or CIELAB-based gradient would.
3/18/2013 6:06:28 PM
3/18/2013 6:25:01 PM
I naively treated it like a rectangular prism, with the explicit goal of preserving hue as much as possible.
3/18/2013 7:43:37 PM
k so I still haven't tried out the Matlab code, but in the R code I think I made an image that is very much like that Wikipedia image that inspired this whole thread; I started with the slightly inaccurate notion that U represents "yellow vs. blue" (hues 60 vs. 240) and V represents "green vs. pink" (perpendicularly in HSV space, hues 150 vs. 330) and imagined that if we were interpolating in RGB space, the extreme -U,+V corner would be the most saturated orange at hue 15, the +U,+V corner would be the most saturated purple at hue 285, and so on (it's not quite accurate, because the YUV and sRGB gamuts don't quite match up, but it makes for good illustration), and then I interpolated in CIELAB space even though yet again it's not quite the same as actually doing the calculations of UV coordinates and it doesn't even match up with the spacing of the HSV model... For comparison, the pic from the OP is on the right.I've noticed that the Wikipedia image has broader regions of nearly flat color, possibly indicative of areas out of the sRGB gamut.[Edited on March 23, 2013 at 2:35 AM. Reason : a clearer comparison
3/23/2013 2:34:10 AM
This might help you understand YUV better:I'm still unclear what your goal is.
3/23/2013 11:16:46 PM
1. knew that, understood what it was about2. I wanted to make pretty pictures.
3/24/2013 5:33:15 AM
It turns out that the standard term (as a generalization) is "mesh gradient"; it's now available by default in Inkscape 0.92: http://wiki.inkscape.org/wiki/index.php/Mesh_Gradients
1/4/2017 8:28:18 PM