From 48f1934387b7a0fb1481182374285a161d96896f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 9 Feb 2023 17:47:33 +0000 Subject: [PATCH] Updated favicon gen to use png-based ICO From testing, worked on Firefox, Chrome, Gnome Web --- .gitignore | 1 + app/Uploads/FaviconHandler.php | 28 +++++++--------------------- public/favicon.ico | Bin 3134 -> 10933 bytes 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 0a858681c..90b80e7b8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ yarn-error.log /public/js /public/bower /public/build/ +/public/favicon.ico /storage/images _ide_helper.php /storage/debugbar diff --git a/app/Uploads/FaviconHandler.php b/app/Uploads/FaviconHandler.php index 39f8b12ca..2e756c587 100644 --- a/app/Uploads/FaviconHandler.php +++ b/app/Uploads/FaviconHandler.php @@ -25,11 +25,9 @@ class FaviconHandler $imageData = file_get_contents($file->getRealPath()); $image = $this->imageTool->make($imageData); $image->resize(32, 32); - $bmpData = $image->encode('bmp'); - $icoData = $this->bmpToIco($bmpData, 32, 32); + $bmpData = $image->encode('png'); + $icoData = $this->pngToIco($bmpData, 32, 32); -// file_put_contents(public_path('icon.bmp'), $bmpData); -// file_put_contents(public_path('icon-test.png'), $image->encode('png')); file_put_contents($targetPath, $icoData); } @@ -48,18 +46,12 @@ class FaviconHandler } /** - * Convert BMP image data to ICO file format. + * Convert PNG image data to ICO file format. * Built following the file format info from Wikipedia: * https://en.wikipedia.org/wiki/ICO_(file_format) */ - protected function bmpToIco(string $bmpData, int $width, int $height): string + protected function pngToIco(string $bmpData, int $width, int $height): string { - // Trim off the header of the bitmap file - $rawBmpData = substr($bmpData, 14); - // Double the height in the "BITMAPINFOHEADER" since, when in an ICO file, half - // of the image data is expected to be a mask. - $rawBmpData[8] = hex2bin(dechex($height * 2)); - // ICO header $header = pack('v', 0x00); // Reserved. Must always be 0 $header .= pack('v', 0x01); // Specifies ico image @@ -71,23 +63,17 @@ class FaviconHandler $entry .= "\0"; // Color palette, typically 0 $entry .= "\0"; // Reserved - // AND mask -// $pxCount = $width * $height; -// $pxMask = hex2bin('00000000'); -// $mask = str_repeat($pxMask, $pxCount); - $mask = ''; - // Color planes, Appears to remain 1 for bmp image data $entry .= pack('v', 0x01); // Bits per pixel, can range from 1 to 32. From testing conversion // via intervention from png typically provides this as 24. - $entry .= pack('v', 0x18); + $entry .= pack('v', 0x00); // Size of the image data in bytes - $entry .= pack('V', strlen($rawBmpData) + strlen($mask)); + $entry .= pack('V', strlen($bmpData)); // Offset of the bmp data from file start $entry .= pack('V', strlen($header) + strlen($entry) + 4); // Join & return the combined parts of the ICO image data - return $header . $entry . $rawBmpData . $mask; + return $header . $entry . $bmpData; } } diff --git a/public/favicon.ico b/public/favicon.ico index e114831177f415bd8dfb65b3f6f9d5988796a7b5..41655ccba55f8dd5f250471eb2e8928b21a85992 100644 GIT binary patch literal 10933 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 XHrNJO5L3!r00000NkvXXu0mjfR=v%1 literal 3134 zcmd5;X-pht7+(JiODmVqhEjgGJG=Sjo%eg*?|t5D zM4}t;U9(1n|C>b_H;P1QB9SNqKZrz|@MGoi51#$+KC#PFxWYkKY$k@q@}3WXk+5%~ zTO!TBMP0i!U{w%v*KdWznTa~24Z{Z>q_UI9MdzlDw`GO{_UmzkoX}^wsH%E}M;R-9p@YJ)C=-z**b{SDrtvivEJ=1lDJ zVuJ$kNHk#XEtKuMjeyX(t0y|M7^mKN>N`3ob@cE{UgLSEqII}r17}67X?UM;YRJK^ z78LgBOf0_f;n|Ii+XFVG^+LIZiGK4Bc1$=;$l$LPq4ggn5RZvsNUMLy5* zZnwHi@ynAuvaDp~?oCEU?8?x3>8oP51wq}e+@C`^OV%ICd?0hSQXm!QuAC^~nQu{|^B z)R{W=(79;@0SuVW6)+B*^HVUR{B@&S-RaSEE6SfH3iwwYdEGxTWS2G0rm-YN*Yr`) zZ6sDgL6@d(8z{039g!7hBsPNQ=Fhj=l#6t%DVCmMGIXD-Eq*F-~2) z4AY4a98R3cjmCno;x+UuD>o;Qairf~_Kja~jx>*ytmlN{vFa_d{kJCobJI*6KL(Lk zZQrBfh)}lw4om+*#y+M!{vjnvaLBj}(dn?f@E)QweBc3i3V&7ATR7w-MAoA{i_ByL z+Omt1tR#=*Mfcib?sYxuoR__xm0aleV?-OIj8|Y=$ph-XKlygU;~5hn&Mr@w$F>)_Ub;kG>a}iqc0pVKUpPEOPr$HG&%sxpgOY z2JC9fKnZ*#I&7b5{{fXXetI`T&uwJ8kgDo6-^3-S{5Z^UaxpmJ5I7EVQjsvxCW(?q>)#1jM{Jj>WJPy#2#NkiZfVI1!=JklP;*b7G@lD7%YXzK$TGlj2!2qxd}=Am zo^Xx*?a`f6Ry?~PvQUU{Pxk%9IMlimAM*j_B1n-40zVREsGL=@f;%n$lrnae_Sgq} z1qsovwpNrr;!^(QG4zifdV$wL2BPkefg!&wIu#yo-_2%k*Iqg=;ViGYxJ9zM=1u>k z+)mZXi|IeU*g0Y&di-VdI2;mkqSmUX0krJlPEWT5LA9TF9i4gb!OTsNn zSj!66TF#dTY@^zS?ckZW$CuS!mtEw`XsPfj}@pSOZ>ImwSpNs6KQGng><