/* * @(#)PolarColorWheelImageProducer.java * * Copyright (c) 2008 The authors and contributors of JHotDraw. * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.color; import java.awt.*; import java.awt.color.ColorSpace; /** * Produces the image of a {@link JColorWheel} by interpreting two components * of a {@code ColorSpace} as polar coordinates (angle and radius). * * @author Werner Randelshofer * @version $Id$ */ public class PolarColorWheelImageProducer extends AbstractColorWheelImageProducer { /** Lookup table for angular component values. */ protected float[] angulars; /** Lookup table for radial component values. */ protected float[] radials; /** Lookup table for alphas. * The alpha value is used for antialiasing the * color wheel. */ protected int[] alphas; /** Creates a new instance. */ public PolarColorWheelImageProducer(ColorSpace sys, int w, int h) { super(sys, w, h); } protected void generateLookupTables() { radials = new float[w * h]; angulars = new float[w * h]; alphas = new int[w * h]; float radius = getRadius(); // blend is used to create a linear alpha gradient of two extra pixels float blend = (radius + 2f) / radius - 1f; // Center of the color wheel circle int cx = w / 2; int cy = h / 2; float maxR = colorSpace.getMaxValue(radialIndex); float minR = colorSpace.getMinValue(radialIndex); float extentR = maxR - minR; float maxA = colorSpace.getMaxValue(angularIndex); float minA = colorSpace.getMinValue(angularIndex); float extentA = maxA - minA; for (int x = 0; x < w; x++) { int kx = x - cx; // Kartesian coordinates of x int squarekx = kx * kx; // Square of kartesian x for (int y = 0; y < h; y++) { int ky = cy - y; // Kartesian coordinates of y int index = x + y * w; float radiusRatio = (float) (Math.sqrt(squarekx + ky * ky) / radius); if (radiusRatio <= 1f) { alphas[index] = 0xff000000; radials[index] = radiusRatio * extentR + minR; } else { alphas[index] = (int) ((blend - Math.min(blend, radiusRatio - 1f)) * 255 / blend) << 24; radials[index] = maxR; } if (alphas[index] != 0) { angulars[index] = (float) (Math.atan2(ky, kx) / Math.PI / 2d) * extentA + minA; } } } isLookupValid = true; } @Override public void generateColorWheel() { if (!isLookupValid) { generateLookupTables(); } float[] components = new float[colorSpace.getNumComponents()]; float[] rgb=new float[3]; for (int index = 0; index < pixels.length; index++) { if (alphas[index] != 0) { components[angularIndex] = angulars[index]; components[radialIndex] = radials[index]; components[verticalIndex] = verticalValue; pixels[index] = alphas[index] | 0xffffff & ColorUtil.CStoRGB24(colorSpace, components, rgb); } } newPixels(); isPixelsValid = true; } @Override public Point getColorLocation(Color c) { float[] hsb = ColorUtil.fromColor(colorSpace, c); return getColorLocation(hsb); } @Override public Point getColorLocation(float[] components) { float radial = (components[radialIndex] - colorSpace.getMinValue(radialIndex))// / (colorSpace.getMaxValue(radialIndex) - colorSpace.getMinValue(radialIndex)); float angular = (components[angularIndex] - colorSpace.getMinValue(angularIndex))// / (colorSpace.getMaxValue(angularIndex) - colorSpace.getMinValue(angularIndex)); float radius = Math.min(w, h) / 2f; radial = Math.max(0f, Math.min(1f, radial)); Point p = new Point( w / 2 + (int) (radius * radial * Math.cos(angular * Math.PI * 2d)), h / 2 - (int) (radius * radial * Math.sin(angular * Math.PI * 2d))); return p; } @Override public float[] getColorAt(int x, int y) { x -= w / 2; y -= h / 2; float r = (float) Math.sqrt(x * x + y * y); float theta = (float) Math.atan2(y, -x); float angular = (float) (0.5 + (theta / Math.PI / 2d)); float radial=Math.min(1f, r / getRadius()); float[] hsb = new float[3]; hsb[angularIndex] = angular// * (colorSpace.getMaxValue(angularIndex) - colorSpace.getMinValue(angularIndex))// + colorSpace.getMinValue(angularIndex); hsb[radialIndex] = radial// * (colorSpace.getMaxValue(radialIndex) - colorSpace.getMinValue(radialIndex))// + colorSpace.getMinValue(radialIndex); hsb[verticalIndex] = verticalValue; return hsb; } }