tutoriales tutorial programar objetos español ejemplos con como arreglos arreglo aprendiendo php math rotation imagemagick imagick

php - programar - tutorial json javascript



Cómo crear una imagen grande(Alta calidad 300 ppp) a partir de JSON/matriz de datos(ancho, alto, x, y, ángeles) usando PHP ImageMagic/Imagick (3)

Creé un diseño (270x470) con algunas imágenes y texto en Canvas utilizando FabricJs luego FabricJs toda la información de imágenes / texto en formato JSON mediante el método canvas.toJSON () de fabricJS. 2790x4560) imagen en PHP usando Imagick.

JSON dataArray para el diseño anterior que contiene toda la información del objeto como tamaño, posición, ángulo, etc.

{ "width": "2790", "height": "4560", "json_data": { "objects": [{ "type": "image", "originX": "left", "originY": "top", "left": "5", "top": "105", "width": "260", "height": "260", "scaleX": "1", "scaleY": "1", "angle": "0", "opacity": "1", "src": "http://example.com/images/098f20be9fb7b66d00cb573acc771e99.JPG", }, { "type": "image", "originX": "left", "originY": "top", "left": "5", "top": "229.5", "width": "260", "height": "11", "scaleX": "1", "scaleY": "1", "angle": "0", "opacity": "1", "src": "http://example.com/images/aeced466089d875a7c0dc2467d179e58.png", }, { "type": "image", "originX": "left", "originY": "top", "left": "51.07", "top": "135.58", "width": "260", "height": "11", "scaleX": "1", "scaleY": "1", "angle": "47.41", "opacity": "1", "src": "http://example.com/images/910ce024d984b6419d708354bf3641a3.png", }, { "type": "image", "originX": "left", "originY": "top", "left": "139.71", "top": "104.97", "width": "260", "height": "11", "scaleX": "1", "scaleY": "1", "angle": "89.65", "opacity": "1", "src": "http://example.com/images/88e096a82e5f8a503a71233addaff64c.png", }, { "type": "image", "originX": "left", "originY": "top", "left": "230.78", "top": "146.93", "width": "260", "height": "11", "scaleX": "1", "scaleY": "1", "angle": "134.98", "src": "http://example.com/images/d2c0ec738c1fec827381cfeb600bd87d.png", }, { "type": "image", "originX": "left", "originY": "top", "left": "265.01", "top": "240.19", "width": "260", "height": "11", "scaleX": "1", "scaleY": "1", "angle": "179.86", "opacity": "1", "src": "http://example.com/images/3f0bc771261860d917e0ad6d09cb2064.png", }], "background": "#FF00FF" }}

Y aquí mi Fragmento de Código para generar Imagen de Alta Calidad en PHP usando JSON dataArray

error_reporting(E_ALL | E_STRICT); try { $id = $_GET[''id'']; // Design ID define(''DS'', DIRECTORY_SEPARATOR); $jsonDir = dirname(__FILE__) . DS . ''media'' . DS . ''designs''; $printData = json_decode(file_get_contents($jsonDir . DS . $id . ''.json'')); } catch (Exception $e) { echo $e->getMessage(); } try { $print = new Imagick(); $print->setResolution(300, 300); $background = (empty($printData->json_data->background)) ? ''transparent'' : $printData->json_data->background; $print->newImage($printData->width, $printData->height, new ImagickPixel($background)); $print->setImageFormat(''png32''); $print->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER); } catch (Exception $e) { echo $e->getMessage(); } // Re-Scaling each Image/Text for Larger Canvas/Image foreach ($printData->json_data->objects as $i => $object) { if ($object->type == ''image'') { addImage($object, $print, $printData); } else { addText($object, $print, $printData); } } try { // Saving High Quality Image in (300 dpi) $fileDir = dirname(__FILE__) . DS . ''media'' . DS . ''prints''; if (!file_exists($fileDir) || !is_dir($fileDir)) { if (!mkdir($fileDir)) die("Could not create directory: {$fileDir}/n"); } $saved = $print->writeimage($fileDir . DS . $id . ''.png''); header(''Content-type: image/png''); echo $print; } catch (Exception $e) { echo $e->getMessage(); }

añadir imagen();

function addImage($object, $print, $printData) { try { $widthScale = ($printData->width / 270); $heightScale = ($printData->height / 470); $fileDir = dirname(__FILE__) . DS . ''media'' . DS . ''original'' . DS; $src = new Imagick($fileDir . basename($object->src)); $size = $src->getImageGeometry(); $resizeWidth = ($object->width * $object->scaleX) * $widthScale; $resizeHeight = ($object->height * $object->scaleY) * $heightScale; $src->resizeImage($resizeWidth, $resizeHeight, Imagick::FILTER_LANCZOS, 1); $sizeAfterResize = $src->getImageGeometry(); $src->rotateImage(new ImagickPixel(''none''), $object->angle); $sizeAfterRotate = $src->getImageGeometry(); if (!$object->angle) { $left = $object->left * $widthScale; $top = $object->top * $heightScale; } else { switch ($object->angle) { case $object->angle > 315: $left = ($object->left * $widthScale); $top = ($object->top * $heightScale); break; case $object->angle > 270: $left = ($object->left * $widthScale); $top = ($object->top * $heightScale); break; case $object->angle > 225: $left = ($object->left * $widthScale); $top = ($object->top * $heightScale); break; case $object->angle > 180: $left = ($object->left * $widthScale); $top = ($object->top * $heightScale); break; case $object->angle > 135: $left = ($object->left * $widthScale); $top = ($object->top * $heightScale); break; case $object->angle > 90: $left = ($object->left * $heightScale) - ($sizeAfterRotate[''width''] / 2); $top = ($object->top * $heightScale) - ($sizeAfterRotate[''width''] / 2); break; case $object->angle > 45: $left = ($object->left * $widthScale) - $size[''height''] * $widthScale; $top = ($object->top * $heightScale) - $size[''height''] * $heightScale; break; default: $left = $object->left * $widthScale; $top = $object->top * $heightScale; break; } } $print->compositeImage($src, Imagick::COMPOSITE_DEFAULT, $left, $top); } catch (Exception $e) { echo $e->getMessage(); } }

Los resultados de Mi salida (90%) están allí con la solución anterior, pero como podemos ver, algunas imágenes (línea de número azul) no se colocan en la posición exacta que debería verse como la primera imagen de diseño

Básicamente, lo que estoy tratando de hacer es: "Dentro de un bucle que llama a un método addImage para escalar - rotar - coloque cada imagen en la imagen de impresión (300DPi)

no estoy seguro de lo que me falta para obtener el desplazamiento exacto (nuevas coordenadas x, y / posición / Izquierda-Arriba) después de la Rotación para una imagen en Imagick o estoy girando el objeto después de Escala y luego componer

o puede ser una fórmula matemática como Math.PI :)

La pregunta es : ¿Cómo puedo calcular el nuevo desplazamiento / posición según el grado de rotación / ángulo después de la escala?

Espero que el fragmento publicado sea útil para todos.


Aquí obtengo una solución, puede ser que ayude a otros como para mí.

<?php // AZinkey ini_set(''memory_limit'', ''1024M''); // may be need increase memory size ini_set(''display_errors'', 1); // enable error display error_reporting(E_ALL); // show all type errors $id = $_GET[''id'']; $file = $id . ".json"; // json file e.g. 1234.json $printData = json_decode(file_get_contents($file)); $mask = "mask.png"; // a image (4395x4395) which contains 2669x4395 black fill in center $maskImg = new Imagick($mask); $d = $maskImg->getImageGeometry(); $maskWidth = $d[''width'']; $maskHeight = $d[''height'']; // Then reduce any list of integer $cd = array_reduce(array($maskWidth, 400), ''gcd''); $r1 = $maskWidth / $cd; $r2 = 400 / $cd; $newPrintData[''r1''] = $r1; $newPrintData[''r2''] = $r2; try { $print = new Imagick(); $print->setResolution(300, 300); $background = (empty($printData->json_data->background)) ? ''transparent'' : $printData->json_data->background; $print->newImage($maskWidth, $maskHeight, new ImagickPixel($background)); $print->setImageMatte(TRUE); $print->setImageFormat(''png32''); $print->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER); } catch (Exception $e) { echo $e->getMessage(); } // create two array for store text & images information separately $imageObjects = $textObjects = []; foreach ($printData->json_data->objects as $object) { if ($object->type == ''image'') { $imageObjects[] = $object; } else if ($object->type == ''text'') { $imageObjects[] = $object; } } foreach ($imageObjects as $object) { addImageToLarge($object, $print, $printData, $newPrintData); } foreach ($imageObjects as $object) { addTextToLarge($object, $print, $printData, $newPrintData); } try { $print->setImageFormat(''png''); $saveFile = $id . "_print.json"; // save large image _print.png file_put_contents($saveFile, $print); } catch (Exception $e) { echo $e->getMessage(); exit(); } function addImageToLarge($object, $print, $printData, $newPrintData) { try { $src = new Imagick($object->src); $size = $src->getImageGeometry(); $resizeWidth = changeDpi(scale($object->width, $newPrintData[''r1''], $newPrintData[''r2'']) * $object->scaleX); $resizeHeight = changeDpi(scale($object->height, $newPrintData[''r1''], $newPrintData[''r2'']) * $object->scaleY); $src->resizeImage($resizeWidth, $resizeHeight, Imagick::FILTER_LANCZOS, 1); $sizeAfterResize = $src->getImageGeometry(); $src->rotateImage(new ImagickPixel(''none''), $object->angle); $sizeAfterRotate = $src->getImageGeometry(); $left = $object->left < 0 ? -1 * abs(changeDpi(scale($object->left, $newPrintData[''r1''], $newPrintData[''r2'']))) : changeDpi(scale($object->left, $newPrintData[''r1''], $newPrintData[''r2''])); $top = $object->top < 0 ? -1 * abs(changeDpi(scale($object->top, $newPrintData[''r1''], $newPrintData[''r2'']))) : changeDpi(scale($object->top, $newPrintData[''r1''], $newPrintData[''r2''])); $print->compositeImage($src, Imagick::COMPOSITE_OVER, $left, $top); } catch (Exception $e) { echo $e->getMessage(); exit(); } } function addTextToLarge($object, $print, $printData, $newPrintData) { $fnt[''Times New Roman''] = "font/times_6.ttf"; $fnt[''Arial''] = "font/arial_8.ttf"; $fnt[''Arial Black''] = "font/ariblk_8.ttf"; $fnt[''Comic Sans MS''] = "font/comic_5.ttf"; $fnt[''Courier New''] = "font/cour_5.ttf"; $fnt[''Georgia''] = "font/georgia_5.ttf"; $fnt[''Impact''] = "font/impact_7.ttf"; $fnt[''Lucida Console''] = "font/lucon_3.ttf"; $fnt[''Lucida Sans Unicode''] = "font/l_4.ttf"; $fnt[''Palatino Linotype''] = "font/pala_7.ttf"; $fnt[''Tahoma''] = "font/tahoma_3.ttf"; $fnt[''Trebuchet MS''] = "font/trebuc_3.ttf"; $fnt[''Verdana''] = "font/verdana_5.ttf"; try { $line_height_ratio = $object->lineHeight; $resizeWidth = changeDpi(scale($object->width, $newPrintData[''r1''], $newPrintData[''r2'']) * $object->scaleX); $resizeHeight = changeDpi(scale($object->height, $newPrintData[''r1''], $newPrintData[''r2'']) * $object->scaleY); $print2 = new Imagick(); $print2->setResolution(300, 300); $print2->newImage($resizeWidth, $resizeHeight, "transparent"); $print2->setImageVirtualPixelMethod(imagick::VIRTUALPIXELMETHOD_BACKGROUND); $print2->setImageFormat(''png32''); $print2->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER); // Instantiate Imagick utility objects $draw = new ImagickDraw(); $color = new ImagickPixel($object->fill); //$starting_font_size = 100*1.33; $font_size = (($object->fontSize * $resizeWidth) / $object->width); $draw->setFontWeight(($object->fontWeight == ''bold'') ? 600 : 100 ); $draw->setFontStyle(0); $draw->setFillColor($color); // Load Font //$font_size = $starting_font_size; $draw->setFont($fnt[$object->fontFamily]); $draw->setFontSize($font_size); $draw->setTextAntialias(true); $draw->setGravity(Imagick::GRAVITY_CENTER); if ($object->stroke) { $draw->setStrokeColor($object->stroke); $draw->setStrokeWidth($object->strokeWidth); $draw->setStrokeAntialias(true); //try with and without } $total_height = 0; // Run until we find a font size that doesn''t exceed $max_height in pixels while (0 == $total_height || $total_height > $resizeHeight) { if ($total_height > 0) { $font_size--; // we''re still over height, decrement font size and try again } $draw->setFontSize($font_size); // Calculate number of lines / line height // Props users Sarke / BMiner: http://.com/questions/5746537/how-can-i-wrap-text-using-imagick-in-php-so-that-it-is-drawn-as-multiline-text $words = preg_split(''%/s%'', $object->text, -1, PREG_SPLIT_NO_EMPTY); $lines = array(); $i = 0; $line_height = 0; while (count($words) > 0) { $metrics = $print2->queryFontMetrics($draw, implode('' '', array_slice($words, 0, ++$i))); $line_height = max($metrics[''textHeight''], $line_height); if ($metrics[''textWidth''] > $resizeWidth || count($words) < $i) { $lines[] = implode('' '', array_slice($words, 0, --$i)); $words = array_slice($words, $i); $i = 0; } } $total_height = count($lines) * $line_height * $line_height_ratio; if ($total_height > 0) { } } // Writes text to image $x_pos = 0; $y_pos = 0; for ($i = 0; $i < count($lines); $i++) { $print2->annotateImage($draw, $x_pos, $y_pos + ($i * $line_height * $line_height_ratio), $object->angle, $lines[$i]); } if ($object->flipX == 1) $print2->flopImage(); // x if ($object->flipY == 1) $print2->flipImage(); // y $print2->trimImage(0); $print2->setImagePage(0, 0, 0, 0); $print2->resizeImage($resizeWidth, 0, Imagick::FILTER_CATROM, 0.9, false); $left = $object->left < 0 ? -1 * abs(changeDpi(scale($object->left, $newPrintData[''r1''], $newPrintData[''r2'']))) : changeDpi(scale($object->left, $newPrintData[''r1''], $newPrintData[''r2''])); $top = $object->top < 0 ? -1 * abs(changeDpi(scale($object->top, $newPrintData[''r1''], $newPrintData[''r2'']))) : changeDpi(scale($object->top, $newPrintData[''r1''], $newPrintData[''r2''])); $print->compositeImage($print2, Imagick::COMPOSITE_OVER, $left, $top); //header("Content-Type: image/png"); //echo $print2;exit; } catch (Exception $e) { echo $e->getMessage(); exit(); } } //The greatest common divisor (GCD) function gcd($a, $b) { return $b ? gcd($b, $a % $b) : $a; } function changeDpi($px) { //return ($px/96)*300; return $px; } function scale($px, $r1, $r2) { return $px * $r1 / $r2; }


Creo que obtuve lo que estás buscando, te permitirá tener una función que se utilizó hace unos años para generar una imagen de alta calidad desde una cadena JSON. Aunque tienes que hacer los cambios necesarios. Mi extensión de salida es tiff. Y la cadena json se elabora utilizando versiones de png redimensionadas al 1% más adelante. Escalo los valores s, y para tomar los psd de tamaño completo al 100%.

function generateDesignImage($arr_params,$arr_design){ extract($arr_params); $images = $arr_design[''sprites'']; $dir = $arr_design[''options''][''source_dir'']; $ext = $arr_design[''options''][''in_ext'']; $side = $arr_design[''options''][''img_side'']; $out_ext = $arr_design[''options''][''out_ext'']; // Canvas $im = new Imagick(); $im->newImage(6000,6000,''transparent''); $im->setImageColorSpace(Imagick::COLORSPACE_CMYK); //$im->setImageDepth(8); /********************* Code for image arrangements *************************/ $i =0; $min_X = $min_Y = 6000; $max_X = $max_Y = 0; $scale = 10; foreach($images as $sprites=>$val){ $var = "img_$i"; $var = new Imagick(); $var->resizeImage($var->getImageWidth()/$scale,$var->getImageHeight()/$scale,Imagick::FILTER_LANCZOS,1,TRUE); /************ Find out x,y,width and height *********************/ $c_width = $var->getImageWidth()/2; $c_height = $var->getImageHeight()/2; $x1 = ($val[''x'']*$scale/$val[''scale''])-$c_width; $y1 = ($val[''y'']*$scale/$val[''scale''])-$c_height; $x2 = ($val[''x'']*$scale/$val[''scale''])+$c_width; $y2 = ($val[''y'']*$scale/$val[''scale''])+$c_height; $min_X = ($min_X >= $x1)?$x1:$min_X; $min_Y = ($min_Y >= $y1)?$y1:$min_Y; $max_X = ($max_X <= $x2)?$x2:$max_X; $max_Y = ($max_Y <= $y2)?$y2:$max_Y; /***************************************************************/ $im->compositeImage($var, $var->getImageCompose(), $x1,$y1,imagick::MONTAGEMODE_FRAME); $i++; } /**************************************************************************/ $im->setImageFormat( $out_ext ); /******************Crop to Exact Fit ********************************/ $im->cropImage ( $max_X-$min_X+100,$max_Y-$min_Y+100 ,$min_X-50 ,$min_Y-50 ); /************************************************************************/ $success1 = $im->writeImage( ''Out_image_''.$design_id.''.''.$out_ext); $var->BorderImage(new ImagickPixel("white") , 5,5); return $success1; }


Esta no es una respuesta completa, pero lo estás haciendo completamente mal.

Fabric.js ya tiene una forma de guardar un lienzo en formato SVG con la función canvas.toSVG() . Imagick puede abrir archivos SVG y convertirlos a PNG en la calidad que desee.

Habrá un problema al tratar de incluir los mapas de bits que se incluyen en la imagen, por ejemplo,

"src": "http://example.com/images/3f0bc771261860d917e0ad6d09cb2064.png",

Recomiendo encarecidamente descargarlos en el servidor, en lugar de permitir que Imagick los descargue. Eso no solo le dará un mejor control sobre cualquier error que pueda ocurrir, sino que también limitará algunos riesgos de seguridad. No es una buena idea permitir que las personas descarguen datos arbitrarios desde su servidor y luego usar esos datos en una biblioteca que ha tenido muchos errores con el acceso a la memoria.

La forma general de hacer esto sería reemplazar el src de la imagen con una referencia a un nombre de archivo local, ya sea antes de que Fabric.js cree el SVG o podría hacerlo de forma aún más imprudente después de que se haya convertido, y cuando haga este reemplazo. genere una lista de archivos que deben descargarse desde un servidor remoto.

Los detalles reales de la implementación se dejan como un ejercicio para OP.

Por cierto, existe una posibilidad razonable de que alguien ya haya hecho esto ... ¿ha buscado minuciosamente el paquete / github?