001/** 002 * 003 * Copyright 2006 Jerry Huxtable 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.jingleold.mediaimpl.sshare.api; 018 019import java.awt.Color; 020import java.util.Random; 021 022 023/** 024 * Some more useful math functions for image processing. 025 * These are becoming obsolete as we move to Java2D. Use MiscComposite instead. 026 */ 027public class PixelUtils { 028 029 public static final int REPLACE = 0; 030 public static final int NORMAL = 1; 031 public static final int MIN = 2; 032 public static final int MAX = 3; 033 public static final int ADD = 4; 034 public static final int SUBTRACT = 5; 035 public static final int DIFFERENCE = 6; 036 public static final int MULTIPLY = 7; 037 public static final int HUE = 8; 038 public static final int SATURATION = 9; 039 public static final int VALUE = 10; 040 public static final int COLOR = 11; 041 public static final int SCREEN = 12; 042 public static final int AVERAGE = 13; 043 public static final int OVERLAY = 14; 044 public static final int CLEAR = 15; 045 public static final int EXCHANGE = 16; 046 public static final int DISSOLVE = 17; 047 public static final int DST_IN = 18; 048 public static final int ALPHA = 19; 049 public static final int ALPHA_TO_GRAY = 20; 050 051 private static Random randomGenerator = new Random(); 052 053 /** 054 * Clamp a value to the range 0..255. 055 * 056 * @param c the input integer. 057 * @return the output integer. 058 */ 059 public static int clamp(int c) { 060 if (c < 0) 061 return 0; 062 if (c > 255) 063 return 255; 064 return c; 065 } 066 067 public static int interpolate(int v1, int v2, float f) { 068 return clamp((int) (v1 + f * (v2 - v1))); 069 } 070 071 public static int brightness(int rgb) { 072 int r = (rgb >> 16) & 0xff; 073 int g = (rgb >> 8) & 0xff; 074 int b = rgb & 0xff; 075 return (r + g + b) / 3; 076 } 077 078 public static boolean nearColors(int rgb1, int rgb2, int tolerance) { 079 int r1 = (rgb1 >> 16) & 0xff; 080 int g1 = (rgb1 >> 8) & 0xff; 081 int b1 = rgb1 & 0xff; 082 int r2 = (rgb2 >> 16) & 0xff; 083 int g2 = (rgb2 >> 8) & 0xff; 084 int b2 = rgb2 & 0xff; 085 return Math.abs(r1 - r2) <= tolerance && Math.abs(g1 - g2) <= tolerance && Math.abs(b1 - b2) <= tolerance; 086 } 087 088 private static final float[] hsb1 = new float[3];//FIXME-not thread safe 089 private static final float[] hsb2 = new float[3];//FIXME-not thread safe 090 091 // Return rgb1 painted onto rgb2 092 public static int combinePixels(int rgb1, int rgb2, int op) { 093 return combinePixels(rgb1, rgb2, op, 0xff); 094 } 095 096 public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) { 097 return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha); 098 } 099 100 public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) { 101 if (op == REPLACE) 102 return rgb1; 103 int a1 = (rgb1 >> 24) & 0xff; 104 int r1 = (rgb1 >> 16) & 0xff; 105 int g1 = (rgb1 >> 8) & 0xff; 106 int b1 = rgb1 & 0xff; 107 int a2 = (rgb2 >> 24) & 0xff; 108 int r2 = (rgb2 >> 16) & 0xff; 109 int g2 = (rgb2 >> 8) & 0xff; 110 int b2 = rgb2 & 0xff; 111 112 switch (op) { 113 case NORMAL: 114 break; 115 case MIN: 116 r1 = Math.min(r1, r2); 117 g1 = Math.min(g1, g2); 118 b1 = Math.min(b1, b2); 119 break; 120 case MAX: 121 r1 = Math.max(r1, r2); 122 g1 = Math.max(g1, g2); 123 b1 = Math.max(b1, b2); 124 break; 125 case ADD: 126 r1 = clamp(r1 + r2); 127 g1 = clamp(g1 + g2); 128 b1 = clamp(b1 + b2); 129 break; 130 case SUBTRACT: 131 r1 = clamp(r2 - r1); 132 g1 = clamp(g2 - g1); 133 b1 = clamp(b2 - b1); 134 break; 135 case DIFFERENCE: 136 r1 = clamp(Math.abs(r1 - r2)); 137 g1 = clamp(Math.abs(g1 - g2)); 138 b1 = clamp(Math.abs(b1 - b2)); 139 break; 140 case MULTIPLY: 141 r1 = clamp(r1 * r2 / 255); 142 g1 = clamp(g1 * g2 / 255); 143 b1 = clamp(b1 * b2 / 255); 144 break; 145 case DISSOLVE: 146 if ((randomGenerator.nextInt() & 0xff) <= a1) { 147 r1 = r2; 148 g1 = g2; 149 b1 = b2; 150 } 151 break; 152 case AVERAGE: 153 r1 = (r1 + r2) / 2; 154 g1 = (g1 + g2) / 2; 155 b1 = (b1 + b2) / 2; 156 break; 157 case HUE: 158 case SATURATION: 159 case VALUE: 160 case COLOR: 161 Color.RGBtoHSB(r1, g1, b1, hsb1); 162 Color.RGBtoHSB(r2, g2, b2, hsb2); 163 switch (op) { 164 case HUE: 165 hsb2[0] = hsb1[0]; 166 break; 167 case SATURATION: 168 hsb2[1] = hsb1[1]; 169 break; 170 case VALUE: 171 hsb2[2] = hsb1[2]; 172 break; 173 case COLOR: 174 hsb2[0] = hsb1[0]; 175 hsb2[1] = hsb1[1]; 176 break; 177 } 178 rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]); 179 r1 = (rgb1 >> 16) & 0xff; 180 g1 = (rgb1 >> 8) & 0xff; 181 b1 = rgb1 & 0xff; 182 break; 183 case SCREEN: 184 r1 = 255 - ((255 - r1) * (255 - r2)) / 255; 185 g1 = 255 - ((255 - g1) * (255 - g2)) / 255; 186 b1 = 255 - ((255 - b1) * (255 - b2)) / 255; 187 break; 188 case OVERLAY: 189 int m, s; 190 s = 255 - ((255 - r1) * (255 - r2)) / 255; 191 m = r1 * r2 / 255; 192 r1 = (s * r1 + m * (255 - r1)) / 255; 193 s = 255 - ((255 - g1) * (255 - g2)) / 255; 194 m = g1 * g2 / 255; 195 g1 = (s * g1 + m * (255 - g1)) / 255; 196 s = 255 - ((255 - b1) * (255 - b2)) / 255; 197 m = b1 * b2 / 255; 198 b1 = (s * b1 + m * (255 - b1)) / 255; 199 break; 200 case CLEAR: 201 r1 = g1 = b1 = 0xff; 202 break; 203 case DST_IN: 204 r1 = clamp((r2 * a1) / 255); 205 g1 = clamp((g2 * a1) / 255); 206 b1 = clamp((b2 * a1) / 255); 207 a1 = clamp((a2 * a1) / 255); 208 return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; 209 case ALPHA: 210 a1 = a1 * a2 / 255; 211 return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2; 212 case ALPHA_TO_GRAY: 213 int na = 255 - a1; 214 return (a1 << 24) | (na << 16) | (na << 8) | na; 215 } 216 if (extraAlpha != 0xff || a1 != 0xff) { 217 a1 = a1 * extraAlpha / 255; 218 int a3 = (255 - a1) * a2 / 255; 219 r1 = clamp((r1 * a1 + r2 * a3) / 255); 220 g1 = clamp((g1 * a1 + g2 * a3) / 255); 221 b1 = clamp((b1 * a1 + b2 * a3) / 255); 222 a1 = clamp(a1 + a3); 223 } 224 return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; 225 } 226 227}