ウェブサイトの最適化を追求して、最適化されたファイルのサイズを犠牲にすることなく、リクエストの数を減らしたいと思いました。
目標は、さまざまな最適化設定を使用して、さまざまな形式の画像を1つのファイルに転送することです。
ツールとして、データuriとgzip cssファイルを選択しました。 ただし、データURIを使用するIEは非常にうまく機能しません。 しかし、それらにはmhtmlが含まれています。 既存の実装は私の要件を満たしていませんでした、なぜなら 1つのファイルを2回転送する必要がありました。1つはIEの場合はmhtmlで、もう1つは他の全員の場合はデータURIで転送します。 解決策を探して、私は
bolkの記事に出会いました 。この
記事では、jpeg形式の解決策と、gifおよびpngの理論計算について説明しました。 ほぼ3週間の喫煙マナの後、私はgifとpngのソリューションを実装し、3つの形式すべてのプロセスを自動化することができました。
BASE64
画像はbase64で送信されるため、このエンコードに関連するいくつかのポイントを強調する価値があります。
- 最初:base64は[A-Za-z0-9 + /]のみを理解します。
ブラウザまたはルビーによって解読されると、他のシンボルはすべてドロップされます。
Linux上のコンソールbase64はそれらをドロップせず、エラーを表示します。 - 2番目:base64は、3つのソースバイト(この場合はASCII文字)ごとに4つのASCII文字に変換します。
したがって、デコードされたCSS行は、エンコードされたファイル内で正しく動作するように、たとえばゼロでバランスを取る必要があります。
考慮すべき情報:英語版ウィキペディアのBase64Jpeg
JPEGのセクション形式: [ヘッダー] [データ]C jpegは単純であり、
bolkによって記述されてい
ます 。
HEXエディターを開きます。
FF D8 -IE用のJPEGヘッダー
FF E0 -APP0セクションのアナウンス。画像データまですべてが隠されていますが、
“ ; Background-color:url(data:image / jpeg; base64、 ”-これは他のブラウザで見られます。
IEがこの行をデコードすると、何にも影響しないゴミが判明します
FF D8-他のブラウザーのJPEGの始まり
「 画像データ 」-すべてのブラウザでこの場所が既に表示されています
ポイントは、CSSの行が次のようになることです。
IEで次のように復号化されます。
他の人は彼女を次のように見ました:
base64の特性により、文字列が正しく暗号化/復号化されるように、一定数の文字を追加で送信する必要があります。 CSSの前後に挿入されます。 数は経験的に計算され選択されました:
/ 9j / 4AA0; background-image:url(データ:image / jpeg; base64; 00、
このプロセスを自動化する私のスクリプト:
#!/usr/bin/ruby
require 'base64'
# :
a= "/9j/4AA0;background-image:url(data:image/jpeg;base64;00,"
#
b=Base64.encode64( File .open( "#{ARGV[0]}" , 'r' ){|f| f.read})
#
File .open( 'temp' , 'w' ){|i| i.write( "#{Base64.decode64(a)}#{Base64.decode64(b)}" )}
# base64
#cat test | base64 | tr -d "\n" > jpeg64.txt
File .open( 'temp2' , 'w' ){|o| o.write(Base64.encode64( File .open( 'temp' , 'r' ){|f| f.read}))}
# File .delete( 'temp' )
c= File .open( 'temp2' , 'r' ){|f| f.read}.gsub(/\/9j\/4AA0backgroundimageurldataimage\/jpegbase6400/, "/9j/4AA0;background-image:url(data:image/jpeg;base64;00," ).gsub(/\n/, "" )
File .open( 'out_jpeg64' , 'w' ){|s| s.write( "#{c}\);" )}
File .delete( 'temp2' )
# css
# cat output64 | tr -d "\n"
# mhtml!!!
* This source code was highlighted with Source Code Highlighter .
考慮すべき情報:ウィキペディアのJPEGGIF
この形式では、物事はそれほど良くありません。
- まず、セクションのサイズは1バイトを設定します。 ffセクションの最大長または255文字。
- 第二に、コメントセクションのサイズは何らかの理由で240バイトのサイズに制限されており、CSS文字列は30文字を占有し、base64の「バランスをとる」にはさらにいくつかが必要です。
- 3番目:「ゴミ」を詰め込めるブロックは2つだけです-アプリケーション拡張機能とコメント拡張機能であり、一般色テーブルの前に移動できません。 また、カラーテーブルは最大256 * 3 = 768バイトを占有できます。
できること:- 色数が〜70を超えない場合は、一般色テーブルに触れないでください
- 一般カラーテーブルの内容をローカルカラーテーブルに移動します
2番目のオプションを選択しました。これにより、base64文字列が読みやすくなり、アニメーション化されていないgifを変換できます。
多かれ少なかれGIFセクションの標準バージョン: [ヘッダー] [サイズ] [データ] [00]多くのGIFには正しいフィールド順序がありません。 たとえば、
「convert jpeg gif」を作成
すると 、結果のファイルはスクリプトによって適切に処理されません。 GIMPを使用します。
最初の13バイトは削減できないinfaです。 さらに、11バイトは複雑で、グローバルカラーテーブルを記述します。 00に変更します
カラーテーブルを切り取ります (14バイトからワイヤまで-21 FE xx、xxはコメントサイズ)
cssと最初の13バイトでコメントします。
カラーテーブルを切り取ります (14バイトからワイヤまで-21 FE xx、xxはコメントサイズ)
1文字の「内部コメント」
カラーテーブルを切り取ります (14バイトからワイヤまで-21 FE xx、xxはコメントサイズ)
2c 00 00 00 00-イメージ記述子。 10バイト目は複雑で、ローカルカラーテーブルを記述しています。 11番目のバイトから転送されるものすべて(ローカルカラーテーブルの宣言、並べ替えられた\いいえ、ローカルカラーテーブルのサイズ)、さらにフォーマット仕様を転送します。
カラーテーブルを挿入する
続きの画像記述子
ポイントは、CSSの行が次のようになることです。
すべての編集の前にファイルが次のように見えたという事実にもかかわらず:
プロセスを自動化するスクリプト:
#!/usr/bin/ruby
# CONVERT INCORRECTLY TRANSFER DATA. USE GIMP INSTEAD
# USE: ./GIF_SCRIPT.RB [GIF_FILE]
require 'base64'
# OPEN GIF FILE IN HEX
orig= File .open( "#{ARGV[0]}" , 'r' ){|f| f.read.unpack( "H*" )}.to_s
# FUTURE HEADER
header=orig[0..25]
# GREP GENERAL COLOR TABLE
# [26..1565]/6 = 256 BYTE (MAX SIZE OF COLOR TABLE)
color_table=orig[26..1565][/(.*)21fe/,1]
if color_table. class == NilClass
color_table=orig[26..1575][/(.*?)2c0000/,1]
end
# FOR DEBUGING
#puts color_table
#puts color_table.length
puts "COLORS IN PALLETE: #{color_table.length/6}"
# GIF IMAGE DATA
data=orig[/2c0000.*/]
# SAVE 11 BYTE 'S INFO AND ADOPT IT FOR LOCAL COLOR TABLE
eleven=header[20..21].to_i(16).to_s(2)
local_mix="10#{eleven.split("")[4].to_s}00#{eleven.split("")[5..7].to_s}".to_i(2).to_s(16)
# 11 BYTE TO ZERO
header[20..21]="00"
# DECLARE LOCAL COLOR TABLE
data[18..19]=local_mix
# MAGIC COMMENT
comment=Base64.decode64(";background-image:url(data:image/gif;base64;pzd,").unpack("H*").to_s
# WRITE ALL IN ONE FILE
var=header+"21fe313030"+comment+header+"21fe013000"+data[0..19]+color_table+data[20..-1]
File.open(' out .gif ',' w '){|f| f.write(var.to_a.pack("H*"))}
# ENCODE FILE TO BASE64 WITH "\n" REMOVING
File.open(' temp ',' w '){|o| o.write(Base64.encode64(File.open(' out .gif ',' r '){|f| f.read}).gsub(/\n/,""))}
# MAKE STRING CSS READEABLE
c=File.open(' temp ',' r '){|f| f.read}.gsub(/backgroundimageurldataimage\/gifbase64pzd/,";background-image:url(data:image/gif;base64;pzd,").gsub(/\n/,"")
File.delete(' temp ')
# JUST PASTE TEXT FROM THIS FILE TO CSS
File.open(' out_gif64 ',' w'){|s| s.write( "#{c}\);" )}
* This source code was highlighted with Source Code Highlighter .
アニメーションgif用のスクリプトはありません。 アニメーション化されたCSSスプライトを使用する方が良いと思います。
理論計算:- フレームごとに、ローカルカラーテーブルを実行しても意味がありません。 これによりサイズが大きくなります。
- 64色のアニメーションGIFは、一般的なカラーテーブルをコメントに含めることで処理できます。
- アプリケーション拡張機能とコメント拡張機能は連続して使用できるため、x2のサイズが大きくなります。
- インターネットでは、アプリケーション拡張機能で、実際には2ブロックがサイズを指定するという情報に出会いました。
21 ff SizeSize 'NETSCAPE2.0' SizeSize 01 0000。SizeSizeはサイズが2バイト、無限ループが01バイトです。
- これは、理論的には、より多くの色を「スコアリング」する機会を提供できます。 しかし、まだ256未満(約230)です。
考慮すべき情報:GIFカラーテーブルGIF仕様PNG
gifの後は静かな天国です。 セクションのサイズは無制限で、4バイトのヘッダーがあり、検索に非常に便利です。 比較のために、gifの場合はほぼ1日中頭を悩ませてスクリプトを非難しましたが、pngの場合は1時間ですべてを行いました。
PNGのセクションの形式: [サイズ(4バイト)] [データ] [CRC(4バイト)]そして、いくつかの落とし穴がありました。 CRCはIEにとって非常に重要です。CRCが壊れている場合、IEは画像を表示しません。 残りのすべてに、彼は並行して深くbeatられたりされません。
多くのPNGの構造は正しくありません。いずれの場合も、
optipngを実行するまでスクリプトは機能しません。 画像の最適化に加えて、このプログラムはフィールドを正しい順序に配置します。 また、PhotoshopがsRGBフィールドを時々カットし、保存されたpngが常に処理されるわけではないことに気付きました。
CSSはtEXtセクションで非表示になります
PNGはoptipngですぐに最適化する必要があり、tExtがIHDRのすぐ後ろになるように切り刻む必要があります。
Keyword00はtEXtセクションで渡される必要があり、その長さはセクションの全長で考慮されます。 この「コメント」があります
一般注文:Ihdr
tExt
その他のサービス情報
データ
それは:
次のようになりました:
スクリプトはよくコメントされており、仕様から多くを学ぶことができます。
IE6は透明度を認識しません。必要な背景色を設定することでbKGDで修正できる場合があります。
次に、
`optipng -fix FILE`を実行して、tEXtセクションのCRCを修正します
プロセスを自動化するスクリプト:
#!/usr/bin/ruby
#
#!!!! RUN optipng FIRST !!!!
#
# USE: ./PNG_SCRIPT.RB [PNG_FILE]
require 'base64'
# OPEN GIF FILE IN HEX
orig= File .open( "#{ARGV[0]}" , 'r' ){|f| f.read.unpack( "H*" )}.to_s
#ihdr=orig[0..65]
ihdr=orig[/(.*?)73524742/,1][0..-9]
#sRGB - 73 52 47 42 & -4b (8 characters)
#srgb_phys=orig[66..171]
#check for tEXt existence
if orig[/74455874/]. class == NilClass
srgb_phys=orig[/(.{8}73524742.*?)49444154/,1][0..-9]
else
srgb_phys=orig[/(.{8}73524742.*?)74455874/,1][0..-9]
end
#srgb_phys=orig[/(.{8}73524742.*?)74455874/,1][0..-9]
#tEXt - 74 45 58 74 –њ–Њ—–ї–µ–і–љ–Є–µ 8 –љ–∞–і–Њ –Љ–µ–љ——— –љ–∞ CRC 00000000
#text=orig[172..245]
#text=orig[/(.{8}74455874.*?)49444154/,1][0..-9]
#IDAT - 49444154
#data=orig[246..-1]
data=orig[/.{8}49444154.*/]
#MAGIC COMMENT
comment=Base64.decode64( ";background-image:url(data:image/png;base64;pzd," ).unpack( "H*" ).to_s
###### OUTER PNG
# "00000059" + "74455874" + "436f6d6d656e7400"
# tEXt_length + 'tEXt' + 'Comment.'
# "3030" - two zero for base64 balance
###### INNER PNG
# "00000008" + "74455874" + "436f6d6d656e7400" + "00000000"
# min_tEXt_length + 'tEXt' + 'Comment.' + blank CRC
#
# CRC field one for two PNG 's
# IE can' t live without it, but others feel indifferently
var =ihdr+ "00000059" + "74455874" + "436f6d6d656e7400" + "3030" +comment+ihdr+ "00000008" + "74455874" + "436f6d6d656e7400" + "00000000" +srgb_phys+data
File .open( 'out.png' , 'w' ){|f| f.write( var .to_a.pack( "H*" ))}
# CRC FIX
puts "optipng -fix started..."
`optipng -fix out .png`
puts "optipng -fix completed"
# ENCODE FILE TO BASE64 WITH "\n" REMOVING
File .open( 'temp' , 'w' ){|o| o.write(Base64.encode64( File .open( 'out.png' , 'r' ){|f| f.read}).gsub(/\n/, "" ))}
# MAKE STRING CSS READEABLE
c= File .open( 'temp' , 'r' ){|f| f.read}.gsub(/backgroundimageurldataimage\/pngbase64pzd/, ";background-image:url(data:image/png;base64;pzd," ).gsub(/\n/, "" )
File .delete( 'temp' )
# JUST PASTE TEXT FROM THIS FILE TO CSS
File .open( 'out_png64' , 'w' ){|s| s.write( "#{c}\);" )}
* This source code was highlighted with Source Code Highlighter .
考慮すべき情報:PNGの基本PNG仕様Mhtml
MHTMLを使用する場合は、CSSを完全に編集し、セクションに分割する必要があります(アーカイブ内の例)。
/*
Content-Type: multipart/related; boundary="_"
--_
Content-Type: text/css;
*/
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#half_logo {
/*
--_
Content-Location:logo
Content-Transfer-Encoding:base64
Content-Type: image/png;*/
iVBORw0KGgoAAAANSUhEUgAAAT4AAAA3CAMAAACintZ+AAAAWXRFWHRDb21tZW50ADAw;background-image:url(data:image/png;base64;pzd,iVBORw0K...);
/*
--_
Content-Type: text/css;
*/
background-image: url(mhtml:http://192.168.1.2/test.css!logo) !ie;
/*
--_--
*/
* This source code was highlighted with Source Code Highlighter .
ソースとスクリプトでアーカイブする作業現場の例FF 3.6、Opera 10.10、クロム、クロム、IE6-8でテスト済み
PS:この記事の著者は、私の親友であるBanderlogです。 私は彼の要求に応じて記事を投稿します;したがって、jabber:banderlog@jabber.com.uaで直接質問することをお勧めします
PPS:記事の投稿中にスクリプトで地獄のような間違いが行われたという事実が2日目に明らかになったことは奇妙です。 3つすべてが同じでした。