tag strip_tags remove preg_match_all parser img from ejemplo php binary png chunks

strip_tags - remove html tags php



Agregar un fragmento de png pHYs en php (2)

Estoy intentando agregar algo de información sobre el tamaño físico para imprimir mis PNG justo antes de que se generen.

Leer el documento libpng y las especificaciones de fragmento pHY ha sido útil, pero parece que no puedo descifrarlo.

He intentado agregar este fragmento de la manera más manual y simple posible, sin embargo, el archivo .png termina dañado. ¿Me estoy perdiendo un truco de codificación?

Para el cálculo de CRC he utilizado el resultado de 32 bits de este sitio , habiendo conectado los valores ASCII para el fragmento que me da el código siguiente.

$encoded = $_POST[''imgdata'']; $encoded = str_replace('' '', ''+'', $encoded); $decoded= base64_decode($encoded); $test = explode(''IDAT'',$decoded); $ppu=''00000000000000000010111000100011''; //32-bit integer for the pixels per unit $dppu=bindec($ppu); $test[0].=sprintf("%c",bindec(''00000000000000000000000000001001'')) //length, also 32-bit .''pHYs'' //type . sprintf("%c",$dppu) //Pixels per unit, x axis . sprintf("%c",$dppu) //Pixels per unit, y axis .''1'' //Units in metres (1 byte) . sprintf("%c", bindec(base_convert(''0x0BFAAA7E'', 16, 2))) //CRC (32-bit) .''IDAT''; $fintest=implode($test); echo $fintest;

Por favor, avíseme si es probable que funcione de esta manera. También estoy inseguro acerca de mis enteros de 32 bits: ¿tiene relleno cero ya que estoy haciendo la forma correcta de convertirlos en 32 bits?


Después de haber pasado el día en esto, descubrí que la forma de hacerlo era traducir todo byte por byte. Siguiendo los documentos, el fragmento pHYs toma:

  • 4 bytes para la longitud del fragmento (solo los datos)
  • 4 bytes para el tipo de fragmento (los caracteres ''pHYs'')
  • 9 bytes para datos de fragmentos: 4 bytes cada uno para xey densidad y 1 byte para unidad de elección
  • 4 bytes para el CRC

Escribí todo esto como una cadena binaria, rellenando los bytes con 0 según sea necesario. Luego resulta que la función chr() codifica correctamente esto para ser utilizado en el archivo PNG, a diferencia del método sprintf("%c",$string) que uso en la pregunta. Aquí está el código

$encoded = $_POST[''imgdata'']; $encoded = str_replace('' '', ''+'', $encoded); $decoded= base64_decode($encoded); $binstring=''00000000000000000000000000001001'' //4-byte length . ''01110000010010000101100101110011'' //4-byte type or ''pHYs'' . ''000000000000000000101110001000110000000000000000001011100010001100000001'' //9-byte data . base_convert(''0x0BFAAA7E'', 16, 2); //4-byte CRC foreach (str_split($binstring,8) as $b) { $on.=chr(bindec($b)); }

La variable $ on se agrega a la posición justo antes de los 4 bytes de la longitud del fragmento IDAT .


Extendiendo la respuesta de Alex y corrigiendo errores menores en su código, intentaré proporcionar un ejemplo de trabajo sobre cómo agregar un fragmento PNG pHYs, o establecer la resolución de imagen PNG en PHP puro sin remuestrear la imagen. El siguiente código lee datos de file.png y envía imágenes modificadas a la salida estándar.

<?php // Read file data $data = file_get_contents(''file.png''); // Pixels per inch $ppi = 300; // Unit conversion PPI to PPM $ppm = round($ppi * 100 / 2.54); $ppm_bin = str_pad(base_convert($ppm, 10, 2), 32, ''0'', STR_PAD_LEFT); // Split PNG data at first IDAT chunk $data_splitted = explode(''IDAT'', $data, 2); // Generate "pHYs" chunk data // 4-byte data length $length_bin = ''00000000000000000000000000001001''; // 4-byte type or ''pHYs'' $chunk_name_bin = ''01110000010010000101100101110011''; // 9-byte data $ppu_data_bin = $ppm_bin // Pixels per unit, x axis .$ppm_bin // Pixels per unit, y axis .''00000001''; // units - 1 for meters // Calculate 4-byte CRC $hash_buffer = ''''; foreach(str_split($chunk_name_bin.$ppu_data_bin, 8) as $b) $hash_buffer .= chr(bindec($b)); $crc_bin = str_pad(base_convert(crc32($hash_buffer), 10, 2), 32, ''0'', STR_PAD_LEFT); // Create chunk binary string $binstring = $length_bin . $chunk_name_bin . $ppu_data_bin . $crc_bin; // Convert binary string to raw $phys_chunk_raw = ''''; foreach(str_split($binstring, 8) as $b) $phys_chunk_raw .= chr(bindec($b)); // Insert "pHYs" chunk before first IDAT tag $new_image_data = substr($data_splitted[0], 0, strlen($data_splitted[0]) - 4) . $phys_chunk_raw . substr($data_splitted[0], strlen($data_splitted[0]) - 4, 4) . ''IDAT'' . $data_splitted[1]; // Output modified image header("Content-Type: image/png"); echo $new_image_data; ?>

O, fragmento más elegante que hace lo mismo (encontrado en habrahabr.ru ):

<?php // Read file data $data = file_get_contents(''file.png''); // Pixels per inch $ppi = 300; $incPos = strpos($data, ''IDAT'') - 4; // Get chunk position $chunk = ''pHYs''.pack(''NNc'', round($ppi/0.0254), round($ppi/0.0254), 1); // Pack chunk type + chunk data $incData = pack(''N'', 9).$chunk.pack(''N'', crc32($chunk)); // Append chunk''s size at beginning, it''s crc at the end $new_image_data = substr_replace($data, $incData, $incPos, 0); // Output modified image header("Content-Type: image/png"); echo $new_image_data; ?>

Lo único que debe recordar: este enfoque solo funciona con archivos PNG que no tienen ningún fragmento de pHYs . Por ejemplo, generado por PHP GD o JavaScript HTMLCanvasElement.toDataURL (). Si su PNG ya tiene un fragmento de pHYs, debe buscar y modificar el fragmento existente .