透明度のあるJPEGの使用

もちろん、JPEG形式は透明度をサポートしていませんが、透明なテクスチャにPNGの代わりにJPEGを使用するというアイデアは長い間刺激的でした。 PaulZi同志は最近、画像自体とマスクを保存するHTMLにSVG形式を使用すること提案しました。 Jim Studt 、JPEGでEXIFフィールドを使用し、マスクをそこに保存し、Canvasを使用してWebページに表示すること提案しています。
どちらの方法も使用が比較的難しく、Web用に設計されているため、最も単純なオプションに決めました:RGBのロッシーJPEGとロスレスマスクをPNGに別々に保存し、プログラムでUIImageを取得する段階でそれらを結合します。 ObjCでは構文を考慮してほぼ同じように行われますが、コードはC#で提供されるため、すぐにMonoTouchで記述します。


チャンネル分離


分離には、 ImageMagikコンソールユーティリティを使用します。
このコマンドは、アルファチャネルを分離します。
convert file.png -channel Alpha -separate file.mask.png

次のコマンドは、透明度データを破棄してJPEGファイルを作成します。 通常、PNGファイルをJPEGに変換するときに他のユーティリティ(Photoshopを含む)は、特定のモノクロカラーを追加してからRGBで保存するだけです。これにより、アルファがあらかじめ乗算された美しいが誤った画像が得られます。
convert file.png -quality 90 -alpha off file.jpg

受信したファイルの品質は、 quality 90パラメーターによって規制されています。 JPEGの品質の90%は、Appleがプログラムや映画のスクリーンショットに置いている以上のものです。 誰もがこの価値を好みに合わせて調整できると思います。

最適化


マスクは、透過性のない8ビットグレースケールPNGとして取得されます。 この形式は、 optipngまたはWebサイトwww.tinypng.orgにより完全に圧縮されています。
JPEGを使用すると、状況はさらに興味深いものになります。 それは質の高いタスクに限定される可能性がありますが、最近、ffmpegとx264エンコーダーの開発者の1人であるLoren Merrittから素晴らしいユーティリティjpegrescanに出会い ました彼のアカウントに 、彼がエイリアンマインドまたはサイバネティックブレインの代表である疑いがあります )。
ユーティリティは通常とは異なるアプローチを使用します。プログレッシブ圧縮用に異なる係数を選択し、最適な係数を選択します。 同じ画質で5〜15%勝ちます。 ユーティリティには独自のページはなく、ディスカッションとperlコード自体のトピックのみがあります: pastebin.com/f78dbc4bc

毎回手動でコマンドを入力しないように、単純なbashスクリプトを作成しました。
 #!/bin/bash basefile=${1##*/} maskfile="${basefile%.*}.mask.png" jpegfile="${basefile%.*}.jpg" convert $1 -channel Alpha -separate $maskfile convert $1 -quality 90 -alpha off $jpegfile optipng $maskfile jpegrescan $jpegfile $jpegfile 


スクリプトの結果は次のとおりです。

私の場合、1.8MBのファイルから、380Kbと35Kbの2つのファイルを取得しました。

ボンディング


接着自体は非常に簡単です-2つの画像がUIImageに読み込まれ、WithMaskメソッドを使用してそれらに基づいてCGImageが作成され(ObjCではそれぞれCGImageRefとinitWithMaskです)、新しいUIImageにラップされます。
  UIImage result; using(UIImage uiimage = UIImage.FromFile(file)) using(UIImage mask = UIImage.FromFile(maskFile)) { CGImage image = uiimage.CGImage; image = image.WithMask(mask.CGImage); result = UIImage.FromImage(image, uiimage.CurrentScale, uiimage.Orientation); } 


実際のプロジェクトでは、もう少し複雑にして* .mask.pngファイルが存在するかどうかを確認し、見つからない場合は通常のUIImage.FromFile()を返します。

利益




視覚的には、ゲームはまったく変更されていません。 目によるテクスチャの読み込みと接着の遅延は目立たないため、測定しませんでした。 プロジェクト自体は、.ipa形式、iTunesおよびデバイスの両方で6(!!)メガバイト減少しました。



PNGのゲームの画面。 アーティファクトや圧縮/透明性の問題は見られません。
プロジェクトフォルダー内の画像の数が2倍になっていることで少し混乱していますが、それでも生き残ることができます。 コードの変更は最小限です。 インターフェイスグラフィックスの場合、この方法はUIImageを手動で割り当てる必要があり、NIB / XIBからロードする必要がないため理想的ではありませんが、独自のコントロールまたはテクスチャに非常に適しています。 JPEGを100%の品質で保存した場合でも、品質を損なうことなく、生成されるファイルのサイズは元のPNGよりも小さくなる場合があります。

PS ImageMagickとoptipngはポート(MacPorts / Fink / Brew)から配置され、同じ名前が付けられます。 Jpegrescanスクリプトはpastebinでスイングし、jpegポートを使用します

Source: https://habr.com/ru/post/J152225/


All Articles