Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.image; 027 028import java.nio.Buffer; 029import java.nio.ByteBuffer; 030import java.nio.IntBuffer; 031import java.util.Arrays; 032 033/** 034 * A {@code PixelFormat} object defines the layout of data for a pixel of 035 * a given format. 036 * @since 2.2 037 */ 038public abstract class PixelFormat<T extends Buffer> { 039 public enum Type { 040 /** 041 * The pixels are stored in 32-bit integers with the premultiplied 042 * components stored in order, from MSb to LSb: 043 * alpha, red, green, blue. 044 */ 045 INT_ARGB_PRE, 046 /** 047 * The pixels are stored in 32-bit integers with the non-premultiplied 048 * components stored in order, from MSb to LSb: 049 * alpha, red, green, blue. 050 */ 051 INT_ARGB, 052 /** 053 * The pixels are stored in adjacent bytes with the premultiplied 054 * components stored in order of increasing index: 055 * blue, green, red, alpha. 056 */ 057 BYTE_BGRA_PRE, 058 /** 059 * The pixels are stored in adjacent bytes with the non-premultiplied 060 * components stored in order of increasing index: 061 * blue, green, red, alpha. 062 */ 063 BYTE_BGRA, 064 /** 065 * The opaque pixels are stored in adjacent bytes with the color 066 * components stored in order of increasing index: 067 * red, green, blue. 068 */ 069 BYTE_RGB, 070 /** 071 * The pixel colors are referenced by byte indices stored in the 072 * pixel array, with the byte interpreted as an unsigned index into 073 * a list of colors provided by the {@code PixelFormat} object. 074 */ 075 BYTE_INDEXED, 076 } 077 078 private Type type; 079 080 PixelFormat(Type type) { 081 this.type = type; 082 } 083 084 public static WritablePixelFormat<IntBuffer> getIntArgbInstance() { 085 return WritablePixelFormat.IntArgb.INSTANCE; 086 } 087 088 public static WritablePixelFormat<IntBuffer> getIntArgbPreInstance() { 089 return WritablePixelFormat.IntArgbPre.INSTANCE; 090 } 091 092 public static WritablePixelFormat<ByteBuffer> getByteBgraInstance() { 093 return WritablePixelFormat.ByteBgra.INSTANCE; 094 } 095 096 public static WritablePixelFormat<ByteBuffer> getByteBgraPreInstance() { 097 return WritablePixelFormat.ByteBgraPre.INSTANCE; 098 } 099 100 public static PixelFormat<ByteBuffer> getByteRgbInstance() { 101 return ByteRgb.instance; 102 } 103 104 public static PixelFormat<ByteBuffer> 105 createByteIndexedPremultipliedInstance(int colors[]) 106 { 107 return IndexedPixelFormat.createByte(colors, true); 108 } 109 110 public static PixelFormat<ByteBuffer> 111 createByteIndexedInstance(int colors[]) 112 { 113 return IndexedPixelFormat.createByte(colors, false); 114 } 115 116 public Type getType() { 117 return type; 118 } 119 120 public abstract boolean isWritable(); 121 122 public abstract boolean isPremultiplied(); 123 124 static int NonPretoPre(int nonpre) { 125 int a = nonpre >>> 24; 126 if (a == 0xff) return nonpre; 127 if (a == 0x00) return 0; 128 int r = (nonpre >> 16) & 0xff; 129 int g = (nonpre >> 8) & 0xff; 130 int b = (nonpre ) & 0xff; 131 r = (r * a + 127) / 0xff; 132 g = (g * a + 127) / 0xff; 133 b = (b * a + 127) / 0xff; 134 return (a << 24) | (r << 16) | (g << 8) | b; 135 } 136 137 static int PretoNonPre(int pre) { 138 int a = pre >>> 24; 139 if (a == 0xff || a == 0x00) return pre; 140 int r = (pre >> 16) & 0xff; 141 int g = (pre >> 8) & 0xff; 142 int b = (pre ) & 0xff; 143 int halfa = a >> 1; 144 r = (r >= a) ? 0xff : (r * 0xff + halfa) / a; 145 g = (g >= a) ? 0xff : (g * 0xff + halfa) / a; 146 b = (b >= a) ? 0xff : (b * 0xff + halfa) / a; 147 return (a << 24) | (r << 16) | (g << 8) | b; 148 } 149 150 /** 151 * Reads a 32-bit integer representation of the color from the buffer 152 * at the specified coordinates. 153 * The 32-bit integer will contain the 4 color components in separate 154 * 8-bit fields in ARGB order from the most significant byte to the least 155 * significant byte. 156 * The buffer should be positioned to the start of the pixel data such 157 * that {@code buf.get(0)} would return the pixel information for the 158 * pixel at coordinates {@code (0, 0)}. 159 * The {@code scanlineStride} parameter defines the distance from the pixel 160 * data at the start of one row to the pixel data at the start of the 161 * immediately following row at the next higher Y coordinate. Usually, 162 * {@code scanlineStride} is the same as the width of the image multiplied 163 * by the number of data elements per pixel (1 for the case of the 164 * integer and indexed formats, or 3 or 4 in the case of the byte 165 * formats), but some images may have further padding between rows for 166 * alignment or other purposes. 167 * 168 * @param buf the buffer of pixel data 169 * @param x the X coordinate of the pixel to be read 170 * @param y the Y coordinate of the pixel to be read 171 * @param scanlineStride the number of buffer elements between the 172 * start of adjacent pixel rows in the buffer 173 * @return a 32-bit value with the color of the pixel in a format 174 * similar to the {@code Type.INT_ARGB} pixel format 175 */ 176 public abstract int getArgb(T buf, int x, int y, int scanlineStride); 177 178 static class ByteRgb extends PixelFormat<ByteBuffer> { 179 static final ByteRgb instance = new ByteRgb(); 180 181 private ByteRgb() { 182 super(Type.BYTE_RGB); 183 } 184 185 @Override 186 public boolean isWritable() { 187 return true; 188 } 189 190 @Override 191 public boolean isPremultiplied() { 192 return false; 193 } 194 195 @Override 196 public int getArgb(ByteBuffer buf, int x, int y, int scanlineStride) { 197 int index = y * scanlineStride + x * 3; 198 int r = buf.get(index ) & 0xff; 199 int g = buf.get(index + 1) & 0xff; 200 int b = buf.get(index + 2) & 0xff; 201 return (0xff << 24) | (r << 16) | (g << 8) | b; 202 } 203 } 204 205 static class IndexedPixelFormat extends PixelFormat<ByteBuffer> { 206 int precolors[]; 207 int nonprecolors[]; 208 boolean premult; 209 210 static PixelFormat createByte(int colors[], boolean premult) { 211 return new IndexedPixelFormat(Type.BYTE_INDEXED, premult, 212 Arrays.copyOf(colors, 256)); 213 } 214 215 private IndexedPixelFormat(Type type, boolean premult, int colors[]) { 216 super(type); 217 if (premult) { 218 this.precolors = colors; 219 } else { 220 this.nonprecolors = colors; 221 } 222 this.premult = premult; 223 } 224 225 @Override 226 public boolean isWritable() { 227 return false; 228 } 229 230 @Override 231 public boolean isPremultiplied() { 232 return premult; 233 } 234 235 private int[] getPreColors() { 236 if (precolors == null) { 237 int colors[] = new int[nonprecolors.length]; 238 for (int i = 0; i < colors.length; i++) { 239 colors[i] = NonPretoPre(nonprecolors[i]); 240 } 241 this.precolors = colors; 242 } 243 return precolors; 244 } 245 246 private int[] getNonPreColors() { 247 if (nonprecolors == null) { 248 int colors[] = new int[precolors.length]; 249 for (int i = 0; i < colors.length; i++) { 250 colors[i] = PretoNonPre(precolors[i]); 251 } 252 this.nonprecolors = colors; 253 } 254 return nonprecolors; 255 } 256 257 @Override 258 public int getArgb(ByteBuffer buf, int x, int y, int scanlineStride) { 259 return getNonPreColors()[buf.get(y * scanlineStride + x) & 0xff]; 260 } 261 } 262}