open-tibia-tools 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/effectFramesGenerator.html +42 -0
- package/effectFramesGenerator.ts +95 -0
- package/itemImageFramesGenerator.html +45 -0
- package/itemImageFramesGenerator.ts +140 -0
- package/itemImageGenerator.html +40 -0
- package/itemImageGenerator.ts +161 -0
- package/missileFramesGenerator.html +42 -0
- package/missileFramesGenerator.ts +95 -0
- package/otbEditor.html +21 -0
- package/otbEditor.ts +106 -0
- package/outfitImageGenerator.html +38 -0
- package/outfitImageGenerator.ts +109 -0
- package/outfitImagePhpGeneratorCode.ts +19 -0
- package/package.json +28 -0
- package/tests.html +29 -0
- package/tests.ts +218 -0
- package/tools/colored-outfit-images-generator/README.md +7 -0
- package/tools/colored-outfit-images-generator/abuse_warning.png +0 -0
- package/tools/colored-outfit-images-generator/animoutfit.php +103 -0
- package/tools/colored-outfit-images-generator/cacheGenerator.php +40 -0
- package/tools/colored-outfit-images-generator/config.php +25 -0
- package/tools/colored-outfit-images-generator/filesAsJson.php +22 -0
- package/tools/colored-outfit-images-generator/index.php +21 -0
- package/tools/colored-outfit-images-generator/libs/gifCreator.php +343 -0
- package/tools/colored-outfit-images-generator/libs/outfitter.php +312 -0
- package/tools/colored-outfit-images-generator/outfit.php +77 -0
- package/tools/colored-outfit-images-generator/release.php +40 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/1.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/1.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/10.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/10.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/2.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/2.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/3.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/3.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/4.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/4.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/5.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/5.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/6.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/6.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/7.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/7.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/8.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/8.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/9.gif +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/1-10/9.png +0 -0
- package/tools/item-image-frames-to-animated-gif-converter/README.md +20 -0
- package/tools/item-image-frames-to-animated-gif-converter/cli_convert.php +42 -0
- package/tools/item-image-frames-to-animated-gif-converter/generated-zip-archives/.gitignore +3 -0
- package/tools/item-image-frames-to-animated-gif-converter/generated-zip-archives/index.html +1 -0
- package/tools/item-image-frames-to-animated-gif-converter/index.php +97 -0
- package/tools/item-image-frames-to-animated-gif-converter/lib/abstractPngConverterAnimation.php +87 -0
- package/tools/item-image-frames-to-animated-gif-converter/lib/apngCreator.php +247 -0
- package/tools/item-image-frames-to-animated-gif-converter/lib/converterPngToApngAnimation.php +93 -0
- package/tools/item-image-frames-to-animated-gif-converter/lib/converterPngToGifAnimation.php +90 -0
- package/tools/item-image-frames-to-animated-gif-converter/lib/gifCreator.php +339 -0
- package/tsconfig.json +12 -0
- package/webpack.config.js +53 -0
- package/websiteImageGeneratorBase.ts +156 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create an animated GIF from multiple images
|
|
5
|
+
*
|
|
6
|
+
* @update by gesior, php 8.0 compatibility
|
|
7
|
+
*
|
|
8
|
+
* @version 1.0
|
|
9
|
+
* @link https://github.com/Sybio/GifCreator
|
|
10
|
+
* @author Sybio (Clément Guillemain / @Sybio01)
|
|
11
|
+
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
|
12
|
+
* @copyright Clément Guillemain
|
|
13
|
+
*/
|
|
14
|
+
class GifCreator
|
|
15
|
+
{
|
|
16
|
+
/**
|
|
17
|
+
* @var string The gif string source (old: this->GIF)
|
|
18
|
+
*/
|
|
19
|
+
private $gif;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @var string Encoder version (old: this->VER)
|
|
23
|
+
*/
|
|
24
|
+
private $version;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @var boolean Check the image is build or not (old: this->IMG)
|
|
28
|
+
*/
|
|
29
|
+
private $imgBuilt;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @var array Frames string sources (old: this->BUF)
|
|
33
|
+
*/
|
|
34
|
+
private $frameSources;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @var integer Gif loop (old: this->LOP)
|
|
38
|
+
*/
|
|
39
|
+
private $loop;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @var integer Gif dis (old: this->DIS)
|
|
43
|
+
*/
|
|
44
|
+
private $dis;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @var integer Gif color (old: this->COL)
|
|
48
|
+
*/
|
|
49
|
+
private $colour;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @var array (old: this->ERR)
|
|
53
|
+
*/
|
|
54
|
+
private $errors;
|
|
55
|
+
|
|
56
|
+
// Methods
|
|
57
|
+
// ===================================================================================
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Constructor
|
|
61
|
+
*/
|
|
62
|
+
public function __construct()
|
|
63
|
+
{
|
|
64
|
+
$this->reset();
|
|
65
|
+
|
|
66
|
+
// Static data
|
|
67
|
+
$this->version = 'GifCreator: Under development';
|
|
68
|
+
$this->errors = array(
|
|
69
|
+
'ERR00' => 'Does not supported function for only one image.',
|
|
70
|
+
'ERR01' => 'Source is not a GIF image.',
|
|
71
|
+
'ERR02' => 'You have to give resource image variables, image URL or image binary sources in $frames array.',
|
|
72
|
+
'ERR03' => 'Does not make animation from animated GIF source.',
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create the GIF string (old: GIFEncoder)
|
|
78
|
+
*
|
|
79
|
+
* @param array $frames An array of frame: can be file paths, resource image variables, binary sources or image URLs
|
|
80
|
+
* @param array $durations An array containing the duration of each frame
|
|
81
|
+
* @param integer $loop Number of GIF loops before stopping animation (Set 0 to get an infinite loop)
|
|
82
|
+
*
|
|
83
|
+
* @return string The GIF string source
|
|
84
|
+
*/
|
|
85
|
+
public function create($frames = array(), $durations = array(), $loop = 0)
|
|
86
|
+
{
|
|
87
|
+
if (!is_array($frames) && !is_array($durations)) {
|
|
88
|
+
throw new \Exception($this->version . ': ' . $this->errors['ERR00']);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
$this->loop = ($loop > -1) ? $loop : 0;
|
|
92
|
+
$this->dis = 2;
|
|
93
|
+
|
|
94
|
+
for ($i = 0; $i < count($frames); $i++) {
|
|
95
|
+
if ($frames[$i] instanceof GdImage || is_resource($frames[$i])) { // Resource var
|
|
96
|
+
|
|
97
|
+
$resourceImg = $frames[$i];
|
|
98
|
+
|
|
99
|
+
ob_start();
|
|
100
|
+
imagegif($frames[$i]);
|
|
101
|
+
$this->frameSources[] = ob_get_contents();
|
|
102
|
+
ob_end_clean();
|
|
103
|
+
} elseif (is_string($frames[$i])) { // File path or URL or Binary source code
|
|
104
|
+
|
|
105
|
+
if (file_exists($frames[$i]) || filter_var($frames[$i], FILTER_VALIDATE_URL)) { // File path
|
|
106
|
+
|
|
107
|
+
$frames[$i] = file_get_contents($frames[$i]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
$resourceImg = imagecreatefromstring($frames[$i]);
|
|
111
|
+
|
|
112
|
+
ob_start();
|
|
113
|
+
imagegif($resourceImg);
|
|
114
|
+
$this->frameSources[] = ob_get_contents();
|
|
115
|
+
ob_end_clean();
|
|
116
|
+
} else { // Fail
|
|
117
|
+
|
|
118
|
+
throw new \Exception($this->version . ': ' . $this->errors['ERR02']);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if ($i == 0) {
|
|
122
|
+
$transparentIndex = imagecolortransparent($resourceImg);
|
|
123
|
+
if ($transparentIndex >= 0 && (imageistruecolor($resourceImg) || $transparentIndex < imagecolorstotal($resourceImg))) {
|
|
124
|
+
$colors = imagecolorsforindex($resourceImg, $transparentIndex);
|
|
125
|
+
$colour = ($colors['red'] << 16) | ($colors['green'] << 8) | $colors['blue'];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (substr($this->frameSources[$i], 0, 6) != 'GIF87a' && substr(
|
|
130
|
+
$this->frameSources[$i],
|
|
131
|
+
0,
|
|
132
|
+
6
|
|
133
|
+
) != 'GIF89a') {
|
|
134
|
+
throw new \Exception($this->version . ': ' . $i . ' ' . $this->errors['ERR01']);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
for ($j = (13 + 3 * (2 << (ord($this->frameSources[$i] [10]) & 0x07))), $k = true; $k; $j++) {
|
|
138
|
+
switch ($this->frameSources[$i] [$j]) {
|
|
139
|
+
case '!':
|
|
140
|
+
|
|
141
|
+
if ((substr($this->frameSources[$i], ($j + 3), 8)) == 'NETSCAPE') {
|
|
142
|
+
throw new \Exception(
|
|
143
|
+
$this->version . ': ' . $this->errors['ERR03'] . ' (' . ($i + 1) . ' source).'
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
case ';':
|
|
150
|
+
|
|
151
|
+
$k = false;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
unset($resourceImg);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (isset($colour)) {
|
|
160
|
+
$this->colour = $colour;
|
|
161
|
+
} else {
|
|
162
|
+
$red = $green = $blue = 0;
|
|
163
|
+
$this->colour = ($red > -1 && $green > -1 && $blue > -1) ? ($red | ($green << 8) | ($blue << 16)) : -1;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
$this->gifAddHeader();
|
|
167
|
+
|
|
168
|
+
for ($i = 0; $i < count($this->frameSources); $i++) {
|
|
169
|
+
$this->addGifFrames($i, $durations[$i]);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
$this->gifAddFooter();
|
|
173
|
+
|
|
174
|
+
return $this->gif;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Internals
|
|
178
|
+
// ===================================================================================
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Add the header gif string in its source (old: GIFAddHeader)
|
|
182
|
+
*/
|
|
183
|
+
public function gifAddHeader()
|
|
184
|
+
{
|
|
185
|
+
$cmap = 0;
|
|
186
|
+
|
|
187
|
+
if (ord($this->frameSources[0] [10]) & 0x80) {
|
|
188
|
+
$cmap = 3 * (2 << (ord($this->frameSources[0] [10]) & 0x07));
|
|
189
|
+
|
|
190
|
+
$this->gif .= substr($this->frameSources[0], 6, 7);
|
|
191
|
+
$this->gif .= substr($this->frameSources[0], 13, $cmap);
|
|
192
|
+
$this->gif .= "!\377\13NETSCAPE2.0\3\1" . $this->encodeAsciiToChar($this->loop) . "\0";
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Add the frame sources to the GIF string (old: GIFAddFrames)
|
|
198
|
+
*
|
|
199
|
+
* @param integer $i
|
|
200
|
+
* @param integer $d
|
|
201
|
+
*/
|
|
202
|
+
public function addGifFrames($i, $d)
|
|
203
|
+
{
|
|
204
|
+
$Locals_str = 13 + 3 * (2 << (ord($this->frameSources[$i] [10]) & 0x07));
|
|
205
|
+
|
|
206
|
+
$Locals_end = strlen($this->frameSources[$i]) - $Locals_str - 1;
|
|
207
|
+
$Locals_tmp = substr($this->frameSources[$i], $Locals_str, $Locals_end);
|
|
208
|
+
|
|
209
|
+
$Global_len = 2 << (ord($this->frameSources[0] [10]) & 0x07);
|
|
210
|
+
$Locals_len = 2 << (ord($this->frameSources[$i] [10]) & 0x07);
|
|
211
|
+
|
|
212
|
+
$Global_rgb = substr($this->frameSources[0], 13, 3 * (2 << (ord($this->frameSources[0] [10]) & 0x07)));
|
|
213
|
+
$Locals_rgb = substr($this->frameSources[$i], 13, 3 * (2 << (ord($this->frameSources[$i] [10]) & 0x07)));
|
|
214
|
+
|
|
215
|
+
$Locals_ext = "!\xF9\x04" . chr(($this->dis << 2) + 0) . chr(($d >> 0) & 0xFF) . chr(
|
|
216
|
+
($d >> 8) & 0xFF
|
|
217
|
+
) . "\x0\x0";
|
|
218
|
+
|
|
219
|
+
if ($this->colour > -1 && ord($this->frameSources[$i] [10]) & 0x80) {
|
|
220
|
+
for ($j = 0; $j < (2 << (ord($this->frameSources[$i] [10]) & 0x07)); $j++) {
|
|
221
|
+
if (ord($Locals_rgb [3 * $j + 0]) == (($this->colour >> 16) & 0xFF) &&
|
|
222
|
+
ord($Locals_rgb [3 * $j + 1]) == (($this->colour >> 8) & 0xFF) &&
|
|
223
|
+
ord($Locals_rgb [3 * $j + 2]) == (($this->colour >> 0) & 0xFF)
|
|
224
|
+
) {
|
|
225
|
+
$Locals_ext = "!\xF9\x04" . chr(($this->dis << 2) + 1) . chr(($d >> 0) & 0xFF) . chr(
|
|
226
|
+
($d >> 8) & 0xFF
|
|
227
|
+
) . chr($j) . "\x0";
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
switch ($Locals_tmp [0]) {
|
|
234
|
+
case '!':
|
|
235
|
+
|
|
236
|
+
$Locals_img = substr($Locals_tmp, 8, 10);
|
|
237
|
+
$Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18);
|
|
238
|
+
|
|
239
|
+
break;
|
|
240
|
+
|
|
241
|
+
case ',':
|
|
242
|
+
|
|
243
|
+
$Locals_img = substr($Locals_tmp, 0, 10);
|
|
244
|
+
$Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10);
|
|
245
|
+
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (ord($this->frameSources[$i] [10]) & 0x80 && $this->imgBuilt) {
|
|
250
|
+
if ($Global_len == $Locals_len) {
|
|
251
|
+
if ($this->gifBlockCompare($Global_rgb, $Locals_rgb, $Global_len)) {
|
|
252
|
+
$this->gif .= $Locals_ext . $Locals_img . $Locals_tmp;
|
|
253
|
+
} else {
|
|
254
|
+
$byte = ord($Locals_img [9]);
|
|
255
|
+
$byte |= 0x80;
|
|
256
|
+
$byte &= 0xF8;
|
|
257
|
+
$byte |= (ord($this->frameSources[0] [10]) & 0x07);
|
|
258
|
+
$Locals_img [9] = chr($byte);
|
|
259
|
+
$this->gif .= $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp;
|
|
260
|
+
}
|
|
261
|
+
} else {
|
|
262
|
+
$byte = ord($Locals_img [9]);
|
|
263
|
+
$byte |= 0x80;
|
|
264
|
+
$byte &= 0xF8;
|
|
265
|
+
$byte |= (ord($this->frameSources[$i] [10]) & 0x07);
|
|
266
|
+
$Locals_img [9] = chr($byte);
|
|
267
|
+
$this->gif .= $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp;
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
$this->gif .= $Locals_ext . $Locals_img . $Locals_tmp;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
$this->imgBuilt = true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Add the gif string footer char (old: GIFAddFooter)
|
|
278
|
+
*/
|
|
279
|
+
public function gifAddFooter()
|
|
280
|
+
{
|
|
281
|
+
$this->gif .= ';';
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Compare two block and return the version (old: GIFBlockCompare)
|
|
286
|
+
*
|
|
287
|
+
* @param string $globalBlock
|
|
288
|
+
* @param string $localBlock
|
|
289
|
+
* @param integer $length
|
|
290
|
+
*
|
|
291
|
+
* @return integer
|
|
292
|
+
*/
|
|
293
|
+
public function gifBlockCompare($globalBlock, $localBlock, $length)
|
|
294
|
+
{
|
|
295
|
+
for ($i = 0; $i < $length; $i++) {
|
|
296
|
+
if ($globalBlock [3 * $i + 0] != $localBlock [3 * $i + 0] ||
|
|
297
|
+
$globalBlock [3 * $i + 1] != $localBlock [3 * $i + 1] ||
|
|
298
|
+
$globalBlock [3 * $i + 2] != $localBlock [3 * $i + 2]) {
|
|
299
|
+
return 0;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return 1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Encode an ASCII char into a string char (old: GIFWord)
|
|
308
|
+
*
|
|
309
|
+
* $param integer $char ASCII char
|
|
310
|
+
*
|
|
311
|
+
* @return string
|
|
312
|
+
*/
|
|
313
|
+
public function encodeAsciiToChar($char)
|
|
314
|
+
{
|
|
315
|
+
return (chr($char & 0xFF) . chr(($char >> 8) & 0xFF));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Reset and clean the current object
|
|
320
|
+
*/
|
|
321
|
+
public function reset()
|
|
322
|
+
{
|
|
323
|
+
$this->frameSources;
|
|
324
|
+
$this->gif = 'GIF89a'; // the GIF header
|
|
325
|
+
$this->imgBuilt = false;
|
|
326
|
+
$this->loop = 0;
|
|
327
|
+
$this->dis = 2;
|
|
328
|
+
$this->colour = -1;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Getter / Setter
|
|
332
|
+
// ===================================================================================
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Get the final GIF image string (old: GetAnimation)
|
|
336
|
+
*
|
|
337
|
+
* @return string
|
|
338
|
+
*/
|
|
339
|
+
public function getGif()
|
|
340
|
+
{
|
|
341
|
+
return $this->gif;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* @author Kamil Karkus <kaker@wp.eu>
|
|
4
|
+
* @author Gesior.pl <phoowned@wp.pl>
|
|
5
|
+
* @copyright Copyright (c) 2012, Kamil Karkus
|
|
6
|
+
* @version 6 - fixed background transparency in GIFs
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
class Outfitter {
|
|
10
|
+
protected static $instance = null;
|
|
11
|
+
protected static $outfitColors = array(
|
|
12
|
+
0xFFFFFF, 0xFFD4BF, 0xFFE9BF, 0xFFFFBF, 0xE9FFBF, 0xD4FFBF,
|
|
13
|
+
0xBFFFBF, 0xBFFFD4, 0xBFFFE9, 0xBFFFFF, 0xBFE9FF, 0xBFD4FF,
|
|
14
|
+
0xBFBFFF, 0xD4BFFF, 0xE9BFFF, 0xFFBFFF, 0xFFBFE9, 0xFFBFD4,
|
|
15
|
+
0xFFBFBF, 0xDADADA, 0xBF9F8F, 0xBFAF8F, 0xBFBF8F, 0xAFBF8F,
|
|
16
|
+
0x9FBF8F, 0x8FBF8F, 0x8FBF9F, 0x8FBFAF, 0x8FBFBF, 0x8FAFBF,
|
|
17
|
+
0x8F9FBF, 0x8F8FBF, 0x9F8FBF, 0xAF8FBF, 0xBF8FBF, 0xBF8FAF,
|
|
18
|
+
0xBF8F9F, 0xBF8F8F, 0xB6B6B6, 0xBF7F5F, 0xBFAF8F, 0xBFBF5F,
|
|
19
|
+
0x9FBF5F, 0x7FBF5F, 0x5FBF5F, 0x5FBF7F, 0x5FBF9F, 0x5FBFBF,
|
|
20
|
+
0x5F9FBF, 0x5F7FBF, 0x5F5FBF, 0x7F5FBF, 0x9F5FBF, 0xBF5FBF,
|
|
21
|
+
0xBF5F9F, 0xBF5F7F, 0xBF5F5F, 0x919191, 0xBF6A3F, 0xBF943F,
|
|
22
|
+
0xBFBF3F, 0x94BF3F, 0x6ABF3F, 0x3FBF3F, 0x3FBF6A, 0x3FBF94,
|
|
23
|
+
0x3FBFBF, 0x3F94BF, 0x3F6ABF, 0x3F3FBF, 0x6A3FBF, 0x943FBF,
|
|
24
|
+
0xBF3FBF, 0xBF3F94, 0xBF3F6A, 0xBF3F3F, 0x6D6D6D, 0xFF5500,
|
|
25
|
+
0xFFAA00, 0xFFFF00, 0xAAFF00, 0x54FF00, 0x00FF00, 0x00FF54,
|
|
26
|
+
0x00FFAA, 0x00FFFF, 0x00A9FF, 0x0055FF, 0x0000FF, 0x5500FF,
|
|
27
|
+
0xA900FF, 0xFE00FF, 0xFF00AA, 0xFF0055, 0xFF0000, 0x484848,
|
|
28
|
+
0xBF3F00, 0xBF7F00, 0xBFBF00, 0x7FBF00, 0x3FBF00, 0x00BF00,
|
|
29
|
+
0x00BF3F, 0x00BF7F, 0x00BFBF, 0x007FBF, 0x003FBF, 0x0000BF,
|
|
30
|
+
0x3F00BF, 0x7F00BF, 0xBF00BF, 0xBF007F, 0xBF003F, 0xBF0000,
|
|
31
|
+
0x242424, 0x7F2A00, 0x7F5500, 0x7F7F00, 0x557F00, 0x2A7F00,
|
|
32
|
+
0x007F00, 0x007F2A, 0x007F55, 0x007F7F, 0x00547F, 0x002A7F,
|
|
33
|
+
0x00007F, 0x2A007F, 0x54007F, 0x7F007F, 0x7F0055, 0x7F002A,
|
|
34
|
+
0x7F0000,
|
|
35
|
+
);
|
|
36
|
+
public static $mountsTFS = [
|
|
37
|
+
1 => 368, 2 => 369, 3 => 370, 4 => 371, 5 => 372, 6 => 373, 7 => 374, 8 => 375,
|
|
38
|
+
9 => 376, 10 => 377, 11 => 378, 12 => 379, 13 => 387, 14 => 388, 15 => 389, 16 => 390, 17 => 392,
|
|
39
|
+
18 => 401, 19 => 402, 20 => 405, 21 => 406, 22 => 421, 23 => 426, 24 => 427, 25 => 437, 26 => 438,
|
|
40
|
+
27 => 447, 28 => 450, 29 => 502, 30 => 503, 31 => 506, 32 => 515, 33 => 521, 34 => 522, 35 => 526,
|
|
41
|
+
36 => 546, 37 => 547, 38 => 548, 39 => 559, 40 => 571, 41 => 572, 42 => 580, 43 => 606, 44 => 621,
|
|
42
|
+
45 => 622, 46 => 624, 47 => 626, 48 => 627, 49 => 628, 50 => 629, 51 => 630, 52 => 631, 53 => 644,
|
|
43
|
+
54 => 647, 55 => 648, 56 => 649, 57 => 650, 58 => 651, 59 => 669, 60 => 670, 61 => 671, 62 => 672,
|
|
44
|
+
63 => 673, 64 => 674, 65 => 688, 66 => 689, 67 => 690, 68 => 691, 69 => 692, 70 => 693, 71 => 682,
|
|
45
|
+
72 => 685, 73 => 686, 74 => 687, 75 => 726, 76 => 727, 77 => 728, 78 => 734, 79 => 735, 80 => 736,
|
|
46
|
+
81 => 738, 82 => 739, 83 => 740, 84 => 761, 85 => 762, 86 => 763, 87 => 848, 88 => 849, 89 => 850,
|
|
47
|
+
90 => 851, 91 => 868, 92 => 869, 93 => 870, 94 => 883, 95 => 886, 96 => 887, 97 => 888, 98 => 889,
|
|
48
|
+
99 => 890, 100 => 901, 101 => 902, 102 => 903, 103 => 905, 104 => 906, 105 => 907, 106 => 937,
|
|
49
|
+
107 => 950, 108 => 951, 109 => 952, 110 => 959, 111 => 960, 112 => 961, 113 => 1017, 114 => 1018,
|
|
50
|
+
115 => 1019, 116 => 1025, 117 => 1026, 118 => 1027, 119 => 1049, 120 => 1052, 121 => 1053,
|
|
51
|
+
122 => 1054, 123 => 1091, 124 => 1092, 125 => 1093, 126 => 1101, 127 => 1104, 128 => 1105,
|
|
52
|
+
129 => 1106, 130 => 1150, 131 => 1151, 132 => 1163, 133 => 1164, 134 => 1165, 135 => 1167,
|
|
53
|
+
136 => 1168, 137 => 1169, 138 => 1179, 139 => 1180, 140 => 1181, 141 => 1183, 142 => 1184,
|
|
54
|
+
143 => 1185, 144 => 1191, 145 => 1208, 146 => 1209, 147 => 1229, 148 => 1230, 149 => 1231,
|
|
55
|
+
150 => 1232, 151 => 1233, 152 => 1234, 153 => 1247, 154 => 1248, 155 => 1249, 156 => 1257,
|
|
56
|
+
157 => 1258, 158 => 1259, 159 => 1264, 160 => 1265, 161 => 1266, 162 => 1269, 163 => 1281,
|
|
57
|
+
164 => 1284, 165 => 1285, 166 => 1286, 167 => 1321, 168 => 1324, 169 => 1325, 170 => 1326,
|
|
58
|
+
171 => 1333, 172 => 1334, 173 => 1335, 174 => 1336, 175 => 1363, 176 => 1379, 177 => 1380,
|
|
59
|
+
178 => 1381, 179 => 1389, 180 => 1390, 181 => 1391, 182 => 1417, 183 => 1430, 184 => 1431,
|
|
60
|
+
185 => 1439, 186 => 1440, 187 => 1441
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
public static $data = [];
|
|
64
|
+
private static $transparentBackgroundColor = array(255, 255, 255, 127);
|
|
65
|
+
public static $outfitPath;
|
|
66
|
+
public static $resizeAllOutfitsTo64px = false;
|
|
67
|
+
|
|
68
|
+
public static function instance() {
|
|
69
|
+
if (!isset(self::$instance))
|
|
70
|
+
self::$instance = new self();
|
|
71
|
+
return self::$instance;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public static function setResizeAllOutfitsTo64px($value) {
|
|
75
|
+
self::$resizeAllOutfitsTo64px = (bool)$value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public static function loadData($outfitId, $isMount = false)
|
|
79
|
+
{
|
|
80
|
+
if($isMount)
|
|
81
|
+
{
|
|
82
|
+
$mount = $outfitId;
|
|
83
|
+
if($mount == 0 || $mount >= 65535)
|
|
84
|
+
{
|
|
85
|
+
$outfitId = ($mount & 0xFFFF);
|
|
86
|
+
}
|
|
87
|
+
elseif($mount < 300)
|
|
88
|
+
{
|
|
89
|
+
// tfs 1.x mount system
|
|
90
|
+
$outfitId = self::$mountsTFS[$mount];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if(file_exists(self::$outfitPath . $outfitId . '/outfit.data.txt'))
|
|
94
|
+
{
|
|
95
|
+
if($isMount)
|
|
96
|
+
{
|
|
97
|
+
$tmp = unserialize(file_get_contents(self::$outfitPath . $outfitId . '/outfit.data.txt'));
|
|
98
|
+
self::$data['files'] = array_merge(self::$data['files'], $tmp['files']);
|
|
99
|
+
self::$data['mountFramesNumber'] = $tmp['framesNumber'];
|
|
100
|
+
}
|
|
101
|
+
else
|
|
102
|
+
{
|
|
103
|
+
self::$data = unserialize(file_get_contents(self::$outfitPath . $outfitId . '/outfit.data.txt'));
|
|
104
|
+
self::$data['mountFramesNumber'] = 1;
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public static function getOutfitFramesNumber()
|
|
112
|
+
{
|
|
113
|
+
return self::$data['framesNumber'];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public static function file_exists($filePath)
|
|
117
|
+
{
|
|
118
|
+
return in_array(trim(trim(str_replace('\\', '/', $filePath), '.'), '/'), self::$data['files']);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public function outfit($outfit, $addons, $head, $body, $legs, $feet, $mount, $direction = 3, $animation = 1) {
|
|
122
|
+
if($mount == 0 || $mount >= 65535)
|
|
123
|
+
{
|
|
124
|
+
// old mount system
|
|
125
|
+
$mountId = ($mount & 0xFFFF);
|
|
126
|
+
$mountState = (($mount & 0xFFFF0000) != 0) ? 2 : 1;
|
|
127
|
+
}
|
|
128
|
+
elseif($mount < 300)
|
|
129
|
+
{
|
|
130
|
+
// tfs 1.x mount system
|
|
131
|
+
$mountId = self::$mountsTFS[$mount];
|
|
132
|
+
$mountState = 2;
|
|
133
|
+
}
|
|
134
|
+
else
|
|
135
|
+
{
|
|
136
|
+
$mountId = $mount;
|
|
137
|
+
$mountState = 2;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (self::file_exists(self::$outfitPath . $outfit . '/'.$animation.'_' . $mountState . '_1_'.$direction.'.png')) {
|
|
141
|
+
$image_outfit = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_1_' . $direction . '.png');
|
|
142
|
+
if (file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_1_' . $direction . '_template.png')) {
|
|
143
|
+
$image_template = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_1_' . $direction . '_template.png');
|
|
144
|
+
} else {
|
|
145
|
+
$image_template = imagecreatetruecolor(imagesx($image_outfit), imagesy($image_outfit));
|
|
146
|
+
$bgcolor = imagecolorallocatealpha($image_template, self::$transparentBackgroundColor[0], self::$transparentBackgroundColor[1], self::$transparentBackgroundColor[2], self::$transparentBackgroundColor[3]);
|
|
147
|
+
imagefill($image_template, 0, 0, $bgcolor);
|
|
148
|
+
imagecolortransparent($image_template, $bgcolor);
|
|
149
|
+
|
|
150
|
+
imagealphablending($image_template, false);
|
|
151
|
+
imagesavealpha($image_template, true);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if ($addons == 1 || $addons == 3) {
|
|
155
|
+
if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '.png')) {
|
|
156
|
+
$image_first = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '.png');
|
|
157
|
+
$this->alphaOverlay($image_outfit, $image_first, 64, 64);
|
|
158
|
+
imagedestroy($image_first);
|
|
159
|
+
if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '_template.png')) {
|
|
160
|
+
$image_first_template = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '_template.png');
|
|
161
|
+
$this->alphaOverlay($image_template, $image_first_template, 64, 64);
|
|
162
|
+
imagedestroy($image_first_template);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if ($addons == 2 || $addons == 3) {
|
|
167
|
+
if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '.png')) {
|
|
168
|
+
$image_second = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '.png');
|
|
169
|
+
$this->alphaOverlay($image_outfit, $image_second, 64, 64);
|
|
170
|
+
imagedestroy($image_second);
|
|
171
|
+
if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '_template.png')) {
|
|
172
|
+
$image_second_template = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '_template.png');
|
|
173
|
+
$this->alphaOverlay($image_template, $image_second_template, 64, 64);
|
|
174
|
+
imagedestroy($image_second_template);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
$this->colorize($image_template, $image_outfit, $head, $body, $legs, $feet);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
$mountAnimationFrame = $animation;
|
|
183
|
+
while ($mountAnimationFrame > self::$data['mountFramesNumber']) {
|
|
184
|
+
$mountAnimationFrame -= self::$data['mountFramesNumber'];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if ($mountState == 2 && self::file_exists(self::$outfitPath . $mountId . '/'.$mountAnimationFrame.'_1_1_'.$direction.'.png')) {
|
|
188
|
+
$mount = imagecreatefrompng(self::$outfitPath . $mountId . '/'.$mountAnimationFrame.'_1_1_'.$direction.'.png');
|
|
189
|
+
$this->alphaOverlay($mount, $image_outfit, 64, 64);
|
|
190
|
+
if ($image_outfit) {
|
|
191
|
+
imagedestroy($image_outfit);
|
|
192
|
+
}
|
|
193
|
+
$image_outfit = $mount;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
$width = imagesx($image_outfit);
|
|
197
|
+
$height = imagesy($image_outfit);
|
|
198
|
+
if (self::$resizeAllOutfitsTo64px) {
|
|
199
|
+
$image_outfitT = imagecreatetruecolor(64, 64);
|
|
200
|
+
} else {
|
|
201
|
+
$image_outfitT = imagecreatetruecolor($width, $height);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Use a specific color for transparency (Magenta: 255, 0, 255)
|
|
205
|
+
$bgcolor = imagecolorallocate($image_outfitT, 255, 0, 255);
|
|
206
|
+
imagefill($image_outfitT, 0, 0, $bgcolor);
|
|
207
|
+
|
|
208
|
+
imagecopyresampled($image_outfitT, $image_outfit, imagesx($image_outfitT)-$width, imagesy($image_outfitT)-$height, 0, 0, $width, $height, $width, $height);
|
|
209
|
+
|
|
210
|
+
// Convert truecolor image to palette to fix GIF transparency loss issue
|
|
211
|
+
imagetruecolortopalette($image_outfitT, false, 255);
|
|
212
|
+
|
|
213
|
+
// Get the exact transparent index and assign it
|
|
214
|
+
$transparentIndex = imagecolorclosest($image_outfitT, 255, 0, 255);
|
|
215
|
+
imagecolortransparent($image_outfitT, $transparentIndex);
|
|
216
|
+
|
|
217
|
+
imagedestroy($image_outfit);
|
|
218
|
+
if (isset($image_template) && $image_template) {
|
|
219
|
+
imagedestroy($image_template);
|
|
220
|
+
}
|
|
221
|
+
return $image_outfitT;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
protected function colorizePixel($_color, &$_r, &$_g, &$_b) {
|
|
225
|
+
if ($_color < count(self::$outfitColors))
|
|
226
|
+
$value = self::$outfitColors[$_color];
|
|
227
|
+
else
|
|
228
|
+
$value = 0;
|
|
229
|
+
$ro = ($value & 0xFF0000) >> 16; // rgb outfit
|
|
230
|
+
$go = ($value & 0xFF00) >> 8;
|
|
231
|
+
$bo = ($value & 0xFF);
|
|
232
|
+
$_r = (int) ($_r * ($ro / 255));
|
|
233
|
+
$_g = (int) ($_g * ($go / 255));
|
|
234
|
+
$_b = (int) ($_b * ($bo / 255));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
protected function colorize(&$_image_template, &$_image_outfit, $_head, $_body, $_legs, $_feet) {
|
|
238
|
+
if (!$_image_template) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
for ($i = 0; $i < imagesy($_image_template); $i++) {
|
|
243
|
+
for ($j = 0; $j < imagesx($_image_template); $j++) {
|
|
244
|
+
$templatepixel = imagecolorat($_image_template, $j, $i);
|
|
245
|
+
$outfit = imagecolorat($_image_outfit, $j, $i);
|
|
246
|
+
|
|
247
|
+
if ($templatepixel == $outfit)
|
|
248
|
+
continue;
|
|
249
|
+
|
|
250
|
+
$rt = ($templatepixel >> 16) & 0xFF;
|
|
251
|
+
$gt = ($templatepixel >> 8) & 0xFF;
|
|
252
|
+
$bt = $templatepixel & 0xFF;
|
|
253
|
+
$ro = ($outfit >> 16) & 0xFF;
|
|
254
|
+
$go = ($outfit >> 8) & 0xFF;
|
|
255
|
+
$bo = $outfit & 0xFF;
|
|
256
|
+
|
|
257
|
+
if ($rt && $gt && !$bt) { // yellow == head
|
|
258
|
+
$this->colorizePixel($_head, $ro, $go, $bo);
|
|
259
|
+
} else if ($rt && !$gt && !$bt) { // red == body
|
|
260
|
+
$this->colorizePixel($_body, $ro, $go, $bo);
|
|
261
|
+
} else if (!$rt && $gt && !$bt) { // green == legs
|
|
262
|
+
$this->colorizePixel($_legs, $ro, $go, $bo);
|
|
263
|
+
} else if (!$rt && !$gt && $bt) { // blue == feet
|
|
264
|
+
$this->colorizePixel($_feet, $ro, $go, $bo);
|
|
265
|
+
} else {
|
|
266
|
+
continue; // if nothing changed, skip the change of pixel
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
imagesetpixel($_image_outfit, $j, $i, imagecolorallocate($_image_outfit, $ro, $go, $bo));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
protected function alphaOverlay(&$destImg, &$overlayImg, $imgW, $imgH) {
|
|
275
|
+
if (!$overlayImg) {
|
|
276
|
+
return $destImg;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
for ($y = 0; $y < $imgH; $y++) {
|
|
280
|
+
for ($x = 0; $x < $imgW; $x++) {
|
|
281
|
+
$ovrARGB = imagecolorat($overlayImg, $x, $y);
|
|
282
|
+
$ovrA = ($ovrARGB >> 24) << 1;
|
|
283
|
+
$ovrR = $ovrARGB >> 16 & 0xFF;
|
|
284
|
+
$ovrG = $ovrARGB >> 8 & 0xFF;
|
|
285
|
+
$ovrB = $ovrARGB & 0xFF;
|
|
286
|
+
|
|
287
|
+
$change = false;
|
|
288
|
+
if ($ovrA == 0) {
|
|
289
|
+
$dstR = $ovrR;
|
|
290
|
+
$dstG = $ovrG;
|
|
291
|
+
$dstB = $ovrB;
|
|
292
|
+
$change = true;
|
|
293
|
+
} elseif ($ovrA < 254) {
|
|
294
|
+
$dstARGB = imagecolorat($destImg, $x, $y);
|
|
295
|
+
$dstR = $dstARGB >> 16 & 0xFF;
|
|
296
|
+
$dstG = $dstARGB >> 8 & 0xFF;
|
|
297
|
+
$dstB = $dstARGB & 0xFF;
|
|
298
|
+
|
|
299
|
+
$dstR = (($ovrR * (0xFF - $ovrA)) >> 8) + (($dstR * $ovrA) >> 8);
|
|
300
|
+
$dstG = (($ovrG * (0xFF - $ovrA)) >> 8) + (($dstG * $ovrA) >> 8);
|
|
301
|
+
$dstB = (($ovrB * (0xFF - $ovrA)) >> 8) + (($dstB * $ovrA) >> 8);
|
|
302
|
+
$change = true;
|
|
303
|
+
}
|
|
304
|
+
if ($change) {
|
|
305
|
+
$dstRGB = imagecolorallocatealpha($destImg, $dstR, $dstG, $dstB, 0);
|
|
306
|
+
imagesetpixel($destImg, $x, $y, $dstRGB);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return $destImg;
|
|
311
|
+
}
|
|
312
|
+
}
|