2011-10-21 17 views
11

Sto provando a tagliare una quantità variabile di spazi bianchi in un'immagine solo sul lato sinistro e destro usando ImageMagick e PHP. Qualcuno sa come farlo (forse usando qualcosa di diverso da imagemagick?)?Come posso tagliare solo il lato sinistro e destro di un'immagine usando Imagemagick in PHP?

Ecco un esempio.

Ho questi due immagini:
Test
Test Again
Ognuno ha una quantità variabile di testo che viene creato dinamicamente in un'immagine larghezza fissa. Che cosa devo fare è tagliare il fondo fuori dal lato destro e sinistro in modo che le immagini vengono fuori in questo modo:
TestResult
Test Again Result

Se ImageMagick non può farlo, io sono disposto a usare qualcosa di diverso , ma avrò bisogno di aiuto su come esattamente perché non sono un gran programmatore. Grazie!

Ecco il mio codice corrente che rifila tutti i lati di un'immagine:

<?php 
/* Create the object and read the image in */ 
$i = '3'; 
$im = new Imagick("test".$i.".png"); 

/* Trim the image. */ 
$im->trimImage(0); 

/* Ouput the image */ 
//header("Content-Type: image/" . $im->getImageFormat()); 
//echo $im; 
/*** Write the trimmed image to disk ***/ 
$im->writeImage(dirname(__FILE__) . '/test'.$i.'.png'); 
/*Display Image*/ 
echo $img = "<img src=\"test".$i.".png\">"; 
?> 

risposta

4

Da quello che posso vedere nella documentazione ImageMagick su cropping and borders, non sembra essere possibile.

Non è possibile specificare un fronte per il ritaglio "intelligente" (noto come -trim sulla riga di comando) e tutti i metodi di ritaglio che accettano un argomento di geometria necessitano di un numero fisso per il ritaglio.

L'unica idea che viene in mente è quella di ottenere il colore dell'area rasata in una chiamata separata, eseguire trimImage e aggiungere nuovamente le aree perse utilizzando -border.

Modifica: Il manuale IM suggerisce qualcosa di simile. Controlla Trimming Just One Side of an Image. Non ho familiarità con l'estensione PHP di IM per tradurre il codice in chiamate PHP, ma dovrebbe essere a metà strada semplice.

+3

Sono stato in grado di tagliare il lato destro e sinistro di un'immagine usando questo codice: exec ('convert test4.png -gravity West -background white -splice 5x0 -background black -splice 5x0 -trim + repage -chop 5x0 test44.png '); Grazie! exec ('convert test44.png -gravity East -background white -splice 1x0 -background black -splice 1x0 -trim + repage -chop 1x0 test44.png'); – Nathan

+0

Puoi anche combinare i lati del taglio in un unico comando (che è più efficiente e fornirà una migliore qualità), ad esempio per i margini destro e inferiore: 'convert -gravity North -background white -splice 0x1 -trim + repage -chop 0x1 -gravity West -background white -splice 1x0 -trim + repage -chop 1x0 ' – dvo

0

Usa cropImage() invece. Qualcosa di simile, forse:

$img_x_size = 800; // Set these to relevant values 
$img_y_size = 600; 

$crop_pixels = 20; // How many pixels to crop 

// cropImage(XsizeOfCrop, YsizeOfCrop, CropXPos, CropYPos) 
$im->cropImage($img_x_size - $crop_pixels, $img_y_size, 0, $crop_pixels/2); 
+0

Il problema con questo (se sto capendo crop_pixels co rrectly) è che rimuove solo una quantità fissa di pixel - trimImage effettivamente ritaglia l'immagine finché non si scontra con qualcosa di diverso dal colore di sfondo (in modo da rendere l'immagine più piccola possibile). Quindi non penso che funzionerà ... Ho aggiunto chiarezza alla mia domanda dato che era un po 'confusa. Grazie! – Nathan

1

Utilizzando GD:

function imageautocrop(&$img) { 
    $emptycol = function ($img, $x, $min, $max) { 
     for($y=$min; $y<$max; $y++) { 
      $col = imagecolorsforindex($img, imagecolorat($img, $x, $y)); 
      if($col['alpha'] != 127) return false; 
     } 
     return true; 
    } 
    $trim = Array('top'=>0,'bot'=>0,'lft'=>0,'rgt'=>0); 
    $size = Array('x'=>imagesx($img)-1,'y'=>imagesy($img)-1); 
    // code for affecting rows removed due to question asked 
    while($emptycol($img, $trim['lft'], $trim['top'], $size['y']-$trim['bot'])) $trim['lft']++; 
    while($emptycol($img, $size['x']-$trim['rgt'], $trim['top'], $size['y']-$trim['bot'])) $trim['rgt']++; 
    $newimg = imagecreate($size['x']-$trim['lft']-$trim['rgt']+1, $size['y']-$trim['top']-$trim['bot']+1); 
    imagecopy($newimg, $img, 0, 0, $trim['lft'], $trim['top'], imagesx($newimg)+1, imagesy($newimg)+1); 
    imagedestroy($img); 
    $img = $newimg; 
} 

E 'molto vecchio codice del mio, quindi probabilmente non è ottimale, ma non il lavoro.

+0

Ho provato a usare il tuo codice, ma non riesco a farlo funzionare ... come ho detto che non sono un gran programmatore. Potresti darmi linee per caricare un'immagine e quindi scrivere modifiche all'immagine? Mi dispiace per la mia ignoranza. – Nathan

+0

'$ img = imagecreatefrompng (" FILENAME.png "); imageautocrop ($ img); imagepng ($ img, "NEWFILENAME.png"); ' –

5

La libreria basata su GD WideImage ha qualcosa di simile. Si chiama autoCrop, per impostazione predefinita funziona su tutti e quattro i lati.

Tuttavia, è possibile semplicemente aggiungere un altro parametro e basato su di esso solo ritaglio superiore/inferiore o sinistra/destra.

autoCrop code

E 'abbastanza ben documentato. $img è un tipo WideImage_Image. C'è anche un interactive online demo of it.

domanda relativa: Removing black bars off video thumbnail.

+1

Come commento aggiuntivo: puoi usare quella libreria e tagliare tutti i lati, quindi utilizzare la stessa libreria per centrare l'immagine ritagliata su un'altra immagine che ha la giusta altezza (e la stessa larghezza dell'immagine ritagliata) con il colore di sfondo in questione. Lavoro fatto (se il testo era originariamente centrato sull'asse y). – hakre

+0

Sembra che funzionerà (ho WideImage attivo e funzionante) - ma non sono sicuro di come aggiungere un altro parametro per eseguire solo la copia automatica dei lati sinistro e destro di un'immagine. Potresti fornire il codice? Grazie per l'aiuto. – Nathan

0

Si tratta di un processo in due fasi come testo viene generata dinamicamente

  • generare l'immagine del testo, determinare la larghezza (immagine)
  • immagine Testo di sovrapposizione in fondo, determinare la larghezza (sfondo)
  • Utilizzare uno strumento di cui sopra, delle colture (larghezza (sfondo) -width (immagine)/2 su entrambi i lati

il trucco è capire l'ampiezza (immagine) Vedi:. How can I auto adjust the width of a GD-generated image to fit the text?

Poi di nuovo, se si conosce la larghezza (immagine), è possibile ritagliare la larghezza (sfondo) prima di sovrapposizione

12

penso che siete sulla strada giusta con ImageMagick s' -trim operatore 1), ma il trucco sarebbe quello di farlo dirvi che cosa sarebbe fare a meno realtà farlo, e quindi modificare quello di fare ciò che si vuole veramente ...

quindi, per ottenere l'assetto-box ImageMagick calcola per la tua prima immagine, fai questo:

convert -fuzz 10% image.jpg -format "%@" info: 
60x29+21+31 

Questo è un rettangolo di 60x29 pixel, offset 21 su e 31 in basso dall'angolo in alto a sinistra. Ora, vogliamo ottenere questi valori nella bash variabili, così ho impostato l'IFS (Input Separatore campo) per dividere i campi su spazi, x e anche + segni:

#!/bin/bash 
IFS=" x+" read a b c d < <(convert -fuzz 10% image.jpg -format "%@" info:) 

echo $a $b $c $d 
60 29 21 31 

Ora posso ignorare il 29 e la 31 perché siamo interessati solo ritaglio la larghezza, e raccolto in questo modo:

convert image.jpg -crop "${a}x+${c}+0" out.jpg 

Così, per le 2 immagini, ottengo questi:

enter image description here enter image description here

e l'intera procedura è la seguente:

#!/bin/bash 
IFS=" x+" read a b c d < <(convert -fuzz 10% image.jpg -format "%@" info:) 
convert image.jpg -crop "${a}x+${c}+0" out.jpg 

Note

1) Il -format %@ ossia una scorciatoia per il -trim operatore, che sarebbe presente in piena

convert image.jpg -trim info: 
image.jpg JPEG 72x40 200x100+16+24 8-bit sRGB 0.000u 0:00.000 
+0

Brillante spiegazione e risposta. Funziona liscio come la seta. Grazie mille. –

Problemi correlati