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 final static int REPLACE = 0; 030 public final static int NORMAL = 1; 031 public final static int MIN = 2; 032 public final static int MAX = 3; 033 public final static int ADD = 4; 034 public final static int SUBTRACT = 5; 035 public final static int DIFFERENCE = 6; 036 public final static int MULTIPLY = 7; 037 public final static int HUE = 8; 038 public final static int SATURATION = 9; 039 public final static int VALUE = 10; 040 public final static int COLOR = 11; 041 public final static int SCREEN = 12; 042 public final static int AVERAGE = 13; 043 public final static int OVERLAY = 14; 044 public final static int CLEAR = 15; 045 public final static int EXCHANGE = 16; 046 public final static int DISSOLVE = 17; 047 public final static int DST_IN = 18; 048 public final static int ALPHA = 19; 049 public final static 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 public static int clamp(int c) { 057 if (c < 0) 058 return 0; 059 if (c > 255) 060 return 255; 061 return c; 062 } 063 064 public static int interpolate(int v1, int v2, float f) { 065 return clamp((int)(v1+f*(v2-v1))); 066 } 067 068 public static int brightness(int rgb) { 069 int r = (rgb >> 16) & 0xff; 070 int g = (rgb >> 8) & 0xff; 071 int b = rgb & 0xff; 072 return (r+g+b)/3; 073 } 074 075 public static boolean nearColors(int rgb1, int rgb2, int tolerance) { 076 int r1 = (rgb1 >> 16) & 0xff; 077 int g1 = (rgb1 >> 8) & 0xff; 078 int b1 = rgb1 & 0xff; 079 int r2 = (rgb2 >> 16) & 0xff; 080 int g2 = (rgb2 >> 8) & 0xff; 081 int b2 = rgb2 & 0xff; 082 return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance; 083 } 084 085 private final static float[] hsb1 = new float[3];//FIXME-not thread safe 086 private final static float[] hsb2 = new float[3];//FIXME-not thread safe 087 088 // Return rgb1 painted onto rgb2 089 public static int combinePixels(int rgb1, int rgb2, int op) { 090 return combinePixels(rgb1, rgb2, op, 0xff); 091 } 092 093 public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) { 094 return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha); 095 } 096 097 public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) { 098 if (op == REPLACE) 099 return rgb1; 100 int a1 = (rgb1 >> 24) & 0xff; 101 int r1 = (rgb1 >> 16) & 0xff; 102 int g1 = (rgb1 >> 8) & 0xff; 103 int b1 = rgb1 & 0xff; 104 int a2 = (rgb2 >> 24) & 0xff; 105 int r2 = (rgb2 >> 16) & 0xff; 106 int g2 = (rgb2 >> 8) & 0xff; 107 int b2 = rgb2 & 0xff; 108 109 switch (op) { 110 case NORMAL: 111 break; 112 case MIN: 113 r1 = Math.min(r1, r2); 114 g1 = Math.min(g1, g2); 115 b1 = Math.min(b1, b2); 116 break; 117 case MAX: 118 r1 = Math.max(r1, r2); 119 g1 = Math.max(g1, g2); 120 b1 = Math.max(b1, b2); 121 break; 122 case ADD: 123 r1 = clamp(r1+r2); 124 g1 = clamp(g1+g2); 125 b1 = clamp(b1+b2); 126 break; 127 case SUBTRACT: 128 r1 = clamp(r2-r1); 129 g1 = clamp(g2-g1); 130 b1 = clamp(b2-b1); 131 break; 132 case DIFFERENCE: 133 r1 = clamp(Math.abs(r1-r2)); 134 g1 = clamp(Math.abs(g1-g2)); 135 b1 = clamp(Math.abs(b1-b2)); 136 break; 137 case MULTIPLY: 138 r1 = clamp(r1*r2/255); 139 g1 = clamp(g1*g2/255); 140 b1 = clamp(b1*b2/255); 141 break; 142 case DISSOLVE: 143 if ((randomGenerator.nextInt() & 0xff) <= a1) { 144 r1 = r2; 145 g1 = g2; 146 b1 = b2; 147 } 148 break; 149 case AVERAGE: 150 r1 = (r1+r2)/2; 151 g1 = (g1+g2)/2; 152 b1 = (b1+b2)/2; 153 break; 154 case HUE: 155 case SATURATION: 156 case VALUE: 157 case COLOR: 158 Color.RGBtoHSB(r1, g1, b1, hsb1); 159 Color.RGBtoHSB(r2, g2, b2, hsb2); 160 switch (op) { 161 case HUE: 162 hsb2[0] = hsb1[0]; 163 break; 164 case SATURATION: 165 hsb2[1] = hsb1[1]; 166 break; 167 case VALUE: 168 hsb2[2] = hsb1[2]; 169 break; 170 case COLOR: 171 hsb2[0] = hsb1[0]; 172 hsb2[1] = hsb1[1]; 173 break; 174 } 175 rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]); 176 r1 = (rgb1 >> 16) & 0xff; 177 g1 = (rgb1 >> 8) & 0xff; 178 b1 = rgb1 & 0xff; 179 break; 180 case SCREEN: 181 r1 = 255 - ((255 - r1) * (255 - r2)) / 255; 182 g1 = 255 - ((255 - g1) * (255 - g2)) / 255; 183 b1 = 255 - ((255 - b1) * (255 - b2)) / 255; 184 break; 185 case OVERLAY: 186 int m, s; 187 s = 255 - ((255 - r1) * (255 - r2)) / 255; 188 m = r1 * r2 / 255; 189 r1 = (s * r1 + m * (255 - r1)) / 255; 190 s = 255 - ((255 - g1) * (255 - g2)) / 255; 191 m = g1 * g2 / 255; 192 g1 = (s * g1 + m * (255 - g1)) / 255; 193 s = 255 - ((255 - b1) * (255 - b2)) / 255; 194 m = b1 * b2 / 255; 195 b1 = (s * b1 + m * (255 - b1)) / 255; 196 break; 197 case CLEAR: 198 r1 = g1 = b1 = 0xff; 199 break; 200 case DST_IN: 201 r1 = clamp((r2*a1)/255); 202 g1 = clamp((g2*a1)/255); 203 b1 = clamp((b2*a1)/255); 204 a1 = clamp((a2*a1)/255); 205 return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; 206 case ALPHA: 207 a1 = a1*a2/255; 208 return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2; 209 case ALPHA_TO_GRAY: 210 int na = 255-a1; 211 return (a1 << 24) | (na << 16) | (na << 8) | na; 212 } 213 if (extraAlpha != 0xff || a1 != 0xff) { 214 a1 = a1*extraAlpha/255; 215 int a3 = (255-a1)*a2/255; 216 r1 = clamp((r1*a1+r2*a3)/255); 217 g1 = clamp((g1*a1+g2*a3)/255); 218 b1 = clamp((b1*a1+b2*a3)/255); 219 a1 = clamp(a1+a3); 220 } 221 return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; 222 } 223 224}