@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3/**
4 * @task enormous Detecting Enormous Images
5 * @task save Saving Image Data
6 */
7final class PhabricatorImageTransformer extends Phobject {
8
9
10/* -( Saving Image Data )-------------------------------------------------- */
11
12
13 /**
14 * Save an image resource to a string representation suitable for storage or
15 * transmission as an image file.
16 *
17 * Optionally, you can specify a preferred MIME type like `"image/png"`.
18 * Generally, you should specify the MIME type of the original file if you're
19 * applying file transformations. The MIME type may not be honored if
20 * Phabricator can not encode images in the given format (based on available
21 * extensions), but can save images in another format.
22 *
23 * @param resource $data GD image resource.
24 * @param string $preferred_mime (optional) Preferred mime type.
25 * @return string Bytes of an image file.
26 * @task save
27 */
28 public static function saveImageDataInAnyFormat($data, $preferred_mime = '') {
29 $preferred = null;
30 switch ($preferred_mime) {
31 case 'image/gif':
32 $preferred = self::saveImageDataAsGIF($data);
33 break;
34 case 'image/png':
35 $preferred = self::saveImageDataAsPNG($data);
36 break;
37 case 'image/webp':
38 $preferred = self::saveImageDataAsWEBP($data);
39 break;
40 }
41
42 if ($preferred !== null) {
43 return $preferred;
44 }
45
46 $data = self::saveImageDataAsJPG($data);
47 if ($data !== null) {
48 return $data;
49 }
50
51 $data = self::saveImageDataAsPNG($data);
52 if ($data !== null) {
53 return $data;
54 }
55
56 $data = self::saveImageDataAsGIF($data);
57 if ($data !== null) {
58 return $data;
59 }
60
61 $data = self::saveImageDataAsWEBP($data);
62 if ($data !== null) {
63 return $data;
64 }
65
66 throw new Exception(pht('Failed to save image data into any format.'));
67 }
68
69
70 /**
71 * Save an image in PNG format, returning the file data as a string.
72 *
73 * @param resource $image GD image resource.
74 * @return string|null PNG file as a string, or null on failure.
75 * @task save
76 */
77 private static function saveImageDataAsPNG($image) {
78 if (!function_exists('imagepng')) {
79 return null;
80 }
81
82 // NOTE: Empirically, the highest compression level (9) seems to take
83 // up to twice as long as the default compression level (6) but produce
84 // only slightly smaller files (10% on avatars, 3% on screenshots).
85
86 ob_start();
87 $result = imagepng($image, null, 6);
88 $output = ob_get_clean();
89
90 if (!$result) {
91 return null;
92 }
93
94 return $output;
95 }
96
97
98 /**
99 * Save an image in GIF format, returning the file data as a string.
100 *
101 * @param resource $image GD image resource.
102 * @return string|null GIF file as a string, or null on failure.
103 * @task save
104 */
105 private static function saveImageDataAsGIF($image) {
106 if (!function_exists('imagegif')) {
107 return null;
108 }
109
110 ob_start();
111 $result = imagegif($image);
112 $output = ob_get_clean();
113
114 if (!$result) {
115 return null;
116 }
117
118 return $output;
119 }
120
121
122 /**
123 * Save an image in JPG format, returning the file data as a string.
124 *
125 * @param resource $image GD image resource.
126 * @return string|null JPG file as a string, or null on failure.
127 * @task save
128 */
129 private static function saveImageDataAsJPG($image) {
130 if (!function_exists('imagejpeg')) {
131 return null;
132 }
133
134 ob_start();
135 $result = imagejpeg($image);
136 $output = ob_get_clean();
137
138 if (!$result) {
139 return null;
140 }
141
142 return $output;
143 }
144
145 /**
146 * Save an image in WEBP format, returning the file data as a string.
147 *
148 * @param resource $image GD image resource.
149 * @return string|null WEBP file as a string, or null on failure.
150 * @task save
151 */
152 private static function saveImageDataAsWEBP($image) {
153 if (!function_exists('imagewebp')) {
154 return null;
155 }
156
157 ob_start();
158 $result = imagewebp($image);
159 $output = ob_get_clean();
160
161 if (!$result) {
162 return null;
163 }
164
165 return $output;
166 }
167
168
169}