目次
回复内容:
ホームページ バックエンド開発 PHPチュートリアル gd - php中如何获得双色图片的mask

gd - php中如何获得双色图片的mask

Jun 06, 2016 pm 08:52 PM
gd php 効果 文字

gd - php中如何获得双色图片的mask

在php中如何实现上图的效果?要求:“上”和“爱情”都是通过程序自动输出的,程序能共自动判断画布上得空白部分并输出文字。

在python中,有pygame库直接获得一个画布的mask,然后提供collide函数来判断两个mask是否有交集。php是否有类似功能?

换个问题:
php中如何获得双色图片的mask

回复内容:

gd - php中如何获得双色图片的mask

在php中如何实现上图的效果?要求:“上”和“爱情”都是通过程序自动输出的,程序能共自动判断画布上得空白部分并输出文字。

在python中,有pygame库直接获得一个画布的mask,然后提供collide函数来判断两个mask是否有交集。php是否有类似功能?

换个问题:
php中如何获得双色图片的mask

更新下算法解释,貌似做成php版的还算简单
http://ued.ctrip.com/blog/?p=2471

携程的算法源码如下:

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()  2560) || (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() > 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 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()  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  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 = bitMap.getWidth()) || (y = bitMap.getHeight()))
      return false;
    for (int i = x; i  bi.getWidth())
      r = bi.getWidth();
    if (b > bi.getHeight())
      b = bi.getHeight();
    if ((r = 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 ...");
      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()  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 ? y : 0; for (int y2 = y1 - y; (y1 = 0 ? x : 0; for (int x2 = x1 - x; (x1 = 0 ? y : 0; for (int y2 = y1 - y; (y1 = 0 ? x : 0; for (int x2 = x1 - x; (x1 = this.byteWidth) || (y = this.height))
      throw new IllegalArgumentException();
    int mask = 1 = this.byteWidth) || (y = this.height))
      throw new IllegalArgumentException();
    int mask = 1 <p>反汇编工具jd-gui</p>
<p>写了一个flex版本的,执行时间大约1~2s,效果如下:<br>
<img  src="/static/imghw/default1.png" data-src="http://segmentfault.com/img/cJHB5O" class="lazy" data- alt="gd - php中如何获得双色图片的mask" ></p>
<p>源码layout.mxml:</p>
<pre class="brush:php;toolbar:false"><?xml version="1.0" encoding="utf-8"?>
<application xmlns:mx="http://www.adobe.com/2006/mxml" creationcomplete="onLoad();">
<style> 
 

@font-face{
	src:url("fanghei.ttf");
	font-family:myFont;
}

</style> 
<script>
mxmlc layout.mxml
///

import mx.controls.*;
import mx.core.*;
import mx.effects.*;
import flash.geom.Rectangle


private function clear():void
{
	my_text_input_1.text="clear it!";
}



private function add_text(text_array:Array, text:String):void
{
	text_array.push(text);
}

private function get_bmp_text(text:String):Bitmap
{
	var metrics:TextLineMetrics;
	var tempTextField:TextField = new TextField();

	var tempTextFormat:TextFormat = new TextFormat();
	tempTextFormat.font="myFont";
	tempTextFormat.size = Math.floor(Math.random() * 40 + 20);
	tempTextFormat.color = 0xff00FF;

	tempTextField.width = 200;
	tempTextField.height = 100;
	tempTextField.embedFonts = true;
	tempTextField.appendText(text);
	tempTextField.setTextFormat(tempTextFormat);

	metrics = tempTextField.getLineMetrics(0);
	var myBitmapData:BitmapData = new BitmapData(metrics.width, metrics.height, true ,0x0000FF);
	myBitmapData.draw(tempTextField);
	var myBmp:Bitmap = new Bitmap(myBitmapData);

	//本版本不支持rotation
	//如果要支持rotation,请参考http://www.mikechambers.com/blog/2009/06/24/using-bitmapdata-hittest-for-collision-detection/
	//myBmp.rotation = (Math.random() > 0.5)?0:90;

	return myBmp;
}

private function add_to_canvas(result:Array, bmpText:Bitmap):Boolean
{
	var last_angle:Number = 0;
	var last_radius:Number = 1;
	var x:int = 0;
	var y:int = 0;
	var center_x:int = 256;
	var center_y:int = 256;
	var width:int = 512;
	var height:int = 512;
	var conflict:Boolean = false;

	while(true)
	{
		last_angle = last_angle + 0.1;
		last_radius = last_radius + 0.1;
		x = Math.floor(last_radius * Math.cos(last_angle) + center_x);
		y = Math.floor(last_radius * Math.sin(last_angle) + center_y);
			
		bmpText.x = x;
		bmpText.y = y;

		conflict = false;
		if (result.length > 0)
		{
			var i:int;
			for(i = 0; i ";
			if (last_radius > width || last_radius > height)
			{
				conflict = true;
				break;
			}
		}
	}
	return !conflict;
}


private function draw(result:Array):void
{
	var s:Sprite = new Sprite;

	var i:int;
	for(i = 0; i </script>

	<label text="Hello World"></label>
	<label id="metrics_txt_1" text="Hello World" fontfamily="myFont"></label>
	<label id="metrics_txt_2" text="Hello World"></label>
	<textinput id="my_text_input_1" width="100" text=""></textinput>
	<button id="my_clear_button_1" label="clear" click="clear();"></button>

	<canvas backgroundcolor="0xFFFFFF" width="512" height="512" horizontalcenter="0" verticalcenter="0" id="canvas"></canvas>  
</application>
ログイン後にコピー
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

CakePHP プロジェクトの構成 CakePHP プロジェクトの構成 Sep 10, 2024 pm 05:25 PM

この章では、CakePHP の環境変数、一般設定、データベース設定、電子メール設定について理解します。

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

CakePHP の日付と時刻 CakePHP の日付と時刻 Sep 10, 2024 pm 05:27 PM

Cakephp4 で日付と時刻を操作するには、利用可能な FrozenTime クラスを利用します。

CakePHP ファイルのアップロード CakePHP ファイルのアップロード Sep 10, 2024 pm 05:27 PM

ファイルのアップロードを行うには、フォーム ヘルパーを使用します。ここではファイルアップロードの例を示します。

CakePHP ルーティング CakePHP ルーティング Sep 10, 2024 pm 05:25 PM

この章では、ルーティングに関連する次のトピックを学習します。

CakePHP について話し合う CakePHP について話し合う Sep 10, 2024 pm 05:28 PM

CakePHP は、PHP 用のオープンソース フレームワークです。これは、アプリケーションの開発、展開、保守をより簡単にすることを目的としています。 CakePHP は、強力かつ理解しやすい MVC のようなアーキテクチャに基づいています。モデル、ビュー、コントローラー

CakePHP データベースの操作 CakePHP データベースの操作 Sep 10, 2024 pm 05:25 PM

CakePHP でデータベースを操作するのは非常に簡単です。この章では、CRUD (作成、読み取り、更新、削除) 操作について理解します。

CakePHP バリデータの作成 CakePHP バリデータの作成 Sep 10, 2024 pm 05:26 PM

Validator は、コントローラーに次の 2 行を追加することで作成できます。

See all articles