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}