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;
031
032/**
033 * A {@link PixelFormat} object representing a pixel format that can store
034 * full colors and so can be used as a destination format to write pixel
035 * data from an arbitrary image.
036 * @since 2.2
037 */
038public abstract class WritablePixelFormat<T extends Buffer>
039    extends PixelFormat<T>
040{
041    WritablePixelFormat(Type type) {
042        super(type);
043    }
044
045    @Override
046    public boolean isWritable() {
047        return true;
048    }
049
050    /**
051     * Stores a 32-bit integer representation of the color in the buffer
052     * at the specified coordinates.
053     * The 32-bit integer will contain the 4 color components in separate
054     * 8-bit fields in ARGB order from the most significant byte to the least
055     * significant byte.
056     * The buffer should be positioned to the start of the pixel data such
057     * that {@code buf.get(0)} would return the pixel information for the
058     * pixel at coordinates {@code (0, 0)}.
059     * The {@code scanlineStride} parameter defines the distance from the pixel
060     * data at the start of one row to the pixel data at the start of the
061     * immediately following row at the next higher Y coordinate.  Usually,
062     * {@code scanlineStride} is the same as the width of the image multiplied
063     * by the number of data elements per pixel (1 for the case of the
064     * integer and indexed formats, or 3 or 4 in the case of the byte
065     * formats), but some images may have further padding between rows for
066     * alignment or other purposes.
067     * 
068     * @param buf the buffer of pixel data
069     * @param x the X coordinate of the pixel to be read
070     * @param y the Y coordinate of the pixel to be read
071     * @param scanlineStride the number of buffer elements between the
072     *        start of adjacent pixel rows in the buffer
073     * @param argb a 32-bit value with the color to be stored in the pixel
074     *        in a format similar to the {@code Type.INT_ARGB} pixel format
075     */
076    public abstract void setArgb(T buf, int x, int y, int scanlineStride,
077                                 int argb);
078
079    static class IntArgb extends WritablePixelFormat<IntBuffer> {
080        static final IntArgb INSTANCE = new IntArgb();
081
082        private IntArgb() {
083            super(Type.INT_ARGB);
084        }
085
086        @Override
087        public boolean isPremultiplied() {
088            return false;
089        }
090
091        @Override
092        public int getArgb(IntBuffer buf, int x, int y, int scanlineStride) {
093            return buf.get(y * scanlineStride + x);
094        }
095
096        @Override
097        public void setArgb(IntBuffer buf, int x, int y, int scanlineStride,
098                            int argb)
099        {
100            buf.put(y * scanlineStride + x, argb);
101        }
102    }
103
104    static class IntArgbPre extends WritablePixelFormat<IntBuffer> {
105        static final IntArgbPre INSTANCE = new IntArgbPre();
106
107        private IntArgbPre() {
108            super(Type.INT_ARGB_PRE);
109        }
110
111        @Override
112        public boolean isPremultiplied() {
113            return true;
114        }
115
116        @Override
117        public int getArgb(IntBuffer buf, int x, int y, int scanlineStride) {
118            return PretoNonPre(buf.get(y * scanlineStride + x));
119        }
120
121        @Override
122        public void setArgb(IntBuffer buf, int x, int y, int scanlineStride,
123                            int argb)
124        {
125            buf.put(y * scanlineStride + x, NonPretoPre(argb));
126        }
127    }
128
129    static class ByteBgra extends WritablePixelFormat<ByteBuffer> {
130        static final ByteBgra INSTANCE = new ByteBgra();
131
132        private ByteBgra() {
133            super(Type.BYTE_BGRA);
134        }
135
136        @Override
137        public boolean isPremultiplied() {
138            return false;
139        }
140
141        @Override
142        public int getArgb(ByteBuffer buf, int x, int y, int scanlineStride) {
143            int index = y * scanlineStride + x * 4;
144            int b = buf.get(index    ) & 0xff;
145            int g = buf.get(index + 1) & 0xff;
146            int r = buf.get(index + 2) & 0xff;
147            int a = buf.get(index + 3) & 0xff;
148            return (a << 24) | (r << 16) | (g << 8) | b;
149        }
150
151        @Override
152        public void setArgb(ByteBuffer buf, int x, int y, int scanlineStride,
153                            int argb)
154        {
155            int index = y * scanlineStride + x * 4;
156            buf.put(index,     (byte) (argb      ));
157            buf.put(index + 1, (byte) (argb >>  8));
158            buf.put(index + 2, (byte) (argb >> 16));
159            buf.put(index + 3, (byte) (argb >> 24));
160        }
161    }
162
163    static class ByteBgraPre extends WritablePixelFormat<ByteBuffer> {
164        static final ByteBgraPre INSTANCE = new ByteBgraPre();
165
166        private ByteBgraPre() {
167            super(Type.BYTE_BGRA_PRE);
168        }
169
170        @Override
171        public boolean isPremultiplied() {
172            return true;
173        }
174
175        @Override
176        public int getArgb(ByteBuffer buf, int x, int y, int scanlineStride) {
177            int index = y * scanlineStride + x * 4;
178            int b = buf.get(index    ) & 0xff;
179            int g = buf.get(index + 1) & 0xff;
180            int r = buf.get(index + 2) & 0xff;
181            int a = buf.get(index + 3) & 0xff;
182            if (a > 0x00 && a < 0xff) {
183                int halfa = a >> 1;
184                r = (r >= a) ? 0xff : (r * 0xff + halfa) / a;
185                g = (g >= a) ? 0xff : (g * 0xff + halfa) / a;
186                b = (b >= a) ? 0xff : (b * 0xff + halfa) / a;
187            }
188            return (a << 24) | (r << 16) | (g << 8) | b;
189        }
190
191        @Override
192        public void setArgb(ByteBuffer buf, int x, int y, int scanlineStride,
193                            int argb)
194        {
195            int index = y * scanlineStride + x * 4;
196            int a = (argb >>> 24);
197            int r, g, b;
198            if (a > 0x00) {
199                r = (argb >> 16) & 0xff;
200                g = (argb >>  8) & 0xff;
201                b = (argb      ) & 0xff;
202                if (a < 0xff) {
203                    r = (r * a + 127) / 0xff;
204                    g = (g * a + 127) / 0xff;
205                    b = (b * a + 127) / 0xff;
206                }
207            } else {
208                a = r = g = b = 0;
209            }
210            buf.put(index,     (byte) b);
211            buf.put(index + 1, (byte) g);
212            buf.put(index + 2, (byte) r);
213            buf.put(index + 3, (byte) a);
214        }
215    }
216}