热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AS3版本的MaxRects算法测试

早上,在微博发现一条信息,关于MaxRects算法的,@杜增强DzQ移植的关于AS3版本的MaxRects算法,具体地址是:http:www.duzengqiang.comblogpos

  早上,在微博发现一条信息,关于MaxRects算法的,@杜增强DzQ 移植的关于AS3版本的MaxRects算法,具体地址是:http://www.duzengqiang.com/blog/post/971.html

  代码如下:

/*
Based on the Public Domain MaxRectanglesBinPack.cpp source by Jukka Jylänki
https://github.com/juj/RectangleBinPack/

Based on C# port by Sven Magnus
http://unifycommunity.com/wiki/index.php?title=MaxRectanglesBinPack


Ported to ActionScript3 by DUZENGQIANG
http://www.duzengqiang.com/blog/post/971.html
This version is also public domain - do whatever you want with it.
*/

package
{
import flash.geom.Rectangle;

/**
* MaxRectanglesBinPack
* @author DUZENGQIANG
* @date Jun 7, 2012
* @version 1.0
*

SinaMicroBlog: http://weibo.com/duzengqiang


*

blog: http://www.duzengqiang.com


*/
public class MaxRectsBinPack
{
public
var binWidth:int = 0;
public
var binHeight:int = 0;
public
var allowRotations:Boolean = false;

public
var usedRectangles:Vector. = new Vector.();
public
var freeRectangles:Vector. = new Vector.();

private
var score1:int = 0; // Unused in this function. We don't need to know the score after finding the position.
private var score2:int = 0;
private
var bestShortSideFit:int;
private
var bestLongSideFit:int;

public
function MaxRectsBinPack( width:int, height:int, rotations:Boolean = true) {
init(width, height, rotations);
}


private
function init(width:int, height:int, rotations:Boolean = true):void
{
if( count(width) % 1 != 0 ||count(height) % 1 != 0)
throw new Error("Must be 2,4,8,16,32,...512,1024,...");
binWidth
= width;
binHeight
= height;
allowRotations
= rotations;

var n:Rectangle = new Rectangle();
n.x
= 0;
n.y
= 0;
n.width
= width;
n.height
= height;

usedRectangles.length
= 0;

freeRectangles.length
= 0;
freeRectangles.push( n );
}

private
function count(n:Number):Number
{
if( n >= 2 )
return count(n / 2);
return n;
}

/**
* Insert a new Rectangle
* @param width
* @param height
* @param method
* @return
*
*/
public
function insert(width:int, height:int, method:int):Rectangle {
var newNode:Rectangle = new Rectangle();
score1
= 0;
score2
= 0;
switch(method) {
case FreeRectangleChoiceHeuristic.BestShortSideFit:
newNode
= findPositionForNewNodeBestShortSideFit(width, height);
break;
case FreeRectangleChoiceHeuristic.BottomLeftRule:
newNode
= findPositionForNewNodeBottomLeft(width, height, score1, score2);
break;
case FreeRectangleChoiceHeuristic.ContactPointRule:
newNode
= findPositionForNewNodeContactPoint(width, height, score1);
break;
case FreeRectangleChoiceHeuristic.BestLongSideFit:
newNode
= findPositionForNewNodeBestLongSideFit(width, height, score2, score1);
break;
case FreeRectangleChoiceHeuristic.BestAreaFit:
newNode
= findPositionForNewNodeBestAreaFit(width, height, score1, score2);
break;
}

if (newNode.height == 0)
return newNode;

placeRectangle(newNode);
trace(newNode);
return newNode;
}

public
function insert2( Rectangles:Vector., dst:Vector., method:int):void {
dst.length
= 0;

while(Rectangles.length > 0) {
var bestScore1:int = int.MAX_VALUE;
var bestScore2:int = int.MAX_VALUE;
var bestRectangleIndex:int = -1;
var bestNode:Rectangle = new Rectangle();

for(var i:int = 0; i i) {
var score1:int = 0;
var score2:int = 0;
var newNode:Rectangle = scoreRectangle(Rectangles[i].width, Rectangles[i].height, method, score1, score2);

if (score1 bestScore2)) {
bestScore1 = score1;
bestScore2
= score2;
bestNode
= newNode;
bestRectangleIndex
= i;
}
}

if (bestRectangleIndex == -1)
return;

placeRectangle(bestNode);
Rectangles.splice(bestRectangleIndex,
1);
}
}

private
function placeRectangle(node:Rectangle):void {
var numRectanglesToProcess:int = freeRectangles.length;
for(var i:int = 0; i ) {
if (splitFreeNode(freeRectangles[i], node)) {
freeRectangles.splice(i,
1);
--i;
--numRectanglesToProcess;
}
}

pruneFreeList();

usedRectangles.push(node);
}

private
function scoreRectangle( width:int, height:int, method:int,
score1:
int, score2:int):Rectangle {
var newNode:Rectangle = new Rectangle();
score1
= int.MAX_VALUE;
score2
= int.MAX_VALUE;
switch(method) {
case FreeRectangleChoiceHeuristic.BestShortSideFit:
newNode
= findPositionForNewNodeBestShortSideFit(width, height);
break;
case FreeRectangleChoiceHeuristic.BottomLeftRule:
newNode
= findPositionForNewNodeBottomLeft(width, height, score1,score2);
break;
case FreeRectangleChoiceHeuristic.ContactPointRule:
newNode
= findPositionForNewNodeContactPoint(width, height, score1);
// todo: reverse
score1 = -score1; // Reverse since we are minimizing, but for contact point score bigger is better.
break;
case FreeRectangleChoiceHeuristic.BestLongSideFit:
newNode
= findPositionForNewNodeBestLongSideFit(width, height, score2, score1);
break;
case FreeRectangleChoiceHeuristic.BestAreaFit:
newNode
= findPositionForNewNodeBestAreaFit(width, height, score1, score2);
break;
}

// Cannot fit the current Rectangle.
if (newNode.height == 0) {
score1
= int.MAX_VALUE;
score2
= int.MAX_VALUE;
}

return newNode;
}

/// Computes the ratio of used surface area.
private function occupancy():Number {
var usedSurfaceArea:Number = 0;
for(var i:int = 0; i )
usedSurfaceArea += usedRectangles[i].width * usedRectangles[i].height;

return usedSurfaceArea / (binWidth * binHeight);
}

private
function findPositionForNewNodeBottomLeft(width:int, height:int,
bestY:
int, bestX:int):Rectangle {
var bestNode:Rectangle = new Rectangle();
//memset(bestNode, 0, sizeof(Rectangle));

bestY
= int.MAX_VALUE;
var rect:Rectangle;
var topSideY:int;
for(var i:int = 0; i ) {
rect = freeRectangles[i];
// Try to place the Rectangle in upright (non-flipped) orientation.
if (rect.width >= width && rect.height >= height) {
topSideY
= rect.y + height;
if (topSideY bestX)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= width;
bestNode.height
= height;
bestY
= topSideY;
bestX
= rect.x;
}
}
if (allowRotations && rect.width >= height && rect.height >= width) {
topSideY
= rect.y + width;
if (topSideY bestX)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= height;
bestNode.height
= width;
bestY
= topSideY;
bestX
= rect.x;
}
}
}
return bestNode;
}

private
function findPositionForNewNodeBestShortSideFit(width:int, height:int):Rectangle {
var bestNode:Rectangle = new Rectangle();
//memset(&bestNode, 0, sizeof(Rectangle));

bestShortSideFit
= int.MAX_VALUE;
bestLongSideFit
= score2;
var rect:Rectangle;
var leftoverHoriz:int;
var leftoverVert:int;
var shortSideFit:int;
var longSideFit:int;

for(var i:int = 0; i ) {
rect = freeRectangles[i];
// Try to place the Rectangle in upright (non-flipped) orientation.
if (rect.width >= width && rect.height >= height) {
leftoverHoriz
= Math.abs(rect.width - width);
leftoverVert
= Math.abs(rect.height - height);
shortSideFit
= Math.min(leftoverHoriz, leftoverVert);
longSideFit
= Math.max(leftoverHoriz, leftoverVert);

if (shortSideFit bestLongSideFit)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= width;
bestNode.height
= height;
bestShortSideFit
= shortSideFit;
bestLongSideFit
= longSideFit;
}
}
var flippedLeftoverHoriz:Number;
var flippedLeftoverVert:Number;
var flippedShortSideFit:Number;
var flippedLongSideFit:Number;
if (allowRotations && rect.width >= height && rect.height >= width) {
flippedLeftoverHoriz
= Math.abs(rect.width - height);
flippedLeftoverVert
= Math.abs(rect.height - width);
flippedShortSideFit
= Math.min(flippedLeftoverHoriz, flippedLeftoverVert);
flippedLongSideFit
= Math.max(flippedLeftoverHoriz, flippedLeftoverVert);

if (flippedShortSideFit bestLongSideFit)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= height;
bestNode.height
= width;
bestShortSideFit
= flippedShortSideFit;
bestLongSideFit
= flippedLongSideFit;
}
}
}

return bestNode;
}

private
function findPositionForNewNodeBestLongSideFit(width:int, height:int, bestShortSideFit:int, bestLongSideFit:int):Rectangle {
var bestNode:Rectangle = new Rectangle();
//memset(&bestNode, 0, sizeof(Rectangle));
bestLOngSideFit= int.MAX_VALUE;
var rect:Rectangle;

var leftoverHoriz:int;
var leftoverVert:int;
var shortSideFit:int;
var longSideFit:int;
for(var i:int = 0; i ) {
rect = freeRectangles[i];
// Try to place the Rectangle in upright (non-flipped) orientation.
if (rect.width >= width && rect.height >= height) {
leftoverHoriz
= Math.abs(rect.width - width);
leftoverVert
= Math.abs(rect.height - height);
shortSideFit
= Math.min(leftoverHoriz, leftoverVert);
longSideFit
= Math.max(leftoverHoriz, leftoverVert);

if (longSideFit bestShortSideFit)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= width;
bestNode.height
= height;
bestShortSideFit
= shortSideFit;
bestLongSideFit
= longSideFit;
}
}

if (allowRotations && rect.width >= height && rect.height >= width) {
leftoverHoriz
= Math.abs(rect.width - height);
leftoverVert
= Math.abs(rect.height - width);
shortSideFit
= Math.min(leftoverHoriz, leftoverVert);
longSideFit
= Math.max(leftoverHoriz, leftoverVert);

if (longSideFit bestShortSideFit)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= height;
bestNode.height
= width;
bestShortSideFit
= shortSideFit;
bestLongSideFit
= longSideFit;
}
}
}
trace(bestNode);
return bestNode;
}

private
function findPositionForNewNodeBestAreaFit(width:int, height:int, bestAreaFit:int, bestShortSideFit:int):Rectangle {
var bestNode:Rectangle = new Rectangle();
//memset(&bestNode, 0, sizeof(Rectangle));

bestAreaFit
= int.MAX_VALUE;

var rect:Rectangle;

var leftoverHoriz:int;
var leftoverVert:int;
var shortSideFit:int;
var areaFit:int;

for(var i:int = 0; i ) {
rect = freeRectangles[i];
areaFit
= rect.width * rect.height - width * height;

// Try to place the Rectangle in upright (non-flipped) orientation.
if (rect.width >= width && rect.height >= height) {
leftoverHoriz
= Math.abs(rect.width - width);
leftoverVert
= Math.abs(rect.height - height);
shortSideFit
= Math.min(leftoverHoriz, leftoverVert);

if (areaFit bestShortSideFit)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= width;
bestNode.height
= height;
bestShortSideFit
= shortSideFit;
bestAreaFit
= areaFit;
}
}

if (allowRotations && rect.width >= height && rect.height >= width) {
leftoverHoriz
= Math.abs(rect.width - height);
leftoverVert
= Math.abs(rect.height - width);
shortSideFit
= Math.min(leftoverHoriz, leftoverVert);

if (areaFit bestShortSideFit)) {
bestNode.x = rect.x;
bestNode.y
= rect.y;
bestNode.width
= height;
bestNode.height
= width;
bestShortSideFit
= shortSideFit;
bestAreaFit
= areaFit;
}
}
}
return bestNode;
}

/// Returns 0 if the two intervals i1 and i2 are disjoint, or the length of their overlap otherwise.
private function commonIntervalLength(i1start:int, i1end:int, i2start:int, i2end:int):int {
if (i1end i1start)
return 0;
return Math.min(i1end, i2end) - Math.max(i1start, i2start);
}

private
function contactPointScoreNode(x:int, y:int, width:int, height:int):int {
var score:int = 0;

if (x == 0 || x + width == binWidth)
score
+= height;
if (y == 0 || y + height == binHeight)
score
+= width;
var rect:Rectangle;
for(var i:int = 0; i ) {
rect = usedRectangles[i];
if (rect.x == x + width || rect.x + rect.width == x)
score
+= commonIntervalLength(rect.y, rect.y + rect.height, y, y + height);
if (rect.y == y + height || rect.y + rect.height == y)
score
+= commonIntervalLength(rect.x, rect.x + rect.width, x, x + width);
}
return score;
}

private
function findPositionForNewNodeContactPoint(width:int, height:int, bestContactScore:int):Rectangle {
var bestNode:Rectangle = new Rectangle();
//memset(&bestNode, 0, sizeof(Rectangle));

bestContactScore
= -1;

var rect:Rectangle;
var score:int;
for(var i:int = 0; i ) {
rect = freeRectangles[i];
// Try to place the Rectangle in upright (non-flipped) orientation.
if (rect.width >= width && rect.height >= height) {
score
= contactPointScoreNode(rect.x, rect.y, width, height);
if (score > bestContactScore) {
bestNode.x
= rect.x;
bestNode.y
= rect.y;
bestNode.width
= width;
bestNode.height
= height;
bestContactScore
= score;
}
}
if (allowRotations && rect.width >= height && rect.height >= width) {
score
= contactPointScoreNode(rect.x, rect.y, height, width);
if (score > bestContactScore) {
bestNode.x
= rect.x;
bestNode.y
= rect.y;
bestNode.width
= height;
bestNode.height
= width;
bestContactScore
= score;
}
}
}
return bestNode;
}

private
function splitFreeNode(freeNode:Rectangle, usedNode:Rectangle):Boolean {
// Test with SAT if the Rectangles even intersect.
if (usedNode.x >= freeNode.x + freeNode.width || usedNode.x + usedNode.width <= freeNode.x ||
usedNode.y
>= freeNode.y + freeNode.height || usedNode.y + usedNode.height <= freeNode.y)
return false;
var newNode:Rectangle;
if (usedNode.x freeNode.x) {
// New node at the top side of the used node.
if (usedNode.y > freeNode.y && usedNode.y freeNode.height) {
newNode = freeNode.clone();
newNode.height
= usedNode.y - newNode.y;
freeRectangles.push(newNode);
}

// New node at the bottom side of the used node.
if (usedNode.y + usedNode.height freeNode.height) {
newNode = freeNode.clone();
newNode.y
= usedNode.y + usedNode.height;
newNode.height
= freeNode.y + freeNode.height - (usedNode.y + usedNode.height);
freeRectangles.push(newNode);
}
}

if (usedNode.y freeNode.y) {
// New node at the left side of the used node.
if (usedNode.x > freeNode.x && usedNode.x freeNode.width) {
newNode = freeNode.clone();
newNode.width
= usedNode.x - newNode.x;
freeRectangles.push(newNode);
}

// New node at the right side of the used node.
if (usedNode.x + usedNode.width freeNode.width) {
newNode = freeNode.clone();
newNode.x
= usedNode.x + usedNode.width;
newNode.width
= freeNode.x + freeNode.width - (usedNode.x + usedNode.width);
freeRectangles.push(newNode);
}
}

return true;
}

private
function pruneFreeList():void {
for(var i:int = 0; i )
for(var j:int = i+1; j ) {
if (isContainedIn(freeRectangles[i], freeRectangles[j])) {
freeRectangles.splice(i,
1);
break;
}
if (isContainedIn(freeRectangles[j], freeRectangles[i])) {
freeRectangles.splice(j,
1);
}
}
}

private
function isContainedIn(a:Rectangle, b:Rectangle):Boolean {
return a.x >= b.x && a.y >= b.y
&& a.x+a.width <= b.x+b.width
&& a.y+a.height <= b.y+b.height;
}
}

}
package
{
public class FreeRectangleChoiceHeuristic {
public static const BestShortSideFit:
int = 0; ///<-BSSF: Positions the Rectangle against the short side of a free Rectangle into which it fits the best.
public static const BestLongSideFit:int = 1; ///<-BLSF: Positions the Rectangle against the long side of a free Rectangle into which it fits the best.
public static const BestAreaFit:int = 2; ///<-BAF: Positions the Rectangle into the smallest free Rectangle into which it fits.
public static const BottomLeftRule:int = 3; ///<-BL: Does the Tetris placement.
public static const ContactPointRule:int = 4; ///<-CP: Choosest the placement where the Rectangle touches other Rectangles as much as possible.
}
}

  好奇,做了个测试,代码如下:

package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Point;
import flash.geom.Rectangle;

[SWF(width
="800", , frameRate="30")]
public class Demo extends Sprite
{
[Embed(source
="assets/1.png")]
private
var defence:Class;

public
function Demo()
{
var bitmap:Bitmap = Bitmap(new defence());
trace(bitmap.width, bitmap.height);

//Create new MaxRectsBinPack instance
var maxRect:MaxRectsBinPack = new MaxRectsBinPack(bitmap.width,bitmap.height,false);
// insert new rectangle
//maxRect.insert(bitmap.width/2, bitmap.height/2, FreeRectangleChoiceHeuristic.BestLongSideFit);
// insert new rectangle
//maxRect.insert(bitmap.width/2, bitmap.height/2, FreeRectangleChoiceHeuristic.BestLongSideFit);
// insert new rectangle
//maxRect.insert(bitmap.width/2, bitmap.height/2, FreeRectangleChoiceHeuristic.BestLongSideFit);
// insert new rectangle
//maxRect.insert(bitmap.width/2, bitmap.height/2, FreeRectangleChoiceHeuristic.BestLongSideFit);


var rects:Vector. = new Vector.();
rects.push(
new Rectangle(0,0,bitmap.width/2, bitmap.height/2));
rects.push(
new Rectangle(0,0,bitmap.width/2, bitmap.height/2));
rects.push(
new Rectangle(0,0,bitmap.width/2, bitmap.height/2));
rects.push(
new Rectangle(0,0,bitmap.width/2, bitmap.height/2));
maxRect.insert2(rects,
new Vector.(), FreeRectangleChoiceHeuristic.BestLongSideFit);

for(var i:int = 0; i ) {
var rect:Rectangle = maxRect.usedRectangles[i];
trace(rect);
var bitmapData:BitmapData = new BitmapData(rect.width, rect.height, true, 0);
bitmapData.copyPixels(bitmap.bitmapData, rect,
new Point());

var newBitmap:Bitmap = new Bitmap(bitmapData);
newBitmap.x
= rect.x;
newBitmap.y
= rect.y;
this.addChild(newBitmap);
}
}
}
}

  图片用的我们游戏里的,正面2帧,背面2帧,嘿嘿

  

  有几个疑问:

  首先,图片要求是2的次幂,如果有的图片,做成影片剪辑时,是3帧,如果能满足 2的次幂的结果是3的倍数呢?这里,我认为有一种方案,可以通过每一帧的偏移量来做,而不是非要3的倍数,不知道这样理解对不对?

  其次,这个图片的空白区域,不知道用@杜增强DzQ提供的工具类里,是否带透明部分的自动裁剪。

  最后,我试了下面几种方法,但是没感觉到有什么区别,不知道能不能帮忙解答下,非常感谢。

    public class FreeRectangleChoiceHeuristic {
public static const BestShortSideFit:
int = 0; ///<-BSSF: Positions the Rectangle against the short side of a free Rectangle into which it fits the best.
public static const BestLongSideFit:int = 1; ///<-BLSF: Positions the Rectangle against the long side of a free Rectangle into which it fits the best.
public static const BestAreaFit:int = 2; ///<-BAF: Positions the Rectangle into the smallest free Rectangle into which it fits.
public static const BottomLeftRule:int = 3; ///<-BL: Does the Tetris placement.
public static const ContactPointRule:int = 4; ///<-CP: Choosest the placement where the Rectangle touches other Rectangles as much as possible.
}

推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 本文详细介绍了PHP中与URL处理相关的三个函数:http_build_query、parse_str和查询字符串的解析。通过示例和语法说明,讲解了这些函数的使用方法和作用,帮助读者更好地理解和应用。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
author-avatar
手机用户2502892757
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有