Skip to content

Commit

Permalink
Reuse color ramp memorry placement when already available
Browse files Browse the repository at this point in the history
  • Loading branch information
karimnaaji committed May 15, 2020
1 parent 8d83283 commit 13779a5
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/style/style_layer/line_style_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class LineStyleLayer extends StyleLayer {
const maxTilePixelSize = 1024;
const maxTextureCoverage = geometryTileCoverageAtMaxZoom * maxTilePixelSize;
const textureResolution = nextPowerOfTwo(clamp(maxTextureCoverage, 256, maxTextureSize));
this.gradient = renderColorRamp(expression, 'lineProgress', this.stepInterpolant ? textureResolution : 256);
this.gradient = renderColorRamp(expression, 'lineProgress', this.stepInterpolant ? textureResolution : 256, this.gradient || undefined);
}
recalculate(parameters: EvaluationParameters, availableImages: Array<string>) {
Expand Down
22 changes: 15 additions & 7 deletions src/util/color_ramp.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,28 @@ import type {StylePropertyExpression} from '../style-spec/expression/index';
*
* @private
*/
export default function renderColorRamp(expression: StylePropertyExpression, colorRampEvaluationParameter: string, textureResolution?: number): RGBAImage {
export default function renderColorRamp(expression: StylePropertyExpression, colorRampEvaluationParameter: string, textureResolution?: number, image?: RGBAImage): RGBAImage {
const resolution = textureResolution || 256;
assert(isPowerOfTwo(resolution));
const colorRampData = new Uint8Array(resolution * 4);
let outImage;

if (image && image.width === resolution) {
outImage = image;
} else {
outImage = new RGBAImage({width: resolution, height: 1});
}

const evaluationGlobals = {};
for (let i = 0, j = 0; i < resolution; i++, j += 4) {
evaluationGlobals[colorRampEvaluationParameter] = i / (resolution - 1);
const pxColor = expression.evaluate((evaluationGlobals: any));
// the colors are being unpremultiplied because Color uses
// premultiplied values, and the Texture class expects unpremultiplied ones
colorRampData[j + 0] = Math.floor(pxColor.r * 255 / pxColor.a);
colorRampData[j + 1] = Math.floor(pxColor.g * 255 / pxColor.a);
colorRampData[j + 2] = Math.floor(pxColor.b * 255 / pxColor.a);
colorRampData[j + 3] = Math.floor(pxColor.a * 255);
outImage.data[j + 0] = Math.floor(pxColor.r * 255 / pxColor.a);
outImage.data[j + 1] = Math.floor(pxColor.g * 255 / pxColor.a);
outImage.data[j + 2] = Math.floor(pxColor.b * 255 / pxColor.a);
outImage.data[j + 3] = Math.floor(pxColor.a * 255);
}
return new RGBAImage({width: resolution, height: 1}, colorRampData);

return outImage;
}
60 changes: 59 additions & 1 deletion test/unit/util/color_ramp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function nearlyEquals(a, b) {
return a.every((e, i) => Math.abs(e - b[i]) <= 3);
}

test('renderColorRamp', (t) => {
test('renderColorRamp linear', (t) => {

const expression = createPropertyExpression([
'interpolate',
Expand All @@ -47,3 +47,61 @@ test('renderColorRamp', (t) => {

t.end();
});

test('renderColorRamp step', (t) => {

const expression = createPropertyExpression([
'step',
['line-progress'],
'rgba(0, 0, 255, 0.1)',
0.1, 'red',
0.2, 'yellow',
0.3, 'white',
0.5, 'black',
1, 'black'
], spec, {handleErrors: false}).value;

const ramp = renderColorRamp(expression, 'lineProgress', 512);

t.equal(ramp.width, 512);
t.equal(ramp.height, 1);

t.equal(pixelAt(ramp, 0)[3], 25, 'pixel at 0.0 matches input alpha');
t.ok(nearlyEquals(pixelAt(ramp, 50), [0, 0, 255, 25]), 'pixel < 0.1 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 53), [255, 0, 0, 255]), 'pixel > 0.1 & < 0.2 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 103), [255, 255, 0, 255]), 'pixel > 0.2 & < 0.3 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 160), [255, 255, 255, 255]), 'pixel > 0.3 & < 0.5 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 256), [0, 0, 0, 255]), 'pixel > 0.5 matches input');

t.end();
});

test('renderColorRamp usePlacement', (t) => {

const expression = createPropertyExpression([
'step',
['line-progress'],
'rgba(255, 0, 0, 0.5)',
0.1, 'black',
0.2, 'red',
0.3, 'blue',
0.5, 'white',
1, 'white'
], spec, {handleErrors: false}).value;

let ramp = renderColorRamp(expression, 'lineProgress', 512);

t.equal(ramp.width, 512);
t.equal(ramp.height, 1);

ramp = renderColorRamp(expression, 'lineProgress', 512, ramp);

t.equal(pixelAt(ramp, 0)[3], 127, 'pixel at 0.0 matches input alpha');
t.ok(nearlyEquals(pixelAt(ramp, 50), [255, 0, 0, 127]), 'pixel < 0.1 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 53), [0, 0, 0, 255]), 'pixel > 0.1 & < 0.2 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 103), [255, 0, 0, 255]), 'pixel > 0.2 & < 0.3 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 160), [0, 0, 255, 255]), 'pixel > 0.3 & < 0.5 matches input');
t.ok(nearlyEquals(pixelAt(ramp, 256), [255, 255, 255, 255]), 'pixel > 0.5 matches input');

t.end();
});

0 comments on commit 13779a5

Please sign in to comment.