├── php.exe ├── php7.dll ├── php_gd2.dll ├── php_fileinfo.dll ├── lvgl_image_convert.exe ├── php.ini ├── Mutiple_image_convert.png ├── Readme.md └── img_conv_core.php /php.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjingxun12/Lvgl_image_convert_tool/HEAD/php.exe -------------------------------------------------------------------------------- /php7.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjingxun12/Lvgl_image_convert_tool/HEAD/php7.dll -------------------------------------------------------------------------------- /php_gd2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjingxun12/Lvgl_image_convert_tool/HEAD/php_gd2.dll -------------------------------------------------------------------------------- /php_fileinfo.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjingxun12/Lvgl_image_convert_tool/HEAD/php_fileinfo.dll -------------------------------------------------------------------------------- /lvgl_image_convert.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjingxun12/Lvgl_image_convert_tool/HEAD/lvgl_image_convert.exe -------------------------------------------------------------------------------- /php.ini: -------------------------------------------------------------------------------- 1 | extension_dir = ".\" 2 | extension=php_fileinfo.dll 3 | extension=php_gd2.dll 4 | memory_limit = 512M 5 | -------------------------------------------------------------------------------- /Mutiple_image_convert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjingxun12/Lvgl_image_convert_tool/HEAD/Mutiple_image_convert.png -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2020-01-08: 2 | 3 | 修复了工具当前预览的图片被锁定无法外部修改的问题 4 | 5 | 2019-12-22: 6 | 7 | 增加了图片批量转换,并将图片名称作为转换后的文件名和变量名 8 | 1. 由于图片名可能作为转换后的变量名,增加了对图片名的规范检测,大体同前一个版本的lv_img_dsc_t检测一致 9 | 2. 根据lvgl支持的图片种类做了分类 10 | 3. 对各个图片加了转换前的检测结果及转换后的转换结果的tip提示 11 | 大致如下: 12 | 13 | 14 | ![批量转换示意图](https://whycan.cn/files/members/1913/none.png) 15 | 16 | 17 | 18 | 2019-11-20: 19 | 20 | 增加了对转换操作结果的验证,避免了转换图片时界面卡死的问题 21 | 22 | 添加了原php环境下的内存限制设置参数 23 | 24 | 对于转换提示的问题: 25 | 26 | 1.在转换图片时,提示转换成功,但找不到转换后的文件 27 | 28 | 原因:图片分辨率过大,修改php环境内存限制参数 29 | 30 | 解决办法:修改转换工具根目录下php.ini配置文件 31 | ```php 32 | memory_limit = _xxx_M // _xxx_ 根据实际使用修改该值,图片分辨率越大,需要设置的值就越大 33 | ``` 34 | 35 | 2.在转换图片时,提示转换失败 36 | 37 | 原因1:图片分辨率过大,转换时间太长(这么大的图片……),超时了 38 | 原因2:图片资源编码问题,测试发现截屏保存的图片不能直接转换,否则转换失败,先使用图片编辑工具打开,然后另存就可以了 39 | 40 | 目前发现以上问题 41 | 42 | 2019-11-16: 43 | 44 | ## 界面如下 45 | 设置输出文件类型,c测试没问题,bin格式没用到,如果有用到的朋友欢迎反馈 46 | 47 | ![设置输出文件类型](https://whycan.cn/files/members/1913/1573874174(1).png) 48 | 49 | 转换方式跟官方网页一样 50 | 51 | ![设置图片转换方式](https://whycan.cn/files/members/1913/1573812405(1)_20191116-1119.png) 52 | 53 | lv_img_dsc_t,为生成的c文件下该图片资源的名字 54 | 55 | 56 | 2019-11-15: 57 | 58 | ## 说明 59 | 60 | 软件为基于LVGL离线版图片转换封装的小工具,避免了常使用界面工具的朋友操作控制台指令的不便利 61 | 62 | 运行环境为windows 63 | 64 | 修改了原官方离线版php文件接口,便于保存到指定目录 65 | 66 | 避免计算机没有php环境,在工具所在目录配置了一个php小环境(人懒,php不懂瞎裁) 67 | 68 | 69 | 70 | ## 初衷 71 | 72 | 手头项目用到lvgl做界面设计,前期在lvgl官网做图片转换,感觉挺好 但界面嘛,美观度重口难调,所以这周把界面元素重设计了一遍, 然后昨天在官网做转换时,下载n次失败……所以就有了这个基于官方离线版封装的转换工具,有问题可以通过软件界面的qq和邮箱联系我 73 | 74 | ## 后续 75 | 76 | 如果后面有时间或者用到的话,加一个批量转换的。。。这个先用吧 77 | -------------------------------------------------------------------------------- /img_conv_core.php: -------------------------------------------------------------------------------- 1 | dith = $dith; 59 | $this->out_name = $out_name; 60 | $this->path = $path; 61 | $this->output_dir = $output; 62 | 63 | $size = getimagesize($path); 64 | $this->w = $size[0]; 65 | $this->h = $size[1]; 66 | 67 | $ext = pathinfo($real_name, PATHINFO_EXTENSION); 68 | if(!strcmp(strtolower($ext), "png")) $this->img = imagecreatefrompng($path); 69 | else if(!strcmp(strtolower($ext), "bmp")) $this->img = imagecreatefrombmp($path); 70 | else if(!strcmp(strtolower($ext), "jpg")) $this->img = imagecreatefromjpeg($path); 71 | else if(!strcmp(strtolower($ext), "jpeg")) $this->img = imagecreatefromjpeg($path); 72 | else { 73 | echo("$ext is a not supported image type. use png, jpg, jpeg or bmp"); 74 | exit(1); 75 | } 76 | 77 | $this->r_earr = array(); /*Classification error for next row of pixels*/ 78 | $this->g_earr = array(); 79 | $this->b_earr = array(); 80 | 81 | if($this->dith) { 82 | for($i = 0; $i < $this->w + 2; ++$i){ 83 | $this->r_earr[$i] = 0; 84 | $this->g_earr[$i] = 0; 85 | $this->b_earr[$i] = 0; 86 | } 87 | } 88 | 89 | $this->r_nerr = 0; /*Classification error for next pixel*/ 90 | $this->g_nerr = 0; 91 | $this->b_nerr = 0; 92 | } 93 | 94 | function convert($cf, $alpha = 0) { 95 | $this->cf = $cf; 96 | $this->d_out = array(); 97 | $this->alpha = $alpha; 98 | 99 | if($this->cf == self::CF_RAW || $this->cf == self::CF_RAW_ALPHA || $this->cf == self::CF_RAW_CHROMA) { 100 | $myfile = fopen($this->path, "r") or die("Unable to open file!"); 101 | $this->d_out = unpack('C*', fread($myfile, filesize($this->path))); 102 | fclose($myfile); 103 | return; 104 | } 105 | 106 | $palette_size = 0; 107 | if($this->cf == self::CF_INDEXED_1_BIT) $palette_size = 2; 108 | if($this->cf == self::CF_INDEXED_2_BIT) $palette_size = 4; 109 | if($this->cf == self::CF_INDEXED_4_BIT) $palette_size = 16; 110 | if($this->cf == self::CF_INDEXED_8_BIT) $palette_size = 256; 111 | 112 | if($palette_size) { 113 | $img_tmp = imagecreatetruecolor($this->w, $this->h); 114 | imagecopy ($img_tmp, $this->img, 0 , 0 , 0 , 0, $this->w , $this->h); 115 | imagetruecolortopalette($this->img, false, $palette_size); 116 | $real_palette_size = imagecolorstotal($this->img); /*The real number of colos in the image's palette*/ 117 | for($i = 0; $i < $palette_size; $i++) { 118 | if($i < $real_palette_size) { 119 | $c = imagecolorsforindex ($this->img , $i); 120 | array_push($this->d_out, $c['blue'], $c['green'], $c['red'], 0xFF); 121 | } else { 122 | array_push($this->d_out, 0xFF, 0xFF, 0xFF, 0xFF); 123 | } 124 | } 125 | } 126 | 127 | /*Convert all the pixels*/ 128 | for($y = 0; $y < $this->h; $y++) { 129 | $this->dith_reset(); 130 | 131 | for($x = 0; $x < $this->w; ++$x){ 132 | $this->conv_px($x, $y); 133 | } 134 | } 135 | 136 | /*Revert the original image if it was converted to indexed*/ 137 | if($palette_size) { 138 | imagecopy ($this->img, $img_tmp, 0 , 0 , 0 , 0 , $this->w , $this->h); 139 | } 140 | } 141 | 142 | function format_to_c_array() { 143 | 144 | $c_array = ""; 145 | $i = 0; 146 | $y_end = $this->h; 147 | $x_end = $this->w; 148 | 149 | if($this->cf == self::CF_TRUE_COLOR_332) { 150 | $c_array .= "\n#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8"; 151 | if(!$this->alpha) $c_array .= "\n /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/"; 152 | else $c_array .= "\n /*Pixel format: Alpha 8 bit, Red: 3 bit, Green: 3 bit, Blue: 2 bit*/"; 153 | } else if($this->cf == self::CF_TRUE_COLOR_565) { 154 | $c_array .= "\n#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0"; 155 | if(!$this->alpha) $c_array .= "\n /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/"; 156 | else $c_array .= "\n /*Pixel format: Alpha 8 bit, Red: 5 bit, Green: 6 bit, Blue: 5 bit*/"; 157 | } else if($this->cf == self::CF_TRUE_COLOR_565_SWAP) { 158 | $c_array .= "\n#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP != 0"; 159 | if(!$this->alpha) $c_array .= "\n /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/"; 160 | else $c_array .= "\n /*Pixel format: Alpha 8 bit, Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 color bytes are swapped*/"; 161 | } else if($this->cf == self::CF_TRUE_COLOR_888) { 162 | $c_array .= "\n#if LV_COLOR_DEPTH == 32"; 163 | if(!$this->alpha) $c_array .= "\n /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/"; 164 | else "\n /*Pixel format: Alpha 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/"; 165 | } else if($this->cf == self::CF_INDEXED_1_BIT) { 166 | $c_array .= "\n"; 167 | for($p = 0; $p < 2; $p ++) { 168 | $c_array .= " 0x" . str_pad(dechex($this->d_out[$p * 4 + 0]), 2, '0', STR_PAD_LEFT) . ", "; 169 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 1]), 2, '0', STR_PAD_LEFT) . ", "; 170 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 2]), 2, '0', STR_PAD_LEFT) . ", "; 171 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 3]), 2, '0', STR_PAD_LEFT) . ", "; 172 | $c_array .= "\t/*Color of index $p*/\n"; 173 | } 174 | 175 | $i = $p * 4; 176 | } 177 | else if($this->cf == self::CF_INDEXED_2_BIT) { 178 | $c_array .= "\n"; 179 | for($p = 0; $p < 4; $p ++) { 180 | $c_array .= " 0x" . str_pad(dechex($this->d_out[$p * 4 + 0]), 2, '0', STR_PAD_LEFT) . ", "; 181 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 1]), 2, '0', STR_PAD_LEFT) . ", "; 182 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 2]), 2, '0', STR_PAD_LEFT) . ", "; 183 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 3]), 2, '0', STR_PAD_LEFT) . ", "; 184 | $c_array .= "\t/*Color of index $p*/\n"; 185 | } 186 | 187 | $i = $p * 4; 188 | } 189 | else if($this->cf == self::CF_INDEXED_4_BIT) { 190 | $c_array .= "\n"; 191 | for($p = 0; $p < 16; $p ++) { 192 | $c_array .= " 0x" . str_pad(dechex($this->d_out[$p * 4 + 0]), 2, '0', STR_PAD_LEFT) . ", "; 193 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 1]), 2, '0', STR_PAD_LEFT) . ", "; 194 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 2]), 2, '0', STR_PAD_LEFT) . ", "; 195 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 3]), 2, '0', STR_PAD_LEFT) . ", "; 196 | $c_array .= "\t/*Color of index $p*/\n"; 197 | } 198 | 199 | $i = $p * 4; 200 | } 201 | else if($this->cf == self::CF_INDEXED_8_BIT) { 202 | $c_array .= "\n"; 203 | for($p = 0; $p < 256; $p ++) { 204 | $c_array .= " 0x" . str_pad(dechex($this->d_out[$p * 4 + 0]), 2, '0', STR_PAD_LEFT) . ", "; 205 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 1]), 2, '0', STR_PAD_LEFT) . ", "; 206 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 2]), 2, '0', STR_PAD_LEFT) . ", "; 207 | $c_array .= "0x" . str_pad(dechex($this->d_out[$p * 4 + 3]), 2, '0', STR_PAD_LEFT) . ", "; 208 | $c_array .= "\t/*Color of index $p*/\n"; 209 | } 210 | 211 | $i = $p * 4; 212 | } 213 | else if($this->cf == self::CF_RAW || $this->cf == self::CF_RAW_ALPHA || $this->cf == self::CF_RAW_CHROMA) { 214 | $y_end = 1; 215 | $x_end = count($this->d_out); 216 | $i = 1; 217 | } 218 | 219 | 220 | for($y = 0; $y < $y_end; $y++) { 221 | $c_array .= "\n "; 222 | for($x = 0; $x < $x_end; $x++) { 223 | if($this->cf == self::CF_TRUE_COLOR_332) { 224 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; $i++; 225 | if($this->alpha) { 226 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; 227 | $i++; 228 | } 229 | } 230 | else if($this->cf == self::CF_TRUE_COLOR_565 || $this->cf == self::CF_TRUE_COLOR_565_SWAP) { 231 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; $i++; 232 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; $i++; 233 | if($this->alpha) { 234 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; 235 | $i++; 236 | } 237 | } 238 | else if($this->cf == self::CF_TRUE_COLOR_888) { 239 | 240 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; $i++; 241 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; $i++; 242 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; $i++; 243 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; $i++; 244 | } 245 | else if($this->cf == self::CF_ALPHA_1_BIT || $this->cf == self::CF_INDEXED_1_BIT) { 246 | if(($x & 0x7) == 0) { 247 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; 248 | $i++; 249 | } 250 | } 251 | else if($this->cf == self::CF_ALPHA_2_BIT || $this->cf == self::CF_INDEXED_2_BIT) { 252 | if(($x & 0x3) == 0) { 253 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; 254 | $i++; 255 | } 256 | } 257 | else if($this->cf == self::CF_ALPHA_4_BIT || $this->cf == self::CF_INDEXED_4_BIT) { 258 | if(($x & 0x1) == 0) { 259 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; 260 | $i++; 261 | } 262 | } 263 | else if($this->cf == self::CF_ALPHA_8_BIT || $this->cf == self::CF_INDEXED_8_BIT) { 264 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; 265 | $i++; 266 | } 267 | else if($this->cf == self::CF_RAW || $this->cf == self::CF_RAW_ALPHA || $this->cf == self::CF_RAW_CHROMA) { 268 | $c_array .= "0x" . str_pad(dechex($this->d_out[$i]), 2, '0', STR_PAD_LEFT) . ", "; 269 | if($i != 0 && (($i % 16) == 0)) $c_array .= "\n "; 270 | $i++; 271 | } 272 | } 273 | } 274 | 275 | if($this->cf == self::CF_TRUE_COLOR_332 || $this->cf == self::CF_TRUE_COLOR_565 || $this->cf == self::CF_TRUE_COLOR_565_SWAP || $this->cf == self::CF_TRUE_COLOR_888) { 276 | $c_array .= "\n#endif"; 277 | } 278 | 279 | return $c_array; 280 | 281 | } 282 | 283 | function get_c_header() { 284 | $c_header = 285 | "#include \"lvgl/lvgl.h\" 286 | 287 | #ifndef LV_ATTRIBUTE_MEM_ALIGN 288 | #define LV_ATTRIBUTE_MEM_ALIGN 289 | #endif 290 | 291 | "; 292 | $attr_name = "LV_ATTRIBUTE_IMG_" . strtoupper($this->out_name); 293 | $c_header .= 294 | "#ifndef $attr_name 295 | #define $attr_name 296 | #endif 297 | 298 | const LV_ATTRIBUTE_MEM_ALIGN $attr_name uint8_t " . $this->out_name . "_map[] = {"; 299 | 300 | return $c_header; 301 | } 302 | 303 | function get_c_footer($cf) { 304 | $c_footer = 305 | "\n};\n 306 | const lv_img_dsc_t " . $this->out_name . " = { 307 | .header.always_zero = 0, 308 | .header.w = " . $this->w . ", 309 | .header.h = " . $this->h . ",\n"; 310 | 311 | if($cf == self::CF_TRUE_COLOR) $c_footer .= " .data_size = " . $this->w * $this->h . " * LV_COLOR_SIZE / 8,\n .header.cf = LV_IMG_CF_TRUE_COLOR,"; 312 | else if($cf == self::CF_TRUE_COLOR_ALPHA) $c_footer .= " .data_size = " . $this->w * $this->h . " * LV_IMG_PX_SIZE_ALPHA_BYTE,\n .header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,"; 313 | else if($cf == self::CF_TRUE_COLOR_CHROMA) $c_footer .= " .data_size = " . $this->w * $this->h . " * LV_COLOR_SIZE / 8,\n .header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED,"; 314 | else if($cf == self::CF_ALPHA_1_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_ALPHA_1BIT,"; 315 | else if($cf == self::CF_ALPHA_2_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_ALPHA_2BIT,"; 316 | else if($cf == self::CF_ALPHA_4_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_ALPHA_4BIT,"; 317 | else if($cf == self::CF_ALPHA_8_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_ALPHA_8BIT,"; 318 | else if($cf == self::CF_INDEXED_1_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_INDEXED_1BIT,"; 319 | else if($cf == self::CF_INDEXED_2_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_INDEXED_2BIT,"; 320 | else if($cf == self::CF_INDEXED_4_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_INDEXED_4BIT,"; 321 | else if($cf == self::CF_INDEXED_8_BIT) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_INDEXED_8BIT,"; 322 | else if($cf == self::CF_RAW) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_RAW,"; 323 | else if($cf == self::CF_RAW_ALPHA) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_RAW_ALPHA,"; 324 | else if($cf == self::CF_RAW_CHROMA) $c_footer .= " .data_size = " . count($this->d_out) . ",\n .header.cf = LV_IMG_CF_RAW_CHROMA_KEYED,"; 325 | 326 | $c_footer .= "\n .data = " . $this->out_name . "_map, 327 | };\n"; 328 | 329 | return $c_footer; 330 | } 331 | 332 | function download_c($name, $cf = -1, $content = ""){ 333 | global $offline; 334 | 335 | if(strlen($content) < 1) { 336 | $content = $this->format_to_c_array(); 337 | } 338 | 339 | if($cf < 0) $cf = $this->cf; 340 | 341 | $out = $this->get_c_header() . $content . "" . $this->get_c_footer($cf); 342 | $name = $name . ".c"; 343 | 344 | if($offline){ 345 | $name = $this->output_dir.$name; 346 | $file = fopen($name, "w"); 347 | fwrite($file, $out); 348 | fclose($file); 349 | } 350 | else{ 351 | header('Content-Type: application/text'); 352 | header('Content-disposition: attachment; filename='.$name); 353 | header('Content-Length: ' . strlen($out)); 354 | 355 | echo($out); 356 | 357 | } 358 | } 359 | 360 | 361 | function download_bin($name, $cf = -1, $content = 0){ 362 | global $offline; 363 | 364 | if($content == 0) { 365 | $content = $this->d_out; 366 | } 367 | 368 | if($cf < 0) $cf = $this->cf; 369 | $name .= ".bin"; 370 | 371 | $lv_cf = 4; /*Color format in LittlevGL*/ 372 | switch($cf) { 373 | case self::CF_TRUE_COLOR: 374 | $lv_cf = 4; break; 375 | case self::CF_TRUE_COLOR_ALPHA: 376 | $lv_cf = 5; break; 377 | case self::CF_TRUE_COLOR_CHROMA: 378 | $lv_cf = 6; break; 379 | case self::CF_INDEXED_1_BIT: 380 | $lv_cf = 7; break; 381 | case self::CF_INDEXED_2_BIT: 382 | $lv_cf = 8; break; 383 | case self::CF_INDEXED_4_BIT: 384 | $lv_cf = 9; break; 385 | case self::CF_INDEXED_8_BIT: 386 | $lv_cf = 10; break; 387 | case self::CF_ALPHA_1_BIT: 388 | $lv_cf = 11; break; 389 | case self::CF_ALPHA_2_BIT: 390 | $lv_cf = 12; break; 391 | case self::CF_ALPHA_4_BIT: 392 | $lv_cf = 13; break; 393 | case self::CF_ALPHA_8_BIT: 394 | $lv_cf = 14; break; 395 | } 396 | 397 | 398 | $header = $lv_cf + ($this->w << 10) + ($this->h << 21); 399 | $header_bin = pack("V", $header); 400 | 401 | $content = pack("C*", ...$content); 402 | 403 | if($offline){ 404 | $name = $this->output_dir.$name; 405 | $file = fopen($name, "w"); 406 | fwrite($file, $header_bin); 407 | fwrite($file, $content); 408 | fclose($file); 409 | } 410 | else{ 411 | $len = strlen($content) + 4; 412 | header('Content-Type: application/text'); 413 | header('Content-disposition: attachment; filename='.$name); 414 | header('Content-Length:' . $len); 415 | echo($header_bin[0]); 416 | echo($header_bin[1]); 417 | echo($header_bin[2]); 418 | echo($header_bin[3]); 419 | echo($content); 420 | 421 | 422 | } 423 | } 424 | 425 | private function conv_px($x, $y) { 426 | $c = imagecolorat($this->img, $x, $y); 427 | if($this->alpha){ 428 | $a = ($c & 0xff000000) >> 23; /*Alpha is 7 bit*/ 429 | if($a & 0x02) $a |= 0x01; /*Repeate the last bit: 0000000 -> 00000000; 1111110 -> 11111111*/ 430 | $a = 255 - $a; 431 | } else { 432 | $a = 0xff; 433 | } 434 | $r = ($c & 0x00ff0000) >> 16; 435 | $g = ($c & 0x0000ff00) >> 8; 436 | $b = ($c & 0x000000ff) >> 0; 437 | 438 | $this->dith_next($r, $g, $b, $x); 439 | 440 | if($this->cf == self::CF_TRUE_COLOR_332) { 441 | $c8 = ($this->r_act) | ($this->g_act >> 3) | ($this->b_act >> 6); //RGB332 442 | array_push($this->d_out, $c8); 443 | if($this->alpha) array_push($this->d_out, $a); 444 | } else if($this->cf == self::CF_TRUE_COLOR_565) { 445 | $c16 = (($this->r_act) << 8) | (($this->g_act) << 3) | (($this->b_act) >> 3); //RGR565 446 | array_push($this->d_out, $c16 & 0xFF); 447 | array_push($this->d_out, ($c16 >> 8) & 0xFF); 448 | if($this->alpha) array_push($this->d_out, $a); 449 | } else if($this->cf == self::CF_TRUE_COLOR_565_SWAP) { 450 | $c16 = (($this->r_act) << 8) | (($this->g_act) << 3) | (($this->b_act) >> 3); //RGR565 451 | array_push($this->d_out, ($c16 >> 8) & 0xFF); 452 | array_push($this->d_out, $c16 & 0xFF); 453 | if($this->alpha) array_push($this->d_out, $a); 454 | } else if($this->cf == self::CF_TRUE_COLOR_888) { 455 | array_push($this->d_out, $this->b_act); 456 | array_push($this->d_out, $this->g_act); 457 | array_push($this->d_out, $this->r_act); 458 | array_push($this->d_out, $a); 459 | } else if($this->cf == self::CF_ALPHA_1_BIT) { 460 | $w = $this->w >> 3; 461 | if($this->w & 0x07) $w++; 462 | $p = $w * $y + ($x >> 3); 463 | if(!isset($this->d_out[$p])) $this->d_out[$p] = 0; /*Clear the bits first*/ 464 | if($a > 0x80) { 465 | $this->d_out[$p] |= 1 << (7 - ($x & 0x7)); 466 | } 467 | } 468 | else if($this->cf == self::CF_ALPHA_2_BIT) { 469 | $w = $this->w >> 2; 470 | if($this->w & 0x03) $w++; 471 | 472 | $p = $w * $y + ($x >> 2); 473 | if(!isset($this->d_out[$p])) $this->d_out[$p] = 0; /*Clear the bits first*/ 474 | $this->d_out[$p] |= ($a >> 6) << (6 - (($x & 0x3) * 2)); 475 | } 476 | else if($this->cf == self::CF_ALPHA_4_BIT) { 477 | $w = $this->w >> 1; 478 | if($this->w & 0x01) $w++; 479 | 480 | $p = $w * $y + ($x >> 1); 481 | if(!isset($this->d_out[$p])) $this->d_out[$p] = 0; /*Clear the bits first*/ 482 | $this->d_out[$p] |= ($a >> 4) << (4 - (($x & 0x1) * 4)); 483 | } 484 | else if($this->cf == self::CF_ALPHA_8_BIT) { 485 | $p = $this->w * $y + $x; 486 | $this->d_out[$p] = $a; 487 | } 488 | else if($this->cf == self::CF_INDEXED_1_BIT) { 489 | $w = $this->w >> 3; 490 | if($this->w & 0x07) $w++; 491 | 492 | $p = $w * $y + ($x >> 3) + 8; /* +8 for the palette*/ 493 | if(!isset($this->d_out[$p])) $this->d_out[$p] = 0; /*Clear the bits first*/ 494 | $this->d_out[$p] |= ($c & 0x1) << (7 - ($x & 0x7)); 495 | } 496 | else if($this->cf == self::CF_INDEXED_2_BIT) { 497 | $w = $this->w >> 2; 498 | if($this->w & 0x03) $w++; 499 | 500 | $p = $w * $y + ($x >> 2) + 16; /* +16 for the palette*/ 501 | if(!isset($this->d_out[$p])) $this->d_out[$p] = 0; /*Clear the bits first*/ 502 | $this->d_out[$p] |= ($c & 0x3) << (6 - (($x & 0x3) * 2)); 503 | } 504 | else if($this->cf == self::CF_INDEXED_4_BIT) { 505 | $w = $this->w >> 1; 506 | if($this->w & 0x01) $w++; 507 | 508 | $p = $w * $y + ($x >> 1) + 64; /* +64 for the palette*/ 509 | if(!isset($this->d_out[$p])) $this->d_out[$p] = 0; /*Clear the bits first*/ 510 | $this->d_out[$p] |= ($c & 0xF) << (4 - (($x & 0x1) * 4)); 511 | } 512 | else if($this->cf == self::CF_INDEXED_8_BIT) { 513 | $p = $this->w * $y + $x + 1024; /* +1024 for the palette*/ 514 | $this->d_out[$p] = $c & 0xFF; 515 | } 516 | } 517 | 518 | private function dith_reset() { 519 | if($this->dith){ 520 | $this->r_nerr = 0; 521 | $this->g_nerr = 0; 522 | $this->b_nerr = 0; 523 | } 524 | } 525 | 526 | private function dith_next($r, $g, $b, $x) { 527 | 528 | if($this->dith){ 529 | $this->r_act = $r + $this->r_nerr + $this->r_earr[$x+1]; 530 | $this->r_earr[$x+1] = 0; 531 | 532 | $this->g_act = $g + $this->g_nerr + $this->g_earr[$x+1]; 533 | $this->g_earr[$x+1] = 0; 534 | 535 | $this->b_act = $b + $this->b_nerr + $this->b_earr[$x+1]; 536 | $this->b_earr[$x+1] = 0; 537 | 538 | if($this->cf == self::CF_TRUE_COLOR_332) { 539 | $this->r_act = $this->classify_pixel($this->r_act, 3); 540 | $this->g_act = $this->classify_pixel($this->g_act, 3); 541 | $this->b_act = $this->classify_pixel($this->b_act, 2); 542 | 543 | if($this->r_act > 0xE0) $this->r_act = 0xE0; 544 | if($this->g_act > 0xE0) $this->g_act = 0xE0; 545 | if($this->b_act > 0xC0) $this->b_act = 0xC0; 546 | 547 | } else if($this->cf == self::CF_TRUE_COLOR_565 || $this->cf == self::CF_TRUE_COLOR_565_SWAP) { 548 | $this->r_act = $this->classify_pixel($this->r_act, 5); 549 | $this->g_act = $this->classify_pixel($this->g_act, 6); 550 | $this->b_act = $this->classify_pixel($this->b_act, 5); 551 | 552 | if($this->r_act > 0xF8) $this->r_act = 0xF8; 553 | if($this->g_act > 0xFC) $this->g_act = 0xFC; 554 | if($this->b_act > 0xF8) $this->b_act = 0xF8; 555 | 556 | } else if($this->cf == self::CF_TRUE_COLOR_888) { 557 | $this->r_act = $this->classify_pixel($this->r_act, 8); 558 | $this->g_act = $this->classify_pixel($this->g_act, 8); 559 | $this->b_act = $this->classify_pixel($this->b_act, 8); 560 | 561 | if($this->r_act > 0xFF) $this->r_act = 0xFF; 562 | if($this->g_act > 0xFF) $this->g_act = 0xFF; 563 | if($this->b_act > 0xFF) $this->b_act = 0xFF; 564 | } 565 | 566 | $this->r_err = $r - $this->r_act; 567 | $this->g_err = $g - $this->g_act; 568 | $this->b_err = $b - $this->b_act; 569 | 570 | $this->r_nerr = round((7 * $this->r_err) / 16); 571 | $this->g_nerr = round((7 * $this->g_err) / 16); 572 | $this->b_nerr = round((7 * $this->b_err) / 16); 573 | 574 | $this->r_earr[$x] += round((3 * $this->r_err) / 16); 575 | $this->g_earr[$x] += round((3 * $this->g_err) / 16); 576 | $this->b_earr[$x] += round((3 * $this->b_err) / 16); 577 | 578 | $this->r_earr[$x+1] += round((5 * $this->r_err) / 16); 579 | $this->g_earr[$x+1] += round((5 * $this->g_err) / 16); 580 | $this->b_earr[$x+1] += round((5 * $this->b_err) / 16); 581 | 582 | $this->r_earr[$x+2] += round($this->r_err / 16); 583 | $this->g_earr[$x+2] += round($this->g_err / 16); 584 | $this->b_earr[$x+2] += round($this->b_err / 16); 585 | } 586 | else{ 587 | if($this->cf == self::CF_TRUE_COLOR_332) { 588 | $this->r_act = $this->classify_pixel($r, 3); 589 | $this->g_act = $this->classify_pixel($g, 3); 590 | $this->b_act = $this->classify_pixel($b, 2); 591 | 592 | if($this->r_act > 0xE0) $this->r_act = 0xE0; 593 | if($this->g_act > 0xE0) $this->g_act = 0xE0; 594 | if($this->b_act > 0xC0) $this->b_act = 0xC0; 595 | 596 | } else if($this->cf == self::CF_TRUE_COLOR_565 || $this->cf == self::CF_TRUE_COLOR_565_SWAP) { 597 | $this->r_act = $this->classify_pixel($r, 5); 598 | $this->g_act = $this->classify_pixel($g, 6); 599 | $this->b_act = $this->classify_pixel($b, 5); 600 | 601 | if($this->r_act > 0xF8) $this->r_act = 0xF8; 602 | if($this->g_act > 0xFC) $this->g_act = 0xFC; 603 | if($this->b_act > 0xF8) $this->b_act = 0xF8; 604 | 605 | } else if($this->cf == self::CF_TRUE_COLOR_888) { 606 | $this->r_act = $this->classify_pixel($r, 8); 607 | $this->g_act = $this->classify_pixel($g, 8); 608 | $this->b_act = $this->classify_pixel($b, 8); 609 | 610 | if($this->r_act > 0xFF) $this->r_act = 0xFF; 611 | if($this->g_act > 0xFF) $this->g_act = 0xFF; 612 | if($this->b_act > 0xFF) $this->b_act = 0xFF; 613 | } 614 | } 615 | } 616 | 617 | private function classify_pixel($value, $bits){ 618 | $tmp = 1 << (8 - $bits); 619 | $val = round($value / $tmp, 0, PHP_ROUND_HALF_DOWN) * $tmp; 620 | if($val < 0) $val = 0; 621 | return $val; 622 | } 623 | } 624 | 625 | $offline = 0; 626 | if (!isset($_SERVER["HTTP_HOST"])) { 627 | parse_str($argv[1], $_POST); 628 | $offline = 1; 629 | } 630 | 631 | 632 | if($offline == 0){ 633 | /*The scripts runs ONLINE (likely on littelvgl.com)*/ 634 | header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); 635 | header("Cache-Control: post-check=0, pre-check=0", false); 636 | header("Pragma: no-cache"); 637 | 638 | $img_file = $_FILES["img_file"]["tmp_name"]; 639 | $img_file_name = $_FILES["img_file"]["name"]; 640 | $output_name = $_POST["name"]; 641 | $cf = $_POST["cf"]; 642 | $format = $_POST["format"]; 643 | $dith = $_POST["dith"]; 644 | } 645 | else{ 646 | /*The scripts runs OFFLINE (likely in command)*/ 647 | if(isset($_POST["name"])){ 648 | $output_name = $_POST["name"]; 649 | echo"Convert:".$output_name; 650 | } 651 | else{ 652 | echo("Mising Name\n"); 653 | exit(0); 654 | } 655 | 656 | if(isset($_POST["img"])){ 657 | $img_file = $_POST["img"]; 658 | $img_file_name = $_POST["img"]; 659 | echo "\nimg=".$img_file; 660 | } 661 | else{ 662 | echo("Mising image file\n"); 663 | exit(0); 664 | } 665 | 666 | if(isset($_POST["format"])){ 667 | $format = $_POST["format"]; 668 | } 669 | else{ 670 | $format = "c_array"; 671 | } 672 | 673 | if(isset($_POST["dith"])){ 674 | $dith = $_POST["dith"]; 675 | } 676 | else { 677 | $dith = 0; 678 | } 679 | if(isset($_POST["outdir"])) 680 | { 681 | $outdir = $_POST["outdir"]; 682 | }else 683 | { 684 | $outdir = "./"; 685 | echo "\noutdir=".$outdir; 686 | } 687 | if(isset($_POST["cf"])){ 688 | $cf = $_POST["cf"]; 689 | } 690 | else { 691 | $cf = "true_color"; 692 | } 693 | } 694 | 695 | $conv = new Converter($img_file, $img_file_name,$outdir, $output_name, $dith); 696 | 697 | if(!strcmp($format, "c_array")) { 698 | if(!strcmp($cf, "true_color") || !strcmp($cf, "true_color_alpha") || !strcmp($cf, "true_color_chroma")) { 699 | $alpha = 0; 700 | if(!strcmp($cf, "true_color_alpha")) $alpha = 1; 701 | 702 | $conv->convert($conv::CF_TRUE_COLOR_332, $alpha); 703 | $c_332 = $conv->format_to_c_array(); 704 | 705 | $conv->convert($conv::CF_TRUE_COLOR_565, $alpha); 706 | $c_565 = $conv->format_to_c_array(); 707 | 708 | $conv->convert($conv::CF_TRUE_COLOR_565_SWAP, $alpha); 709 | $c_565_swap = $conv->format_to_c_array(); 710 | 711 | $conv->convert($conv::CF_TRUE_COLOR_888, $alpha); 712 | $c_888 = $conv->format_to_c_array(); 713 | 714 | $c_res = $c_332 . $c_565 . $c_565_swap . $c_888; 715 | 716 | if(!strcmp($cf, "true_color")) $conv->download_c($conv->out_name, $conv::CF_TRUE_COLOR, $c_res); 717 | if(!strcmp($cf, "true_color_alpha")) $conv->download_c($conv->out_name, $conv::CF_TRUE_COLOR_ALPHA, $c_res); 718 | if(!strcmp($cf, "true_color_chroma")) $conv->download_c($conv->out_name, $conv::CF_TRUE_COLOR_CHROMA, $c_res); 719 | } 720 | else if(!strcmp($cf, "alpha_1")) { 721 | $conv->convert($conv::CF_ALPHA_1_BIT, 1); 722 | $conv->download_c($conv->out_name); 723 | } 724 | else if(!strcmp($cf, "alpha_2")) { 725 | $conv->convert($conv::CF_ALPHA_2_BIT, 1); 726 | $conv->download_c($conv->out_name); 727 | } 728 | else if(!strcmp($cf, "alpha_4")) { 729 | $conv->convert($conv::CF_ALPHA_4_BIT, 1); 730 | $conv->download_c($conv->out_name); 731 | } 732 | else if(!strcmp($cf, "alpha_8")) { 733 | $conv->convert($conv::CF_ALPHA_8_BIT, 1); 734 | $conv->download_c($conv->out_name); 735 | } 736 | else if(!strcmp($cf, "indexed_1")) { 737 | $conv->convert($conv::CF_INDEXED_1_BIT); 738 | $conv->download_c($conv->out_name); 739 | } 740 | else if(!strcmp($cf, "indexed_2")) { 741 | $conv->convert($conv::CF_INDEXED_2_BIT); 742 | $conv->download_c($conv->out_name); 743 | } 744 | else if(!strcmp($cf, "indexed_4")) { 745 | $conv->convert($conv::CF_INDEXED_4_BIT); 746 | $conv->download_c($conv->out_name); 747 | } 748 | else if(!strcmp($cf, "indexed_8")) { 749 | $conv->convert($conv::CF_INDEXED_8_BIT); 750 | $conv->download_c($conv->out_name); 751 | } 752 | else if(!strcmp($cf, "raw")) { 753 | $conv->convert($conv::CF_RAW); 754 | $conv->download_c($conv->out_name); 755 | } 756 | else if(!strcmp($cf, "raw_alpha")) { 757 | $conv->convert($conv::CF_RAW_ALPHA, 1); 758 | $conv->download_c($conv->out_name); 759 | } 760 | else if(!strcmp($cf, "raw_chroma")) { 761 | $conv->convert($conv::CF_RAW_CHROMA); 762 | $conv->download_c($conv->out_name); 763 | } 764 | } 765 | /*Binary download*/ 766 | else { 767 | if(!strcmp($cf, "true_color") || !strcmp($cf, "true_color_alpha") || !strcmp($cf, "true_color_chroma")) { 768 | $alpha = 0; 769 | if(!strcmp($cf, "true_color_alpha")) $alpha = 1; 770 | 771 | if (!strcmp($format, "bin_332")) $conv->convert($conv::CF_TRUE_COLOR_332, $alpha); 772 | else if (!strcmp($format, "bin_565")) $conv->convert($conv::CF_TRUE_COLOR_565, $alpha); 773 | else if (!strcmp($format, "bin_565_swap")) $conv->convert($conv::CF_TRUE_COLOR_565_SWAP, $alpha); 774 | else if (!strcmp($format, "bin_888")) $conv->convert($conv::CF_TRUE_COLOR_888, $alpha); 775 | else { 776 | echo("Unknown output file format: $format"); 777 | exit(1); 778 | } 779 | if(!strcmp($cf, "true_color")) $conv->download_bin($conv->out_name, $conv::CF_TRUE_COLOR); 780 | if(!strcmp($cf, "true_color_alpha")) $conv->download_bin($conv->out_name, $conv::CF_TRUE_COLOR_ALPHA); 781 | if(!strcmp($cf, "true_color_chroma")) $conv->download_bin($conv->out_name, $conv::CF_TRUE_COLOR_CHROMA); 782 | } 783 | else if(!strcmp($cf, "alpha_1")) { 784 | $conv->convert($conv::CF_ALPHA_1_BIT, 1); 785 | $conv->download_bin($conv->out_name); 786 | } 787 | else if(!strcmp($cf, "alpha_2")) { 788 | $conv->convert($conv::CF_ALPHA_2_BIT, 1); 789 | $conv->download_bin($conv->out_name); 790 | } 791 | else if(!strcmp($cf, "alpha_4")) { 792 | $conv->convert($conv::CF_ALPHA_4_BIT, 1); 793 | $conv->download_bin($conv->out_name); 794 | } 795 | else if(!strcmp($cf, "alpha_8")) { 796 | $conv->convert($conv::CF_ALPHA_8_BIT, 1); 797 | $conv->download_bin($conv->out_name); 798 | } 799 | else if(!strcmp($cf, "indexed_1")) { 800 | $conv->convert($conv::CF_INDEXED_1_BIT); 801 | $conv->download_bin($conv->out_name); 802 | } 803 | else if(!strcmp($cf, "indexed_2")) { 804 | $conv->convert($conv::CF_INDEXED_2_BIT); 805 | $conv->download_bin($conv->out_name); 806 | } 807 | else if(!strcmp($cf, "indexed_4")) { 808 | $conv->convert($conv::CF_INDEXED_4_BIT); 809 | $conv->download_bin($conv->out_name); 810 | } 811 | else if(!strcmp($cf, "indexed_8")) { 812 | $conv->convert($conv::CF_INDEXED_8_BIT); 813 | $conv->download_bin($conv->out_name); 814 | } 815 | } 816 | 817 | 818 | 819 | 820 | /* 821 | $c_array .= "#include 822 | #include \"lv_conf.h\" 823 | #include \"lvgl/lv_draw/lv_draw.h\""; */ 824 | 825 | 826 | //download("test", $c_565); 827 | 828 | ?> 829 | --------------------------------------------------------------------------------