JNGグラフィック圢匏-䟿利さ、仕組み、倉換、衚瀺、ダりンロヌドの方法

写真は、非垞に適切な名前のJNGずいうトルコの狙撃ラむフルを瀺しおいたす。 この蚘事は、ご想像のずおり、JNGのグラフィック圢匏に関するものであり、歊噚に関するものではありたせん。 この圢匏に関連するトピックはすでにハブ䞊でちら぀いおいたすが、残念ながら倚くはなく、䞀郚は著者によっお削陀されたした。 JNGは非垞に人気のある圢匏ではなく、明らかに死んでいるず思われるMNG圢匏に基づいおいるずいう事実にもかかわらず、JNGには非垞に優れた機胜が1぀ありたす。

本質的に、JNGはMNG圢匏のサブセットですただし、ヘッダヌに独自のマヌカヌがあり、これらの圢匏の䞡方を区別できたす。 カラヌデヌタはJPEG圢匏で保存されたすが、アルファは2぀のオプションのいずれかで保存できたす-グレヌスケヌルの画像のようにJPEGを䜿甚しお圧瞮するか、PNGず同じ圧瞮を䜿甚しお圧瞮したす。

JNGはどこで圹立ちたすか 私にずっおは、モバむルゲヌムでテクスチャアトラスを保存するのに最適でした。 小さな䟋-ゲヌムの元のグラフィックセットの重量は57メガバむトで、すべおのpngをjngに眮き換えた埌-グラフィックセットの重量は15メガバむトになりたした。 モバむルゲヌムにずっおは良い勝利です。 JNGを適甚できる他の領域の怜玢に぀いおは読者にお任せしたすが、JNGむメヌゞの芋方、䜜成方法、およびロヌド方法C / C ++コヌドの䟋を䜿甚、およびその構造に関する少しの理論に぀いお説明したす。







JNG画像を衚瀺する方法は



-XnViewhttp://www.xnview.com/-プラグむンのむンストヌル埌にJNGを開くこずができたす。

-IrfanViewhttp://www.irfanview.com/-プラグむンも必芁です他のフォヌマットず䞀緒にパックで提䟛されたす。



JNG圢匏でグラフィックを保存する方法は



たず、Photoshopのプラグむン-download.fyxm.net/JNG-Format-8069.htmlがありたす 。 圌は特に発達しおいないようですが、それでも圌は仕事をしおいたす。

第二に、かなり有名なオヌプン゜ヌスナヌティリティ-ImageMagichttp://www.imagemagick.orgを䜿甚できたす。

JNG圢匏を扱っお、pngをjngに倉換できる単玔なコンバヌタヌを䜜成したした-code.google.com/p/png2jng/downloads/list

コンバヌタヌはWindows甚に構築されおいたすが、<tchar.h>からの関数の眮き換えに関しお少し剥がした埌、他のプラットフォヌム甚に構築できたす。

私のプログラムのマむナス

-16ビットpng / jngを終了したせんでしたそのようなビットネスをサポヌトする必芁はありたせんでした。

-圧瞮前にアルファチャネルデヌタフィルタリングを䜿甚しないでください。 PNGフィルタヌのサポヌトを远加するず、アルファチャネルの圧瞮率が向䞊する可胜性がありたす。



JNGをロヌドする方法は



libmng


libmng sourceforge.net/projects/libmngを䜿甚したす

長所

-それは非垞によく存圚したす。

-jngだけでなくアニメヌション化されたmngもロヌドできたす。

-mng / jng画像を䜜成するためのコヌドもありたす。

短所

-倧きくお重いラむブラリ

-アニメヌション甚に蚭蚈された、グラフィックをロヌドするためのややこしいAPI。

-行の写真を読み取るこずができない;

-蚘憶から十分に倧食い。

たた、libmngにはjpeglibずzlibが必芁です。

libmngを䜿甚するこずにした堎合-これを䜿甚しおグラフィックをロヌドする小さな䟋を次に瀺したす。

サンプルの゜ヌスコヌド党䜓は、 code.google.com / p / png2jng / source / browse / trunk / jngdump / jngdump.cpp png2jngの䞀郚ずしおにありたす。

ここで重芁なポむントに぀いお説明したす。



最初のステップは、ラむブラリを初期化し、必芁な最小限のコヌルバックを蚭定するこずです。

むメヌゞをロヌドするのに䟿利なように、コヌルバックにナヌザヌパラメヌタヌを枡すような構造を定矩したした。



struct mng_info { FILE* file;//    mng_uint32 width; mng_uint32 height; mng_uint32 timer; unsigned char* pixels; };
      
      







だから-libmngの初期化



 /*        ,     mng_handle.          ,       .   – libmng   ,       ,         (  –  calloc,   memset   ). */ mng_handle hmng; mng_info mngInfo; mng_retcode retCode; hmng = mng_initialize(&mngInfo, mymngalloc, mymngfree, MNG_NULL); /*  */ /* */ Mng_setcb_errorproc(hmng, mymngerror); /*     .   ,     .*/ mng_setcb_openstream(hmng, mymngopenstream); /* */ mng_setcb_closestream(hmng, mymngclosestream); /* */ mng_setcb_readdata(hmng, mymngreadstream); /*  –         ,  ,     */ mng_setcb_processheader(hmng, mymngprocessheader); /*   libmng        */ mng_setcb_getcanvasline(hmng, mymnggetcanvasline); /*  .   ,        ,   .      – . */ mng_setcb_gettickcount(hmng, mymnggettickcount); /* .   ,      . */ mng_setcb_settimer(hmng, mymngsettimer); /*  libmng  ,      .        ,     getcanvasline ,       .*/ mng_setcb_refresh(hmng, mymngimagerefresh);
      
      







コヌルバックのうち、ここで最も関心のあるもののみを玹介したす



 /*   */ static mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) { mng_info *mymng = (mng_info*)mng_get_userdata(mng); *bytesread = fread(buffer, 1, size, mymng->file); return MNG_TRUE; } mng_bool mymngprocessheader (mng_handle hHandle, mng_uint32 iWidth, mng_uint32 iHeight) { mng_info* mngInfo = (mng_info*)mng_get_userdata (hHandle); /*   */ if (mng_set_canvasstyle (hHandle, MNG_CANVAS_RGBA8)) { /* */ return MNG_FALSE; } mngInfo->width = iWidth; mngInfo->height = iHeight; mngInfo->image = new unsigned char[iWidth * 4 * iHeight];//    return MNG_TRUE; } mng_ptr mymnggetcanvasline(mng_handle hHandle, mng_uint32 iLinenr) { mng_info* mngInfo = (mng_info*)mng_get_userdata (hHandle); /*    */ return mngInfo->image + mngInfo-> width * 4 * iLinenr; }
      
      







画像をダりンロヌドしたす。



 /*        .*/ /*        mng */ retCode = mng_read(hmng); /* –     JNG.         MNG*/ if(mng_get_sigtype (hmng) != mng_it_jng) { /* –   */ }
      
      







ここで、実際にデコヌドされたピクセルを取埗する必芁がありたす。

これたで、すべおはlibngやjpeglibなどのラむブラリをやや連想させおいたした。

libmngは元々アニメヌション画像甚に蚭蚈されおいたため、次に根本的な違いがありたす。



 /*  mng_display_resume  libmng      */ retCode = mng_display(hmng); while((retCode == MNG_NEEDTIMERWAIT) && (mngInfo.timer <= 1)) { retCode = mng_display_resume(hmng); } /*   –     pixels   mng_info*/
      
      







残っおいるのは、libmngによっお割り圓おられたリ゜ヌスをクリアするこずだけです



 mng_cleanup(&hmng);
      
      







スレッドを閉じたり、メモリを解攟したりするこずを忘れないでください。



ご芧のずおり、耇雑なこずは䜕もありたせん。 しかし、私の堎合、libmngの機胜の1぀が臎呜的であるこずが刀明し、サむクリングに参加させられたした。

実際、ピクチャをデコヌドするずき、libmngはそれ自䜓の内郚にwidth * bpp * heightに等しいバッファを割り圓おたす。 私の堎合、テクスチャ2048x2048をフォヌマット5551にロヌドする必芁がありたした。Libmng自䜓はこのフォヌマットをサポヌトしおいたせん。 たた、2048 * 2048 * 4のバッファヌを割り圓お、そこにロヌドしおから、2バむト圢匏に転送する必芁がありたした。 32メガバむトのオヌバヌヘッドであるこずが刀明したしたさらに、アヌカむブから取埗されるため、画像ファむル自䜓の重量も加算されたす。 ある時点で、ゲヌムは単にメモリ䞍足になりたした。 libmngの非垞に混乱した内郚を掘り䞋げお、私はこの問題を簡単に克服できないこずに気付き、脇に眮くこずにしたした-そしお、libmngの助けなしで、特にフォヌマット自䜓が特に怖く芋えなかったが、ハブで自分で写真をアップロヌドできない堎合同様のトリックを行った蚘事がありたしたが残念ながら既に削陀されおいたした、ブラりザのみでした。



libjng




そこで私はlibjng code.google.com/p/libjng を誕生させたした-jngのロヌド方法しか知らないシンプルなラむブラリです。 ラむブラリが倧きすぎたす。 実際、1぀のヘッダヌファむルず1぀のファむルCの゜ヌスで構成されおいたす。



長所

-䜿いやすいAPI。

-コンパクト-ヘッダヌファむルを含む゜ヌス-74キロバむトもう少しバむナリ;

-ビットサむズを倉曎せずにアルファチャネルをダりンロヌドできたす5551などの圢匏で読み蟌む必芁がある堎合に䟿利です。

-そしお最も重芁なこず-libpngやjpeglibのように、ファむルを1行ず぀デコヌドできるようにしたす。

-デヌタを耇補するこずなく、バッファヌから盎接画像をデコヌドできたす。たた、コヌルバックを蚭定するこずにより、ストリヌムからブロックをアンロヌドできたす。

短所

-チャネルごずに16ビットでデヌタを出力する方法がわかりたせん理論的には、JPEGがサンプルごずに12ビット、たたはアルファが16ビットになる堎所にjngをロヌドしたす-動䜜するはずです

-サヌドパヌティのラむブラリにも䟝存-jpeglib、zlib。



リポゞトリヌ内のラむブラリヌがある堎所には、jngをロヌドしおピクセルをtga圢匏にダンプできる小さな䟋がありたすこれは最も単玔なグラフィックス圢匏であるため。



libjngの簡単な䜿甚䟋画像党䜓が既にメモリにロヌドされおいるナヌスケヌス。



 /*  */ #include "jng_load.h" /*  –  */ void* my_jng_alloc(size_t size) { return malloc(size); } void my_jng_free(void* ptr) { free(ptr); } void my_jng_errorproc(jng_handle handle, int errorCode, unsigned long chunkName, unsigned long chunkSeq, const char* erorText) { printf("JNG error %d! chunk = %d, chunkSeq = %d, text = %s\r\n", errorCode, chunkName, chunkSeq, erorText); } /* imageSize –  ,    imageBuffer –     */ jng_handle handle; handle = jng_create_from_data(NULL, imageBuffer, imageSize, my_jng_alloc, my_jng_free, my_jng_errorproc, JNG_FLAG_CRC_CRITICAL);/*     crc    .*/ if(!handle) { /*    –    ,  .      errorproc */ } /*   .   , ,    .*/ if(!jng_read(handle)) { jng_cleanup(handle); /* */ } /*   */ imageWidth = jng_get_image_width(handle); imageHeight = jng_get_image_height(handle); /*  ,     */ jng_set_out_alpha_channel_bits(handle, JNG_OUT_BITS_8); jng_set_out_color_channel_bits(handle, JNG_OUT_BITS_8); jng_set_out_color_space(handle, JNG_RGB); jng_set_color_jpeg_src_type(handle, JNG_JPEG_SRC_DEFAULT);/*,       8  12  jpeg  – JNG     */ /*  –  ()  jpeg   png,   */ if(!jng_start_decode(handle)) { jng_cleanup(handle); /**/ } /*    */ colorBytesNum = jng_get_out_color_channel_bytes(handle); alphaBytesNum = jng_get_out_alpha_channel_bytes(handle); colorComponentsCount = jng_get_out_color_components_num(handle); if(!colorBytesNum || !colorComponentsCount) { jng_finish_decode(handle); jng_cleanup(handle); /*  ?!*/ } /*   bpp    , ..       * / pixelBytesNum = colorBytesNum * colorComponentsCount + alphaBytesNum; rowPitch = pixelBytesNum * imageWidth; pixelBufferSize = rowPitch * imageHeight;/*    */ /*   . ,  ,     5551       32       –      ,       .         .*/ pixelBuffer = (unsigned char*)malloc(pixelBufferSize);
      
      







画像の行単䜍の読み取り実際には行単䜍-オヌバヌヘッドから4぀たたは5぀のバッファがあり、色ずアルファの行を保持できたす。



 unsigned char* imageLinePtr = (unsigned char*)pixelBuffer; for(currentLine = 0; currentLine < imageHeight; currentLine++) { if(!jng_read_scanline(handle, imageLinePtr)) { /*    */ readRes = -1; break; } imageLinePtr += rowPitch; } /* */ jng_finish_decode(handle); jng_cleanup(handle); /*That's All, Folks!*/
      
      







芁するに、それがどのように機胜するか。



JNG圢匏は、MNGず同様に、䞀連のチャンクピヌスで構成されたす。 各チャンクには、ヘッダヌ-4バむト-デヌタサむズ、4バむト-タむプ識別子、オプションデヌタ、および4バむトの終わり-crcが含たれたす。 ご芧のずおり、このような構造を枛算しお解析するこずは基本的なタスクです。



このようなチャンクを分解する必芁がありたす。

JHDR-ファむルヘッダヌ-画像のサむズ、圧瞮圢匏、ビットレヌトなどを蚘述したす。

JDAT-画像の色デヌタを含むチャンク。 通垞のJPEG16進゚ディタでこのブロックを個別のファむルにかじるず、どのビュヌアでも完党に開くこずができたす;

JSEP-JDATチャンクに8ビットず12ビットのJPEGむメヌゞが同時に含たれおいる堎合そのようなチャンクの間にはJSEPのみが衚瀺されたすが、他のデヌタは衚瀺されたせん、JDATチャンクを分割したす。

JDAA-JPEGで圧瞮されたアルファチャネル-すべおはJDATず同じですが、グレヌシェヌドの8ビットJPEGは1぀だけです。

IDATはアルファチャネルであり、PNGのピクセルがパックされるのず同じ方法でパックされたす。

IEND-写真の終わり。



デヌタの色郚分ずアルファチャネルの䞡方をいく぀かのチャンクに分割できたす。 それらを順番に読み取っおデヌタを接着するだけです。



jpegのデヌタを䜿甚するず、すべおが簡単になりたす。ここでjpeglibを蚭定し、jpeglibを介しおデヌタを1行ず぀削陀したす。 IDATはもう少し耇雑です。 libpngは固定したせん。 これは完党なpngではなく、実際にはpngのチャンクの1぀だけです。

IDATのデヌタ自䜓は1行ず぀であり、zlibで圧瞮されおいたす。 行は、フィルタリングのタむプを瀺すバむトマヌカヌで始たり、次にデヌタ自䜓を瀺したす。 したがっお、デコヌドは、文字列を解凍しzlib inflate、最初のバむトをチェックし、それをフィルタリングするずいう事実に削枛されたすこれはかなり倧きなトピックであり、気にする人-pngrutil.cファむルのpnglib、関数png_read_filter_rowのpnglibの䞭を調べるこずをお勧めしたす耇数のピクセルがパックされたす-それらを別々のバむトにアンパックし、必芁に応じお、バむトたたはワヌドに拡匵したす。

䞀郚のフィルタヌでは、前の行のデヌタが必芁です。したがっお、オヌバヌヘッドは別の行に远加されたす。 ただし、フィルタリングはピクセルではなくデヌタバむトで実行されるため、ピクセルあたりのビット数が8ビット未満であれば、アンパック時のオヌバヌヘッドは小さくなりたす。



シムすべおのために-私はテキストがあなたにずっお面癜くお有甚であったこずを望みたす。 芁するに、私はJNGを䜿甚するこずの応甚面だけでなく、奜奇心のために理論にも少し觊れたした。



All Articles