php擴充開發筆記(10)自訂 libpng 函式庫中的 IO 函數,將圖片寫入記憶體
在開發這個生成二維碼擴展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>
<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>
- 第一個函數
dcode_png_writer
是自訂的寫 png 資料的 callback 函數。 - 第二個函數
dcode_write_to_png
是將QRcode 資料寫入png
主要可以看下這個部分
<code>png_set_write_fn(png_ptr, &state, &dcode_png_writer, NULL);</code>
這個地方就是調用了自定義的write 函數結構體裡,
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
error handler 而不是讓其在內部退出。更多的相關程式碼請看DCode 擴充
產生QRCode 的速度還是很快的,如果用
for ($i = 0; $i 的
$i 作為參數,3秒就能生成10000 個。
以上就介紹了php擴充開發筆記(10)自訂 libpng 庫中的 IO 函數,將圖片寫入內存,包括了方面的內容,希望對PHP教程有興趣的朋友有所幫助。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何在Windows11上將PNG轉換為JPG在Windows10和11上,您可以使用Microsoft內建的Paint應用程式快速轉換圖片檔案。若要在Windows11上將PNG映像轉換為JPG,請使用下列步驟:開啟檔案總管並導航至要轉換的PNG映像。右鍵單擊圖像並從選單中選擇開啟方式>繪製。您的照片或圖像會在「畫圖」應用程式中開啟。注意螢幕底部的檔案大小。若要將檔案從PNG轉換為JPG,請按一下檔案並從選單中選擇另存為>JPEG圖片。當文件資源

使用Java的File.length()函數取得檔案的大小檔案大小是在處理檔案作業時很常見的一個需求,Java提供了一個很方便的方法來取得檔案的大小,即使用File類別的length()方法。本文將介紹如何使用此方法來取得檔案的大小,並給出對應的程式碼範例。首先,我們需要建立一個File物件來表示我們想要取得大小的檔案。以下是建立File物件的方法:Filef

假設您需要將檔案的副檔名從一個副檔名重新命名為另一個副檔名,例如jpg到png。這很簡單,當然!但是,如果您有多個需要更改擴展名的檔案怎麼辦?或者更糟的是,如果這些多個檔案也位於多個資料夾和子資料夾中,在一個資料夾中呢?好吧,對於一個普通人來說,這可能是一場噩夢。但對於一個極客來說,絕對不是。現在的問題是,你是不是極客。好吧,有了 極客專頁的幫助,您絕對是!在本文中,我們透過批次腳本的方法解釋瞭如何輕鬆地重命名資料夾內所有檔案的副檔名,包括您選擇的子資料夾從一個副檔名到另一個副檔名。注意:

在JavaScript 中,undefined和null都代表著「無」的概念:1、undefined 表示一個未初始化的變數或一個不存在的屬性,當宣告了一個變數但沒有對其賦值時,這個變數的值就是undefined ,當存取物件中不存在的屬性時,傳回的值也是undefined;2、null表示一個空的物件引用,在某些情況下,可以將物件的引用設為null,以便釋放其佔用的記憶體。

c語言中null和NULL的差異是:null是C語言中的一個宏定義,通常用來表示一個空指針,可以用來初始化指針變量,或是在條件語句中判斷指針是否為空;NULL是C語言中的一個預先定義常數,通常用來表示一個空值,用來表示一個空的指標、空的指標數組或是空的結構體指標。

null和undefined的差異在:1、語意意義;2、使用場景;3、與其它值的比較;4、與全域變數的關係;5、與函數參數的關係;6、可空性檢定;7、性能考慮;8、在JSON序列化中的表現;9、與類型的關係。詳細介紹:1、語意意義,null通常表示知道這個變數不會擁有任何有效的物件值,而undefined則通常表示變數未被賦值,或物件沒有此屬性;2、使用場景等等。

null和undefined都表示缺少值或未定義的狀態,根據使用場景的不同,選擇使用null或undefined有以下一些指導原則:1、當需要明確指示一個變數為空或無效時,可以使用null;2、當一個變數已經宣告但尚未賦值時,會被預設為undefined;3、當需要檢查一個變數是否為空或未定義時,使用嚴格相等運算子「===」來判斷變數是否為null或undefined 。

用法:1、將引用類型的變數初始化為null,表示該變數目前不指向任何物件;2、將引用類型的變數設為null,可以釋放該變數所引用的物件的記憶體空間,幫助垃圾回收器回收該物件;3、使用null來檢查一個引用是否為空,可以透過判斷引用是否為null來避免NullPointerException異常的發生;4、在條件判斷中使用null,可以判斷某個引用是否為空。
