地図のレンダリングでは多種類の領域をそれぞれの色で塗りつぶす。 このとき、枠線は塗りつぶしの色を少し濃くしたい。 このような元の色より少し濃い色を計算式で求めたい。
ここでは精度は要求されないので、とりあえず、簡単な方法を試したい。 記事[2]によれば、HSV空間が良さそうだ。 色相、彩度、明度で表現され、明度100%が最も明るく、0%が真っ黒のようだ。 ただし、R、G、Bが最大値のとき明度100%とするので、 赤(ff0000)、緑(00ff00)、青(0000ff) などは明度だけではこれ以上明るくできない ようだ。このため記事[1]は別の方法(HSL?)を使っているのかも知れない。
今回は色を明るくする必要はなく、濃く(暗く)するだけなので、 RGB を HSV に変換して、明度(Value・Brightness)を小さくして、RGB に戻す。
しかし、いざ、プログラムということで、ネット検索してみると、 プログラムは色々見つかるが、RGB -> HSV、HSV -> RGB を合わせると 結構なプログラム行数となる。 精度はいらない、ただ、ちょっと色を濃くしたいだけなのに。
一般には、RGB の値をそれぞれ小さくすれば、暗い(濃い)色になる。 因みに、適当な数値 #458723 を記事[1]のサイトに入れると、少し暗い色は #305C18、少し明るい色は #5AAD2E となった。 0x30/0x45=48/69=0.70、0x5C/0x87=92/135=0.68、0x18/0x23=24/35=0.69 であるから、 少し暗くするには、RGB を 30%減にすればいいだろう。
とりあえず、RGB の値をそれぞれ 30〜50%減として、地図をレンダリングしてみる。
プログラムは赤字の部分を追加した。
private void fillPolygon(Canvas canvas, int color, int zoom, int x, int y,
int offset, int length) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setStyle(Paint.Style.FILL);
android.graphics.Path path = new android.graphics.Path();
path.moveTo(OSM.xf(zoom, x, lonlats[offset*2]),
OSM.yf(zoom, y, lonlats[offset*2+1]));
for (int n = offset*2+2; n < offset*2 + length*2; n+=2) {
path.lineTo(OSM.xf(zoom, x, lonlats[n]), OSM.yf(zoom, y, lonlats[n+1]));
}
path.close();
canvas.drawPath(path, paint);
int red = (color & 0x00ff0000) >> 16;
int green = (color & 0x0000ff00) >> 8;
int blue = (color & 0x000000ff);
int darkColor = (color & 0xff000000) | ((red*7/10)<<16) | ((green*7/10)<<8) | (blue*7/10);
paint.setColor(darkColor);
paint.setStrokeWidth(0.3f);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, paint);
}
レンダリング結果(スマホ画面のコピー)を下に示す。十分満足できる結果が得られた。