IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Edition photo dans un canvas [API HTML5]


Sujet :

JavaScript

  1. #1
    Membre éprouvé Avatar de scandinave
    Homme Profil pro
    Développeur Java, NodeJs/Angular
    Inscrit en
    Mai 2009
    Messages
    277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Java, NodeJs/Angular

    Informations forums :
    Inscription : Mai 2009
    Messages : 277
    Points : 919
    Points
    919
    Par défaut Edition photo dans un canvas
    Bonjour, j'essaye d'exploiter un peu les possibilités du canvas dans le traitement d'image.
    Voici ce que j'essaye de faire :


    En gros je récupère une image du bureau en drag&drop. Et je souhaite pouvoir modifier sa taille, son orientation, et la déplacer dans le canvas.

    Chaque fonctionnalité prise séparément est facile à mettre en place mais, pour les combiner, c'est autre chose. En effet pour la rotation faire en sorte que mon image tourne sur elle même en changeant l'origine du repère par le centre de l'image quand le canvas à été redimensionner avec scale est plus compliqué.

    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
     
    function ImagePicker(dz){
    	var dropZone = document.getElementById(dz);
    	var zoom = null; // Zoom Slider
    	var rotate = null; // Rotate Slider
    	var canvas = document.getElementById("canvas");
    	var ctx = canvas.getContext("2d");
    	var img = new Image();
    	var WIDTH = canvas.width; // Canvas width;
    	var HEIGHT = canvas.height; // Canvas height;
    	var posX = null;
    	var posY = null;
     
    	/**
    	 * Control slider activation and default values.
    	 */
    	var adaptSlider = function(width, height){
    		rotate.disabled = false;
    		zoom.disabled = false;
    		zoom.oldValue = 100;
    	};
     
     
    	/**
    	 * Handles dropped file and draws it into canvas.
    	 */
    	var handleFileSelect = function(evt){
     
    		evt.stopPropagation();
    		evt.preventDefault();
     
    		var file = evt.dataTransfer.files[0]; // FileList object.
     
    		var reader = new FileReader();
     
    		// Closure to capture the file information.
    		reader.onload = (function(f) {
    			return function(e) {
    				img.src = e.target.result;
    				img.onload = function(){
    					adaptSlider(this.width, this.height);
    					ctx.drawImage(this, 0, 0, this.width, this.height);
    				};
    			};
    		})(file);
     
    		// Read in the image file as a data URL.
    		reader.readAsDataURL(file);
    	};
     
    	/**
    	 * Handles dropped file when it is not on the drop zone
    	 */
    	var handleDragOver = function(evt){
    		evt.stopPropagation();
    		evt.preventDefault();
    		evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
    	};
     
    	/**
    	 * Handles image zoom.
    	 */
    	var onZoom = function(evt){
     
    			/*
    			 * I want to rescale image from its own center if it is smaller that canvas. not from the left-top corner.
    			 * Doesn't work.
    			 */
    			if(img.width * zoom.value / 100 < WIDTH || img.height * zoom.value / 100 < HEIGHT){ 
     
    				/*ctx.scale(zoom.value / 100, zoom.value / 100);
    				var decalWidth =  - ((img.width * zoom.value / 100));
    				var decalHeight = - ((img.height * zoom.value / 100));
    				console.log(decalWidth,  decalHeight);
    				ctx.translate(WIDTH - decalWidth, HEIGHT - decalHeight);
    				ctx.drawImage(img, 0, 0 , img.width, img.height);*/
    			} else { // Default béhavior.
    				ctx.clearRect ( 0 ,0 , WIDTH , HEIGHT );
    				ctx.save();
    				ctx.scale(zoom.value / 100, zoom.value / 100);
    				ctx.drawImage(img, 0, 0, img.width, img.height);
    				ctx.restore();
    			}
     
    	};
     
    	/**
    	 * Handles image rotation.
    	 */
    	var onRotate = function(evt){
    		ctx.clearRect ( 0 ,0 , WIDTH , HEIGHT );
    		ctx.save();
    		/*
    		 * Quel valeur dois-je utiliser pour que le point d'origine correspond au centre de mon image même si le canvas à été redimensionné?
    		 * Quel valeur doi-je ensuite utilisé comme coordonnée de l'image? 
    		 */
    		ctx.translate(img.width * (zoom.value/100) /2, img.height * (zoom.value/100) /2); 
    		ctx.rotate(rotate.value*Math.PI/180);
    		ctx.drawImage(img, -1 * (img.width * (zoom.value/100) /2), -1 * (img.height * (zoom.value/100) /2), img.width, img.height );
    		ctx.restore();
    	};
     
     
    	/**
    	 * Handles image move.
    	 */
    	var onMouseMove = function(evt){
    		var newPosX = evt.pageX;
    		var newPosY = evt.pageY;
    		ctx.clearRect ( 0 ,0 , WIDTH , HEIGHT );
    		//ctx.drawImage(img, newPosX - posX , newPosY - posY , img.width, img.height );
     
    		if(newPosX > posX && newPosY > posY) 
    			ctx.drawImage(img, newPosX - posX , newPosY - posY , img.width, img.height );
    		else if(newPosX < posX && newPosY < posY) 
    			ctx.drawImage(img, newPosX - posX , newPosY - posY , img.width, img.height );
    		else if(newPosX > posX && newPosY < posY) 
    			ctx.drawImage(img, newPosX - posX , newPosY - posY , img.width, img.height );
    		else if(newPosX < posX && newPosY > posY) 
    			ctx.drawImage(img, newPosX - posX , newPosY - posY , img.width, img.height );
    	};
     
    	var handlePictureMove = function(evt){
    		posX = evt.pageX;
    		posY = evt.pageY;
    		canvas.addEventListener('mousemove', onMouseMove, false);
    		canvas.addEventListener('mouseup', function(evt){
    			canvas.removeEventListener('mousemove', onMouseMove, false);
    		}, false);
    	};
     
     
    	/**
    	 * Set the slider that control zoom.
    	 */
    	this.setZoom = function(elem){
    		zoom = elem;
    		zoom.addEventListener('input', onZoom, false);
    		zoom.addEventListener('change', onZoom, false);
    	};
     
     
    	/**
    	 * Set the slider that control rotation.
    	 */
    	this.setRotate = function(elem){
    		rotate = elem;
    		rotate.addEventListener('input', onRotate, false);
    		rotate.addEventListener('change', onRotate, false);
    	};
     
    	dropZone.addEventListener('dragover', handleDragOver, false);
    	dropZone.addEventListener('drop', handleFileSelect, false);
    	canvas.addEventListener('mousedown', handlePictureMove, false);
    };
    Le code qui pose problème est situé dans les fonctions onZoom et onRotate.

    OnZoom :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    /**
    	 * Handles image zoom.
    	 */
    	var onZoom = function(evt){
     
    			/*
    			 * I want to rescale image from its own center if it is smaller that canvas. not from the left-top corner.
    			 * Doesn't work.
    			 */
    			if(img.width * zoom.value / 100 < WIDTH || img.height * zoom.value / 100 < HEIGHT){ 
     
    				/*ctx.scale(zoom.value / 100, zoom.value / 100);
    				var decalWidth =  - ((img.width * zoom.value / 100));
    				var decalHeight = - ((img.height * zoom.value / 100));
    				console.log(decalWidth,  decalHeight);
    				ctx.translate(WIDTH - decalWidth, HEIGHT - decalHeight);
    				ctx.drawImage(img, 0, 0 , img.width, img.height);*/
    			} else { // Default béhavior.
    				ctx.clearRect ( 0 ,0 , WIDTH , HEIGHT );
    				ctx.save();
    				ctx.scale(zoom.value / 100, zoom.value / 100);
    				ctx.drawImage(img, 0, 0, img.width, img.height);
    				ctx.restore();
    			}
     
    	};
    onRotate :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    /**
    	 * Handles image rotation.
    	 */
    	var onRotate = function(evt){
    		ctx.clearRect ( 0 ,0 , WIDTH , HEIGHT );
    		ctx.save();
    		/*
    		 * Quel valeur dois-je utiliser pour que le point d'origine correspond au centre de mon image même si le canvas à été redimensionné?
    		 * Quel valeur doi-je ensuite utilisé comme coordonnée de l'image? 
    		 */
    		ctx.translate(img.width * (zoom.value/100) /2, img.height * (zoom.value/100) /2); 
    		ctx.rotate(rotate.value*Math.PI/180);
    		ctx.drawImage(img, -1 * (img.width * (zoom.value/100) /2), -1 * (img.height * (zoom.value/100) /2), img.width, img.height );
    		ctx.restore();
    	};
    Quelqu'un aurait une idée pour résoudre mon problème?

  2. #2
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 060
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 060
    Points : 44 585
    Points
    44 585
    Par défaut
    Bonjour,
    tu n'as normalement pas de calcul à faire en jouant sur la translation du context.

    Un petit exemple d'animation utilisant rotate et scale
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Canvas rotation Image</title>
    <style>
    body {
      margin: 10px;
      padding: 0px;
    }
    #myCanvas{
      border:1px solid #CCF;
    }
    </style>
    </head>
    <body>
    <canvas id="myCanvas" width="400" height="400"></canvas>
    <script>
    function drawImage(imageObj){
      var imageLarg = imageObj.width,
          imageHaut = imageObj.height,
          // centre du canvas
          centreX = canvas.width  /2,
          centreY = canvas.height /2;
      // efface l'espace
      context.clearRect(0, 0, canvas.width, canvas.height);
      // sauvegarde context
      context.save();
      // translation du context au centre du canvas
      context.translate( centreX, centreY);
      // fond d'image
      context.fillStyle = '#EEF';
      context.fillRect( -imageLarg/2, -imageHaut/2,  imageLarg, imageHaut);
      context.strokeStyle = '#CCF';
      context.strokeRect( -imageLarg/2, -imageHaut/2,  imageLarg, imageHaut);
      // rotation du context
      context.rotate( angle);
      // applique le facteur d'échelle
      context.scale( scaleX, scaleY);
      // affiche image
      context.drawImage( imageObj, -imageLarg/2, -imageHaut/2);
      // restaure context
      context.restore();
    }
    var canvas = document.getElementById('myCanvas'),
        context = canvas.getContext('2d'),
        scaleY = 2.0,
        scaleX = 2.0,
        angle  = 0,
        oImage = new Image();
        
    oImage.onload = function() {
    //  drawImage(this);
      for( var i = 0; i <20; i++){
        (function( ind){
          window.setTimeout( function(){
            scaleY -= 0.1;
            scaleX -= 0.1;
            angle  += .314/2;
            drawImage(oImage);
          }, ind* 100);
        })(i);
      }
    };
    oImage.src = 'http://www.developpez.net/template/images/logo.png';
    </script>
     </body>
    </html>

  3. #3
    Membre éprouvé Avatar de scandinave
    Homme Profil pro
    Développeur Java, NodeJs/Angular
    Inscrit en
    Mai 2009
    Messages
    277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Java, NodeJs/Angular

    Informations forums :
    Inscription : Mai 2009
    Messages : 277
    Points : 919
    Points
    919
    Par défaut
    Merci de ton aide.
    Cela marche parce que dans ton cas les deux actions sont effectués l'une après l'autre entre un même save et un restore.

    Dans mon cas si tu regarde l'image que j'ai mis, chaque action est fait indépendemment de l'autre tout en étant liées. En effet si j'ai bien compris , réaliser une translation de 100px aprés un scale x2, fera bouger le centre du context de 200 px.

    Du coup j'i bien un calcul à effectuer.

  4. #4
    Invité
    Invité(e)
    Par défaut
    on est pas obligé d'utiliser scal pour jouer sur la taille d'une image on peut le faire au moment de l'insertion dans le contexte

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    drawImage(image, x, y, largeur, hauteur)

  5. #5
    Membre éprouvé Avatar de scandinave
    Homme Profil pro
    Développeur Java, NodeJs/Angular
    Inscrit en
    Mai 2009
    Messages
    277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Java, NodeJs/Angular

    Informations forums :
    Inscription : Mai 2009
    Messages : 277
    Points : 919
    Points
    919
    Par défaut
    J'avais pensé à cette solution aussi, mais je trouvais plus élégant de passer par la méthode scale du canvas. Enfin je pense que je vais partir sur le redimensionnement de l'image comme tu le suggère. Cela rendra les calculs plus simple.

  6. #6
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 060
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 060
    Points : 44 585
    Points
    44 585
    Par défaut
    Dans mon cas si tu regarde l'image que j'ai mis, chaque action est fait indépendemment de l'autre tout en étant liées.
    je ne vois pas où est le problème, tu utilises bien le même context.
    Dans ton cas UNE SEULE fonction de dessin est suffisante.

    Enfin je pense que je vais partir sur le redimensionnement de l'image comme tu le suggère. Cela rendra les calculs plus simple.
    Plus simple en quoi ?

    Je te mets l'exemple complet "amélioré" qui tiens compte de ta façon de gérer les différents paramètres, Zoom, Rotation et Translation
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>[HTML5] Canvas et Image</title>
    <meta name="Author" content="NoSmoking">
    <style>
    body {
      font-family:Verdana, Arial, sans-serif;
      margin: 0px;
      padding: 0px;
      background:#EFEFEF;
      overflow-y:scroll;
    }
    #main{
      width:600px;
      margin:1em auto;
    }
    h1{
      color:#AAA;
      margin-left:-1em;
      text-shadow: 1px 1px 0 #FFF;
    }
    #myCanvas{
      border:1px solid #CCF;
      background:#FFF;
    }
    #cde{
      text-align:center;
    }
    #cde > * + *{
      margin-left:1em;
    }
    button{
      font-family:Arial;
      font-size:0.8em;
      margin:1em 0;
      padding:0.5em;
      min-width:2em;
      line-height:1.5em;
      border:1px solid #CCC;
      border-radius:5px;
      background:#DDD;
      background-image: -webkit-linear-gradient(top,#EEE,#DDD);
      background-image:    -moz-linear-gradient(top,#EEE,#DDD);
      background-image:         linear-gradient(top,#EEE,#DDD);
      text-shadow: 1px 1px 0 #FFF;
      cursor: pointer;
    }
    </style>
    </head>
    <body>
    <div id="main">
      <h1>[HTML5] Canvas et Image</h1>
      <canvas id="myCanvas" width="600" height="450"></canvas>
      <div id="cde">
        <button id="btn_zoom_plus">Zoom +</button>
        <button id="btn_zoom_moins">Zoom -</button>
        <button id="btn_rot_plus">Rot. +</button>
        <button id="btn_rot_moins">Rot. -</button>
        <button id="btn_gauche"></button>
        <button id="btn_droite"></button>
        <button id="btn_haut"></button>
        <button id="btn_bas"></button>
        <button id="btn_reset">Reset</button>
      </div>
    </div>
    <script>
    (function(){
      var canvas = document.getElementById('myCanvas'),
          context = canvas.getContext('2d'),
          scaleY = 1.0, scaleX = 1.0, angle  = 0,
          offsetX = 0, offsetY = 0, incX = 2, incY = 2,
          oImage = new Image();
     
      function drawImage(imageObj){
        var imageLarg = imageObj.width,
            imageHaut = imageObj.height,
            // centre du canvas
            centreX = (canvas.width  /2) -offsetX,
            centreY = (canvas.height /2) -offsetY;
        // efface l'espace
        context.clearRect(0, 0, canvas.width, canvas.height);
        // sauvegarde context
        context.save();
        // translation du context au centre du canvas
        context.translate( centreX, centreY);
        // rotation du context
        context.rotate( angle);
        // applique le facteur d'échelle
        context.scale( scaleX, scaleY);
        // affiche image
        context.drawImage( imageObj, -imageLarg/2, -imageHaut/2);
        // restaure context
        context.restore();
      }
     
      oImage.onload = function() {
        drawImage(this);
     
        var obj = this,
        oBtn = document.getElementById('btn_zoom_plus');
        
        oBtn.onclick= function(){
          scaleY += 0.1;
          scaleX += 0.1;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_zoom_moins');
        oBtn.onclick= function(){
          scaleY -= 0.1;
          scaleX -= 0.1;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_rot_moins');
        oBtn.onclick= function(){
          angle  -= .314/2;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_rot_plus');
        oBtn.onclick= function(){
          angle  += .314/2;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_reset');
        oBtn.onclick= function(){
          scaleX = scaleY = 1;
          angle  = offsetX = offsetY = 0;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_gauche');
        oBtn.onclick= function(){
          offsetX += incX;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_droite');
        oBtn.onclick= function(){
          offsetX -= incX;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_haut');
        oBtn.onclick= function(){
          offsetY += incY;
          drawImage(obj);
        };
        oBtn = document.getElementById('btn_bas');
        oBtn.onclick= function(){
          offsetY -= incY;
          drawImage(obj);
        };
      };
      oImage.src = 'http://www.developpez.net/template/images/logo.png';
    })();
    </script>
     </body>
    </html>
    Le tout fonctionne avec une seule fonction drawImage(), somme toute assez sommaire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
      function drawImage(imageObj){
        var imageLarg = imageObj.width,
            imageHaut = imageObj.height,
            // centre du canvas
            centreX = (canvas.width  /2) -offsetX,
            centreY = (canvas.height /2) -offsetY;
        // efface l'espace
        context.clearRect(0, 0, canvas.width, canvas.height);
        // sauvegarde context
        context.save();
        // translation du context au centre du canvas
        context.translate( centreX, centreY);
        // rotation du context
        context.rotate( angle);
        // applique le facteur d'échelle
        context.scale( scaleX, scaleY);
        // affiche image
        context.drawImage( imageObj, -imageLarg/2, -imageHaut/2);
        // restaure context
        context.restore();
      }

  7. #7
    Membre éprouvé Avatar de scandinave
    Homme Profil pro
    Développeur Java, NodeJs/Angular
    Inscrit en
    Mai 2009
    Messages
    277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Java, NodeJs/Angular

    Informations forums :
    Inscription : Mai 2009
    Messages : 277
    Points : 919
    Points
    919
    Par défaut
    Ok merci beaucoup. Cela fonctionne effectivement. Je comprend mieux comment le mettre en oeuvre. Grâce à toi je vais pouvoir continuer ^^

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Photo dans formulaire
    Par pascale86 dans le forum Access
    Réponses: 3
    Dernier message: 26/09/2005, 16h41
  2. Photo dans Etat
    Par Coquelicot dans le forum IHM
    Réponses: 19
    Dernier message: 16/09/2005, 02h51
  3. Inserer une photo dans une base 8i à partir de form 6i
    Par armando123 dans le forum Forms
    Réponses: 3
    Dernier message: 20/06/2005, 19h01
  4. Photo dans un Etat?
    Par cams dans le forum IHM
    Réponses: 4
    Dernier message: 02/02/2005, 12h05
  5. Photos dans la base
    Par manu00 dans le forum Bases de données
    Réponses: 5
    Dernier message: 20/06/2004, 15h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo