imagemodule.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,229 行 · 第 1/4 页
JAVA
2,229 行
{ // don't forget: PHP alpha channel is only 7 bits int alpha = argb >> 24; alpha <<= 1; alpha |= ((alpha & 0x2) >> 1); // copy bit #2 to LSB return new Color((argb >> 16) & 0xff, (argb >> 8) & 0xff, (argb >> 0) & 0xff, alpha); } /** * Parses the image size from the file. */ private static boolean parseImageSize(ReadStream is, ImageInfo info) throws IOException { int ch; ch = is.read(); if (ch == 137) { // PNG - http://www.libpng.org/pub/png/spec/iso/index-object.html if (is.read() != 'P' || is.read() != 'N' || is.read() != 'G' || is.read() != '\r' || is.read() != '\n' || is.read() != 26 || is.read() != '\n') return false; return parsePNGImageSize(is, info); } else if (ch == 'G') { // GIF if (is.read() != 'I' || is.read() != 'F' || is.read() != '8' || ((ch = is.read()) != '7' && ch != '9') || is.read() != 'a') return false; return parseGIFImageSize(is, info); } else if (ch == 0xff) { // JPEG if (is.read() != 0xd8) return false; return parseJPEGImageSize(is, info); } else return false; } /** * Parses the image size from the PNG file. */ private static boolean parsePNGImageSize(ReadStream is, ImageInfo info) throws IOException { int length; while ((length = readInt(is)) > 0) { int type = readInt(is); if (type == PNG_IHDR) { int width = readInt(is); int height = readInt(is); int depth = is.read() & 0xff; int color = is.read() & 0xff; int compression = is.read() & 0xff; int filter = is.read() & 0xff; int interlace = is.read() & 0xff; info._width = width; info._height = height; info._type = IMAGETYPE_PNG; info._bits = depth; info._mime = "image/png"; return true; } else { for (int i = 0; i < length; i++) { if (is.read() < 0) return false; } } int crc = readInt(is); } return false; } /** * Parses the image size from the PNG file. */ private static boolean parseGIFImageSize(ReadStream is, ImageInfo info) throws IOException { int length; int width = (is.read() & 0xff) + 256 * (is.read() & 0xff); int height = (is.read() & 0xff) + 256 * (is.read() & 0xff); int flags = is.read() & 0xff; info._width = width; info._height = height; info._type = IMAGETYPE_GIF; info._bits = flags & 0x7; info._mime = "image/gif"; return true; } /** * Parses the image size from the PNG file. */ private static boolean parseJPEGImageSize(ReadStream is, ImageInfo info) throws IOException { int ch; while ((ch = is.read()) == 0xff) { ch = is.read(); if (ch == 0xff) { is.unread(); } else if (0xd0 <= ch && ch <= 0xd9) { // rst } else if (0x01 == ch) { // rst } else if (ch == 0xc0) { int len = 256 * is.read() + is.read(); int bits = is.read(); int height = 256 * is.read() + is.read(); int width = 256 * is.read() + is.read(); info._width = width; info._height = height; info._type = IMAGETYPE_JPEG; info._bits = bits; info._mime = "image/jpeg"; return true; } else { int len = 256 * is.read() + is.read(); is.skip(len - 2); } } return false; } private static int pngCode(String code) { return ((code.charAt(0) << 24) | (code.charAt(1) << 16) | (code.charAt(2) << 8) | (code.charAt(3))); } private static int readInt(ReadStream is) throws IOException { return (((is.read() & 0xff) << 24) | ((is.read() & 0xff) << 16) | ((is.read() & 0xff) << 8) | ((is.read() & 0xff))); } // Inner Classes //////////////////////////////////////////////////////// static class ImageInfo { int _width; int _height; int _type; int _bits; String _mime; } public static class QuercusImage extends ResourceValue { private HashMap<String,Font> _fontMap = new HashMap<String,Font>(); private Font []_fontArray = new Font[6]; private int _width; private int _height; BufferedImage _bufferedImage; private Graphics2D _graphics; private boolean _isInterlace; private BufferedImage _brush; private int[] _style; private int _thickness; public QuercusImage(int width, int height) { _width = width; _height = height; _bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); _graphics = (Graphics2D)_bufferedImage.getGraphics(); } public QuercusImage(InputStream inputStream) { try { _bufferedImage = ImageIO.read(inputStream); _width = _bufferedImage.getWidth(null); _height = _bufferedImage.getHeight(null); _graphics = (Graphics2D)_bufferedImage.getGraphics(); } catch (IOException e) { throw new QuercusException(e); } } public QuercusImage(Env env, Path filename) { try { _bufferedImage = ImageIO.read(filename.openRead()); _width = _bufferedImage.getWidth(null); _height = _bufferedImage.getHeight(null); _graphics = (Graphics2D)_bufferedImage.getGraphics(); } catch (IOException e) { throw new QuercusException(e); } } public String toString() { return "resource(Image)"; } public void setInterlace(boolean isInterlace) { _isInterlace = isInterlace; } public boolean isInterlace() { return _isInterlace; } public int getPixel(int x, int y) { return _bufferedImage.getRGB(x, y); } public void setPixel(int x, int y, int color) { _bufferedImage.setRGB(x, y, color); } public Graphics2D getGraphics() { return _graphics; } public Font getFont(int fontIndex) { if (fontIndex < 0) fontIndex = 0; else if (fontIndex > 5) fontIndex = 5; Font font = _fontArray[fontIndex]; if (font == null) { switch (fontIndex) { case 0: case 1: font = new Font("sansserif", 0, 8); break; case 2: font = new Font("sansserif", 0, 10); break; case 3: font = new Font("sansserif", 0, 11); break; case 4: font = new Font("sansserif", 0, 12); break; default: font = new Font("sansserif", 0, 14); break; } _fontArray[fontIndex] = font; } return font; } public Font getTrueTypeFont(Env env, String fontPath) throws FontFormatException, IOException { Font font = _fontMap.get(fontPath); if (font != null) return font; Path pwd = env.getPwd(); Path path = pwd.lookup(fontPath); if (path.canRead()) { ReadStream is = path.openRead(); try { font = Font.createFont(Font.TRUETYPE_FONT, is); } finally { is.close(); } _fontMap.put(fontPath, font); return font; } if (fontPath.startsWith("/")) return null; StringValue gdFontPathKey = env.createString("GDFONTPATH"); String gdFontPath = OptionsModule.getenv(env, gdFontPathKey).toString(); for (String item : gdFontPath.split("[:;]")) { path = pwd.lookup(item).lookup(fontPath); if (path.canRead()) { ReadStream is = path.openRead(); try { font = Font.createFont(Font.TRUETYPE_FONT, is); } finally { is.close(); } _fontMap.put(fontPath, font); return font; } } return null; } public int getWidth() { return _bufferedImage.getWidth(null); } public int getHeight() { return _bufferedImage.getHeight(null); } public void fill(Shape shape, int color) { _graphics.setColor(intToColor(color)); _graphics.fill(shape); } public void stroke(Shape shape, int color) { switch(color) { case IMG_COLOR_STYLED: strokeStyled(shape); break; case IMG_COLOR_BRUSHED: strokeBrushed(shape); break; default: _graphics.setColor(intToColor(color)); _graphics.setStroke(new BasicStroke(_thickness)); _graphics.draw(shape); break; } } private void strokeStyled(Shape shape) { for(int i=0; i<_style.length; i++) { _graphics.setColor(intToColor(_style[i])); Stroke stroke = new BasicStroke(_thickness, BasicStroke.JOIN_ROUND, BasicStroke.CAP_ROUND, 1, new float[] { 1, _style.length-1 }, i); _graphics.setStroke(stroke); _graphics.draw(shape); } } private void strokeBrushed(Shape shape) { // XXX: support "styled brushes" (see imagesetstyle() example on php.net) Graphics2D g = _graphics; FlatteningPathIterator fpi = new FlatteningPathIterator(shape.getPathIterator(g.getTransform()), 1); float[] floats = new float[6]; fpi.currentSegment(floats); float last_x = floats[0]; float last_y = floats[1]; while(! fpi.isDone()) { fpi.currentSegment(floats); int distance = (int)Math.sqrt((floats[0]-last_x)*(floats[0]-last_x)+ (floats[1]-last_y)*(floats[1]-last_y)); if (distance <= 1) distance = 1; for(int i=1; i<=distance; i++) { int x = (int)(floats[0]*i+last_x*(distance-i))/distance; x -= _brush.getWidth() / 2; int y = (int)(floats[1]*i+last_y*(distance-i))/distance; y -= _brush.getHeight() / 2; g.drawImage(_brush, x, y, null); } last_x = floats[0]; last_y = floats[1]; fpi.next(); } } public void setThickness(int thickness) { _style = null; _thickness = thickness; } public void setStyle(Env env, ArrayValue colors) { _style = new int[colors.getSize()]; Iterator<Value> iter = colors.getValueIterator(env); for(int i = 0; i < _style.length; i++) { _style[i] = iter.next().toInt(); } } public void setBrush(QuercusImage image) { _brush = image._bufferedImage; } public BufferedImage getBrush() { return _brush; } public void flood(int x, int y, int color) { flood(x, y, color, 0, false); } public void flood(int x, int y, int color, int border) { flood(x, y, color, border, true); } private void flood(int startx, int starty, int color, int border, boolean useBorder) { java.util.Queue<Integer> xq = new LinkedList<Integer>(); java.util.Queue<Integer> yq = new LinkedList<Integer>(); xq.add(startx); yq.add(starty); color &= 0x00ffffff; border &= 0x00ffffff; int height = getHeight(); while(xq.size() > 0) { int x = xq.poll(); int y = yq.poll(); int p = (getPixel(x, y) & 0x00ffffff); if (useBorder ? (p==border||p==color) : (p != 0)) continue; setPixel(x, y, color); for(int i = x - 1; i >= 0; i--) { p = (getPixel(i, y) & 0x00ffffff); if (useBorder ? (p==border||p==color) : (p!= 0)) break; setPixel(i, y, color); if (y + 1 < height) { xq.add(i); yq.add(y+1); } if (y - 1 >= 0) { xq.add(i); yq.add(y-1); } } for(int i = x + 1; i < getWidth(); i++) { p = (getPixel(i, y) & 0x00ffffff); if (useBorder ? (p==border||p==color) : (p != 0)) break; setPixel(i, y, color); if (y + 1 < height) { xq.add(i); yq.add(y+1); } if (y - 1 >= 0) { xq.add(i); yq.add(y-1); } } if (y + 1 < height) { xq.add(x); yq.add(y+1); } if (y - 1 >= 0) { xq.add(x); yq.add(y-1); } } } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?