要求:“上”和“爱情”都是通过程序自动输出的,程序能共自动判断画布上得空白部分并输出文字。在python中,有pygame库直接获得一个画布的mask,然后提供collide函数来判断两个mask是否有交集。php是否有类似功能?换个问题:php中如何获得双色图片的mask
1 回答
交互式爱情
TA贡献1712条经验 获得超3个赞
package com.ctrip; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Paint; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.imageio.ImageIO; public class WordsThumb { public static final int MIN_WIDTH = 320; public static final int MIN_HEIGHT = 240; public static final int MAX_WIDTH = 2560; public static final int MAX_HEIGHT = 1920; public static final int BLOCK = 4; public static final String DEF_FONT = "微软雅黑"; public static final int MIN_FONT_SIZE = 12; private static final int[] COLORS = { 11682842, 14439168, 13081114, 10300417, 14450176, 13052357, 11665801, 1739698, 101319, 84146, 15580865, 1722823, 6664705, 11257601, 7582257, 11665680, 14425600, 10768192, 14360836, 15515347, 111266, 49372, 15436032, 15436032 }; public BufferedImage createWordsThumb(Map<String, Integer> words, int width, int height, String fontName, Integer maxFontSize, Integer minFontSize) { if ((words == null) || (words.size() < 1) || (width < 320) || (width > 2560) || (height < 240) || (height > 1920)) return null; fontName = validateFontName(fontName, "微软雅黑"); List sortedWords = sortWordsMap(words); BufferedImage bi = createBufferedImage(width, height); if (bi == null) { return null; } if (maxFontSize == null) { maxFontSize = Integer.valueOf(Math.min(width, height) / 5); } if (minFontSize == null) { minFontSize = Integer.valueOf(Math.min(width, height) / 40); } if (minFontSize.intValue() < 12) minFontSize = Integer.valueOf(12); if (maxFontSize.intValue() < minFontSize.intValue()) { maxFontSize = minFontSize; } if (paintWords(bi, sortedWords, fontName, maxFontSize.intValue(), minFontSize.intValue()) < 1) { return null; } return bi; } private String validateFontName(String fontName, String defFont) { if (fontName != null) { Font font = new Font(fontName, 0, 16); if (font.getName().equals(fontName)) return fontName; } return defFont; } private List<Map.Entry<String, Integer>> sortWordsMap(Map<String, Integer> words) { if (words == null) return null; ArrayList wordsList = new ArrayList( words.entrySet()); Collections.sort(wordsList, new Comparator() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2 == null ? -1 : o1 == null ? 1 : ((Integer)o2 .getValue()).intValue() - ((Integer)o1.getValue()).intValue(); } }); return wordsList; } private BufferedImage createBufferedImage(int width, int height) { BufferedImage bi = new BufferedImage(width, height, 2); Graphics2D g2 = bi.createGraphics(); bi = g2.getDeviceConfiguration().createCompatibleImage(width, height, 3); g2.dispose(); return bi; } private int paintWords(BufferedImage bi, List<Map.Entry<String, Integer>> words, String fontName, int maxFontSize, int minFontSize) { BitMap bitMap = initBitMap(bi); Graphics2D g2 = bi.createGraphics(); int wordCount = 0; int fontSizeAdjust = 0; int maxFrequency = ((Integer)((Map.Entry)words.get(0)).getValue()).intValue(); int minFrequency = ((Integer)((Map.Entry)words.get(words.size() - 1)).getValue()).intValue(); for (Map.Entry entry : words) { while (true) { Font font = initFont(g2, fontName, Integer.valueOf(maxFontSize), Integer.valueOf(minFontSize), (Integer)entry.getValue(), Integer.valueOf(maxFrequency), Integer.valueOf(minFrequency), Integer.valueOf(fontSizeAdjust)); if (font.getSize() < minFontSize) return wordCount; Rectangle2D bounds = getStringBounds(g2, font, (String)entry.getKey()); int direction = (int)(Math.random() * 10000.0D % 4.0D % 3.0D); Rectangle2D rect = bounds.getBounds(); if (direction != 0) { rect.setRect(rect.getX(), rect.getY(), rect.getHeight(), rect.getWidth()); } rect = findSpace(bitMap, rect); if (rect == null) { rect = bounds.getBounds(); if (direction == 0) { direction = (int)(Math.random() * 10000.0D % 2.0D + 1.0D); rect.setRect(rect.getX(), rect.getY(), rect.getHeight(), rect.getWidth()); } else { direction = 0; } rect = findSpace(bitMap, rect); } if (rect != null) { paintOneWord(bi, g2, (String)entry.getKey(), direction, rect, bounds); updateBitMap(bitMap, bi, rect); wordCount++; break; } fontSizeAdjust--; } } return wordCount; } private BitMap initBitMap(BufferedImage bi) { int w = (int)Math.ceil(bi.getWidth() / 4.0D); int h = (int)Math.ceil(bi.getHeight() / 4.0D); return new BitMap(w, h); } private Font initFont(Graphics2D g2, String fontName, Integer maxFontSize, Integer minFontSize, Integer frequency, Integer maxFrequency, Integer minFrequency, Integer fontSizeAdjust) { int fs = 24; if (maxFrequency.intValue() > minFrequency.intValue()) { fs = (int)((frequency.intValue() - minFrequency.intValue()) * ( maxFontSize.intValue() - minFontSize.intValue()) / ( maxFrequency.intValue() - minFrequency.intValue()) + minFontSize.intValue()); } if (fontSizeAdjust != null) { fs += fontSizeAdjust.intValue(); } Font font = new Font(fontName, 1, fs); g2.setFont(font); g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); return font; } private Rectangle2D getStringBounds(Graphics2D g2, Font font, String key) { FontRenderContext frc = g2.getFontRenderContext(); Rectangle2D rc = font.getStringBounds(key, frc); return rc; } private Rectangle2D findSpace(BitMap bitMap, Rectangle2D rect) { int w = pixel2bitMap((int)rect.getWidth()); int h = pixel2bitMap((int)rect.getHeight()); int boundW = bitMap.getWidth() - w; int boundH = bitMap.getHeight() - h; int start_x = boundW / 2; int start_y = boundH / 2; int maxBound = Math.max(boundW, boundH); double wRatio = boundW / maxBound; double hRatio = boundH / maxBound; double max_r = Math.sin(0.7853981633974483D) * maxBound; double r = 1.0D; double a = 0.0D; double a_tmp = 0.0D; double s = 1.0D; double step = 1.0D; int x = start_x; int y = start_y; while (r < max_r) { if (isClean(bitMap, x, y, w, h)) { int targetX = bit2pixel(x); int targetY = bit2pixel(y); return new Rectangle(targetX, targetY, (int)rect.getWidth(), (int)rect.getHeight()); } a_tmp = s / r > 0.7853981633974483D ? 0.7853981633974483D : s / r; a += a_tmp; r += step * (a_tmp / 6.283185307179586D); x = (int)(Math.sin(a) * r * wRatio + start_x); y = (int)(Math.cos(a) * r * hRatio + start_y); } return null; } private Rectangle2D findSpace2(BitMap bitMap, Rectangle2D rect) { int w = pixel2bitMap((int)rect.getWidth()); int h = pixel2bitMap((int)rect.getHeight()); int[] bounds = { bitMap.getWidth() - w, bitMap.getHeight() - h }; int[] step_len = new int[2]; int marchDir = 0; int x; int y; if (bounds[0] > bounds[1]) { int y = bounds[1] / 2; int x = y; bounds[0] -= bounds[1]; step_len[1] = 1; } else { marchDir = 3; x = bounds[0] / 2; y = x; step_len[0] = 1; bounds[1] -= bounds[0]; if (step_len[1] == 0) { step_len[1] = 1; } } int[] step = new int[4]; while (!isClean(bitMap, x, y, w, h)) { step[marchDir] += 1; if (step[marchDir] > step_len[(marchDir % 2)]) { step[marchDir] = 0; step_len[(marchDir % 2)] += 1; marchDir++; marchDir %= 4; if (step_len[(marchDir % 2)] > bounds[(marchDir % 2)]) { return null; } } switch (marchDir) { case 0: x++; break; case 1: y--; break; case 2: x--; break; case 3: y++; } } int targetX = bit2pixel(x); int targetY = bit2pixel(y); return new Rectangle(targetX, targetY, (int)rect.getWidth(), (int)rect.getHeight()); } private int pixel2bitMap(int v) { return (int)Math.ceil(v / 4.0D); } private boolean isClean(BitMap bitMap, int x, int y, int w, int h) { if ((x < 0) || (x + w >= bitMap.getWidth()) || (y < 0) || (y + h >= bitMap.getHeight())) return false; for (int i = x; i < x + w; i++) { for (int j = y; j < y + h; j++) { if (bitMap.isUsed(i, j)) return false; } } return true; } private int bit2pixel(int v) { return v * 4; } private void paintOneWord(BufferedImage bi, Graphics2D g2, String word, int direction, Rectangle2D rect, Rectangle2D orgBounds) { g2.setPaint(randomColor()); if (direction == 1) { g2.rotate(1.570796326794897D, rect.getX(), rect.getY()); g2.drawString(word, (int)rect.getX(), (int)(rect.getY() - rect.getWidth() - orgBounds.getY())); g2.rotate(-1.570796326794897D, rect.getX(), rect.getY()); } else if (direction == 2) { g2.rotate(-1.570796326794897D, rect.getX(), rect.getY()); g2.drawString(word, (int)(rect.getX() - rect.getHeight()), (int)(rect.getY() - orgBounds.getY())); g2.rotate(1.570796326794897D, rect.getX(), rect.getY()); } else { g2.drawString(word, (int)rect.getX(), (int)(rect.getY() - orgBounds.getY())); } bi.flush(); } private Paint randomColor() { int rgb = COLORS[((int)(Math.random() * 10000.0D) % COLORS.length)]; return new Color(rgb); } private void updateBitMap(BitMap bitMap, BufferedImage bi, Rectangle2D rect) { int l = (int)rect.getX(); int t = (int)rect.getY(); int r = l + (int)rect.getWidth(); int b = t + (int)rect.getHeight(); if (l < 0) l = 0; if (t < 0) t = 0; if (r > bi.getWidth()) r = bi.getWidth(); if (b > bi.getHeight()) b = bi.getHeight(); if ((r <= l) || (b <= t)) { return; } for (int y = t; y < b + 4 - 1; y += 4) for (int x = l; x < r + 4 - 1; x += 4) for (int i = 0; i < 16; i++) { int x2 = x + i % 4; int y2 = y + i / 4; if ((x2 >= bi.getWidth()) || (y2 >= bi.getHeight())) continue; if (bi.getRGB(x + i % 4, y + i / 4) != 0) { bitMap.setUsed(pixel2bitMap(x), pixel2bitMap(y), true); break; } } } public BufferedImage mixImages(BufferedImage[] images, Float[] alphas, int width, int height) { return mixImages(images, alphas, createBufferedImage(width, height)); } public BufferedImage mixImages(BufferedImage[] images, Float[] alphas, BufferedImage targetImage) { if ((images == null) || (images.length < 1)) return targetImage; if (targetImage == null) { for (int i = 0; i < images.length; i++) { if (images[i] != null) { targetImage = createBufferedImage(images[0].getWidth(), images[0].getHeight()); break; } } if (targetImage == null) return null; } Graphics2D g2 = targetImage.createGraphics(); float alpha = 1.0F; for (int i = 0; i < images.length; i++) { if (images[i] == null) continue; if ((alphas != null) && (i < alphas.length) && (alphas[i] != null)) alpha = alphas[i].floatValue(); else { alpha = 1.0F; } g2.setComposite(AlphaComposite.getInstance(3, alpha)); g2.drawImage(images[i], 0, 0, targetImage.getWidth(), targetImage.getHeight(), 0, 0, images[i].getWidth(), images[i].getHeight(), null); } g2.dispose(); targetImage.flush(); return targetImage; } public static void main(String[] args) throws IOException { String fileName = "./wordsthumb.png"; String bgPic = null; String waterMarkPic = null; int width = 640; int height = 480; String fontName = "微软雅黑"; Map words = new HashMap(); try { int i = 0; for (i = 0; i < args.length; i++) { if ("-o".equals(args[i])) { i++; fileName = args[i]; } else if ("-b".equals(args[i])) { i++; bgPic = args[i]; } else if ("-m".equals(args[i])) { i++; waterMarkPic = args[i]; } else if ("-w".equals(args[i])) { i++; width = Integer.parseInt(args[i]); } else if ("-h".equals(args[i])) { i++; height = Integer.parseInt(args[i]); } else { if (!"-f".equals(args[i])) break; i++; fontName = args[i]; } } for (; i < args.length - 1; i += 2) words.put(args[i], Integer.valueOf(Integer.parseInt(args[(i + 1)]))); } catch (RuntimeException e) { System.out.println("Usage: " + WordsThumb.class.getName() + " [options] <word frequency>..."); System.out.println("\t-o:\tOutput image file name"); System.out.println("\t-b:\tBackground image file name"); System.out.println("\t-m:\tWater mark image file name"); System.out.println("\t-w:\tWidth of target image"); System.out.println("\t-h:\tHeight of target image"); System.out.println("\t-f:\tFont name"); System.exit(1); } if (words.size() < 1) { readWords(words); } if (words.size() < 1) { return; } WordsThumb wt = new WordsThumb(); BufferedImage bi = wt.createWordsThumb(words, width, height, fontName, null, null); BufferedImage bg = null; BufferedImage wm = null; Float fgAlpha = Float.valueOf(0.8F); Float wmAlpha = Float.valueOf(1.0F); if (bgPic != null) bg = ImageIO.read(new FileInputStream(bgPic)); if (waterMarkPic != null) { wm = ImageIO.read(new FileInputStream(waterMarkPic)); } bi = wt.mixImages(new BufferedImage[] { bg, bi, wm }, new Float[] { Float.valueOf(1.0F), fgAlpha, wmAlpha }, bi.getWidth(), bi.getHeight()); File file = new File(fileName); ImageIO.write(bi, "png", file); } private static void readWords(Map<String, Integer> words) throws IOException { BufferedReader rd = new BufferedReader(new InputStreamReader(System.in)); System.out.println("请输入词汇和词频,格式为每行一个词、一个空格、一个词频数字,以空行结束输入。"); String line = null; while ((line = rd.readLine()) != null) { line = line.trim(); if ("".equals(line)) { System.out.println("好,马上处理!"); break; } String[] parts = line.split("\\s+"); if (parts.length != 2) continue; try { words.put(parts[0], Integer.valueOf(Integer.parseInt(parts[1]))); } catch (NumberFormatException e) { System.out.println("无效的输入。"); } } } } package com.ctrip; import java.io.IOException; import java.io.PrintStream; public class BitMap { private byte[][] bitMap; private int width; private int height; private int byteWidth; public BitMap(int width, int height) { if ((width <= 0) || (height <= 0)) throw new IllegalArgumentException(); this.width = width; this.height = height; this.byteWidth = (int)Math.ceil(width / 8.0D); this.bitMap = new byte[height][this.byteWidth]; for (int y = 0; y < height; y++) for (int x = 0; x < this.byteWidth; x++) this.bitMap[y][x] = 0; } public int getWidth() { return this.width; } public int getHeight() { return this.height; } public void updateArea(BitMap bm, int x, int y) { int y1 = y >= 0 ? y : 0; for (int y2 = y1 - y; (y1 < this.height) && (y2 < bm.height); y2++) { int x1 = x >= 0 ? x : 0; for (int x2 = x1 - x; (x1 < this.byteWidth) && (x2 < bm.byteWidth); ) { setUsed(x1, y1, bm.isUsed(x2, y2)); x1++; x2++; } y1++; } } public boolean isOverlap(BitMap bm, int x, int y) { int y1 = y >= 0 ? y : 0; for (int y2 = y1 - y; (y1 < this.height) && (y2 < bm.height); y2++) { int x1 = x >= 0 ? x : 0; for (int x2 = x1 - x; (x1 < this.width) && (x2 < bm.width); x2++) { if ((isUsed(x1, y1)) && (bm.isUsed(x2, y2))) return true; x1++; } y1++; } return false; } public boolean isUsed(int x, int y) { int byteX = x / 8; if ((byteX < 0) || (byteX >= this.byteWidth) || (y < 0) || (y >= this.height)) throw new IllegalArgumentException(); int mask = 1 << 7 - (x % 8 + 8) % 8; return (this.bitMap[y][byteX] & mask) != 0; } public void setUsed(int x, int y, boolean used) { int byteX = x / 8; if ((byteX < 0) || (byteX >= this.byteWidth) || (y < 0) || (y >= this.height)) throw new IllegalArgumentException(); int mask = 1 << 7 - (x % 8 + 8) % 8; if (used) { int tmp69_67 = byteX; byte[] tmp69_66 = this.bitMap[y]; tmp69_66[tmp69_67] = (byte)(tmp69_66[tmp69_67] | mask); } else { int tmp87_85 = byteX; byte[] tmp87_84 = this.bitMap[y]; tmp87_84[tmp87_85] = (byte)(tmp87_84[tmp87_85] & (mask ^ 0xFFFFFFFF)); } } public static void main(String[] args) throws IOException { BitMap m = new BitMap(9, 9); m.setUsed(1, 1, true); m.debug(); BitMap m2 = new BitMap(16, 15); m2.setUsed(14, 8, true); m2.debug(); m2.updateArea(m, 0, 0); m2.debug(); } public void debug() { System.out.println("=== DEBUG ( " + this.width + " x " + this.height + " ) ==="); for (int y = 0; y < this.height; y++) { for (int x = 0; x < this.width; x++) { boolean used = isUsed(x, y); System.out.print(!used ? "." : "*"); } System.out.println(); } } }
- 1 回答
- 0 关注
- 126 浏览
添加回答
举报
0/150
提交
取消