Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
cf4fc46757
89
.example.env
89
.example.env
@ -1 +1,88 @@
|
||||
APP_DEBUG=true
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=likeadmin
DB_USERNAME=root
DB_PASSWORD=root
SESSION_DRIVER=file
REDIS_CONNECTION=default
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_DB=24
YLY_PARTNER=25991
YLY_API_KEY=d955cc2296d69b4094c6465aad360dc6b19a8c77
YLY_REQUEST_URL=http://open.10ss.net:8888
UNIQUE_IDENTIFICATION = "11d3"
DEMO_ENV = ""
|
||||
APP_DEBUG=true
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=likeadmin
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=root
|
||||
|
||||
SESSION_DRIVER=file
|
||||
|
||||
REDIS_CONNECTION=default
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
REDIS_DB=24
|
||||
|
||||
YLY_PARTNER=25991
|
||||
YLY_API_KEY=d955cc2296d69b4094c6465aad360dc6b19a8c77
|
||||
YLY_REQUEST_URL=http://open.10ss.net:8888
|
||||
|
||||
UNIQUE_IDENTIFICATION = "11d3"
|
||||
DEMO_ENV = ""
|
||||
|
||||
$manager = new ImageManager(
|
||||
Driver::class
|
||||
);
|
||||
// open an image file
|
||||
$image = $manager->create(250,300)->fill('#ffffff');
|
||||
$image->text('莲花池农贸市场', 125, 30, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
$font->align('center'); // 设置文字对齐方式,这里以居中对齐为例
|
||||
});
|
||||
$image->text('单号:PF1717393175823834', 10, 60, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
|
||||
$image->text('下单时间:2024-5-15 18:00:35', 10, 75, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('================================', 10, 90, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('单价', 10, 105, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('数量', 115, 105, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('小计', 210, 105, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('白菜大白菜', 10, 120, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('236.60元', 10, 135, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('13KG', 115, 135, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('12896.34元', 180, 135, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('================================', 10, 145, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('应付款30.01元', 10, 155, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('实付款30.01元', 10, 170, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('支付方式:微信支付', 10, 185, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('支付单号:fn1717552219113289171', 10, 200, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('联系电话:0830-2669767', 10, 215, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('================================', 10, 230, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
||||
$image->text('欢迎下次光临!', 85, 260, function ($font) {
|
||||
$font->file(runtime_path() . '/ali.ttf'); // 设置字体文件路径,这里以微软雅黑字体为例
|
||||
});
|
@ -7,7 +7,7 @@ use app\admin\controller\BaseAdminController;
|
||||
use app\admin\lists\store_product\StoreProductLists;
|
||||
use app\admin\logic\store_product\StoreProductLogic;
|
||||
use app\admin\validate\store_product\StoreProductValidate;
|
||||
|
||||
use app\common\model\store_branch_product\StoreBranchProduct;
|
||||
|
||||
/**
|
||||
* 门店商品辅助控制器
|
||||
@ -65,7 +65,32 @@ class StoreBranchProductController extends BaseAdminController
|
||||
return $this->success('编辑成功', [], 1, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @notes 编辑门店商品辅助价格
|
||||
* @return \think\response\Json
|
||||
* @author likeadmin
|
||||
* @date 2024/05/31 10:53
|
||||
*/
|
||||
public function edit_price()
|
||||
{
|
||||
$params =$this->request->post();
|
||||
$res= StoreBranchProduct::where('id',$params['id'])->update(['price'=>$params['price']]);
|
||||
if($res){
|
||||
return $this->success('编辑成功', [], 1, 1);
|
||||
}else{
|
||||
return $this->fail('编辑失败', [], 1, 1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @notes 编辑门店商品辅助库存
|
||||
* @return \think\response\Json
|
||||
* @author likeadmin
|
||||
* @date 2024/05/31 10:53
|
||||
*/
|
||||
public function edit_stock()
|
||||
{
|
||||
return $this->success('编辑成功', [], 1, 1);
|
||||
}
|
||||
/**
|
||||
* @notes 删除门店商品辅助列表
|
||||
* @return \think\response\Json
|
||||
|
@ -8,6 +8,7 @@ use app\common\enum\OrderEnum;
|
||||
use app\common\enum\PayEnum;
|
||||
use app\common\model\store_finance_flow\StoreFinanceFlow;
|
||||
use app\common\lists\ListsSearchInterface;
|
||||
use app\common\model\system_store\SystemStore;
|
||||
use app\common\model\system_store\SystemStoreStaff;
|
||||
use app\common\model\user\User;
|
||||
|
||||
@ -29,7 +30,7 @@ class StoreFinanceFlowLists extends BaseAdminDataLists implements ListsSearchInt
|
||||
public function setSearch(): array
|
||||
{
|
||||
return [
|
||||
'=' => ['store_id', 'user_id', 'create_time'],
|
||||
'=' => ['store_id', 'uid', 'create_time'],
|
||||
];
|
||||
}
|
||||
|
||||
@ -46,20 +47,37 @@ class StoreFinanceFlowLists extends BaseAdminDataLists implements ListsSearchInt
|
||||
public function lists(): array
|
||||
{
|
||||
return StoreFinanceFlow::where($this->searchWhere)
|
||||
->when(!empty($this->params['start_time']), function ($query) {
|
||||
$query->whereTime('create_time', '>=', $this->params['start_time']);
|
||||
})
|
||||
->when(!empty($this->params['end_time']), function ($query) {
|
||||
if ($this->params['end_time'] == $this->params['start_time']) {
|
||||
$this->params['end_time'] = strtotime($this->params['end_time']) + 86399;
|
||||
}
|
||||
$query->whereTime('create_time', '<=', $this->params['end_time']);
|
||||
})
|
||||
->when(!empty($this->request->adminInfo['store_id']), function ($query) {
|
||||
$query->where('store_id', '=', $this->request->adminInfo['store_id']);
|
||||
})
|
||||
->limit($this->limitOffset, $this->limitLength)
|
||||
->order(['id' => 'desc'])
|
||||
->select()->each(function ($item) {
|
||||
if($item['user_id']<=0){
|
||||
$item['nickname']='游客';
|
||||
}else{
|
||||
$item['nickname']=User::where('id',$item['user_id'])->value('nickname');
|
||||
$id=$item['user_id'];
|
||||
$item['nickname']=User::where('id',$item['user_id'])->value('nickname')."($id)";
|
||||
}
|
||||
if($item['financial_pm']==0){
|
||||
$item['number']='-'.$item['number'];
|
||||
}else{
|
||||
$item['number']='+'.$item['number'];
|
||||
if (!empty($this->request->adminInfo['store_id'])) {
|
||||
$item['financial_pm'] = $item['financial_pm'] == 0 ? 1 : 0;
|
||||
}
|
||||
if ($item['financial_pm'] == 0) {
|
||||
$item['number'] = '-' . $item['number'];
|
||||
} else {
|
||||
$item['number'] = '+' . $item['number'];
|
||||
}
|
||||
$item['staff_name']=SystemStoreStaff::where('id',$item['staff_id'])->value('staff_name');
|
||||
$item['store_name']=$item['store_id']>0?SystemStore::where('id',$item['store_id'])->value('name'):'';
|
||||
$item['pay_type_name']=PayEnum::getPaySceneDesc($item['pay_type']);
|
||||
$item['financial_type_name']=OrderEnum::getFinancialType($item['financial_type']);
|
||||
})
|
||||
@ -78,4 +96,4 @@ class StoreFinanceFlowLists extends BaseAdminDataLists implements ListsSearchInt
|
||||
return StoreFinanceFlow::where($this->searchWhere)->count();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ class SystemStoreLists extends BaseAdminDataLists implements ListsSearchInterfac
|
||||
public function setSearch(): array
|
||||
{
|
||||
return [
|
||||
'=' => ['name', 'phone'],
|
||||
'=' => ['phone'],
|
||||
'%like%'=>['name']
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,6 @@ class PayNotifyLogic extends BaseLogic
|
||||
if (!$order->save()) {
|
||||
throw new \Exception('订单保存出错');
|
||||
}
|
||||
self::afterPay($order);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,9 +203,9 @@ class PayNotifyLogic extends BaseLogic
|
||||
$financeLogic->user = ['uid' => $order['uid']];
|
||||
if ($order->pay_type != 9 || $order->pay_type != 10) {
|
||||
$financeLogic->in($transaction_id,$order['pay_price'], OrderEnum::USER_ORDER_PAY);
|
||||
$financeLogic->out($transaction_id,$order['pay_price'], OrderEnum::MERCHANT_ORDER_OBTAINS, $order['store_id'], $order['staff_id'], 0);
|
||||
$financeLogic->save();
|
||||
}
|
||||
$financeLogic->out($transaction_id,$order['pay_price'], OrderEnum::MERCHANT_ORDER_OBTAINS, $order['store_id'], $order['staff_id'], 0);
|
||||
$financeLogic->save();
|
||||
}
|
||||
|
||||
//等级处理
|
||||
|
@ -26,7 +26,7 @@ class StoreFinanceFlowLogic extends BaseLogic
|
||||
*/
|
||||
public function out($transaction_id,$number, $financialType, $storeId = 0, $staffId = 0, $status = 1)
|
||||
{
|
||||
$this->setData($number, $financialType, 1, $storeId, $staffId, $status,$transaction_id);
|
||||
$this->setData($number, $financialType, 0, $storeId, $staffId, $status,$transaction_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,7 +40,7 @@ class StoreFinanceFlowLogic extends BaseLogic
|
||||
*/
|
||||
public function in($transaction_id,$number, $financialType, $storeId = 0, $staffId = 0, $status = 1)
|
||||
{
|
||||
$this->setData($number, $financialType, 0, $storeId, $staffId, $status,$transaction_id);
|
||||
$this->setData($number, $financialType, 1, $storeId, $staffId, $status,$transaction_id);
|
||||
}
|
||||
|
||||
public function setData($number, $financialType, $pm, $storeId, $staffId, $status,$transaction_id)
|
||||
|
51
app/store/controller/finance/FinanceController.php
Normal file
51
app/store/controller/finance/FinanceController.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace app\store\controller\finance;
|
||||
|
||||
use app\admin\lists\store_finance_flow\StoreFinanceFlowLists;
|
||||
use app\common\controller\Definitions;
|
||||
use app\store\controller\BaseAdminController;
|
||||
use hg\apidoc\annotation as ApiDoc;
|
||||
|
||||
#[ApiDoc\title('财务')]
|
||||
class FinanceController extends BaseAdminController
|
||||
{
|
||||
|
||||
#[
|
||||
ApiDoc\Title('财务流水'),
|
||||
ApiDoc\url('/store/finance/finance/lists'),
|
||||
ApiDoc\Method('GET'),
|
||||
ApiDoc\NotHeaders(),
|
||||
ApiDoc\Author('中国队长'),
|
||||
ApiDoc\Query(name: 'keyword', type: 'string', require: false, desc: '订单编号'),
|
||||
ApiDoc\Query(name: 'staff_id', type: 'int', require: false, desc: '店员id'),
|
||||
ApiDoc\Query(name: 'start_time', type: 'string', require: false, desc: '开始时间'),
|
||||
ApiDoc\Query(name: 'end_time', type: 'string', require: false, desc: '结束时间'),
|
||||
ApiDoc\Header(ref: [Definitions::class, "token"]),
|
||||
ApiDoc\Query(ref: [Definitions::class, "page"]),
|
||||
ApiDoc\ResponseSuccess("data", type: "array", children: [
|
||||
['name' => 'id', 'desc' => 'ID', 'type' => 'int'],
|
||||
['name' => 'order_id', 'desc' => '订单编号', 'type' => 'string'],
|
||||
['name' => 'pay_price', 'desc' => '支付金额', 'type' => 'string'],
|
||||
['name' => 'pay_time', 'desc' => '支付时间', 'type' => 'float'],
|
||||
['name' => 'pay_type', 'desc' => '支付方式', 'type' => 'float'],
|
||||
['name' => 'status_name', 'desc' => '状态', 'type' => 'int'],
|
||||
['name' => 'staff_name', 'desc' => '店员', 'type' => 'int'],
|
||||
['name' => 'nickname', 'desc' => '用户昵称', 'type' => 'string'],
|
||||
['name' => 'avatar', 'desc' => '用户头像', 'type' => 'string'],
|
||||
['name' => 'product', 'desc' => '商品信息', 'type' => 'array', 'children' => [
|
||||
['name' => 'cart_info', 'desc' => '商品信息', 'type' => 'array', 'children' => [
|
||||
['name' => 'name', 'desc' => '商品名称', 'type' => 'int'],
|
||||
['name' => 'image', 'desc' => '图片', 'type' => 'string'],
|
||||
['name' => 'cart_num', 'desc' => '购买数量', 'type' => 'string'],
|
||||
['name' => 'price', 'desc' => '单价', 'type' => 'string'],
|
||||
]],
|
||||
]],
|
||||
]),
|
||||
]
|
||||
public function lists()
|
||||
{
|
||||
return $this->dataLists(new StoreFinanceFlowLists());
|
||||
}
|
||||
|
||||
}
|
@ -54,7 +54,8 @@
|
||||
"ext-bcmath": "*",
|
||||
"jpush/jpush": "^3.6",
|
||||
"workerman/crontab": "^1.0",
|
||||
"hg/apidoc": "^5.2"
|
||||
"hg/apidoc": "^5.2",
|
||||
"intervention/image": "^3.6"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
|
152
composer.lock
generated
152
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1af6ecc42a475bea0bb2a849fdce3e61",
|
||||
"content-hash": "dbe3251ac873990fcca149094effefa5",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aliyuncs/oss-sdk-php",
|
||||
@ -1953,6 +1953,154 @@
|
||||
},
|
||||
"time": "2024-04-07T17:47:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "intervention/gif",
|
||||
"version": "4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/gif.git",
|
||||
"reference": "3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/gif/zipball/3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3",
|
||||
"reference": "3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"slevomat/coding-standard": "~8.0",
|
||||
"squizlabs/php_codesniffer": "^3.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Gif\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"description": "Native PHP GIF Encoder/Decoder",
|
||||
"homepage": "https://github.com/intervention/gif",
|
||||
"keywords": [
|
||||
"animation",
|
||||
"gd",
|
||||
"gif",
|
||||
"image"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Intervention/gif/issues",
|
||||
"source": "https://github.com/Intervention/gif/tree/4.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://paypal.me/interventionio",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Intervention",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-26T17:23:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "intervention/image",
|
||||
"version": "3.6.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/image.git",
|
||||
"reference": "193324ec88bc5ad4039e57ce9b926ae28dfde813"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/image/zipball/193324ec88bc5ad4039e57ce9b926ae28dfde813",
|
||||
"reference": "193324ec88bc5ad4039e57ce9b926ae28dfde813",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"intervention/gif": "^4.1",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.6",
|
||||
"phpstan/phpstan": "^1",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"slevomat/coding-standard": "~8.0",
|
||||
"squizlabs/php_codesniffer": "^3.8"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-exif": "Recommended to be able to read EXIF data properly."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"description": "PHP image manipulation",
|
||||
"homepage": "https://image.intervention.io/",
|
||||
"keywords": [
|
||||
"gd",
|
||||
"image",
|
||||
"imagick",
|
||||
"resize",
|
||||
"thumbnail",
|
||||
"watermark"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Intervention/image/issues",
|
||||
"source": "https://github.com/Intervention/image/tree/3.6.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://paypal.me/interventionio",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Intervention",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-08T13:53:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jpush/jpush",
|
||||
"version": "v3.6.8",
|
||||
@ -7065,5 +7213,5 @@
|
||||
"ext-bcmath": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
2
vendor/composer/autoload_psr4.php
vendored
2
vendor/composer/autoload_psr4.php
vendored
@ -81,6 +81,8 @@ return array(
|
||||
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
|
||||
'JPush\\' => array($vendorDir . '/jpush/jpush/src/JPush'),
|
||||
'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
|
||||
'Intervention\\Image\\' => array($vendorDir . '/intervention/image/src'),
|
||||
'Intervention\\Gif\\' => array($vendorDir . '/intervention/gif/src'),
|
||||
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/conditionable', $vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/support'),
|
||||
'Illuminate\\Redis\\' => array($vendorDir . '/illuminate/redis'),
|
||||
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
|
||||
|
10
vendor/composer/autoload_static.php
vendored
10
vendor/composer/autoload_static.php
vendored
@ -172,6 +172,8 @@ class ComposerStaticInitcefecbcff919f3c1c8084830bbb72adc
|
||||
'I' =>
|
||||
array (
|
||||
'Invoker\\' => 8,
|
||||
'Intervention\\Image\\' => 19,
|
||||
'Intervention\\Gif\\' => 17,
|
||||
'Illuminate\\Support\\' => 19,
|
||||
'Illuminate\\Redis\\' => 17,
|
||||
'Illuminate\\Contracts\\' => 21,
|
||||
@ -529,6 +531,14 @@ class ComposerStaticInitcefecbcff919f3c1c8084830bbb72adc
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-di/invoker/src',
|
||||
),
|
||||
'Intervention\\Image\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/intervention/image/src',
|
||||
),
|
||||
'Intervention\\Gif\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/intervention/gif/src',
|
||||
),
|
||||
'Illuminate\\Support\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/collections',
|
||||
|
154
vendor/composer/installed.json
vendored
154
vendor/composer/installed.json
vendored
@ -2031,6 +2031,160 @@
|
||||
},
|
||||
"install-path": "../illuminate/support"
|
||||
},
|
||||
{
|
||||
"name": "intervention/gif",
|
||||
"version": "4.1.0",
|
||||
"version_normalized": "4.1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/gif.git",
|
||||
"reference": "3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/gif/zipball/3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3",
|
||||
"reference": "3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"slevomat/coding-standard": "~8.0",
|
||||
"squizlabs/php_codesniffer": "^3.8"
|
||||
},
|
||||
"time": "2024-03-26T17:23:47+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Gif\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"description": "Native PHP GIF Encoder/Decoder",
|
||||
"homepage": "https://github.com/intervention/gif",
|
||||
"keywords": [
|
||||
"animation",
|
||||
"gd",
|
||||
"gif",
|
||||
"image"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Intervention/gif/issues",
|
||||
"source": "https://github.com/Intervention/gif/tree/4.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://paypal.me/interventionio",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Intervention",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"install-path": "../intervention/gif"
|
||||
},
|
||||
{
|
||||
"name": "intervention/image",
|
||||
"version": "3.6.4",
|
||||
"version_normalized": "3.6.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/image.git",
|
||||
"reference": "193324ec88bc5ad4039e57ce9b926ae28dfde813"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/image/zipball/193324ec88bc5ad4039e57ce9b926ae28dfde813",
|
||||
"reference": "193324ec88bc5ad4039e57ce9b926ae28dfde813",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"intervention/gif": "^4.1",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.6",
|
||||
"phpstan/phpstan": "^1",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"slevomat/coding-standard": "~8.0",
|
||||
"squizlabs/php_codesniffer": "^3.8"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-exif": "Recommended to be able to read EXIF data properly."
|
||||
},
|
||||
"time": "2024-05-08T13:53:15+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"description": "PHP image manipulation",
|
||||
"homepage": "https://image.intervention.io/",
|
||||
"keywords": [
|
||||
"gd",
|
||||
"image",
|
||||
"imagick",
|
||||
"resize",
|
||||
"thumbnail",
|
||||
"watermark"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Intervention/image/issues",
|
||||
"source": "https://github.com/Intervention/image/tree/3.6.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://paypal.me/interventionio",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Intervention",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"install-path": "../intervention/image"
|
||||
},
|
||||
{
|
||||
"name": "jpush/jpush",
|
||||
"version": "v3.6.8",
|
||||
|
30
vendor/composer/installed.php
vendored
30
vendor/composer/installed.php
vendored
@ -1,9 +1,9 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'workerman/webman',
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '272597cc5c5f8a88f8124e91ea19bf8217a25a58',
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => null,
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@ -262,6 +262,24 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'intervention/gif' => array(
|
||||
'pretty_version' => '4.1.0',
|
||||
'version' => '4.1.0.0',
|
||||
'reference' => '3a2b5f8a8856e8877cdab5c47e51aab2d4cb23a3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../intervention/gif',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'intervention/image' => array(
|
||||
'pretty_version' => '3.6.4',
|
||||
'version' => '3.6.4.0',
|
||||
'reference' => '193324ec88bc5ad4039e57ce9b926ae28dfde813',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../intervention/image',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jpush/jpush' => array(
|
||||
'pretty_version' => 'v3.6.8',
|
||||
'version' => '3.6.8.0',
|
||||
@ -1011,9 +1029,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'workerman/webman' => array(
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '272597cc5c5f8a88f8124e91ea19bf8217a25a58',
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => null,
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
4
vendor/composer/platform_check.php
vendored
4
vendor/composer/platform_check.php
vendored
@ -8,6 +8,10 @@ if (!(PHP_VERSION_ID >= 80100)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if (PHP_INT_SIZE !== 8) {
|
||||
$issues[] = 'Your Composer dependencies require a 64-bit build of PHP.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
|
21
vendor/intervention/gif/LICENSE
vendored
Normal file
21
vendor/intervention/gif/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020-2024 Oliver Vogel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
100
vendor/intervention/gif/README.md
vendored
Normal file
100
vendor/intervention/gif/README.md
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
# Intervention GIF
|
||||
## Native PHP GIF Encoder/Decoder
|
||||
|
||||
[](https://packagist.org/packages/intervention/gif)
|
||||

|
||||
[](https://packagist.org/packages/intervention/gif/stats)
|
||||
|
||||
Intervention GIF is a PHP encoder and decoder for the GIF image format that
|
||||
does not depend on any image processing extension.
|
||||
|
||||
Only the special `Splitter::class` class divides the data stream of an animated
|
||||
GIF into individual `GDImage` objects for each frame and is therefore dependent
|
||||
on the GD library.
|
||||
|
||||
The library is the main component of [Intervention
|
||||
Image](https://github.com/Intervention/image) for processing animated GIF files
|
||||
with the GD library, but also works independently.
|
||||
|
||||
## Installation
|
||||
|
||||
You can easily install this package using [Composer](https://getcomposer.org).
|
||||
Just request the package with the following command:
|
||||
|
||||
```bash
|
||||
composer require intervention/gif
|
||||
```
|
||||
|
||||
## Code Examples
|
||||
|
||||
### Decoding
|
||||
|
||||
```php
|
||||
use Intervention\Gif\Decoder;
|
||||
|
||||
// Decode filepath to Intervention\Gif\GifDataStream::class
|
||||
$gif = Decoder::decode('images/animation.gif');
|
||||
|
||||
// Decoder can also handle binary content directly
|
||||
$gif = Decoder::decode($contents);
|
||||
```
|
||||
|
||||
### Encoding
|
||||
|
||||
Use the Builder class to create a new GIF image.
|
||||
|
||||
```php
|
||||
use Intervention\Gif\Builder;
|
||||
|
||||
// create new gif canvas
|
||||
$gif = Builder::canvas(width: 32, height: 32);
|
||||
|
||||
// add animation frames to canvas
|
||||
$delay = .25; // delay in seconds after next frame is displayed
|
||||
$left = 0; // position offset (left)
|
||||
$top = 0; // position offset (top)
|
||||
|
||||
// add animation frames with optional delay in seconds
|
||||
// and optional position offset for each frame
|
||||
$gif->addFrame('images/frame01.gif', $delay, $left, $top);
|
||||
$gif->addFrame('images/frame02.gif', $delay, $left);
|
||||
$gif->addFrame('images/frame03.gif', $delay);
|
||||
$gif->addFrame('images/frame04.gif');
|
||||
|
||||
// set loop count; 0 for infinite looping
|
||||
$gif->setLoops(12);
|
||||
|
||||
// encode
|
||||
$data = $gif->encode();
|
||||
```
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
- PHP >= 8.1
|
||||
|
||||
## Development & Testing
|
||||
|
||||
With this package comes a Docker image to build a test suite and analysis
|
||||
container. To build this container you have to have Docker installed on your
|
||||
system. You can run all tests with this command.
|
||||
|
||||
```bash
|
||||
docker-compose run --rm --build tests
|
||||
```
|
||||
|
||||
Run the static analyzer on the code base.
|
||||
|
||||
```bash
|
||||
docker-compose run --rm --build analysis
|
||||
```
|
||||
|
||||
## Authors
|
||||
|
||||
This library is developed and maintained by [Oliver Vogel](https://intervention.io)
|
||||
|
||||
Thanks to the community of [contributors](https://github.com/Intervention/gif/graphs/contributors) who have helped to improve this project.
|
||||
|
||||
## License
|
||||
|
||||
Intervention GIF is licensed under the [MIT License](LICENSE).
|
44
vendor/intervention/gif/composer.json
vendored
Normal file
44
vendor/intervention/gif/composer.json
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "intervention/gif",
|
||||
"description": "Native PHP GIF Encoder/Decoder",
|
||||
"homepage": "https://github.com/intervention/gif",
|
||||
"keywords": [
|
||||
"image",
|
||||
"gd",
|
||||
"gif",
|
||||
"animation"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"phpstan/phpstan": "^1",
|
||||
"squizlabs/php_codesniffer": "^3.8",
|
||||
"slevomat/coding-standard": "~8.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Gif\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Intervention\\Gif\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
}
|
||||
}
|
13
vendor/intervention/gif/phpunit.xml.dist
vendored
Normal file
13
vendor/intervention/gif/phpunit.xml.dist
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" beStrictAboutTestsThatDoNotTestAnything="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
|
||||
<testsuites>
|
||||
<testsuite name="Unit Tests">
|
||||
<directory suffix=".php">./tests/Unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
37
vendor/intervention/gif/src/AbstractEntity.php
vendored
Normal file
37
vendor/intervention/gif/src/AbstractEntity.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Intervention\Gif\Traits\CanDecode;
|
||||
use Intervention\Gif\Traits\CanEncode;
|
||||
use ReflectionClass;
|
||||
|
||||
abstract class AbstractEntity
|
||||
{
|
||||
use CanEncode;
|
||||
use CanDecode;
|
||||
|
||||
public const TERMINATOR = "\x00";
|
||||
|
||||
/**
|
||||
* Get short classname of current instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getShortClassname(): string
|
||||
{
|
||||
return (new ReflectionClass(static::class))->getShortName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast object to string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->encode();
|
||||
}
|
||||
}
|
10
vendor/intervention/gif/src/AbstractExtension.php
vendored
Normal file
10
vendor/intervention/gif/src/AbstractExtension.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
abstract class AbstractExtension extends AbstractEntity
|
||||
{
|
||||
public const MARKER = "\x21";
|
||||
}
|
62
vendor/intervention/gif/src/Blocks/ApplicationExtension.php
vendored
Normal file
62
vendor/intervention/gif/src/Blocks/ApplicationExtension.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
|
||||
class ApplicationExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\xFF";
|
||||
|
||||
/**
|
||||
* Application Identifier & Auth Code
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $application = '';
|
||||
|
||||
/**
|
||||
* Data Sub Blocks
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $blocks = [];
|
||||
|
||||
public function getBlockSize(): int
|
||||
{
|
||||
return strlen($this->application);
|
||||
}
|
||||
|
||||
public function setApplication(string $value): self
|
||||
{
|
||||
$this->application = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getApplication(): string
|
||||
{
|
||||
return $this->application;
|
||||
}
|
||||
|
||||
public function addBlock(DataSubBlock $block): self
|
||||
{
|
||||
$this->blocks[] = $block;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBlocks(array $blocks): self
|
||||
{
|
||||
$this->blocks = $blocks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBlocks(): array
|
||||
{
|
||||
return $this->blocks;
|
||||
}
|
||||
}
|
100
vendor/intervention/gif/src/Blocks/Color.php
vendored
Normal file
100
vendor/intervention/gif/src/Blocks/Color.php
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class Color extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param int $r
|
||||
* @param int $g
|
||||
* @param int $b
|
||||
*/
|
||||
public function __construct(
|
||||
protected int $r = 0,
|
||||
protected int $g = 0,
|
||||
protected int $b = 0
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get red value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRed()
|
||||
{
|
||||
return $this->r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set red value
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setRed(int $value): self
|
||||
{
|
||||
$this->r = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get green value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getGreen()
|
||||
{
|
||||
return $this->g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set green value
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setGreen(int $value): self
|
||||
{
|
||||
$this->g = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get blue value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlue()
|
||||
{
|
||||
return $this->b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set blue value
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setBlue(int $value): self
|
||||
{
|
||||
$this->b = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return hash value of current color
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHash(): string
|
||||
{
|
||||
return md5($this->r . $this->g . $this->b);
|
||||
}
|
||||
}
|
151
vendor/intervention/gif/src/Blocks/ColorTable.php
vendored
Normal file
151
vendor/intervention/gif/src/Blocks/ColorTable.php
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class ColorTable extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param array $colors
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(protected array $colors = [])
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of current colors
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColors(): array
|
||||
{
|
||||
return array_values($this->colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add color to table
|
||||
*
|
||||
* @param int $r
|
||||
* @param int $g
|
||||
* @param int $b
|
||||
*/
|
||||
public function addRgb(int $r, int $g, int $b): self
|
||||
{
|
||||
$this->addColor(new Color($r, $g, $b));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add color to table
|
||||
*
|
||||
* @param Color $color
|
||||
*/
|
||||
public function addColor(Color $color): self
|
||||
{
|
||||
$this->colors[] = $color;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset colors to array of color objects
|
||||
*
|
||||
* @param array $colors
|
||||
*/
|
||||
public function setColors(array $colors): self
|
||||
{
|
||||
$this->empty();
|
||||
foreach ($colors as $color) {
|
||||
$this->addColor($color);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count colors of current instance
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countColors(): int
|
||||
{
|
||||
return count($this->colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any colors are present on the current table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasColors(): bool
|
||||
{
|
||||
return $this->countColors() >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty color table
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function empty(): self
|
||||
{
|
||||
$this->colors = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of color table in logical screen descriptor
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLogicalSize(): int
|
||||
{
|
||||
switch ($this->countColors()) {
|
||||
case 4:
|
||||
return 1;
|
||||
|
||||
case 8:
|
||||
return 2;
|
||||
|
||||
case 16:
|
||||
return 3;
|
||||
|
||||
case 32:
|
||||
return 4;
|
||||
|
||||
case 64:
|
||||
return 5;
|
||||
|
||||
case 128:
|
||||
return 6;
|
||||
|
||||
case 256:
|
||||
return 7;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of bytes contained by the current table
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getByteSize(): int
|
||||
{
|
||||
if (!$this->hasColors()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 3 * pow(2, $this->getLogicalSize() + 1);
|
||||
}
|
||||
}
|
52
vendor/intervention/gif/src/Blocks/CommentExtension.php
vendored
Normal file
52
vendor/intervention/gif/src/Blocks/CommentExtension.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
|
||||
class CommentExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\xFE";
|
||||
|
||||
/**
|
||||
* Comment blocks
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $comments = [];
|
||||
|
||||
/**
|
||||
* Get all or one comment
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getComments()
|
||||
{
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one comment by key
|
||||
*
|
||||
* @param int $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function getComment(int $key): mixed
|
||||
{
|
||||
return array_key_exists($key, $this->comments) ? $this->comments[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set comment text
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function addComment(string $value): self
|
||||
{
|
||||
$this->comments[] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
30
vendor/intervention/gif/src/Blocks/DataSubBlock.php
vendored
Normal file
30
vendor/intervention/gif/src/Blocks/DataSubBlock.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
use Intervention\Gif\Exceptions\FormatException;
|
||||
|
||||
class DataSubBlock extends AbstractEntity
|
||||
{
|
||||
public function __construct(protected string $value)
|
||||
{
|
||||
if ($this->getSize() > 255) {
|
||||
throw new FormatException(
|
||||
'Data Sub-Block can not have a block size larger than 255 bytes.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function getSize(): int
|
||||
{
|
||||
return strlen($this->value);
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
175
vendor/intervention/gif/src/Blocks/FrameBlock.php
vendored
Normal file
175
vendor/intervention/gif/src/Blocks/FrameBlock.php
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class FrameBlock extends AbstractEntity
|
||||
{
|
||||
protected ?GraphicControlExtension $graphicControlExtension = null;
|
||||
protected ?ColorTable $colorTable = null;
|
||||
protected ?PlainTextExtension $plainTextExtension = null;
|
||||
protected array $applicationExtensions = [];
|
||||
protected array $commentExtensions = [];
|
||||
|
||||
public function __construct(
|
||||
protected ImageDescriptor $imageDescriptor = new ImageDescriptor(),
|
||||
protected ImageData $imageData = new ImageData()
|
||||
) {
|
||||
}
|
||||
|
||||
public function addEntity(AbstractEntity $entity): self
|
||||
{
|
||||
switch (true) {
|
||||
case $entity instanceof TableBasedImage:
|
||||
$this->setTableBasedImage($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof GraphicControlExtension:
|
||||
$this->setGraphicControlExtension($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof ImageDescriptor:
|
||||
$this->setImageDescriptor($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof ColorTable:
|
||||
$this->setColorTable($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof ImageData:
|
||||
$this->setImageData($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof PlainTextExtension:
|
||||
$this->setPlainTextExtension($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof NetscapeApplicationExtension:
|
||||
$this->addApplicationExtension($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof ApplicationExtension:
|
||||
$this->addApplicationExtension($entity);
|
||||
break;
|
||||
|
||||
case $entity instanceof CommentExtension:
|
||||
$this->addCommentExtension($entity);
|
||||
break;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getApplicationExtensions(): array
|
||||
{
|
||||
return $this->applicationExtensions;
|
||||
}
|
||||
|
||||
public function getCommentExtensions(): array
|
||||
{
|
||||
return $this->commentExtensions;
|
||||
}
|
||||
|
||||
public function setGraphicControlExtension(GraphicControlExtension $extension): self
|
||||
{
|
||||
$this->graphicControlExtension = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGraphicControlExtension(): ?GraphicControlExtension
|
||||
{
|
||||
return $this->graphicControlExtension;
|
||||
}
|
||||
|
||||
public function setImageDescriptor(ImageDescriptor $descriptor): self
|
||||
{
|
||||
$this->imageDescriptor = $descriptor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getImageDescriptor(): ImageDescriptor
|
||||
{
|
||||
return $this->imageDescriptor;
|
||||
}
|
||||
|
||||
public function setColorTable(ColorTable $table): self
|
||||
{
|
||||
$this->colorTable = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getColorTable(): ?ColorTable
|
||||
{
|
||||
return $this->colorTable;
|
||||
}
|
||||
|
||||
public function hasColorTable(): bool
|
||||
{
|
||||
return !is_null($this->colorTable);
|
||||
}
|
||||
|
||||
public function setImageData(ImageData $data): self
|
||||
{
|
||||
$this->imageData = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getImageData(): ImageData
|
||||
{
|
||||
return $this->imageData;
|
||||
}
|
||||
|
||||
public function setPlainTextExtension(PlainTextExtension $extension): self
|
||||
{
|
||||
$this->plainTextExtension = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPlainTextExtension(): ?PlainTextExtension
|
||||
{
|
||||
return $this->plainTextExtension;
|
||||
}
|
||||
|
||||
public function addApplicationExtension(ApplicationExtension $extension): self
|
||||
{
|
||||
$this->applicationExtensions[] = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addCommentExtension(CommentExtension $extension): self
|
||||
{
|
||||
$this->commentExtensions[] = $extension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNetscapeExtension(): ?NetscapeApplicationExtension
|
||||
{
|
||||
$extensions = array_filter($this->applicationExtensions, function ($extension) {
|
||||
return $extension instanceof NetscapeApplicationExtension;
|
||||
});
|
||||
|
||||
return count($extensions) ? reset($extensions) : null;
|
||||
}
|
||||
|
||||
public function setTableBasedImage(TableBasedImage $tableBasedImage): self
|
||||
{
|
||||
$this->setImageDescriptor($tableBasedImage->getImageDescriptor());
|
||||
|
||||
if ($colorTable = $tableBasedImage->getColorTable()) {
|
||||
$this->setColorTable($colorTable);
|
||||
}
|
||||
|
||||
$this->setImageData($tableBasedImage->getImageData());
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
159
vendor/intervention/gif/src/Blocks/GraphicControlExtension.php
vendored
Normal file
159
vendor/intervention/gif/src/Blocks/GraphicControlExtension.php
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
use Intervention\Gif\DisposalMethod;
|
||||
|
||||
class GraphicControlExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\xF9";
|
||||
public const BLOCKSIZE = "\x04";
|
||||
|
||||
/**
|
||||
* Existance flag of transparent color
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $transparentColorExistance = false;
|
||||
|
||||
/**
|
||||
* Transparent color index
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $transparentColorIndex = 0;
|
||||
|
||||
/**
|
||||
* User input flag
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $userInput = false;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param int $delay
|
||||
* @param DisposalMethod $disposalMethod
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
protected int $delay = 0,
|
||||
protected DisposalMethod $disposalMethod = DisposalMethod::UNDEFINED,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set delay time (1/100 second)
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setDelay(int $value): self
|
||||
{
|
||||
$this->delay = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return delay time (1/100 second)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDelay(): int
|
||||
{
|
||||
return $this->delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set disposal method
|
||||
*
|
||||
* @param DisposalMethod $method
|
||||
* @return self
|
||||
*/
|
||||
public function setDisposalMethod(DisposalMethod $method): self
|
||||
{
|
||||
$this->disposalMethod = $method;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get disposal method
|
||||
*
|
||||
* @return DisposalMethod
|
||||
*/
|
||||
public function getDisposalMethod(): DisposalMethod
|
||||
{
|
||||
return $this->disposalMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transparent color index
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTransparentColorIndex(): int
|
||||
{
|
||||
return $this->transparentColorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transparent color index
|
||||
*
|
||||
* @param int $index
|
||||
*/
|
||||
public function setTransparentColorIndex(int $index): self
|
||||
{
|
||||
$this->transparentColorIndex = $index;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current transparent color existance
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getTransparentColorExistance(): bool
|
||||
{
|
||||
return $this->transparentColorExistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set existance flag of transparent color
|
||||
*
|
||||
* @param bool $existance
|
||||
*/
|
||||
public function setTransparentColorExistance(bool $existance = true): self
|
||||
{
|
||||
$this->transparentColorExistance = $existance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user input flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUserInput(): bool
|
||||
{
|
||||
return $this->userInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user input flag
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setUserInput(bool $value = true): self
|
||||
{
|
||||
$this->userInput = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
42
vendor/intervention/gif/src/Blocks/Header.php
vendored
Normal file
42
vendor/intervention/gif/src/Blocks/Header.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class Header extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Header signature
|
||||
*/
|
||||
public const SIGNATURE = 'GIF';
|
||||
|
||||
/**
|
||||
* Current GIF version
|
||||
*/
|
||||
protected string $version = '89a';
|
||||
|
||||
/**
|
||||
* Set GIF version
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setVersion(string $value): self
|
||||
{
|
||||
$this->version = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current version
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVersion(): string
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
}
|
80
vendor/intervention/gif/src/Blocks/ImageData.php
vendored
Normal file
80
vendor/intervention/gif/src/Blocks/ImageData.php
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class ImageData extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* LZW min. code size
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $lzw_min_code_size;
|
||||
|
||||
/**
|
||||
* Sub blocks
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $blocks = [];
|
||||
|
||||
/**
|
||||
* Get LZW min. code size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLzwMinCodeSize(): int
|
||||
{
|
||||
return $this->lzw_min_code_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set lzw min. code size
|
||||
*
|
||||
* @param int $size
|
||||
* @return ImageData
|
||||
*/
|
||||
public function setLzwMinCodeSize(int $size): self
|
||||
{
|
||||
$this->lzw_min_code_size = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current data sub blocks
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBlocks(): array
|
||||
{
|
||||
return $this->blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Addd sub block
|
||||
*
|
||||
* @param DataSubBlock $block
|
||||
* @return ImageData
|
||||
*/
|
||||
public function addBlock(DataSubBlock $block): self
|
||||
{
|
||||
$this->blocks[] = $block;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if data sub blocks are present
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBlocks(): bool
|
||||
{
|
||||
return count($this->blocks) >= 1;
|
||||
}
|
||||
}
|
246
vendor/intervention/gif/src/Blocks/ImageDescriptor.php
vendored
Normal file
246
vendor/intervention/gif/src/Blocks/ImageDescriptor.php
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class ImageDescriptor extends AbstractEntity
|
||||
{
|
||||
public const SEPARATOR = "\x2C";
|
||||
|
||||
/**
|
||||
* Width of frame
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $width = 0;
|
||||
|
||||
/**
|
||||
* Height of frame
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $height = 0;
|
||||
|
||||
/**
|
||||
* Left position of frame
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $left = 0;
|
||||
|
||||
/**
|
||||
* Top position of frame
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $top = 0;
|
||||
|
||||
/**
|
||||
* Determine if frame is interlaced
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $interlaced = false;
|
||||
|
||||
/**
|
||||
* Local color table flag
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $localColorTableExistance = false;
|
||||
|
||||
/**
|
||||
* Sort flag of local color table
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $localColorTableSorted = false;
|
||||
|
||||
/**
|
||||
* Size of local color table
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $localColorTableSize = 0;
|
||||
|
||||
/**
|
||||
* Get current width
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWidth(): int
|
||||
{
|
||||
return intval($this->width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current width
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeight(): int
|
||||
{
|
||||
return intval($this->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current Top
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTop(): int
|
||||
{
|
||||
return intval($this->top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current Left
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLeft(): int
|
||||
{
|
||||
return intval($this->left);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of current instance
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*/
|
||||
public function setSize(int $width, int $height): self
|
||||
{
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set position of current instance
|
||||
*
|
||||
* @param int $left
|
||||
* @param int $top
|
||||
*/
|
||||
public function setPosition(int $left, int $top): self
|
||||
{
|
||||
$this->left = $left;
|
||||
$this->top = $top;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if frame is interlaced
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInterlaced(): bool
|
||||
{
|
||||
return $this->interlaced === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or unset interlaced value
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setInterlaced(bool $value = true): self
|
||||
{
|
||||
$this->interlaced = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if local color table is present
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getLocalColorTableExistance(): bool
|
||||
{
|
||||
return $this->localColorTableExistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for getLocalColorTableExistance
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLocalColorTable(): bool
|
||||
{
|
||||
return $this->getLocalColorTableExistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set local color table flag
|
||||
*
|
||||
* @param bool $existance
|
||||
* @return self
|
||||
*/
|
||||
public function setLocalColorTableExistance($existance = true): self
|
||||
{
|
||||
$this->localColorTableExistance = $existance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get local color table sorted flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getLocalColorTableSorted(): bool
|
||||
{
|
||||
return $this->localColorTableSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set local color table sorted flag
|
||||
*
|
||||
* @param bool $sorted
|
||||
* @return self
|
||||
*/
|
||||
public function setLocalColorTableSorted($sorted = true): self
|
||||
{
|
||||
$this->localColorTableSorted = $sorted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of local color table
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLocalColorTableSize(): int
|
||||
{
|
||||
return $this->localColorTableSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get byte size of global color table
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLocalColorTableByteSize(): int
|
||||
{
|
||||
return 3 * pow(2, $this->getLocalColorTableSize() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of local color table
|
||||
*
|
||||
* @param int $size
|
||||
*/
|
||||
public function setLocalColorTableSize(int $size): self
|
||||
{
|
||||
$this->localColorTableSize = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
254
vendor/intervention/gif/src/Blocks/LogicalScreenDescriptor.php
vendored
Normal file
254
vendor/intervention/gif/src/Blocks/LogicalScreenDescriptor.php
vendored
Normal file
@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class LogicalScreenDescriptor extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Width
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $width;
|
||||
|
||||
/**
|
||||
* Height
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $height;
|
||||
|
||||
/**
|
||||
* Global color table flag
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $globalColorTableExistance = false;
|
||||
|
||||
/**
|
||||
* Sort flag of global color table
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $globalColorTableSorted = false;
|
||||
|
||||
/**
|
||||
* Size of global color table
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $globalColorTableSize = 0;
|
||||
|
||||
/**
|
||||
* Background color index
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $backgroundColorIndex = 0;
|
||||
|
||||
/**
|
||||
* Color resolution
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $bitsPerPixel = 8;
|
||||
|
||||
/**
|
||||
* Pixel aspect ration
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected int $pixelAspectRatio = 0;
|
||||
|
||||
/**
|
||||
* Set size
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*/
|
||||
public function setSize(int $width, int $height): self
|
||||
{
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get width of current instance
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWidth(): int
|
||||
{
|
||||
return intval($this->width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get height of current instance
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeight(): int
|
||||
{
|
||||
return intval($this->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if global color table is present
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getGlobalColorTableExistance(): bool
|
||||
{
|
||||
return $this->globalColorTableExistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of getGlobalColorTableExistance
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasGlobalColorTable(): bool
|
||||
{
|
||||
return $this->getGlobalColorTableExistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set global color table flag
|
||||
*
|
||||
* @param bool $existance
|
||||
* @return self
|
||||
*/
|
||||
public function setGlobalColorTableExistance($existance = true): self
|
||||
{
|
||||
$this->globalColorTableExistance = $existance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get global color table sorted flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getGlobalColorTableSorted(): bool
|
||||
{
|
||||
return $this->globalColorTableSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set global color table sorted flag
|
||||
*
|
||||
* @param bool $sorted
|
||||
* @return self
|
||||
*/
|
||||
public function setGlobalColorTableSorted($sorted = true): self
|
||||
{
|
||||
$this->globalColorTableSorted = $sorted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of global color table
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getGlobalColorTableSize(): int
|
||||
{
|
||||
return $this->globalColorTableSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get byte size of global color table
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getGlobalColorTableByteSize(): int
|
||||
{
|
||||
return 3 * pow(2, $this->getGlobalColorTableSize() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size of global color table
|
||||
*
|
||||
* @param int $size
|
||||
*/
|
||||
public function setGlobalColorTableSize(int $size): self
|
||||
{
|
||||
$this->globalColorTableSize = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get background color index
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBackgroundColorIndex(): int
|
||||
{
|
||||
return $this->backgroundColorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color index
|
||||
*
|
||||
* @param int $index
|
||||
*/
|
||||
public function setBackgroundColorIndex(int $index): self
|
||||
{
|
||||
$this->backgroundColorIndex = $index;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current pixel aspect ration
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPixelAspectRatio(): int
|
||||
{
|
||||
return $this->pixelAspectRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set pixel aspect ratio
|
||||
*
|
||||
* @param int $ratio
|
||||
*/
|
||||
public function setPixelAspectRatio(int $ratio): self
|
||||
{
|
||||
$this->pixelAspectRatio = $ratio;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color resolution
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBitsPerPixel()
|
||||
{
|
||||
return $this->bitsPerPixel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color resolution
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setBitsPerPixel(int $value): self
|
||||
{
|
||||
$this->bitsPerPixel = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
32
vendor/intervention/gif/src/Blocks/NetscapeApplicationExtension.php
vendored
Normal file
32
vendor/intervention/gif/src/Blocks/NetscapeApplicationExtension.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
class NetscapeApplicationExtension extends ApplicationExtension
|
||||
{
|
||||
public const IDENTIFIER = "NETSCAPE";
|
||||
public const AUTH_CODE = "2.0";
|
||||
public const SUB_BLOCK_PREFIX = "\x01";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setApplication(self::IDENTIFIER . self::AUTH_CODE);
|
||||
$this->setBlocks([new DataSubBlock(self::SUB_BLOCK_PREFIX . "\x00\x00")]);
|
||||
}
|
||||
|
||||
public function getLoops(): int
|
||||
{
|
||||
return unpack('v*', substr($this->getBlocks()[0]->getValue(), 1))[1];
|
||||
}
|
||||
|
||||
public function setLoops(int $loops): self
|
||||
{
|
||||
$this->setBlocks([
|
||||
new DataSubBlock(self::SUB_BLOCK_PREFIX . pack('v*', $loops))
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
63
vendor/intervention/gif/src/Blocks/PlainTextExtension.php
vendored
Normal file
63
vendor/intervention/gif/src/Blocks/PlainTextExtension.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
|
||||
class PlainTextExtension extends AbstractExtension
|
||||
{
|
||||
public const LABEL = "\x01";
|
||||
|
||||
/**
|
||||
* Array of text
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $text = [];
|
||||
|
||||
/**
|
||||
* Get current text
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getText(): array
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add text
|
||||
*
|
||||
* @param string $text
|
||||
*/
|
||||
public function addText(string $text): self
|
||||
{
|
||||
$this->text[] = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text array of extension
|
||||
*
|
||||
* @param array $text
|
||||
*/
|
||||
public function setText(array $text): self
|
||||
{
|
||||
$this->text = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any text is present
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasText(): bool
|
||||
{
|
||||
return count($this->text) > 0;
|
||||
}
|
||||
}
|
50
vendor/intervention/gif/src/Blocks/TableBasedImage.php
vendored
Normal file
50
vendor/intervention/gif/src/Blocks/TableBasedImage.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class TableBasedImage extends AbstractEntity
|
||||
{
|
||||
protected ImageDescriptor $imageDescriptor;
|
||||
protected ?ColorTable $colorTable = null;
|
||||
protected ImageData $imageData;
|
||||
|
||||
public function getImageDescriptor(): ImageDescriptor
|
||||
{
|
||||
return $this->imageDescriptor;
|
||||
}
|
||||
|
||||
public function setImageDescriptor(ImageDescriptor $descriptor): self
|
||||
{
|
||||
$this->imageDescriptor = $descriptor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getImageData(): ImageData
|
||||
{
|
||||
return $this->imageData;
|
||||
}
|
||||
|
||||
public function setImageData(ImageData $data): self
|
||||
{
|
||||
$this->imageData = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getColorTable(): ?ColorTable
|
||||
{
|
||||
return $this->colorTable;
|
||||
}
|
||||
|
||||
public function setColorTable(ColorTable $table): self
|
||||
{
|
||||
$this->colorTable = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
12
vendor/intervention/gif/src/Blocks/Trailer.php
vendored
Normal file
12
vendor/intervention/gif/src/Blocks/Trailer.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Blocks;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
|
||||
class Trailer extends AbstractEntity
|
||||
{
|
||||
public const MARKER = "\x3b";
|
||||
}
|
215
vendor/intervention/gif/src/Builder.php
vendored
Normal file
215
vendor/intervention/gif/src/Builder.php
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Exception;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
use Intervention\Gif\Traits\CanHandleFiles;
|
||||
|
||||
class Builder
|
||||
{
|
||||
use CanHandleFiles;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param GifDataStream $gif
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(protected GifDataStream $gif = new GifDataStream())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GifDataStream object we're currently building
|
||||
*
|
||||
* @return GifDataStream
|
||||
*/
|
||||
public function getGifDataStream(): GifDataStream
|
||||
{
|
||||
return $this->gif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set canvas size of gif
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @return Builder
|
||||
*/
|
||||
public function setSize(int $width, int $height): self
|
||||
{
|
||||
$this->gif->getLogicalScreenDescriptor()->setSize($width, $height);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new canvas
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @return self
|
||||
*/
|
||||
public static function canvas(int $width, int $height): self
|
||||
{
|
||||
return (new self())->setSize($width, $height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set loop count
|
||||
*
|
||||
* @param int $loops
|
||||
* @return Builder
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setLoops(int $loops): self
|
||||
{
|
||||
if (count($this->gif->getFrames()) === 0) {
|
||||
throw new Exception('Add at least one frame before setting the loop count');
|
||||
}
|
||||
|
||||
if ($loops >= 0) {
|
||||
// add frame count to existing or new netscape extension on first frame
|
||||
if (!$this->gif->getFirstFrame()->getNetscapeExtension()) {
|
||||
$this->gif->getFirstFrame()->addApplicationExtension(
|
||||
new NetscapeApplicationExtension()
|
||||
);
|
||||
}
|
||||
$this->gif->getFirstFrame()->getNetscapeExtension()->setLoops($loops);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new animation frame from given source
|
||||
* which can be path to a file or GIF image data
|
||||
*
|
||||
* @param string $source
|
||||
* @param float $delay time delay in seconds
|
||||
* @param int $left position offset in pixels from left
|
||||
* @param int $top position offset in pixels from top
|
||||
* @param bool $interlaced
|
||||
* @return Builder
|
||||
*/
|
||||
public function addFrame(
|
||||
string $source,
|
||||
float $delay = 0,
|
||||
int $left = 0,
|
||||
int $top = 0,
|
||||
bool $interlaced = false
|
||||
): self {
|
||||
$frame = new FrameBlock();
|
||||
$source = Decoder::decode($source);
|
||||
|
||||
// store delay
|
||||
$frame->setGraphicControlExtension(
|
||||
$this->buildGraphicControlExtension(
|
||||
$source,
|
||||
intval($delay * 100)
|
||||
)
|
||||
);
|
||||
|
||||
// store image
|
||||
$frame->setTableBasedImage(
|
||||
$this->buildTableBasedImage($source, $left, $top, $interlaced)
|
||||
);
|
||||
|
||||
// add frame
|
||||
$this->gif->addFrame($frame);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build new graphic control extension with given delay & disposal method
|
||||
*
|
||||
* @param GifDataStream $source
|
||||
* @param int $delay
|
||||
* @param DisposalMethod $disposalMethod
|
||||
* @return GraphicControlExtension
|
||||
*/
|
||||
protected function buildGraphicControlExtension(
|
||||
GifDataStream $source,
|
||||
int $delay,
|
||||
DisposalMethod $disposalMethod = DisposalMethod::BACKGROUND
|
||||
): GraphicControlExtension {
|
||||
// create extension
|
||||
$extension = new GraphicControlExtension($delay, $disposalMethod);
|
||||
|
||||
// set transparency index
|
||||
$control = $source->getFirstFrame()->getGraphicControlExtension();
|
||||
if ($control && $control->getTransparentColorExistance()) {
|
||||
$extension->setTransparentColorExistance();
|
||||
$extension->setTransparentColorIndex(
|
||||
$control->getTransparentColorIndex()
|
||||
);
|
||||
}
|
||||
|
||||
return $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build table based image object from given source
|
||||
*
|
||||
* @param GifDataStream $source
|
||||
* @param int $left
|
||||
* @param int $top
|
||||
* @param bool $interlaced
|
||||
* @return TableBasedImage
|
||||
*/
|
||||
protected function buildTableBasedImage(
|
||||
GifDataStream $source,
|
||||
int $left,
|
||||
int $top,
|
||||
bool $interlaced
|
||||
): TableBasedImage {
|
||||
$block = new TableBasedImage();
|
||||
$block->setImageDescriptor(new ImageDescriptor());
|
||||
|
||||
// set global color table from source as local color table
|
||||
$block->getImageDescriptor()->setLocalColorTableExistance();
|
||||
$block->setColorTable($source->getGlobalColorTable());
|
||||
|
||||
$block->getImageDescriptor()->setLocalColorTableSorted(
|
||||
$source->getLogicalScreenDescriptor()->getGlobalColorTableSorted()
|
||||
);
|
||||
|
||||
$block->getImageDescriptor()->setLocalColorTableSize(
|
||||
$source->getLogicalScreenDescriptor()->getGlobalColorTableSize()
|
||||
);
|
||||
|
||||
$block->getImageDescriptor()->setSize(
|
||||
$source->getLogicalScreenDescriptor()->getWidth(),
|
||||
$source->getLogicalScreenDescriptor()->getHeight()
|
||||
);
|
||||
|
||||
// set position
|
||||
$block->getImageDescriptor()->setPosition($left, $top);
|
||||
|
||||
// set interlaced flag
|
||||
$block->getImageDescriptor()->setInterlaced($interlaced);
|
||||
|
||||
// add image data from source
|
||||
$block->setImageData($source->getFirstFrame()->getImageData());
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the current build
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return $this->gif->encode();
|
||||
}
|
||||
}
|
30
vendor/intervention/gif/src/Decoder.php
vendored
Normal file
30
vendor/intervention/gif/src/Decoder.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Traits\CanHandleFiles;
|
||||
|
||||
class Decoder
|
||||
{
|
||||
use CanHandleFiles;
|
||||
|
||||
/**
|
||||
* Decode given input
|
||||
*
|
||||
* @param mixed $input
|
||||
* @return GifDataStream
|
||||
*/
|
||||
public static function decode(mixed $input): GifDataStream
|
||||
{
|
||||
return GifDataStream::decode(
|
||||
match (true) {
|
||||
self::isFilePath($input) => self::getHandleFromFilePath($input),
|
||||
is_string($input) => self::getHandleFromData($input),
|
||||
default => throw new DecoderException('Decoder input must be either file path or binary data.')
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
153
vendor/intervention/gif/src/Decoders/AbstractDecoder.php
vendored
Normal file
153
vendor/intervention/gif/src/Decoders/AbstractDecoder.php
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
abstract class AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function decode(): mixed;
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param resource $handle
|
||||
* @param null|int $length
|
||||
*/
|
||||
public function __construct(protected $handle, protected ?int $length = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source to decode
|
||||
*
|
||||
* @param resource $handle
|
||||
*/
|
||||
public function setHandle($handle): self
|
||||
{
|
||||
$this->handle = $handle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given number of bytes and move file pointer
|
||||
*
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
protected function getNextBytes(int $length): string
|
||||
{
|
||||
return fread($this->handle, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given number of bytes and move pointer back to previous position
|
||||
*
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
protected function viewNextBytes(int $length): string
|
||||
{
|
||||
$bytes = $this->getNextBytes($length);
|
||||
$this->movePointer($length * -1);
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read next byte and move pointer back to previous position
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function viewNextByte(): string
|
||||
{
|
||||
return $this->viewNextBytes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all remaining bytes from file handler
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getRemainingBytes(): string
|
||||
{
|
||||
$all = '';
|
||||
do {
|
||||
$byte = fread($this->handle, 1);
|
||||
$all .= $byte;
|
||||
} while (!feof($this->handle));
|
||||
|
||||
return $all;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next byte in stream and move file pointer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getNextByte(): string
|
||||
{
|
||||
return $this->getNextBytes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move file pointer on handle by given offset
|
||||
*
|
||||
* @param int $offset
|
||||
* @return self
|
||||
*/
|
||||
protected function movePointer(int $offset): self
|
||||
{
|
||||
fseek($this->handle, $offset, SEEK_CUR);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode multi byte value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeMultiByte(string $bytes): int
|
||||
{
|
||||
return unpack('v*', $bytes)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set length
|
||||
*
|
||||
* @param int $length
|
||||
*/
|
||||
public function setLength(int $length): self
|
||||
{
|
||||
$this->length = $length;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get length
|
||||
*
|
||||
* @return null|int
|
||||
*/
|
||||
public function getLength(): ?int
|
||||
{
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current handle position
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPosition(): int
|
||||
{
|
||||
return ftell($this->handle);
|
||||
}
|
||||
}
|
43
vendor/intervention/gif/src/Decoders/AbstractPackedBitDecoder.php
vendored
Normal file
43
vendor/intervention/gif/src/Decoders/AbstractPackedBitDecoder.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
abstract class AbstractPackedBitDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode packed byte
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodePackedByte(string $byte): int
|
||||
{
|
||||
return unpack('C', $byte)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if packed bit is set
|
||||
*
|
||||
* @param int $num from left to right, starting with 0
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasPackedBit(string $byte, int $num): bool
|
||||
{
|
||||
return (bool) $this->getPackedBits($byte)[$num];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get packed bits
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
protected function getPackedBits(string $byte, int $start = 0, int $length = 8): string
|
||||
{
|
||||
$bits = str_pad(decbin($this->decodePackedByte($byte)), 8, '0', STR_PAD_LEFT);
|
||||
|
||||
return substr($bits, $start, $length);
|
||||
}
|
||||
}
|
67
vendor/intervention/gif/src/Decoders/ApplicationExtensionDecoder.php
vendored
Normal file
67
vendor/intervention/gif/src/Decoders/ApplicationExtensionDecoder.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
|
||||
class ApplicationExtensionDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @return ApplicationExtension
|
||||
*/
|
||||
public function decode(): ApplicationExtension
|
||||
{
|
||||
$result = new ApplicationExtension();
|
||||
|
||||
$this->getNextByte(); // marker
|
||||
$this->getNextByte(); // label
|
||||
$blocksize = $this->decodeBlockSize($this->getNextByte());
|
||||
$application = $this->getNextBytes($blocksize);
|
||||
|
||||
if ($application === NetscapeApplicationExtension::IDENTIFIER . NetscapeApplicationExtension::AUTH_CODE) {
|
||||
$result = new NetscapeApplicationExtension();
|
||||
|
||||
// skip length
|
||||
$this->getNextByte();
|
||||
|
||||
$result->setBlocks([
|
||||
new DataSubBlock(
|
||||
$this->getNextBytes(3)
|
||||
)
|
||||
]);
|
||||
|
||||
// skip terminator
|
||||
$this->getNextByte();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result->setApplication($application);
|
||||
|
||||
// decode data sub blocks
|
||||
$blocksize = $this->decodeBlockSize($this->getNextByte());
|
||||
while ($blocksize > 0) {
|
||||
$result->addBlock(new DataSubBlock($this->getNextBytes($blocksize)));
|
||||
$blocksize = $this->decodeBlockSize($this->getNextByte());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode block size of ApplicationExtension from given byte
|
||||
*
|
||||
* @param string $byte
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeBlockSize(string $byte): int
|
||||
{
|
||||
return (int) @unpack('C', $byte)[1];
|
||||
}
|
||||
}
|
36
vendor/intervention/gif/src/Decoders/ColorDecoder.php
vendored
Normal file
36
vendor/intervention/gif/src/Decoders/ColorDecoder.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Color;
|
||||
|
||||
class ColorDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source to Color
|
||||
*
|
||||
* @return Color
|
||||
*/
|
||||
public function decode(): Color
|
||||
{
|
||||
$color = new Color();
|
||||
|
||||
$color->setRed($this->decodeColorValue($this->getNextByte()));
|
||||
$color->setGreen($this->decodeColorValue($this->getNextByte()));
|
||||
$color->setBlue($this->decodeColorValue($this->getNextByte()));
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode red value from source
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeColorValue(string $byte): int
|
||||
{
|
||||
return unpack('C', $byte)[1];
|
||||
}
|
||||
}
|
26
vendor/intervention/gif/src/Decoders/ColorTableDecoder.php
vendored
Normal file
26
vendor/intervention/gif/src/Decoders/ColorTableDecoder.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Color;
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
|
||||
class ColorTableDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to ColorTable
|
||||
*
|
||||
* @return ColorTable
|
||||
*/
|
||||
public function decode(): ColorTable
|
||||
{
|
||||
$table = new ColorTable();
|
||||
for ($i = 0; $i < ($this->getLength() / 3); $i++) {
|
||||
$table->addColor(Color::decode($this->handle));
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
}
|
58
vendor/intervention/gif/src/Decoders/CommentExtensionDecoder.php
vendored
Normal file
58
vendor/intervention/gif/src/Decoders/CommentExtensionDecoder.php
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
|
||||
class CommentExtensionDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @return CommentExtension
|
||||
*/
|
||||
public function decode(): CommentExtension
|
||||
{
|
||||
$this->getNextBytes(2); // skip marker & label
|
||||
|
||||
$extension = new CommentExtension();
|
||||
foreach ($this->decodeComments() as $comment) {
|
||||
$extension->addComment($comment);
|
||||
}
|
||||
|
||||
return $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode comment from current source
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function decodeComments(): array
|
||||
{
|
||||
$comments = [];
|
||||
|
||||
do {
|
||||
$byte = $this->getNextByte();
|
||||
$size = $this->decodeBlocksize($byte);
|
||||
if ($size > 0) {
|
||||
$comments[] = $this->getNextBytes($size);
|
||||
}
|
||||
} while ($byte !== CommentExtension::TERMINATOR);
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode blocksize of following comment
|
||||
*
|
||||
* @param string $byte
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeBlocksize(string $byte): int
|
||||
{
|
||||
return (int) @unpack('C', $byte)[1];
|
||||
}
|
||||
}
|
23
vendor/intervention/gif/src/Decoders/DataSubBlockDecoder.php
vendored
Normal file
23
vendor/intervention/gif/src/Decoders/DataSubBlockDecoder.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
|
||||
class DataSubBlockDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current sourc
|
||||
*
|
||||
* @return DataSubBlock
|
||||
*/
|
||||
public function decode(): DataSubBlock
|
||||
{
|
||||
$char = $this->getNextByte();
|
||||
$size = (int) unpack('C', $char)[1];
|
||||
|
||||
return new DataSubBlock($this->getNextBytes($size));
|
||||
}
|
||||
}
|
47
vendor/intervention/gif/src/Decoders/FrameBlockDecoder.php
vendored
Normal file
47
vendor/intervention/gif/src/Decoders/FrameBlockDecoder.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
use Intervention\Gif\Blocks\PlainTextExtension;
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
class FrameBlockDecoder extends AbstractDecoder
|
||||
{
|
||||
public function decode(): FrameBlock
|
||||
{
|
||||
$frame = new FrameBlock();
|
||||
|
||||
do {
|
||||
$block = match ($this->viewNextBytes(2)) {
|
||||
AbstractExtension::MARKER . GraphicControlExtension::LABEL
|
||||
=> GraphicControlExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . NetscapeApplicationExtension::LABEL
|
||||
=> NetscapeApplicationExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . ApplicationExtension::LABEL
|
||||
=> ApplicationExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . PlainTextExtension::LABEL
|
||||
=> PlainTextExtension::decode($this->handle),
|
||||
AbstractExtension::MARKER . CommentExtension::LABEL
|
||||
=> CommentExtension::decode($this->handle),
|
||||
default => match ($this->viewNextByte()) {
|
||||
ImageDescriptor::SEPARATOR => TableBasedImage::decode($this->handle),
|
||||
default => throw new DecoderException('Unable to decode Data Block'),
|
||||
}
|
||||
};
|
||||
|
||||
$frame->addEntity($block);
|
||||
} while (!($block instanceof TableBasedImage));
|
||||
|
||||
return $frame;
|
||||
}
|
||||
}
|
57
vendor/intervention/gif/src/Decoders/GifDataStreamDecoder.php
vendored
Normal file
57
vendor/intervention/gif/src/Decoders/GifDataStreamDecoder.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\AbstractExtension;
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
use Intervention\Gif\Blocks\Trailer;
|
||||
use Intervention\Gif\GifDataStream;
|
||||
|
||||
class GifDataStreamDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source to GifDataStream
|
||||
*
|
||||
* @return GifDataStream
|
||||
*/
|
||||
public function decode(): GifDataStream
|
||||
{
|
||||
$gif = new GifDataStream();
|
||||
|
||||
$gif->setHeader(
|
||||
Header::decode($this->handle),
|
||||
);
|
||||
|
||||
$gif->setLogicalScreenDescriptor(
|
||||
LogicalScreenDescriptor::decode($this->handle),
|
||||
);
|
||||
|
||||
if ($gif->getLogicalScreenDescriptor()->hasGlobalColorTable()) {
|
||||
$length = $gif->getLogicalScreenDescriptor()->getGlobalColorTableByteSize();
|
||||
$gif->setGlobalColorTable(
|
||||
ColorTable::decode($this->handle, $length)
|
||||
);
|
||||
}
|
||||
|
||||
while ($this->viewNextByte() != Trailer::MARKER) {
|
||||
match ($this->viewNextBytes(2)) {
|
||||
// trailing "global" comment blocks which are not part of "FrameBlock"
|
||||
AbstractExtension::MARKER . CommentExtension::LABEL
|
||||
=> $gif->addComment(
|
||||
CommentExtension::decode($this->handle)
|
||||
),
|
||||
default => $gif->addFrame(
|
||||
FrameBlock::decode($this->handle)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return $gif;
|
||||
}
|
||||
}
|
95
vendor/intervention/gif/src/Decoders/GraphicControlExtensionDecoder.php
vendored
Normal file
95
vendor/intervention/gif/src/Decoders/GraphicControlExtensionDecoder.php
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
use Intervention\Gif\DisposalMethod;
|
||||
|
||||
class GraphicControlExtensionDecoder extends AbstractPackedBitDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to current instance
|
||||
*
|
||||
* @return GraphicControlExtension
|
||||
*/
|
||||
public function decode(): GraphicControlExtension
|
||||
{
|
||||
$result = new GraphicControlExtension();
|
||||
|
||||
// bytes 1-3
|
||||
$this->getNextBytes(3); // skip marker, label & bytesize
|
||||
|
||||
// byte #4
|
||||
$packedField = $this->getNextByte();
|
||||
$result->setDisposalMethod($this->decodeDisposalMethod($packedField));
|
||||
$result->setUserInput($this->decodeUserInput($packedField));
|
||||
$result->setTransparentColorExistance($this->decodeTransparentColorExistance($packedField));
|
||||
|
||||
// bytes 5-6
|
||||
$result->setDelay($this->decodeDelay($this->getNextBytes(2)));
|
||||
|
||||
// byte #7
|
||||
$result->setTransparentColorIndex($this->decodeTransparentColorIndex(
|
||||
$this->getNextByte()
|
||||
));
|
||||
|
||||
// byte #8 (terminator)
|
||||
$this->getNextByte();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode disposal method
|
||||
*
|
||||
* @return DisposalMethod
|
||||
*/
|
||||
protected function decodeDisposalMethod(string $byte): DisposalMethod
|
||||
{
|
||||
return DisposalMethod::from(
|
||||
bindec($this->getPackedBits($byte, 3, 3))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode user input flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function decodeUserInput(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode transparent color existance
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function decodeTransparentColorExistance(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode delay value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeDelay(string $bytes): int
|
||||
{
|
||||
return unpack('v*', $bytes)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode transparent color index
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeTransparentColorIndex(string $byte): int
|
||||
{
|
||||
return unpack('C', $byte)[1];
|
||||
}
|
||||
}
|
40
vendor/intervention/gif/src/Decoders/HeaderDecoder.php
vendored
Normal file
40
vendor/intervention/gif/src/Decoders/HeaderDecoder.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
|
||||
class HeaderDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current sourc
|
||||
*
|
||||
* @return Header
|
||||
*/
|
||||
public function decode(): Header
|
||||
{
|
||||
$header = new Header();
|
||||
$header->setVersion($this->decodeVersion());
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode version string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function decodeVersion(): string
|
||||
{
|
||||
$parsed = (bool) preg_match("/^GIF(?P<version>[0-9]{2}[a-z])$/", $this->getNextBytes(6), $matches);
|
||||
|
||||
if ($parsed === false) {
|
||||
throw new DecoderException('Unable to parse file header.');
|
||||
}
|
||||
|
||||
return $matches['version'];
|
||||
}
|
||||
}
|
38
vendor/intervention/gif/src/Decoders/ImageDataDecoder.php
vendored
Normal file
38
vendor/intervention/gif/src/Decoders/ImageDataDecoder.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
use Intervention\Gif\Blocks\ImageData;
|
||||
|
||||
class ImageDataDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @return ImageData
|
||||
*/
|
||||
public function decode(): ImageData
|
||||
{
|
||||
$data = new ImageData();
|
||||
|
||||
// LZW min. code size
|
||||
$char = $this->getNextByte();
|
||||
$size = (int) unpack('C', $char)[1];
|
||||
$data->setLzwMinCodeSize($size);
|
||||
|
||||
do {
|
||||
// decode sub blocks
|
||||
$char = $this->getNextByte();
|
||||
$size = (int) unpack('C', $char)[1];
|
||||
if ($size > 0) {
|
||||
$data->addBlock(new DataSubBlock($this->getNextBytes($size)));
|
||||
}
|
||||
} while ($char !== AbstractEntity::TERMINATOR);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
92
vendor/intervention/gif/src/Decoders/ImageDescriptorDecoder.php
vendored
Normal file
92
vendor/intervention/gif/src/Decoders/ImageDescriptorDecoder.php
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
|
||||
class ImageDescriptorDecoder extends AbstractPackedBitDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to current instance
|
||||
*
|
||||
* @return ImageDescriptor
|
||||
*/
|
||||
public function decode(): ImageDescriptor
|
||||
{
|
||||
$descriptor = new ImageDescriptor();
|
||||
|
||||
$this->getNextByte(); // skip separator
|
||||
|
||||
$descriptor->setPosition(
|
||||
$this->decodeMultiByte($this->getNextBytes(2)),
|
||||
$this->decodeMultiByte($this->getNextBytes(2))
|
||||
);
|
||||
|
||||
$descriptor->setSize(
|
||||
$this->decodeMultiByte($this->getNextBytes(2)),
|
||||
$this->decodeMultiByte($this->getNextBytes(2))
|
||||
);
|
||||
|
||||
$packedField = $this->getNextByte();
|
||||
|
||||
$descriptor->setLocalColorTableExistance(
|
||||
$this->decodeLocalColorTableExistance($packedField)
|
||||
);
|
||||
|
||||
$descriptor->setLocalColorTableSorted(
|
||||
$this->decodeLocalColorTableSorted($packedField)
|
||||
);
|
||||
|
||||
$descriptor->setLocalColorTableSize(
|
||||
$this->decodeLocalColorTableSize($packedField)
|
||||
);
|
||||
|
||||
$descriptor->setInterlaced(
|
||||
$this->decodeInterlaced($packedField)
|
||||
);
|
||||
|
||||
return $descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode local color table existance
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function decodeLocalColorTableExistance(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode local color table sort method
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function decodeLocalColorTableSorted(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode local color table size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeLocalColorTableSize(string $byte): int
|
||||
{
|
||||
return bindec($this->getPackedBits($byte, 5, 3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode interlaced flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function decodeInterlaced(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 1);
|
||||
}
|
||||
}
|
137
vendor/intervention/gif/src/Decoders/LogicalScreenDescriptorDecoder.php
vendored
Normal file
137
vendor/intervention/gif/src/Decoders/LogicalScreenDescriptorDecoder.php
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
|
||||
class LogicalScreenDescriptorDecoder extends AbstractPackedBitDecoder
|
||||
{
|
||||
/**
|
||||
* Decode given string to current instance
|
||||
*
|
||||
* @return LogicalScreenDescriptor
|
||||
*/
|
||||
public function decode(): LogicalScreenDescriptor
|
||||
{
|
||||
$logicalScreenDescriptor = new LogicalScreenDescriptor();
|
||||
|
||||
// bytes 1-4
|
||||
$logicalScreenDescriptor->setSize(
|
||||
$this->decodeWidth($this->getNextBytes(2)),
|
||||
$this->decodeHeight($this->getNextBytes(2))
|
||||
);
|
||||
|
||||
// byte 5
|
||||
$packedField = $this->getNextByte();
|
||||
|
||||
$logicalScreenDescriptor->setGlobalColorTableExistance(
|
||||
$this->decodeGlobalColorTableExistance($packedField)
|
||||
);
|
||||
|
||||
$logicalScreenDescriptor->setBitsPerPixel(
|
||||
$this->decodeBitsPerPixel($packedField)
|
||||
);
|
||||
|
||||
$logicalScreenDescriptor->setGlobalColorTableSorted(
|
||||
$this->decodeGlobalColorTableSorted($packedField)
|
||||
);
|
||||
|
||||
$logicalScreenDescriptor->setGlobalColorTableSize(
|
||||
$this->decodeGlobalColorTableSize($packedField)
|
||||
);
|
||||
|
||||
// byte 6
|
||||
$logicalScreenDescriptor->setBackgroundColorIndex(
|
||||
$this->decodeBackgroundColorIndex($this->getNextByte())
|
||||
);
|
||||
|
||||
// byte 7
|
||||
$logicalScreenDescriptor->setPixelAspectRatio(
|
||||
$this->decodePixelAspectRatio($this->getNextByte())
|
||||
);
|
||||
|
||||
return $logicalScreenDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode width
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeWidth(string $source): int
|
||||
{
|
||||
return unpack('v*', $source)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode height
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeHeight(string $source): int
|
||||
{
|
||||
return unpack('v*', $source)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode existance of global color table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function decodeGlobalColorTableExistance(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode color resolution in bits per pixel
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeBitsPerPixel(string $byte): int
|
||||
{
|
||||
return bindec($this->getPackedBits($byte, 1, 3)) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode global color table sorted status
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function decodeGlobalColorTableSorted(string $byte): bool
|
||||
{
|
||||
return $this->hasPackedBit($byte, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode size of global color table
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeGlobalColorTableSize(string $byte): int
|
||||
{
|
||||
return bindec($this->getPackedBits($byte, 5, 3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode background color index
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodeBackgroundColorIndex(string $source): int
|
||||
{
|
||||
return unpack('C', $source)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode pixel aspect ratio
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function decodePixelAspectRatio(string $source): int
|
||||
{
|
||||
return unpack('C', $source)[1];
|
||||
}
|
||||
}
|
9
vendor/intervention/gif/src/Decoders/NetscapeApplicationExtensionDecoder.php
vendored
Normal file
9
vendor/intervention/gif/src/Decoders/NetscapeApplicationExtensionDecoder.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
class NetscapeApplicationExtensionDecoder extends ApplicationExtensionDecoder
|
||||
{
|
||||
}
|
61
vendor/intervention/gif/src/Decoders/PlainTextExtensionDecoder.php
vendored
Normal file
61
vendor/intervention/gif/src/Decoders/PlainTextExtensionDecoder.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\PlainTextExtension;
|
||||
|
||||
class PlainTextExtensionDecoder extends AbstractDecoder
|
||||
{
|
||||
/**
|
||||
* Decode current source
|
||||
*
|
||||
* @return PlainTextExtension
|
||||
*/
|
||||
public function decode(): PlainTextExtension
|
||||
{
|
||||
$extension = new PlainTextExtension();
|
||||
|
||||
// skip marker & label
|
||||
$this->getNextBytes(2);
|
||||
|
||||
// skip info block
|
||||
$this->getNextBytes($this->getInfoBlockSize());
|
||||
|
||||
// text blocks
|
||||
$extension->setText($this->decodeTextBlocks());
|
||||
|
||||
return $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of bytes in header block
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getInfoBlockSize(): int
|
||||
{
|
||||
return unpack('C', $this->getNextByte())[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode text sub blocks
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function decodeTextBlocks(): array
|
||||
{
|
||||
$blocks = [];
|
||||
|
||||
do {
|
||||
$char = $this->getNextByte();
|
||||
$size = (int) unpack('C', $char)[1];
|
||||
if ($size > 0) {
|
||||
$blocks[] = $this->getNextBytes($size);
|
||||
}
|
||||
} while ($char !== PlainTextExtension::TERMINATOR);
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
}
|
35
vendor/intervention/gif/src/Decoders/TableBasedImageDecoder.php
vendored
Normal file
35
vendor/intervention/gif/src/Decoders/TableBasedImageDecoder.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Decoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Blocks\ImageData;
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
|
||||
class TableBasedImageDecoder extends AbstractDecoder
|
||||
{
|
||||
public function decode(): TableBasedImage
|
||||
{
|
||||
$block = new TableBasedImage();
|
||||
|
||||
$block->setImageDescriptor(ImageDescriptor::decode($this->handle));
|
||||
|
||||
if ($block->getImageDescriptor()->hasLocalColorTable()) {
|
||||
$block->setColorTable(
|
||||
ColorTable::decode(
|
||||
$this->handle,
|
||||
$block->getImageDescriptor()->getLocalColorTableByteSize()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$block->setImageData(
|
||||
ImageData::decode($this->handle)
|
||||
);
|
||||
|
||||
return $block;
|
||||
}
|
||||
}
|
13
vendor/intervention/gif/src/DisposalMethod.php
vendored
Normal file
13
vendor/intervention/gif/src/DisposalMethod.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
enum DisposalMethod: int
|
||||
{
|
||||
case UNDEFINED = 0;
|
||||
case NONE = 1; // overlay each frame in sequence
|
||||
case BACKGROUND = 2; // clear to background (as indicated by the logical screen descriptor)
|
||||
case PREVIOUS = 3; // restore the canvas to its previous state
|
||||
}
|
24
vendor/intervention/gif/src/Encoders/AbstractEncoder.php
vendored
Normal file
24
vendor/intervention/gif/src/Encoders/AbstractEncoder.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
abstract class AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param mixed $source
|
||||
*/
|
||||
public function __construct(protected mixed $source)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function encode(): string;
|
||||
}
|
39
vendor/intervention/gif/src/Encoders/ApplicationExtensionEncoder.php
vendored
Normal file
39
vendor/intervention/gif/src/Encoders/ApplicationExtensionEncoder.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
|
||||
class ApplicationExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*
|
||||
* @param ApplicationExtension $source
|
||||
*/
|
||||
public function __construct(ApplicationExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
ApplicationExtension::MARKER,
|
||||
ApplicationExtension::LABEL,
|
||||
pack('C', $this->source->getBlockSize()),
|
||||
$this->source->getApplication(),
|
||||
implode('', array_map(function ($block) {
|
||||
return $block->encode();
|
||||
}, $this->source->getBlocks())),
|
||||
ApplicationExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
}
|
44
vendor/intervention/gif/src/Encoders/ColorEncoder.php
vendored
Normal file
44
vendor/intervention/gif/src/Encoders/ColorEncoder.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Color;
|
||||
|
||||
class ColorEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param Color $source
|
||||
*/
|
||||
public function __construct(Color $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->encodeColorValue($this->source->getRed()),
|
||||
$this->encodeColorValue($this->source->getGreen()),
|
||||
$this->encodeColorValue($this->source->getBlue()),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode color value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeColorValue(int $value): string
|
||||
{
|
||||
return pack('C', $value);
|
||||
}
|
||||
}
|
32
vendor/intervention/gif/src/Encoders/ColorTableEncoder.php
vendored
Normal file
32
vendor/intervention/gif/src/Encoders/ColorTableEncoder.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
|
||||
class ColorTableEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param ColorTable $source
|
||||
*/
|
||||
public function __construct(ColorTable $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', array_map(function ($color) {
|
||||
return $color->encode();
|
||||
}, $this->source->getColors()));
|
||||
}
|
||||
}
|
47
vendor/intervention/gif/src/Encoders/CommentExtensionEncoder.php
vendored
Normal file
47
vendor/intervention/gif/src/Encoders/CommentExtensionEncoder.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
|
||||
class CommentExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*
|
||||
* @param CommentExtension $source
|
||||
*/
|
||||
public function __construct(CommentExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
CommentExtension::MARKER,
|
||||
CommentExtension::LABEL,
|
||||
$this->encodeComments(),
|
||||
CommentExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode comment blocks
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeComments(): string
|
||||
{
|
||||
return implode('', array_map(function ($comment) {
|
||||
return pack('C', strlen($comment)) . $comment;
|
||||
}, $this->source->getComments()));
|
||||
}
|
||||
}
|
30
vendor/intervention/gif/src/Encoders/DataSubBlockEncoder.php
vendored
Normal file
30
vendor/intervention/gif/src/Encoders/DataSubBlockEncoder.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\DataSubBlock;
|
||||
|
||||
class DataSubBlockEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param DataSubBlock $source
|
||||
*/
|
||||
public function __construct(DataSubBlock $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return pack('C', $this->source->getSize()) . $this->source->getValue();
|
||||
}
|
||||
}
|
41
vendor/intervention/gif/src/Encoders/FrameBlockEncoder.php
vendored
Normal file
41
vendor/intervention/gif/src/Encoders/FrameBlockEncoder.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
|
||||
class FrameBlockEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*
|
||||
* @param FrameBlock $source
|
||||
*/
|
||||
public function __construct(FrameBlock $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
public function encode(): string
|
||||
{
|
||||
$graphicControlExtension = $this->source->getGraphicControlExtension();
|
||||
$colorTable = $this->source->getColorTable();
|
||||
$plainTextExtension = $this->source->getPlainTextExtension();
|
||||
|
||||
return implode('', [
|
||||
implode('', array_map(function ($extension) {
|
||||
return $extension->encode();
|
||||
}, $this->source->getApplicationExtensions())),
|
||||
implode('', array_map(function ($extension) {
|
||||
return $extension->encode();
|
||||
}, $this->source->getCommentExtensions())),
|
||||
$plainTextExtension ? $plainTextExtension->encode() : '',
|
||||
$graphicControlExtension ? $graphicControlExtension->encode() : '',
|
||||
$this->source->getImageDescriptor()->encode(),
|
||||
$colorTable ? $colorTable->encode() : '',
|
||||
$this->source->getImageData()->encode(),
|
||||
]);
|
||||
}
|
||||
}
|
70
vendor/intervention/gif/src/Encoders/GifDataStreamEncoder.php
vendored
Normal file
70
vendor/intervention/gif/src/Encoders/GifDataStreamEncoder.php
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\GifDataStream;
|
||||
|
||||
class GifDataStreamEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param GifDataStream $source
|
||||
*/
|
||||
public function __construct(GifDataStream $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->source->getHeader()->encode(),
|
||||
$this->source->getLogicalScreenDescriptor()->encode(),
|
||||
$this->maybeEncodeGlobalColorTable(),
|
||||
$this->encodeFrames(),
|
||||
$this->encodeComments(),
|
||||
$this->source->getTrailer()->encode(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function maybeEncodeGlobalColorTable(): string
|
||||
{
|
||||
if (!$this->source->hasGlobalColorTable()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->source->getGlobalColorTable()->encode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode data blocks of source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeFrames(): string
|
||||
{
|
||||
return implode('', array_map(function ($frame) {
|
||||
return $frame->encode();
|
||||
}, $this->source->getFrames()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode comment extension blocks of source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeComments(): string
|
||||
{
|
||||
return implode('', array_map(function ($commentExtension) {
|
||||
return $commentExtension->encode();
|
||||
}, $this->source->getComments()));
|
||||
}
|
||||
}
|
73
vendor/intervention/gif/src/Encoders/GraphicControlExtensionEncoder.php
vendored
Normal file
73
vendor/intervention/gif/src/Encoders/GraphicControlExtensionEncoder.php
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\GraphicControlExtension;
|
||||
|
||||
class GraphicControlExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param GraphicControlExtension $source
|
||||
*/
|
||||
public function __construct(GraphicControlExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
GraphicControlExtension::MARKER,
|
||||
GraphicControlExtension::LABEL,
|
||||
GraphicControlExtension::BLOCKSIZE,
|
||||
$this->encodePackedField(),
|
||||
$this->encodeDelay(),
|
||||
$this->encodeTransparentColorIndex(),
|
||||
GraphicControlExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode delay time
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeDelay(): string
|
||||
{
|
||||
return pack('v*', $this->source->getDelay());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode transparent color index
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeTransparentColorIndex(): string
|
||||
{
|
||||
return pack('C', $this->source->getTransparentColorIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode packed field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodePackedField(): string
|
||||
{
|
||||
return pack('C', bindec(implode('', [
|
||||
str_pad('0', 3, '0', STR_PAD_LEFT),
|
||||
str_pad(decbin($this->source->getDisposalMethod()->value), 3, '0', STR_PAD_LEFT),
|
||||
(int) $this->source->getUserInput(),
|
||||
(int) $this->source->getTransparentColorExistance(),
|
||||
])));
|
||||
}
|
||||
}
|
30
vendor/intervention/gif/src/Encoders/HeaderEncoder.php
vendored
Normal file
30
vendor/intervention/gif/src/Encoders/HeaderEncoder.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
|
||||
class HeaderEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param Header $source
|
||||
*/
|
||||
public function __construct(Header $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return Header::SIGNATURE . $this->source->getVersion();
|
||||
}
|
||||
}
|
42
vendor/intervention/gif/src/Encoders/ImageDataEncoder.php
vendored
Normal file
42
vendor/intervention/gif/src/Encoders/ImageDataEncoder.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\AbstractEntity;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
use Intervention\Gif\Blocks\ImageData;
|
||||
|
||||
class ImageDataEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param ImageData $source
|
||||
*/
|
||||
public function __construct(ImageData $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
if (!$this->source->hasBlocks()) {
|
||||
throw new EncoderException("No data blocks in ImageData.");
|
||||
}
|
||||
|
||||
return implode('', [
|
||||
pack('C', $this->source->getLzwMinCodeSize()),
|
||||
implode('', array_map(function ($block) {
|
||||
return $block->encode();
|
||||
}, $this->source->getBlocks())),
|
||||
AbstractEntity::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
}
|
113
vendor/intervention/gif/src/Encoders/ImageDescriptorEncoder.php
vendored
Normal file
113
vendor/intervention/gif/src/Encoders/ImageDescriptorEncoder.php
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ImageDescriptor;
|
||||
|
||||
class ImageDescriptorEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param ImageDescriptor $source
|
||||
*/
|
||||
public function __construct(ImageDescriptor $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
ImageDescriptor::SEPARATOR,
|
||||
$this->encodeLeft(),
|
||||
$this->encodeTop(),
|
||||
$this->encodeWidth(),
|
||||
$this->encodeHeight(),
|
||||
$this->encodePackedField(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode left value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeLeft(): string
|
||||
{
|
||||
return pack('v*', $this->source->getLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode top value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeTop(): string
|
||||
{
|
||||
return pack('v*', $this->source->getTop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode width value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeWidth(): string
|
||||
{
|
||||
return pack('v*', $this->source->getWidth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode height value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeHeight(): string
|
||||
{
|
||||
return pack('v*', $this->source->getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode size of local color table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeLocalColorTableSize(): string
|
||||
{
|
||||
return str_pad(decbin($this->source->getLocalColorTableSize()), 3, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode reserved field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeReservedField(): string
|
||||
{
|
||||
return str_pad('0', 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode packed field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodePackedField(): string
|
||||
{
|
||||
return pack('C', bindec(implode('', [
|
||||
(int) $this->source->getLocalColorTableExistance(),
|
||||
(int) $this->source->isInterlaced(),
|
||||
(int) $this->source->getLocalColorTableSorted(),
|
||||
$this->encodeReservedField(),
|
||||
$this->encodeLocalColorTableSize(),
|
||||
])));
|
||||
}
|
||||
}
|
111
vendor/intervention/gif/src/Encoders/LogicalScreenDescriptorEncoder.php
vendored
Normal file
111
vendor/intervention/gif/src/Encoders/LogicalScreenDescriptorEncoder.php
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
|
||||
class LogicalScreenDescriptorEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param LogicalScreenDescriptor $source
|
||||
*/
|
||||
public function __construct(LogicalScreenDescriptor $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->encodeWidth(),
|
||||
$this->encodeHeight(),
|
||||
$this->encodePackedField(),
|
||||
$this->encodeBackgroundColorIndex(),
|
||||
$this->encodePixelAspectRatio(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode width of current instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeWidth(): string
|
||||
{
|
||||
return pack('v*', $this->source->getWidth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode height of current instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeHeight(): string
|
||||
{
|
||||
return pack('v*', $this->source->getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode background color index of global color table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeBackgroundColorIndex(): string
|
||||
{
|
||||
return pack('C', $this->source->getBackgroundColorIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode pixel aspect ratio
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodePixelAspectRatio(): string
|
||||
{
|
||||
return pack('C', $this->source->getPixelAspectRatio());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return color resolution for encoding
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeColorResolution(): string
|
||||
{
|
||||
return str_pad(decbin($this->source->getBitsPerPixel() - 1), 3, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode size of global color table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeGlobalColorTableSize(): string
|
||||
{
|
||||
return str_pad(decbin($this->source->getGlobalColorTableSize()), 3, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode packed field of current instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodePackedField(): string
|
||||
{
|
||||
return pack('C', bindec(implode('', [
|
||||
(int) $this->source->getGlobalColorTableExistance(),
|
||||
$this->encodeColorResolution(),
|
||||
(int) $this->source->getGlobalColorTableSorted(),
|
||||
$this->encodeGlobalColorTableSize(),
|
||||
])));
|
||||
}
|
||||
}
|
40
vendor/intervention/gif/src/Encoders/NetscapeApplicationExtensionEncoder.php
vendored
Normal file
40
vendor/intervention/gif/src/Encoders/NetscapeApplicationExtensionEncoder.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\ApplicationExtension;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
|
||||
class NetscapeApplicationExtensionEncoder extends ApplicationExtensionEncoder
|
||||
{
|
||||
/**
|
||||
* Create new decoder instance
|
||||
*
|
||||
* @param NetscapeApplicationExtension $source
|
||||
*/
|
||||
public function __construct(NetscapeApplicationExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
ApplicationExtension::MARKER,
|
||||
ApplicationExtension::LABEL,
|
||||
pack('C', $this->source->getBlockSize()),
|
||||
$this->source->getApplication(),
|
||||
implode('', array_map(function ($block) {
|
||||
return $block->encode();
|
||||
}, $this->source->getBlocks())),
|
||||
ApplicationExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
}
|
62
vendor/intervention/gif/src/Encoders/PlainTextExtensionEncoder.php
vendored
Normal file
62
vendor/intervention/gif/src/Encoders/PlainTextExtensionEncoder.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\PlainTextExtension;
|
||||
|
||||
class PlainTextExtensionEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param PlainTextExtension $source
|
||||
*/
|
||||
public function __construct(PlainTextExtension $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
if (!$this->source->hasText()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return implode('', [
|
||||
PlainTextExtension::MARKER,
|
||||
PlainTextExtension::LABEL,
|
||||
$this->encodeHead(),
|
||||
$this->encodeTexts(),
|
||||
PlainTextExtension::TERMINATOR,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode head block
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeHead(): string
|
||||
{
|
||||
return "\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text chunks
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeTexts(): string
|
||||
{
|
||||
return implode('', array_map(function ($text) {
|
||||
return pack('C', strlen($text)) . $text;
|
||||
}, $this->source->getText()));
|
||||
}
|
||||
}
|
29
vendor/intervention/gif/src/Encoders/TableBasedImageEncoder.php
vendored
Normal file
29
vendor/intervention/gif/src/Encoders/TableBasedImageEncoder.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\TableBasedImage;
|
||||
|
||||
class TableBasedImageEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param TableBasedImage $source
|
||||
*/
|
||||
public function __construct(TableBasedImage $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
public function encode(): string
|
||||
{
|
||||
return implode('', [
|
||||
$this->source->getImageDescriptor()->encode(),
|
||||
$this->source->getColorTable() ? $this->source->getColorTable()->encode() : '',
|
||||
$this->source->getImageData()->encode(),
|
||||
]);
|
||||
}
|
||||
}
|
30
vendor/intervention/gif/src/Encoders/TrailerEncoder.php
vendored
Normal file
30
vendor/intervention/gif/src/Encoders/TrailerEncoder.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Encoders;
|
||||
|
||||
use Intervention\Gif\Blocks\Trailer;
|
||||
|
||||
class TrailerEncoder extends AbstractEncoder
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param Trailer $source
|
||||
*/
|
||||
public function __construct(Trailer $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode current source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return Trailer::MARKER;
|
||||
}
|
||||
}
|
9
vendor/intervention/gif/src/Exceptions/DecoderException.php
vendored
Normal file
9
vendor/intervention/gif/src/Exceptions/DecoderException.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class DecoderException extends \RuntimeException
|
||||
{
|
||||
}
|
9
vendor/intervention/gif/src/Exceptions/EncoderException.php
vendored
Normal file
9
vendor/intervention/gif/src/Exceptions/EncoderException.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class EncoderException extends \RuntimeException
|
||||
{
|
||||
}
|
9
vendor/intervention/gif/src/Exceptions/FormatException.php
vendored
Normal file
9
vendor/intervention/gif/src/Exceptions/FormatException.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class FormatException extends \RuntimeException
|
||||
{
|
||||
}
|
9
vendor/intervention/gif/src/Exceptions/NotReadableException.php
vendored
Normal file
9
vendor/intervention/gif/src/Exceptions/NotReadableException.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Exceptions;
|
||||
|
||||
class NotReadableException extends \RuntimeException
|
||||
{
|
||||
}
|
218
vendor/intervention/gif/src/GifDataStream.php
vendored
Normal file
218
vendor/intervention/gif/src/GifDataStream.php
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use Intervention\Gif\Blocks\ColorTable;
|
||||
use Intervention\Gif\Blocks\CommentExtension;
|
||||
use Intervention\Gif\Blocks\FrameBlock;
|
||||
use Intervention\Gif\Blocks\Header;
|
||||
use Intervention\Gif\Blocks\LogicalScreenDescriptor;
|
||||
use Intervention\Gif\Blocks\NetscapeApplicationExtension;
|
||||
use Intervention\Gif\Blocks\Trailer;
|
||||
|
||||
class GifDataStream extends AbstractEntity
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*/
|
||||
public function __construct(
|
||||
protected Header $header = new Header(),
|
||||
protected LogicalScreenDescriptor $logicalScreenDescriptor = new LogicalScreenDescriptor(),
|
||||
protected ?ColorTable $globalColorTable = null,
|
||||
protected array $frames = [],
|
||||
protected array $comments = []
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get header
|
||||
*
|
||||
* @return Header
|
||||
*/
|
||||
public function getHeader(): Header
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set header
|
||||
*
|
||||
* @param Header $header
|
||||
*/
|
||||
public function setHeader(Header $header): self
|
||||
{
|
||||
$this->header = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logical screen descriptor
|
||||
*
|
||||
* @return LogicalScreenDescriptor
|
||||
*/
|
||||
public function getLogicalScreenDescriptor(): LogicalScreenDescriptor
|
||||
{
|
||||
return $this->logicalScreenDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set logical screen descriptor
|
||||
*
|
||||
* @param LogicalScreenDescriptor $descriptor
|
||||
* @return GifDataStream
|
||||
*/
|
||||
public function setLogicalScreenDescriptor(LogicalScreenDescriptor $descriptor): self
|
||||
{
|
||||
$this->logicalScreenDescriptor = $descriptor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return global color table if available else null
|
||||
*
|
||||
* @return null|ColorTable
|
||||
*/
|
||||
public function getGlobalColorTable(): ?ColorTable
|
||||
{
|
||||
return $this->globalColorTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set global color table
|
||||
*
|
||||
* @param ColorTable $table
|
||||
* @return GifDataStream
|
||||
*/
|
||||
public function setGlobalColorTable(ColorTable $table): self
|
||||
{
|
||||
$this->globalColorTable = $table;
|
||||
$this->logicalScreenDescriptor->setGlobalColorTableExistance(true);
|
||||
$this->logicalScreenDescriptor->setGlobalColorTableSize(
|
||||
$table->getLogicalSize()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get main graphic control extension
|
||||
*
|
||||
* @return NetscapeApplicationExtension
|
||||
*/
|
||||
public function getMainApplicationExtension(): ?NetscapeApplicationExtension
|
||||
{
|
||||
foreach ($this->frames as $frame) {
|
||||
if ($extension = $frame->getNetscapeExtension()) {
|
||||
return $extension;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of frames
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFrames(): array
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of "global" comments
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getComments(): array
|
||||
{
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first frame
|
||||
*
|
||||
* @return null|FrameBlock
|
||||
*/
|
||||
public function getFirstFrame(): ?FrameBlock
|
||||
{
|
||||
if (!array_key_exists(0, $this->frames)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->frames[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add frame
|
||||
*
|
||||
* @param FrameBlock $frame
|
||||
* @return GifDataStream
|
||||
*/
|
||||
public function addFrame(FrameBlock $frame): self
|
||||
{
|
||||
$this->frames[] = $frame;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add comment extension
|
||||
*
|
||||
* @param CommentExtension $comment
|
||||
* @return GifDataStream
|
||||
*/
|
||||
public function addComment(CommentExtension $comment): self
|
||||
{
|
||||
$this->comments[] = $comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current data
|
||||
*
|
||||
* @param array $frames
|
||||
*/
|
||||
public function setFrames(array $frames): self
|
||||
{
|
||||
$this->frames = $frames;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get trailer
|
||||
*
|
||||
* @return Trailer
|
||||
*/
|
||||
public function getTrailer(): Trailer
|
||||
{
|
||||
return new Trailer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if gif is animated
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAnimated(): bool
|
||||
{
|
||||
return count($this->getFrames()) > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if global color table is set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasGlobalColorTable(): bool
|
||||
{
|
||||
return !is_null($this->globalColorTable);
|
||||
}
|
||||
}
|
277
vendor/intervention/gif/src/Splitter.php
vendored
Normal file
277
vendor/intervention/gif/src/Splitter.php
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif;
|
||||
|
||||
use ArrayIterator;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
class Splitter implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Single frames
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $frames = [];
|
||||
|
||||
/**
|
||||
* Delays of each frame
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $delays = [];
|
||||
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param GifDataStream $stream
|
||||
*/
|
||||
public function __construct(protected GifDataStream $stream)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator
|
||||
*
|
||||
* @return Traversable
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get frames
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFrames(): array
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get delays
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDelays(): array
|
||||
{
|
||||
return $this->delays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stream of instance
|
||||
*
|
||||
* @param GifDataStream $stream
|
||||
*/
|
||||
public function setStream(GifDataStream $stream): self
|
||||
{
|
||||
$this->stream = $stream;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static constructor method
|
||||
*
|
||||
* @param GifDataStream $stream
|
||||
* @return Splitter
|
||||
*/
|
||||
public static function create(GifDataStream $stream): self
|
||||
{
|
||||
return new self($stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split current stream into array of seperate streams for each frame
|
||||
*
|
||||
* @return Splitter
|
||||
*/
|
||||
public function split(): self
|
||||
{
|
||||
$this->frames = [];
|
||||
|
||||
foreach ($this->stream->getFrames() as $frame) {
|
||||
// create separate stream for each frame
|
||||
$gif = Builder::canvas(
|
||||
$this->stream->getLogicalScreenDescriptor()->getWidth(),
|
||||
$this->stream->getLogicalScreenDescriptor()->getHeight()
|
||||
)->getGifDataStream();
|
||||
|
||||
// check if working stream has global color table
|
||||
if ($this->stream->hasGlobalColorTable()) {
|
||||
$gif->setGlobalColorTable($this->stream->getGlobalColorTable());
|
||||
$gif->getLogicalScreenDescriptor()->setGlobalColorTableExistance(true);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setGlobalColorTableSorted(
|
||||
$this->stream->getLogicalScreenDescriptor()->getGlobalColorTableSorted()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setGlobalColorTableSize(
|
||||
$this->stream->getLogicalScreenDescriptor()->getGlobalColorTableSize()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setBackgroundColorIndex(
|
||||
$this->stream->getLogicalScreenDescriptor()->getBackgroundColorIndex()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setPixelAspectRatio(
|
||||
$this->stream->getLogicalScreenDescriptor()->getPixelAspectRatio()
|
||||
);
|
||||
|
||||
$gif->getLogicalScreenDescriptor()->setBitsPerPixel(
|
||||
$this->stream->getLogicalScreenDescriptor()->getBitsPerPixel()
|
||||
);
|
||||
}
|
||||
|
||||
// copy original frame
|
||||
$gif->addFrame($frame);
|
||||
|
||||
$this->frames[] = $gif;
|
||||
$this->delays[] = match (is_object($frame->getGraphicControlExtension())) {
|
||||
true => $frame->getGraphicControlExtension()->getDelay(),
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of GD library resources for each frame
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toResources(): array
|
||||
{
|
||||
$resources = [];
|
||||
|
||||
foreach ($this->frames as $frame) {
|
||||
if (is_a($frame, GifDataStream::class)) {
|
||||
$resource = imagecreatefromstring($frame->encode());
|
||||
imagepalettetotruecolor($resource);
|
||||
imagesavealpha($resource, true);
|
||||
$resources[] = $resource;
|
||||
}
|
||||
}
|
||||
|
||||
return $resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of coalesced GD library resources for each frame
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function coalesceToResources(): array
|
||||
{
|
||||
$resources = $this->toResources();
|
||||
|
||||
// static gif files don't need to be coalesced
|
||||
if (count($resources) === 1) {
|
||||
return $resources;
|
||||
}
|
||||
|
||||
$width = imagesx($resources[0]);
|
||||
$height = imagesy($resources[0]);
|
||||
$transparent = imagecolortransparent($resources[0]);
|
||||
|
||||
foreach ($resources as $key => $resource) {
|
||||
// get meta data
|
||||
$gif = $this->frames[$key];
|
||||
$descriptor = $gif->getFirstFrame()->getImageDescriptor();
|
||||
$offset_x = $descriptor->getLeft();
|
||||
$offset_y = $descriptor->getTop();
|
||||
$w = $descriptor->getWidth();
|
||||
$h = $descriptor->getHeight();
|
||||
|
||||
if (in_array($this->getDisposalMethod($gif), [DisposalMethod::NONE, DisposalMethod::PREVIOUS])) {
|
||||
if ($key >= 1) {
|
||||
// create normalized gd image
|
||||
$canvas = imagecreatetruecolor($width, $height);
|
||||
if (imagecolortransparent($resource) != -1) {
|
||||
$transparent = imagecolortransparent($resource);
|
||||
} else {
|
||||
$transparent = imagecolorallocatealpha($resource, 255, 0, 255, 127);
|
||||
}
|
||||
|
||||
// fill with transparent
|
||||
imagefill($canvas, 0, 0, $transparent);
|
||||
imagecolortransparent($canvas, $transparent);
|
||||
imagealphablending($canvas, true);
|
||||
|
||||
// insert last as base
|
||||
imagecopy(
|
||||
$canvas,
|
||||
$resources[$key - 1],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$width,
|
||||
$height
|
||||
);
|
||||
|
||||
// insert resource
|
||||
imagecopy(
|
||||
$canvas,
|
||||
$resource,
|
||||
$offset_x,
|
||||
$offset_y,
|
||||
0,
|
||||
0,
|
||||
$w,
|
||||
$h
|
||||
);
|
||||
} else {
|
||||
imagealphablending($resource, true);
|
||||
$canvas = $resource;
|
||||
}
|
||||
} else {
|
||||
// create normalized gd image
|
||||
$canvas = imagecreatetruecolor($width, $height);
|
||||
if (imagecolortransparent($resource) != -1) {
|
||||
$transparent = imagecolortransparent($resource);
|
||||
} else {
|
||||
$transparent = imagecolorallocatealpha($resource, 255, 0, 255, 127);
|
||||
}
|
||||
|
||||
// fill with transparent
|
||||
imagefill($canvas, 0, 0, $transparent);
|
||||
imagecolortransparent($canvas, $transparent);
|
||||
imagealphablending($canvas, true);
|
||||
|
||||
// insert frame resource
|
||||
imagecopy(
|
||||
$canvas,
|
||||
$resource,
|
||||
$offset_x,
|
||||
$offset_y,
|
||||
0,
|
||||
0,
|
||||
$w,
|
||||
$h
|
||||
);
|
||||
}
|
||||
|
||||
$resources[$key] = $canvas;
|
||||
}
|
||||
|
||||
return $resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return disposal method of given gif data stream
|
||||
*
|
||||
* @param GifDataStream $gif
|
||||
* @return DisposalMethod
|
||||
*/
|
||||
private function getDisposalMethod(GifDataStream $gif): DisposalMethod
|
||||
{
|
||||
return $gif->getFirstFrame()->getGraphicControlExtension()->getDisposalMethod();
|
||||
}
|
||||
}
|
51
vendor/intervention/gif/src/Traits/CanDecode.php
vendored
Normal file
51
vendor/intervention/gif/src/Traits/CanDecode.php
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Traits;
|
||||
|
||||
use Intervention\Gif\Decoders\AbstractDecoder;
|
||||
use Intervention\Gif\Exceptions\DecoderException;
|
||||
|
||||
trait CanDecode
|
||||
{
|
||||
/**
|
||||
* Decode current instance
|
||||
*
|
||||
* @param resource $source
|
||||
* @param null|int $length
|
||||
* @return mixed
|
||||
*/
|
||||
public static function decode($source, ?int $length = null): mixed
|
||||
{
|
||||
return self::getDecoder($source, $length)->decode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get decoder for current instance
|
||||
*
|
||||
* @param resource $source
|
||||
* @param null|int $length
|
||||
* @return AbstractDecoder
|
||||
*/
|
||||
protected static function getDecoder($source, ?int $length = null): AbstractDecoder
|
||||
{
|
||||
$classname = self::getDecoderClassname();
|
||||
|
||||
if (!class_exists($classname)) {
|
||||
throw new DecoderException("Decoder for '" . static::class . "' not found.");
|
||||
}
|
||||
|
||||
return new $classname($source, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get classname of decoder for current classname
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getDecoderClassname(): string
|
||||
{
|
||||
return sprintf('Intervention\Gif\Decoders\%sDecoder', self::getShortClassname());
|
||||
}
|
||||
}
|
47
vendor/intervention/gif/src/Traits/CanEncode.php
vendored
Normal file
47
vendor/intervention/gif/src/Traits/CanEncode.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Traits;
|
||||
|
||||
use Intervention\Gif\Encoders\AbstractEncoder;
|
||||
use Intervention\Gif\Exceptions\EncoderException;
|
||||
|
||||
trait CanEncode
|
||||
{
|
||||
/**
|
||||
* Encode current entity
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encode(): string
|
||||
{
|
||||
return $this->getEncoder()->encode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoder object for current entity
|
||||
*
|
||||
* @return AbstractEncoder
|
||||
*/
|
||||
protected function getEncoder(): AbstractEncoder
|
||||
{
|
||||
$classname = $this->getEncoderClassname();
|
||||
|
||||
if (!class_exists($classname)) {
|
||||
throw new EncoderException("Encoder for '" . $this::class . "' not found.");
|
||||
}
|
||||
|
||||
return new $classname($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoder classname for current entity
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getEncoderClassname(): string
|
||||
{
|
||||
return sprintf('Intervention\Gif\Encoders\%sEncoder', $this->getShortClassname());
|
||||
}
|
||||
}
|
55
vendor/intervention/gif/src/Traits/CanHandleFiles.php
vendored
Normal file
55
vendor/intervention/gif/src/Traits/CanHandleFiles.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Gif\Traits;
|
||||
|
||||
trait CanHandleFiles
|
||||
{
|
||||
/**
|
||||
* Determines if input is file path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function isFilePath($input): bool
|
||||
{
|
||||
return is_string($input) && !self::hasNullBytes($input) && @is_file($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if given string contains null bytes
|
||||
*
|
||||
* @param string $string
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasNullBytes($string): bool
|
||||
{
|
||||
return strpos($string, chr(0)) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create file pointer from given gif image data
|
||||
*
|
||||
* @param string $data
|
||||
* @return resource
|
||||
*/
|
||||
private static function getHandleFromData($data)
|
||||
{
|
||||
$handle = fopen('php://memory', 'r+');
|
||||
fwrite($handle, $data);
|
||||
rewind($handle);
|
||||
|
||||
return $handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create file pounter from given file path
|
||||
*
|
||||
* @param string $path
|
||||
* @return resource
|
||||
*/
|
||||
private static function getHandleFromFilePath(string $path)
|
||||
{
|
||||
return fopen($path, 'rb');
|
||||
}
|
||||
}
|
21
vendor/intervention/image/LICENSE
vendored
Normal file
21
vendor/intervention/image/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2024 Oliver Vogel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
51
vendor/intervention/image/composer.json
vendored
Normal file
51
vendor/intervention/image/composer.json
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "intervention/image",
|
||||
"description": "PHP image manipulation",
|
||||
"homepage": "https://image.intervention.io/",
|
||||
"keywords": [
|
||||
"image",
|
||||
"gd",
|
||||
"imagick",
|
||||
"watermark",
|
||||
"thumbnail",
|
||||
"resize"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"ext-mbstring": "*",
|
||||
"intervention/gif": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"mockery/mockery": "^1.6",
|
||||
"phpstan/phpstan": "^1",
|
||||
"squizlabs/php_codesniffer": "^3.8",
|
||||
"slevomat/coding-standard": "~8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-exif": "Recommended to be able to read EXIF data properly."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
}
|
||||
}
|
97
vendor/intervention/image/readme.md
vendored
Normal file
97
vendor/intervention/image/readme.md
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
# Intervention Image
|
||||
## PHP Image Processing
|
||||
|
||||
[](https://packagist.org/packages/intervention/image)
|
||||
[](https://github.com/Intervention/image/actions)
|
||||
[](https://packagist.org/packages/intervention/image/stats)
|
||||
|
||||
Intervention Image is a **PHP image processing library** that provides a simple
|
||||
and expressive way to create, edit, and compose images. It features a unified
|
||||
API for the two most popular image manipulation extensions. You can choose
|
||||
between the GD library or Imagick as the base layer for all operations.
|
||||
|
||||
- Simple interface for common image editing tasks
|
||||
- Interchangeable driver architecture
|
||||
- Support for animated images
|
||||
- Framework-agnostic
|
||||
- PSR-12 compliant
|
||||
|
||||
## Installation
|
||||
|
||||
You can easily install this library using [Composer](https://getcomposer.org).
|
||||
Just request the package with the following command:
|
||||
|
||||
```bash
|
||||
composer require intervention/image
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Learn the [basics](https://image.intervention.io/v3/basics/instantiation/) on
|
||||
how to use Intervention Image and more with the [official
|
||||
documentation](https://image.intervention.io/v3/).
|
||||
|
||||
## Code Examples
|
||||
|
||||
```php
|
||||
use Intervention\Image\ImageManager;
|
||||
|
||||
// create image manager with desired driver
|
||||
$manager = new ImageManager(
|
||||
new Intervention\Image\Drivers\Gd\Driver()
|
||||
);
|
||||
|
||||
// open an image file
|
||||
$image = $manager->read('images/example.gif');
|
||||
|
||||
// resize image instance
|
||||
$image->resize(height: 300);
|
||||
|
||||
// insert a watermark
|
||||
$image->place('images/watermark.png');
|
||||
|
||||
// encode edited image
|
||||
$encoded = $image->toJpg();
|
||||
|
||||
// save encoded image
|
||||
$encoded->save('images/example.jpg');
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- PHP >= 8.1
|
||||
|
||||
## Supported Image Libraries
|
||||
|
||||
- GD Library
|
||||
- Imagick PHP extension
|
||||
|
||||
## Development & Testing
|
||||
|
||||
This package contains a Docker image for building a test suite and an analysis
|
||||
container. You must have Docker installed on your system to run all tests using
|
||||
the following command.
|
||||
|
||||
```bash
|
||||
docker-compose run --rm --build tests
|
||||
```
|
||||
|
||||
Run the static analyzer on the code base.
|
||||
|
||||
```bash
|
||||
docker-compose run --rm --build analysis
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
If you discover any security related issues, please email oliver@intervention.io directly.
|
||||
|
||||
## Authors
|
||||
|
||||
This library is developed and maintained by [Oliver Vogel](https://intervention.io)
|
||||
|
||||
Thanks to the community of [contributors](https://github.com/Intervention/image/graphs/contributors) who have helped to improve this project.
|
||||
|
||||
## License
|
||||
|
||||
Intervention Image is licensed under the [MIT License](LICENSE).
|
11
vendor/intervention/image/src/Analyzers/ColorspaceAnalyzer.php
vendored
Normal file
11
vendor/intervention/image/src/Analyzers/ColorspaceAnalyzer.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class ColorspaceAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
}
|
11
vendor/intervention/image/src/Analyzers/HeightAnalyzer.php
vendored
Normal file
11
vendor/intervention/image/src/Analyzers/HeightAnalyzer.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class HeightAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
}
|
17
vendor/intervention/image/src/Analyzers/PixelColorAnalyzer.php
vendored
Normal file
17
vendor/intervention/image/src/Analyzers/PixelColorAnalyzer.php
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class PixelColorAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
public function __construct(
|
||||
public int $x,
|
||||
public int $y,
|
||||
public int $frame_key = 0
|
||||
) {
|
||||
}
|
||||
}
|
16
vendor/intervention/image/src/Analyzers/PixelColorsAnalyzer.php
vendored
Normal file
16
vendor/intervention/image/src/Analyzers/PixelColorsAnalyzer.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class PixelColorsAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
public function __construct(
|
||||
public int $x,
|
||||
public int $y
|
||||
) {
|
||||
}
|
||||
}
|
11
vendor/intervention/image/src/Analyzers/ProfileAnalyzer.php
vendored
Normal file
11
vendor/intervention/image/src/Analyzers/ProfileAnalyzer.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class ProfileAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
}
|
11
vendor/intervention/image/src/Analyzers/ResolutionAnalyzer.php
vendored
Normal file
11
vendor/intervention/image/src/Analyzers/ResolutionAnalyzer.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class ResolutionAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
}
|
11
vendor/intervention/image/src/Analyzers/WidthAnalyzer.php
vendored
Normal file
11
vendor/intervention/image/src/Analyzers/WidthAnalyzer.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Analyzers;
|
||||
|
||||
use Intervention\Image\Drivers\SpecializableAnalyzer;
|
||||
|
||||
class WidthAnalyzer extends SpecializableAnalyzer
|
||||
{
|
||||
}
|
229
vendor/intervention/image/src/Collection.php
vendored
Normal file
229
vendor/intervention/image/src/Collection.php
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image;
|
||||
|
||||
use Intervention\Image\Interfaces\CollectionInterface;
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use Traversable;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* @implements IteratorAggregate<int|string, mixed>
|
||||
*/
|
||||
class Collection implements CollectionInterface, IteratorAggregate, Countable
|
||||
{
|
||||
/**
|
||||
* Create new collection object
|
||||
*
|
||||
* @param array<int|string, mixed> $items
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(protected array $items = [])
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Static constructor
|
||||
*
|
||||
* @param array<int|string, mixed> $items
|
||||
* @return self<int|string, mixed>
|
||||
*/
|
||||
public static function create(array $items = []): self
|
||||
{
|
||||
return new self($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::has()
|
||||
*/
|
||||
public function has(int|string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Iterator
|
||||
*
|
||||
* @return Traversable<int|string, mixed>
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::toArray()
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count items in collection
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append new item to collection
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return CollectionInterface<int|string, mixed>
|
||||
*/
|
||||
public function push($item): CollectionInterface
|
||||
{
|
||||
$this->items[] = $item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first item in collection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function first(): mixed
|
||||
{
|
||||
if ($item = reset($this->items)) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns last item in collection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function last(): mixed
|
||||
{
|
||||
if ($item = end($this->items)) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item at given position starting at 0
|
||||
*
|
||||
* @param int $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAtPosition(int $key = 0, $default = null): mixed
|
||||
{
|
||||
if ($this->count() == 0) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$positions = array_values($this->items);
|
||||
if (!array_key_exists($key, $positions)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $positions[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::get()
|
||||
*/
|
||||
public function get(int|string $query, $default = null): mixed
|
||||
{
|
||||
if ($this->count() == 0) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (is_int($query) && array_key_exists($query, $this->items)) {
|
||||
return $this->items[$query];
|
||||
}
|
||||
|
||||
if (is_string($query) && strpos($query, '.') === false) {
|
||||
return array_key_exists($query, $this->items) ? $this->items[$query] : $default;
|
||||
}
|
||||
|
||||
$query = explode('.', (string) $query);
|
||||
|
||||
$result = $default;
|
||||
$items = $this->items;
|
||||
foreach ($query as $key) {
|
||||
if (!is_array($items) || !array_key_exists($key, $items)) {
|
||||
$result = $default;
|
||||
break;
|
||||
}
|
||||
|
||||
$result = $items[$key];
|
||||
$items = $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map each item of collection by given callback
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return self
|
||||
*/
|
||||
public function map(callable $callback): self
|
||||
{
|
||||
$items = array_map(function ($item) use ($callback) {
|
||||
return $callback($item);
|
||||
}, $this->items);
|
||||
|
||||
return new self($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run callback on each item of the collection an remove it if it does not return true
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return self
|
||||
*/
|
||||
public function filter(callable $callback): self
|
||||
{
|
||||
$items = array_filter($this->items, function ($item) use ($callback) {
|
||||
return $callback($item);
|
||||
});
|
||||
|
||||
return new self($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::empty()
|
||||
*/
|
||||
public function empty(): CollectionInterface
|
||||
{
|
||||
$this->items = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see CollectionInterface::slice()
|
||||
*/
|
||||
public function slice(int $offset, ?int $length = null): CollectionInterface
|
||||
{
|
||||
$this->items = array_slice($this->items, $offset, $length);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
97
vendor/intervention/image/src/Colors/AbstractColor.php
vendored
Normal file
97
vendor/intervention/image/src/Colors/AbstractColor.php
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors;
|
||||
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
abstract class AbstractColor implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* Color channels
|
||||
*
|
||||
* @var array<ColorChannelInterface>
|
||||
*/
|
||||
protected array $channels;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::channels()
|
||||
*/
|
||||
public function channels(): array
|
||||
{
|
||||
return $this->channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::channel()
|
||||
*/
|
||||
public function channel(string $classname): ColorChannelInterface
|
||||
{
|
||||
$channels = array_filter($this->channels(), function (ColorChannelInterface $channel) use ($classname) {
|
||||
return $channel::class == $classname;
|
||||
});
|
||||
|
||||
if (count($channels) == 0) {
|
||||
throw new ColorException('Color channel ' . $classname . ' could not be found.');
|
||||
}
|
||||
|
||||
return reset($channels);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::normalize()
|
||||
*/
|
||||
public function normalize(): array
|
||||
{
|
||||
return array_map(function (ColorChannelInterface $channel) {
|
||||
return $channel->normalize();
|
||||
}, $this->channels());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toArray()
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_map(function (ColorChannelInterface $channel) {
|
||||
return $channel->value();
|
||||
}, $this->channels());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::convertTo()
|
||||
*/
|
||||
public function convertTo(string|ColorspaceInterface $colorspace): ColorInterface
|
||||
{
|
||||
$colorspace = match (true) {
|
||||
is_object($colorspace) => $colorspace,
|
||||
default => new $colorspace(),
|
||||
};
|
||||
|
||||
return $colorspace->importColor($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::__toString()
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
93
vendor/intervention/image/src/Colors/AbstractColorChannel.php
vendored
Normal file
93
vendor/intervention/image/src/Colors/AbstractColorChannel.php
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors;
|
||||
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
|
||||
abstract class AbstractColorChannel implements ColorChannelInterface
|
||||
{
|
||||
protected int $value;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::__construct()
|
||||
*/
|
||||
public function __construct(?int $value = null, ?float $normalized = null)
|
||||
{
|
||||
$this->value = $this->validate(
|
||||
match (true) {
|
||||
is_null($value) && is_numeric($normalized) => intval(round($normalized * $this->max())),
|
||||
is_numeric($value) && is_null($normalized) => $value,
|
||||
default => throw new ColorException('Color channels must either have a value or a normalized value')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of value()
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function toInt(): int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::value()
|
||||
*/
|
||||
public function value(): int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::normalize()
|
||||
*/
|
||||
public function normalize(int $precision = 32): float
|
||||
{
|
||||
return round(($this->value() - $this->min()) / ($this->max() - $this->min()), $precision);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::validate()
|
||||
*/
|
||||
public function validate(mixed $value): mixed
|
||||
{
|
||||
if ($value < $this->min() || $value > $this->max()) {
|
||||
throw new ColorException('Color channel value must be in range ' . $this->min() . ' to ' . $this->max());
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::toString()
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return (string) $this->value();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorChannelInterface::__toString()
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
20
vendor/intervention/image/src/Colors/Cmyk/Channels/Cyan.php
vendored
Normal file
20
vendor/intervention/image/src/Colors/Cmyk/Channels/Cyan.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColorChannel;
|
||||
|
||||
class Cyan extends AbstractColorChannel
|
||||
{
|
||||
public function min(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function max(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
9
vendor/intervention/image/src/Colors/Cmyk/Channels/Key.php
vendored
Normal file
9
vendor/intervention/image/src/Colors/Cmyk/Channels/Key.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
class Key extends Cyan
|
||||
{
|
||||
}
|
9
vendor/intervention/image/src/Colors/Cmyk/Channels/Magenta.php
vendored
Normal file
9
vendor/intervention/image/src/Colors/Cmyk/Channels/Magenta.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
class Magenta extends Cyan
|
||||
{
|
||||
}
|
9
vendor/intervention/image/src/Colors/Cmyk/Channels/Yellow.php
vendored
Normal file
9
vendor/intervention/image/src/Colors/Cmyk/Channels/Yellow.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk\Channels;
|
||||
|
||||
class Yellow extends Cyan
|
||||
{
|
||||
}
|
157
vendor/intervention/image/src/Colors/Cmyk/Color.php
vendored
Normal file
157
vendor/intervention/image/src/Colors/Cmyk/Color.php
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk;
|
||||
|
||||
use Intervention\Image\Colors\AbstractColor;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Cyan;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Magenta;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Yellow;
|
||||
use Intervention\Image\Colors\Cmyk\Channels\Key;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Drivers\AbstractInputHandler;
|
||||
use Intervention\Image\Interfaces\ColorChannelInterface;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Color extends AbstractColor
|
||||
{
|
||||
/**
|
||||
* Create new instance
|
||||
*
|
||||
* @param int $c
|
||||
* @param int $m
|
||||
* @param int $y
|
||||
* @param int $k
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(int $c, int $m, int $y, int $k)
|
||||
{
|
||||
/** @throws void */
|
||||
$this->channels = [
|
||||
new Cyan($c),
|
||||
new Magenta($m),
|
||||
new Yellow($y),
|
||||
new Key($k),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::create()
|
||||
*/
|
||||
public static function create(mixed $input): ColorInterface
|
||||
{
|
||||
return (new class ([
|
||||
Decoders\StringColorDecoder::class,
|
||||
]) extends AbstractInputHandler
|
||||
{
|
||||
})->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::colorspace()
|
||||
*/
|
||||
public function colorspace(): ColorspaceInterface
|
||||
{
|
||||
return new Colorspace();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toHex()
|
||||
*/
|
||||
public function toHex(string $prefix = ''): string
|
||||
{
|
||||
return $this->convertTo(RgbColorspace::class)->toHex($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK cyan channel
|
||||
*
|
||||
* @return ColorChannelInterface
|
||||
*/
|
||||
public function cyan(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Cyan::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK magenta channel
|
||||
*
|
||||
* @return ColorChannelInterface
|
||||
*/
|
||||
public function magenta(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Magenta::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK yellow channel
|
||||
*
|
||||
* @return ColorChannelInterface
|
||||
*/
|
||||
public function yellow(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Yellow::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CMYK key channel
|
||||
*
|
||||
* @return ColorChannelInterface
|
||||
*/
|
||||
public function key(): ColorChannelInterface
|
||||
{
|
||||
/** @throws void */
|
||||
return $this->channel(Key::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::toString()
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'cmyk(%d%%, %d%%, %d%%, %d%%)',
|
||||
$this->cyan()->value(),
|
||||
$this->magenta()->value(),
|
||||
$this->yellow()->value(),
|
||||
$this->key()->value()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isGreyscale()
|
||||
*/
|
||||
public function isGreyscale(): bool
|
||||
{
|
||||
return 0 === array_sum([
|
||||
$this->cyan()->value(),
|
||||
$this->magenta()->value(),
|
||||
$this->yellow()->value(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorInterface::isTransparent()
|
||||
*/
|
||||
public function isTransparent(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
81
vendor/intervention/image/src/Colors/Cmyk/Colorspace.php
vendored
Normal file
81
vendor/intervention/image/src/Colors/Cmyk/Colorspace.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Intervention\Image\Colors\Cmyk;
|
||||
|
||||
use Intervention\Image\Colors\Rgb\Color as RgbColor;
|
||||
use Intervention\Image\Colors\Cmyk\Color as CmykColor;
|
||||
use Intervention\Image\Colors\Hsv\Color as HsvColor;
|
||||
use Intervention\Image\Colors\Hsl\Color as HslColor;
|
||||
use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace;
|
||||
use Intervention\Image\Exceptions\ColorException;
|
||||
use Intervention\Image\Interfaces\ColorInterface;
|
||||
use Intervention\Image\Interfaces\ColorspaceInterface;
|
||||
|
||||
class Colorspace implements ColorspaceInterface
|
||||
{
|
||||
/**
|
||||
* Channel class names of colorspace
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
public static array $channels = [
|
||||
Channels\Cyan::class,
|
||||
Channels\Magenta::class,
|
||||
Channels\Yellow::class,
|
||||
Channels\Key::class
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see ColorspaceInterface::createColor()
|
||||
*/
|
||||
public function colorFromNormalized(array $normalized): ColorInterface
|
||||
{
|
||||
$values = array_map(function ($classname, $value_normalized) {
|
||||
return (new $classname(normalized: $value_normalized))->value();
|
||||
}, self::$channels, $normalized);
|
||||
|
||||
return new Color(...$values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ColorInterface $color
|
||||
* @return ColorInterface
|
||||
* @throws ColorException
|
||||
*/
|
||||
public function importColor(ColorInterface $color): ColorInterface
|
||||
{
|
||||
return match ($color::class) {
|
||||
RgbColor::class => $this->importRgbColor($color),
|
||||
HsvColor::class => $this->importRgbColor($color->convertTo(RgbColorspace::class)),
|
||||
HslColor::class => $this->importRgbColor($color->convertTo(RgbColorspace::class)),
|
||||
default => $color,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ColorInterface $color
|
||||
* @return Color
|
||||
* @throws ColorException
|
||||
*/
|
||||
protected function importRgbColor(ColorInterface $color): CmykColor
|
||||
{
|
||||
if (!($color instanceof RgbColor)) {
|
||||
throw new ColorException('Unabled to import color of type ' . $color::class . '.');
|
||||
}
|
||||
|
||||
$c = (255 - $color->red()->value()) / 255.0 * 100;
|
||||
$m = (255 - $color->green()->value()) / 255.0 * 100;
|
||||
$y = (255 - $color->blue()->value()) / 255.0 * 100;
|
||||
$k = intval(round(min([$c, $m, $y])));
|
||||
|
||||
$c = intval(round($c - $k));
|
||||
$m = intval(round($m - $k));
|
||||
$y = intval(round($y - $k));
|
||||
|
||||
return new CmykColor($c, $m, $y, $k);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user