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