ホームページ バックエンド開発 PHPチュートリアル PHP拡張開発ノート(10) libpngライブラリのIO関数をカスタマイズしてメモリに画像を書き込む

PHP拡張開発ノート(10) libpngライブラリのIO関数をカスタマイズしてメモリに画像を書き込む

Aug 08, 2016 am 09:21 AM
null png size write

このQRコード拡張子コードを開発する場合、ファイルを直接生成するのではなく、生成されたQRコードのpng画像を文字列の形で呼び出し元に返す必要があります。これは、ファイルを操作する必要がないため、より便利です。ファイルの操作は完全にユーザーに任されています。

画像の生成には libpng ライブラリが使用されます。libpng に関するドキュメントについては、こちらの png ドキュメントにアクセスしてください。このライブラリを使用して Ubuntu14.04 で拡張機能をコンパイルしたときも、小さな問題が発生しました。ubuntu 14 の行 0 にある Unknown の png_create_write_struct です。インターネットで検索したところ、これは依然として非常に一般的です。

コードは以下に簡単にリストされています:

<code><span>/** {{{ dcode_png_writer()
 * function is custom png_write callback function
 * Return void */</span><span>static</span><span>void</span> dcode_png_writer(png_structp png_ptr, png_bytep data, png_size_t length)
{
    png_mem_encode* p = (png_mem_encode*) png_get_io_ptr(png_ptr);
    size_t nsize = p->size + length;

    <span>if</span> (p->buffer)
        p->buffer = erealloc(p->buffer, nsize);
    <span>else</span>
        p->buffer = emalloc(nsize);

    <span>if</span> (!p->buffer)
    {
        png_error(png_ptr, <span>"PNG allocate memory error"</span>);
        <span>exit</span>(FAILURE);
    }

    <span>memcpy</span>(p->buffer + p->size, data, length);
    p->size += length;
}
<span>/* }}} */</span></code>
ログイン後にコピー
<code><span>/** {{{ dcode_write_to_png()
 * write qrcode struct to memory
 * Return char* */</span><span>static</span><span>char</span>* dcode_write_to_png(QRcode *qrcode, <span>int</span> size, <span>int</span> margin, <span>int</span> *pp_len)
{

    png_structp png_ptr;
    png_infop info_ptr;

    <span>unsigned</span><span>char</span> *row, *p, *q;
    <span>int</span> x, y, xx, yy, bit;
    <span>int</span> realwidth;

    realwidth = (qrcode->width + margin * <span>2</span>) * size;
    <span>int</span> row_fill_len = (realwidth + <span>7</span>) / <span>8</span>;

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    <span>if</span> (png_ptr == NULL)
    {
        php_error(E_ERROR, <span>"Failed to initialize PNG writer"</span>);
        <span>return</span> NULL;
    }

    info_ptr = png_create_info_struct(png_ptr);
    <span>if</span> (info_ptr == NULL)
    {
        php_error(E_ERROR, <span>"Failed to initialize PNG info"</span>);
        <span>return</span> NULL;
    }

    <span>if</span> (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        php_error(E_ERROR, <span>"Failed to set PNG jmpbuf"</span>);
        <span>return</span> NULL;
    }

    row = (<span>unsigned</span><span>char</span> *) emalloc(row_fill_len);
    <span>if</span> (row == NULL)
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        php_error(E_ERROR, <span>"Failed to allocate memory"</span>);
        <span>return</span> NULL;
    }

    png_mem_encode state = {NULL, <span>0</span>};
    png_set_write_fn(png_ptr, &state, &dcode_png_writer, NULL);

    png_set_IHDR(png_ptr,
                info_ptr,
                realwidth,
                realwidth,
                <span>1</span>,
                PNG_COLOR_TYPE_GRAY,
                PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_DEFAULT,
                PNG_FILTER_TYPE_DEFAULT);

    png_write_info(png_ptr, info_ptr);
    <span>memset</span>(row, <span>0xff</span>, (realwidth + <span>7</span>) / <span>8</span>);
    <span>for</span>(y = <span>0</span>; y < margin * size; y ++) {
        png_write_row(png_ptr, row);
    }

    p = qrcode->data;
    <span>for</span>(y = <span>0</span>; y < qrcode->width; y ++) {
        bit = <span>7</span>;
        <span>memset</span>(row, <span>0xff</span>, (realwidth + <span>7</span>) / <span>8</span>);
        q = row;
        q += margin * size / <span>8</span>;
        bit = <span>7</span> - (margin * size % <span>8</span>);
        <span>for</span>(x = <span>0</span>; x < qrcode->width; x ++) {
            <span>for</span>(xx = <span>0</span>; xx <size; xx ++) {
                *q ^= (*p & <span>1</span>) << bit;
                bit--;
                <span>if</span>(bit < <span>0</span>) {
                    q++;
                    bit = <span>7</span>;
                }
            }
            p++;
        }
        <span>for</span>(yy = <span>0</span>; yy < size; yy ++ ) {
            png_write_row(png_ptr, row);
        }
    }

    <span>memset</span>(row, <span>0xff</span>, (realwidth + <span>7</span>) / <span>8</span>);
    <span>for</span>(y = <span>0</span>; y < margin * size; y ++) {
        png_write_row(png_ptr, row);
    }

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);

    efree(row);

    <span>char</span> *bin_data = NULL;
    <span>if</span> (state.buffer) {
        bin_data = estrndup(state.buffer, state.size);
        *pp_len = state.size;
        efree(state.buffer);
    }

    <span>return</span> bin_data;
}
<span>/** }}} */</span></code>
ログイン後にコピー
  1. 最初の関数 dcode_png_writer は、png データを書き込むためのカスタム コールバック関数です。
  2. dcode_png_writer 是自定义的写 png 数据的 callback 函数。
  3. 第二个函数 dcode_write_to_png 是将 QRcode 数据写入 png

主要可以看下这个部分

<code>png_set_write_fn(png_ptr, &state, &dcode_png_writer, NULL);</code>
ログイン後にコピー

这个地方就是调用了自定义的 write 函数 dcode_png_writer,将数据写到了 state 这个结构体里,state 结构体如下

<code><span>typedef</span><span>struct</span> _png_mem_encode {
    <span>char</span> *buffer;
    size_t size;
} png_mem_encode ;</code>
ログイン後にコピー

png_set_write_fn 函数设置了自定义的 write 函数,通过 dcode_png_writer 来像 state 写入数据,动态的来分配内存。

关于 png_set_write_fn 的定义,可以参看上面提到的 PNG 文档,自定义函数还可以自定义错误处理等功能,这样可以根据实际情况来接管 error handler 而不是让其在内部退出。更多的相关代码请看 DCode 扩展

生成 QRCode 的速度还是很快的,如果用 for ($i = 0; $i < 10000; $i ++)$i 2 番目の関数 dcode_write_to_png は QRcode データを png に書き込むことです

主にこの部分を見ることができますrrreee
この場所はカスタム関数を呼び出します。関数 dcode_png_writerstate 構造体にデータを書き込みます。 state 構造体は次のとおりです

rrreee

png_set_write_fn 関数は次のように設定します。カスタム書き込み関数は、dcode_png_writer を通じてデータをステートに書き込み、メモリを動的に割り当てます。

png_set_write_fn の定義については、上記の PNG ドキュメントを参照してください。カスタム関数は、error handler をカスタマイズすることもできます。 > 内部的に終了させるのではなく、実際の状況に応じて引き継がれます。関連コードの詳細については、DCode 拡張機能を参照してください

for ($i = 0; $i > を使用すると、QRCode の生成速度は依然として非常に高速です。 $i をパラメータとして指定すると、3 秒で 10,000 個を生成できます。

🎜🎜🎜著作権声明: この記事はブロガーによるオリジナルの記事であり、ブロガーの許可なく複製することはできません。 🎜🎜 🎜 以上、PHP拡張開発ノート(10)libpngライブラリのIO関数をカスタマイズしてメモリに画像を書き込む方法を紹介しましたが、PHPチュートリアルに興味のある友人の参考になれば幸いです。 🎜 🎜 🎜
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Windows 11でPNGをJPGに変換する方法 Windows 11でPNGをJPGに変換する方法 May 12, 2023 pm 03:55 PM

Windows 11 で PNG を JPG に変換する方法 Windows 10 および 11 では、Microsoft の組み込みペイント アプリを使用して画像ファイルをすばやく変換できます。 Windows 11 で PNG 画像を JPG に変換するには、次の手順を実行します。 ファイル エクスプローラーを開き、変換する PNG 画像に移動します。画像を右クリックし、メニューから [プログラムから開く] > [描画] を選択します。写真または画像がペイント アプリで開きます。画面の下部にあるファイルサイズに注目してください。ファイルを PNG から JPG に変換するには、[ファイル] をクリックし、メニューから [名前を付けて保存] > [JPEG 画像] を選択します。ファイルリソースが

JavaのFile.length()関数を使用してファイルのサイズを取得します。 JavaのFile.length()関数を使用してファイルのサイズを取得します。 Jul 24, 2023 am 08:36 AM

ファイルのサイズを取得するには、Java の File.length() 関数を使用します。ファイル操作を扱うとき、ファイル サイズは非常に一般的な要件です。Java では、ファイルのサイズを取得するための非常に便利な方法、つまり length( ) File クラスのメソッド。この記事では、このメソッドを使用してファイルのサイズを取得する方法と、対応するコード例を紹介します。まず、サイズを取得したいファイルを表す File オブジェクトを作成する必要があります。 File オブジェクトを作成する方法は次のとおりです: Filef

未定義と null は何を意味しますか? 未定義と null は何を意味しますか? Nov 20, 2023 pm 02:39 PM

JavaScript では、未定義と null はどちらも「何もない」という概念を表します: 1. 未定義は初期化されていない変数または存在しないプロパティを表します。変数が宣言されていても値が割り当てられていない場合、変数の値は未定義です。オブジェクト内に存在しないプロパティにアクセスする場合、戻り値も未定義になります; 2. null は空のオブジェクト参照を表します。場合によっては、オブジェクト参照を null に設定して、オブジェクト参照が占有しているメモリを解放できます。

C言語のnullとNULLの違いは何ですか C言語のnullとNULLの違いは何ですか Sep 22, 2023 am 11:48 AM

null と C 言語の NULL の違いは次のとおりです。 null は C 言語のマクロ定義であり、通常は null ポインタを表すために使用され、ポインタ変数を初期化したり、条件文でポインタが null であるかどうかを判断したりするために使用できます。 NULL は、C 言語のマクロ定義です。 の定義済み定数で、通常は NULL 値を表すために使用され、NULL ポインター、NULL ポインター配列、または NULL 構造体ポインターを表すために使用されます。

サブフォルダーを含むフォルダー内のすべてのファイルの拡張子の名前を変更する方法 サブフォルダーを含むフォルダー内のすべてのファイルの拡張子の名前を変更する方法 Apr 14, 2023 pm 12:22 PM

ファイルの拡張子の名前をある拡張子から別の拡張子に変更する必要があるとします。たとえば、jpg から png に変更します。もちろん簡単です!しかし、拡張子を変更する必要があるファイルが複数ある場合はどうすればよいでしょうか?さらに悪いことに、これらの複数のファイルが 1 つのフォルダー内の複数のフォルダーおよびサブフォルダーにも配置されている場合はどうなるでしょうか。まあ、普通の人にとって、これは悪夢かもしれません。しかし、オタクにとっては、絶対にそうではありません。ここでの質問は、あなたはオタクですか? Geek Page の助けがあれば、間違いなくそうなります!この記事では、バッチ スクリプトを使用して、選択したサブフォルダーを含むフォルダー内のすべてのファイルの拡張子の名前を、ある拡張子から別の拡張子に簡単に変更する方法について説明します。知らせ:

null と unknown を使用する場合 null と unknown を使用する場合 Nov 13, 2023 pm 02:11 PM

null と unknown はどちらも、値が欠落しているか、未定義の状態であることを示します。使用シナリオに応じて、null または unknown の使用を選択するための指針がいくつかあります。1. 変数が空または無効であることを明確に示す必要がある場合、 null を使用できます; 2. 変数が宣言されていても値が割り当てられていない場合、デフォルトで未定義に設定されます; 3. 変数が空か未定義かを確認する必要がある場合は、厳密な等価演算子 "= を使用します。 == 変数が null か未定義かを判断します。

nullと未定義の違いは何ですか nullと未定義の違いは何ですか Nov 08, 2023 pm 04:43 PM

null と未定義の違いは次のとおりです: 1. 意味上の意味; 2. 使用シナリオ; 3. 他の値との比較; 4. グローバル変数との関係; 5. 関数パラメーターとの関係; 6. Nullability チェック; 7. パフォーマンスに関する考慮事項; 8 . JSON シリアル化のパフォーマンス; 9. 型との関係。詳細な紹介: 1. セマンティックな意味。null は通常、この変数が有効なオブジェクト値を持たないことがわかっていることを意味し、未定義は通常、変数に値が割り当てられていない、またはオブジェクトにこの属性がないことを意味します。 2. 使用シナリオ、など。

pngとはどのような形式ですか? pngとはどのような形式ですか? Dec 10, 2020 pm 04:16 PM

png は、可逆圧縮アルゴリズムを使用するビットマップ形式です。 PNG 形式には 3 つの形式があります: 8 ビット、24 ビット、および 32 ビット。8 ビット PNG は 2 つの異なる透明形式をサポートします。24 ビット PNG は透明をサポートしません。32 ビット PNG は 8- ビットを追加します。ビット透明チャネルを 24 ビットに変換できるため、256 レベルの透明度を表示できます。

See all articles