为了账号安全,请及时绑定邮箱和手机立即绑定

在php中如何实现下面图片的效果?

在php中如何实现下面图片的效果?

PHP
HUH函数 2023-04-05 22:18:37
要求:“上”和“爱情”都是通过程序自动输出的,程序能共自动判断画布上得空白部分并输出文字。在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();
    }
  }
}


查看完整回答
反对 回复 2023-04-07
  • 1 回答
  • 0 关注
  • 126 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信