クロスブラウザーデータURIの問題について

ウェブサイトの最適化を追求して、最適化されたファイルのサイズを犠牲にすることなく、リクエストの数を減らしたいと思いました。

目標は、さまざまな最適化設定を使用して、さまざまな形式の画像を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







Jpeg



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 .








考慮すべき情報:

ウィキペディアのJPEG







GIF



この形式では、物事はそれほど良くありません。



できること:





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スプライトを使用する方が良いと思います。



理論計算:







考慮すべき情報:

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つすべてが同じでした。



All Articles