2009-10-19 19 views

risposta

11

Non hai bisogno di un ingresso di file, basta avere i dati con ctx.getImageData() e post al server con l'Ajax.

Vedere MDN Documentation for CanvasRenderingContext2D.getImageData().

Ma non è possibile ottenere i dati di immagine in IE, anche con ExCanvas.

+0

Qualcuno ha questo al lavoro in realtà ? Ho ottenuto che i dati restituiti da getImageData() possono essere inviati al server, ma non riesco a capire come. Ho provato a utilizzare diverse opzioni in jQuery.ajax e jQuery.post, ma non sono riuscito a capire come specificare i dati dell'immagine in una richiesta Ajax. Il mio server non può interpretare i dati che invio. Non sono riuscito a trovare alcun esempio di codice. Hai qualche indicazione? (Ho verificato che il server funzioni correttamente eseguendo la stessa richiesta con Curl come client.) Grazie. – Jayesh

+1

ok, ho funzionato. codice incollato nella risposta. – Jayesh

+3

È possibile utilizzarlo su IE con fxCanvas (non con ExCanvas). È necessario utilizzare la funzione toDataURL ("image/png", function (fxUrl) {...}). –

34

FWIW, è così che ho funzionato.

Il mio server è in google app engine. Invio l'output canvas.toDataURL() come parte della richiesta post utilizzando jQuery.post. L'URL dei dati è costituito da dati immagine codificati in base 64. Così sul server di decodifico e convertirlo in immagine

import re 
import base64 
class TnUploadHandler(webapp.RequestHandler): 
    dataUrlPattern = re.compile('data:image/(png|jpeg);base64,(.*)$') 
    def post(self): 
     uid = self.request.get('uid') 
     img = self.request.get('img') 

     imgb64 = self.dataUrlPattern.match(img).group(2) 
     if imgb64 is not None and len(imgb64) > 0: 
      thumbnail = Thumbnail(
        uid = uid, img = db.Blob(base64.b64decode(imgb64))) 
      thumbnail.put() 

Da cliente mando i dati in questo modo:

$.post('/upload', 
     { 
      uid : uid, 
      img : canvas.toDataURL('image/jpeg') 
     }, 
     function(data) {}); 

questo potrebbe non essere il modo migliore per farlo, ma funziona.

+0

Grazie funziona come burro .. :) – Surya

+0

l'argomento img verrà tagliato se è troppo grande, avere l'hai mai incontrato? – ernest

+0

@ernest Ho cercato le restrizioni post che hai menzionato (sapevo di ottenere la limitazione delle richieste) e non trovo che http://www.w3schools.com/tags/ref_httpmethods.asp W3school dice "Le richieste POST non hanno restrizioni sulla lunghezza dei dati " – ccsakuweb

2

Ecco una demo di un'app di firma online che ho scritto l'anno scorso Canvas Signature Demo. Questo ha il vantaggio di inviare solo i dati vettoriali al server. Con tutte le informazioni sul percorso, è possibile anche applicare gli algoritmi di livellamento o ridimensionarlo in base alle esigenze prima di continuare.

<canvas id="signature" width="300" height="100"></canvas> 
<form method="post" id="signature_form" action="signing.aspx"> 
<input type="hidden" name="paths" id="paths"/> 
    <p><label>Cover #</label> <input type="text" id="covernumber" name="covernumber"/> 
    <input type="submit" id="save" value="Save"/> 
</form> 

Memorizzo i dati del percorso in un campo nascosto e lo invio al server.

signature.js logica di nucleo di seguito:

mouseDown: function(event) { 
    var point = this.getRelativePoint(event); 
    this.paths.push([ point ]); 
    this.ctx.fillRect(point.x,point.y,1,1); 
    this.penDown = true; 
    this.updateField(); 
}, 
mouseUp: function(event) { 
    this.penDown = false; 
    this.ctx.closePath(); 
    if (Prototype.Browser.IE && event.srcElement.tagName != "INPUT") { 
     var ver = getInternetExplorerVersion(); 
     if (ver >= 8 && ver < 9 && document.selection) { 
      document.selection.empty(); 
     } 
    } 
}, 
mouseMove: function(event) { 
    if (this.penDown) { 
     var lastPath = this.paths[ this.paths.length - 1 ]; 
     var lastPoint = lastPath[ lastPath.length - 1 ]; 
     var point = this.getRelativePoint(event); 
     lastPath.push(point); 
     this.ctx.strokeStyle = "#000000"; 
     this.ctx.beginPath(); 
     this.ctx.moveTo(lastPoint.x,lastPoint.y); 
     this.ctx.lineTo(point.x, point.y); 
     this.ctx.stroke(); 
     this.ctx.closePath(); 
     this.updateField(); 
    } 
}, 
updateField: function() { 
    if (this.field) { 
     this.field.value = this.paths.toJSON(); 
    } 
} 

Ecco il mio codice lato server Net rilevanti (C#).

if (Request("paths")) { 
    var objBitmap : Bitmap = new Bitmap(300, 100); 
    var objGraphics : Graphics = Graphics.FromImage(objBitmap); 
    objGraphics.Clear(Color.Transparent); 
    objGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 

    var paths:Array = eval(Request("paths")) || []; 
    var p : int; 
    var q : int; 
    var path : Array; 

    for (p = 0; p< paths.length; p++) { 
     var path = paths[p]; 
     if (path.length == 1) { 
      objGraphics.DrawRectangle(new Pen(Color.Black), path[0].x, path[0].y, 1, 1); 
     } else { 
      for (q = 1; q<path.length; q++) { 
       var prev = path[q-1]; 
       var curr = path[q]; 
       objGraphics.DrawLine(new Pen(Color.Black), parseInt(prev.x),parseInt(prev.y),parseInt(curr.x),parseInt(curr.y)); 
      } 
     } 
    } 
    objBitmap.Save("C:\\temp\\" + Request("covernumber") + ".png", ImageFormat.Png); 
    objBitmap.Dispose(); 
    objGraphics.Dispose(); 
} 
5

Ecco come ho risolto questo. Pubblicare l'immagine come array base64 usando JavaScript e decodificandolo e salvandolo come immagine usando PHP.

lato client (JavaScript):

$.post('/ajax/uploadthumbnail', 
    { 
     id : id, 
     img : canvas.toDataURL("image/png") 
    }, function(data) { 
     console.log(data); 
    }); 

lato server (PHP):

$img = $_POST['img']; 
$img = str_replace('data:image/png;base64,', '', $img); 
$img = str_replace(' ', '+', $img); 
$data = base64_decode($img); 
$file = $_SERVER['DOCUMENT_ROOT'] . '/images/some_name.png'; 
file_put_contents($file, $data);