Rumah pembangunan bahagian belakang tutorial php php扩展开发笔记(10)自定义 libpng 库中的 IO 函数,将图片写入内存

php扩展开发笔记(10)自定义 libpng 库中的 IO 函数,将图片写入内存

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

在开发这个生成二维码扩展 dcode 的时候,需要将生成的二维码 png 图片以字符串的方式返回给调用者,而不是直接生成文件,这样比较方便的是不用去操作文件,将文件的操作完全交给用户。

生成图片采用了 libpng 的库,关于 libpng 的文档大家可以到 这里 png 文档 看。我使用这个库在 Ubuntu14.04 上编译我的扩展的时候还有个小问题 png_create_write_struct in Unknown on line 0 on ubuntu 14,到网上一搜索,还是非常常见的。

下面简单的列一下代码:

<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>
Salin selepas log masuk
<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 data;
    <span>for</span>(y = <span>0</span>; y 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 width; x ++) {
            <span>for</span>(xx = <span>0</span>; xx <size xx>1) if(bit 0) {
                    q++;
                    bit = <span>7</span>;
                }
            }
            p++;
        }
        <span>for</span>(yy = <span>0</span>; yy memset(row, <span>0xff</span>, (realwidth + <span>7</span>) / <span>8</span>);
    <span>for</span>(y = <span>0</span>; y char *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></size></code>
Salin selepas log masuk
  1. 第一个函数 dcode_png_writer 是自定义的写 png 数据的 callback 函数。
  2. 第二个函数 dcode_write_to_png 是将 QRcode 数据写入 png

主要可以看下这个部分

<code>png_set_write_fn(png_ptr, &state, &dcode_png_writer, NULL);</code>
Salin selepas log masuk

这个地方就是调用了自定义的 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>
Salin selepas log masuk

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

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

生成 QRCode 的速度还是很快的,如果用 for ($i = 0; $i 的 <code>$i 作为参数,3秒就能生成 10000 个。

版权声明:本文为博主原创文章,未经博主允许不得转载。

以上就介绍了php扩展开发笔记(10)自定义 libpng 库中的 IO 函数,将图片写入内存,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Bagaimana untuk menukar PNG kepada JPG pada Windows 11 Bagaimana untuk menukar PNG kepada JPG pada Windows 11 May 12, 2023 pm 03:55 PM

Cara Menukar PNG kepada JPG pada Windows 11 Pada Windows 10 dan 11, anda boleh menggunakan aplikasi Paint terbina dalam Microsoft untuk menukar fail imej dengan cepat. Untuk menukar imej PNG kepada JPG pada Windows 11, gunakan langkah berikut: Buka File Explorer dan navigasi ke imej PNG yang anda ingin tukar. Klik kanan imej dan pilih Buka Dengan > Lukis daripada menu. Foto atau imej anda dibuka dalam apl Paint. Perhatikan saiz fail di bahagian bawah skrin. Untuk menukar fail daripada PNG kepada JPG, klik Fail dan pilih Simpan Sebagai > Imej JPEG daripada menu. Apabila sumber fail

Gunakan fungsi File.length() java untuk mendapatkan saiz fail Gunakan fungsi File.length() java untuk mendapatkan saiz fail Jul 24, 2023 am 08:36 AM

Gunakan fungsi File.length() Java untuk mendapatkan saiz fail Saiz fail adalah keperluan yang sangat biasa apabila berurusan dengan operasi fail Java menyediakan cara yang sangat mudah untuk mendapatkan saiz fail, iaitu, menggunakan panjang(. ) kaedah kelas Fail. Artikel ini akan memperkenalkan cara menggunakan kaedah ini untuk mendapatkan saiz fail dan memberikan contoh kod yang sepadan. Pertama, kita perlu mencipta objek Fail untuk mewakili fail yang kita ingin dapatkan saiznya. Berikut ialah cara membuat objek Fail: Filef

Apakah perbezaan antara null dan NULL dalam bahasa c Apakah perbezaan antara null dan NULL dalam bahasa c Sep 22, 2023 am 11:48 AM

Perbezaan antara null dan NULL dalam bahasa C ialah: null ialah definisi makro dalam bahasa C, biasanya digunakan untuk mewakili penunjuk nol, yang boleh digunakan untuk memulakan pembolehubah penunjuk, atau untuk menentukan sama ada penuding adalah nol dalam pernyataan bersyarat; NULL ialah definisi makro dalam bahasa C Pemalar yang dipratentukan dalam , biasanya digunakan untuk mewakili nilai nol, digunakan untuk mewakili penunjuk nol, tatasusunan penunjuk nol atau penunjuk struktur nol.

Apakah maksud undefined dan null? Apakah maksud undefined dan null? Nov 20, 2023 pm 02:39 PM

Dalam JavaScript, kedua-dua undefined dan null mewakili konsep "nothing": 1. undefined mewakili pembolehubah tidak dimulakan atau sifat tidak wujud Apabila pembolehubah diisytiharkan tetapi tiada nilai diberikan kepadanya, nilai pembolehubah adalah undefined . apabila mengakses sifat yang tidak wujud dalam objek, nilai yang dikembalikan juga tidak ditentukan;

Bagaimana untuk menamakan semula sambungan semua fail dalam folder, termasuk subfolder Bagaimana untuk menamakan semula sambungan semua fail dalam folder, termasuk subfolder Apr 14, 2023 pm 12:22 PM

Katakan anda perlu menamakan semula sambungan fail daripada satu sambungan kepada sambungan yang lain, katakan jpg kepada png. Ia mudah, sudah tentu! Tetapi bagaimana jika anda mempunyai berbilang fail yang sambungannya perlu ditukar? Atau lebih teruk, bagaimana jika berbilang fail ini juga terletak dalam berbilang folder dan subfolder, dalam satu folder? Nah, bagi orang biasa, ini boleh menjadi mimpi ngeri. Tetapi untuk seorang geek, sama sekali tidak. Persoalannya sekarang, adakah anda seorang geek? Nah, dengan bantuan Halaman Geek, anda pasti! Dalam artikel ini, kami menerangkan cara mudah menamakan semula sambungan semua fail dalam folder, termasuk subfolder pilihan anda, daripada satu sambungan ke sambungan yang lain melalui kaedah skrip kelompok. Notis:

Bila hendak menggunakan null dan undefined Bila hendak menggunakan null dan undefined Nov 13, 2023 pm 02:11 PM

Kedua-dua null dan undefined menunjukkan kekurangan nilai atau keadaan tidak ditentukan Bergantung pada senario penggunaan, terdapat beberapa prinsip panduan untuk memilih untuk menggunakan null atau undefined: 1. Apabila anda perlu menunjukkan dengan jelas bahawa pembolehubah kosong atau tidak sah, anda. boleh menggunakan null; 2. Apabila pembolehubah telah diisytiharkan tetapi belum diberikan nilai, ia akan ditetapkan kepada tidak ditentukan secara lalai 3. Apabila anda perlu menyemak sama ada pembolehubah kosong atau tidak ditentukan, gunakan pengendali kesamaan yang ketat "= ==" untuk menentukan sama ada pembolehubah itu batal atau tidak ditentukan. .

Apakah perbezaan antara null dan undefined Apakah perbezaan antara null dan undefined Nov 08, 2023 pm 04:43 PM

Perbezaan antara null dan undefined ialah: 1. Makna semantik 2. Senario penggunaan 3. Perbandingan dengan nilai-nilai lain 5. Hubungan dengan parameter fungsi; . Prestasi dalam siri JSON 9. Hubungan dengan jenis. Pengenalan terperinci: 1. Makna semantik, null biasanya bermaksud mengetahui bahawa pembolehubah ini tidak akan mempunyai sebarang nilai objek yang sah, manakala undefined biasanya bermaksud bahawa pembolehubah belum diberikan nilai, atau objek tidak mempunyai atribut ini 2. Senario penggunaan , dsb.

Apakah maksud menulis dalam python Apakah maksud menulis dalam python Mar 07, 2024 am 10:01 AM

Tulis dalam Python ialah kaedah menulis rentetan ke dalam fail Format sintaks ialah "fileObject.write([str])", di mana str merujuk kepada rentetan yang akan ditulis pada fail.

See all articles