Jump to content

Canvas.toDataURL only takes a picture of visible portion ... or is Phaser cutting it off?


ForgeableSum
 Share

Recommended Posts

If you get the base64 of the entire canvas:

var canvasData = game.canvas.toDataURL(); 

Reload the game. Then copy + paste that base64 string into a variable and use said variable to add an image to cache in preload:

var data = new Image();data.src = canvasDataURI;game.cache.addImage('image-data', canvasDataURI, data);

Then create the image:

var image = game.add.image(360, 30, 'image-data');

The image will load into the game but it appears cut off. It's approximately the size of the window ... weird because this same thing was happening when I tried to draw the entire game.canvas into a bitmap data object and add it to the world. The image is cut off! If you use drawGroup, instead of some of the copy method though, it's not cut off. What the eff? I keep running into this issue. HELP!

Link to comment
Share on other sites

When you call toDataURL on the canvas it will only ever capture an image the exact size of the canvas itself, i.e. the size will match the pixel dimensions of the canvas. If it's scaled through CSS it doesn't matter. If it's scaled through code, it doesn't matter. The capture will still only ever be the size of the canvas DOM element.

 

If your game canvas is 640x480 then you'll get a 640x480 image captured, even if your game world is thousands of pixels big.

 

drawGroup doesn't care about the canvas size - it will take a group of objects and render the whole lot of them, regardless if they're actually visible on the canvas or not. It will render as many as it can fit into the BitmapData width/height (which can be anything and doesn't have to match the canvas size).

 

If you want to grab an image of your full game world then you need to render all of the display objects in the world to a BitmapData big enough to hold them all. If you render just the game.canvas to the BitmapData you'll only ever get a result the exact same size of the canvas itself (unless that is bigger than your BitmapData, in which case it'll be cropped off to fit the destination).

Link to comment
Share on other sites

When you call toDataURL on the canvas it will only ever capture an image the exact size of the canvas itself, i.e. the size will match the pixel dimensions of the canvas. If it's scaled through CSS it doesn't matter. If it's scaled through code, it doesn't matter. The capture will still only ever be the size of the canvas DOM element.

 

If your game canvas is 640x480 then you'll get a 640x480 image captured, even if your game world is thousands of pixels big.

 

drawGroup doesn't care about the canvas size - it will take a group of objects and render the whole lot of them, regardless if they're actually visible on the canvas or not. It will render as many as it can fit into the BitmapData width/height (which can be anything and doesn't have to match the canvas size).

 

If you want to grab an image of your full game world then you need to render all of the display objects in the world to a BitmapData big enough to hold them all. If you render just the game.canvas to the BitmapData you'll only ever get a result the exact same size of the canvas itself (unless that is bigger than your BitmapData, in which case it'll be cropped off to fit the destination).

Wow, that explains a lot. So the canvas will only ever be the size of the window because it's only rendering what you see in the window, correct? Damn, so I can't use toDataURL after all.

 

I'm fine with putting everything I need into a bitmap data object, but how do i store that info and re-use it in another game instance? with a base64 (the result of toDataURL), I have everything inside that one string, so it would be easy to create save/load functionality from that. But can it be done with a bitmap data object as well? What properties of the object do I need to store that will allow me to recreate the bitmap data object? Thanks!

Link to comment
Share on other sites

Can you use double buffering for you draws?

 

You have an off screen/invisible (large) canvas that you draw to and then copy the visible portion of that to the displayed canvas. This is an old technique used way back in DOS days for straight to hardware graphics.

Link to comment
Share on other sites

base64 would be fine, but personally I'd just save it as a PNG and load that into the other games. You can save BitmapData.canvas as a PNG, or game.canvas, whatever you need. There's actually some code to do it in the phaser-examples repo. Look in the examples/wip folder for a folder called "spritesheet" (or something like that!) inside you'll find a sprite sheet tool I made, but the important bits you need are the files like canvasToBlob.js and FileSaver.js which will turn a canvas into a PNG saved to your local file system.

Link to comment
Share on other sites

Can you use double buffering for you draws?

 

You have an off screen/invisible (large) canvas that you draw to and then copy the visible portion of that to the displayed canvas. This is an old technique used way back in DOS days for straight to hardware graphics.

 

Ah but wouldn't this but a huge load on performance as I'd be applying draws in two places?

 

base64 would be fine, but personally I'd just save it as a PNG and load that into the other games. You can save BitmapData.canvas as a PNG, or game.canvas, whatever you need. There's actually some code to do it in the phaser-examples repo. Look in the examples/wip folder for a folder called "spritesheet" (or something like that!) inside you'll find a sprite sheet tool I made, but the important bits you need are the files like canvasToBlob.js and FileSaver.js which will turn a canvas into a PNG saved to your local file system.

The problem is that my maps are literally 15,000 pixels in width and height. I'm not sure if it would be feasible to upload/download a PNG/jpeg that big. :)

 

So I can save BitmapData as a base64? I will checkout those examples tonight. Thanks again!

Link to comment
Share on other sites

base64 would be fine, but personally I'd just save it as a PNG and load that into the other games. You can save BitmapData.canvas as a PNG, or game.canvas, whatever you need. There's actually some code to do it in the phaser-examples repo. Look in the examples/wip folder for a folder called "spritesheet" (or something like that!) inside you'll find a sprite sheet tool I made, but the important bits you need are the files like canvasToBlob.js and FileSaver.js which will turn a canvas into a PNG saved to your local file system.

Wow, I just realized from your comment that the bitmapData object has its own canvas. I thought it drew to the visible game canvas? I was confused because I didn't realize a bmd creates its own canvas object. The canvas object isn't added to the dom (I can't find it in explorer) as an HTML element, but it still exists in a variable... curious how that all works. 

 

At any rate, drawing the game world to a BitmapData, then converting the canvas of the bitmap data to a base64 works, and I have the entire canvas! Now to see how big my files will be with a 15K x 15k pixel map ... fingers crossed!

Link to comment
Share on other sites

So I can save up to about 13,000 x 13,000 pixels (base64 in a text file) until my browser crashes. The file size isn't too bad (50 MB). I'm thinking this is probably not the most economical way to save large maps! I haven't even tried to draw that much base64 data back onto the canvas. 

Link to comment
Share on other sites

How are your maps built? Are they using tiles?

 

If it's built from tiles or even larger sections why do you need the whole map built at the start?

 

Haha, if only. But my ground textures aren't restricted to a tile-based system. As you can see from this video, I'm blending images together to create the map. I wouldn't be able to have this level of customization if I stuck with a strict tile-based system.   

 

I am using tiles though. It's just that I'm modifying the tiles as bitmap data - so I can't recreate the map using the original tile images. 

Link to comment
Share on other sites

Hey,

data is key. You should really think about a custom data format to present your maps in basic numbers instead of a full blown bitmap. Think of the maps of a normal tiling system. It's just ridiculous to think that a user will download 50MB for a single map not to talk about the performance hit or even a failure (!) when you hit the system's MAX_TEXURE_SIZE.

 

1. The first step: Record all the drawing the user is doing. This would allow you to replay every action to regenerate the map at runtime. Just this will be a lot smaller than the 50MB png file.

2. But don't stop here: Remove every covered or repeating tile as the user could have drawn to on top of each other. This will save precious rendering time and file size.

3. Finally simplify it. Try to find groups of many tiles that could be represented just by a single tile. This will save you later again rendering time and file size.

4. You should think about tricks. Game development ist all about faking. Maybe you should change the way your map editor ist working. Don't make it totally free. Just use a smaller underlying grid tiles which are overlapping. By limiting the freedom of your user you make your life easier with # 1. to 3. You can always make the underlying grid smaller if you're not satisfied with the results.

 

I would look into other game map files, game implementations or even real map formats to get an idea how other people are doing it. You're not the first nor the last doing this :)

By the way: Forget base64 to represent large data. Base64 makes your data even larger. Always and up to 30%. It's an encoding not a compression format. 

 

Regards George

Link to comment
Share on other sites

Hey,

data is key. You should really think about a custom data format to present your maps in basic numbers instead of a full blown bitmap. Think of the maps of a normal tiling system. It's just ridiculous to think that a user will download 50MB for a single map not to talk about the performance hit or even a failure (!) when you hit the system's MAX_TEXURE_SIZE.

 

1. The first step: Record all the drawing the user is doing. This would allow you to replay every action to regenerate the map at runtime. Just this will be a lot smaller than the 50MB png file.

2. But don't stop here: Remove every covered or repeating tile as the user could have drawn to on top of each other. This will save precious rendering time and file size.

3. Finally simplify it. Try to find groups of many tiles that could be represented just by a single tile. This will save you later again rendering time and file size.

4. You should think about tricks. Game development ist all about faking. Maybe you should change the way your map editor ist working. Don't make it totally free. Just use a smaller underlying grid tiles which are overlapping. By limiting the freedom of your user you make your life easier with # 1. to 3. You can always make the underlying grid smaller if you're not satisfied with the results.

 

I would look into other game map files, game implementations or even real map formats to get an idea how other people are doing it. You're not the first nor the last doing this :)

By the way: Forget base64 to represent large data. Base64 makes your data even larger. Always and up to 30%. It's an encoding not a compression format. 

 

Regards George

thanks for the advice. the advantage of base64 to me is that it saves everything in text format which I suppose, doesn't necessarily mean smaller file size. Do you know of any alternative text/based formats which are compressed? I know there's blob, but that doesn't seem to save much space (though it is a bit smaller). 

 

But you're absolutely right about 50MB not being practical. I'd say my max would be something like 10MB of files and even that is pushing it for a browser game. 

 

I have thought about a lot of alternatives - the most promising one being the following mechanism:

* every map has a base tile which is tiled in the traditional 2D way. When you edit one of those tiles, I draw a rectangle over the area you've edited.  The rectangle increases in size the more of the map you edit.

* When the rectangle reaches a max size or if you begin editing a tile far enough away from the rectangle, a new rectangle is created. 

* When you save the map, find each rectangle area and save those areas as custom tiles, each with their own top left x/y coordinate. 

* When you load the map, place those custom tiles in their respective x/y and tile the base-tile underneath. 

 

Actually, a rectangle might not be the most efficient shape. What if a user drew a really long path that goes all the way across the map? The rectangle could have a a small height and large width, but what about when the user starts drawing vertically? You've got all that extra space. Suppose I could develop code to optimize when and where the rectangle is created. 

 

It's complicated but not too complicated.

I would look into other game map files, game implementations or even real map formats to get an idea how other people are doing it. You're not the first nor the last doing this

I have yet to find a 2d map editor that doesn't adhere to tile restrictions for texture placement, because of all the complications. Do you know of any? I'm definitely going to figure out a way to do it practically, with small map file sizes, even if I have to process data on the server side. 

Link to comment
Share on other sites

Okay, after thinking about it s'more, I've come up with the following solution:

 

Create a grid proportionate to the game world with nodes approximately 300 x 300 (will tweak the size for optimization later). Each node has a boolean value: true/false. If the brush overlaps a node while pushed down, the node gets sets to true. When it's time to save the map, I loop through the grid and convert any nodes set true to mid-quality JPEGs, process that all from the server-side and store it into separate files. Then when it's time to load the map, a base texture will be tiled in the traditional way and on top of those base tiles, I'll place my customized JPEGs ... I might have to experiment a lot with node sizes. Maybe something like 1000 x 1000 would work better. In addition to the actual image, I'd also need to save 4 values: x/y and width/height, which i can do in the file name or I could store those values in an object keyed by filename ... it's simple enough that it just might work!

 

The biggest complication is creating the JPEGs from the grid. I suppose I would just loop through the grid and create a bitmap object for each node set true, then create the jpeg from the bitmap. I'd have to set it on a timer so the browser doesn't crash creating so many bitmaps at once ... Is there a less roundabout way of turning a section of the canvas into a JPEG (only a section) without needing to create a bitmap? what do you guys think of this approach? I'm thinking it's a better idea than what I outlined in my last post. 

Link to comment
Share on other sites

Just 1 thought I had would be to create textured tiles from each layer of the final map image. The important part is to still keep the layers separate.

 

Use something like 128 x 128 or 256 x 256 for sections of the map stored to a png image. Over a number of maps you would probably start to have similar tiles and can recognize them by a hash value of the png tile image. You still layer these images like a regular tile but your tileset is created on the fly in the map creator app.

 

Another part of this might be to do a diff on the tile images that are created from the mapping app and if some of them are only different by about 10% then reuse an existing image rather than create a new tile for unnoticeable difference. So if a desert texture next to another desert texture has a small windswept wave in it but not a large significant change to notice then it simply reuses the first texture instead of creating a new image. I'm not sure if I've explained this part the best I can.

 

If it's difficult to produce these textures on the fly from the mapping app the last option would be to have 3 or 4 textures already created of the terrain type and just randomly place them when you create the map. As you are creating the map you call a small section from inside this pre-made textures so that the map has at least the closest look to the final map. This would be much closer to a ground texture in something like a FPS.

Link to comment
Share on other sites

Honestly feudalwars,

try to think out of your image processing box. It seems that your thinking is totally fixed on that approach.

I see some more problems with your latest idea when you're dealing with editing existing maps.

 

+ JPEG? Mid Quality? Not for something you want to edit again. This map is going to be a soup of blurry artifacts.

+ Ignore the image quality for a moment. What did you just build? A layer of processed image tiles. Now you want to edit the map? Congratulations, you have to include them in your map editor as a separate layer, totally isolated and untouchable from the rest of the map editor. Yes you can overdraw them- but nothing more. I can assure you: This will create problems with your node-splitting-grid-algorithm-thing and it will hinder you in creating super cool features for your map editor. This might be a problem with nearly every solution based on processed images.

 

Do not ignore the replay idea I mentioned before. Record and replay all the brush drawings a user did. This creates a huge list of coordinates over time. This is just plain data which allows you to recreate the map every time with the very exact look. It's lossless and instead of a 50mb png monument or hundreds of filthy jpeg tiles you have nothing but plain text data- data that can fit into a zipped json file with let me guess, 500KB for larger maps and less than 10KB for smaller maps? If this file is growing to large you can always try to optimize it. Remove duplicate coordinates, remove overlapping brushes or create a tight binary file format.

 

Good luck!

Regards George

Link to comment
Share on other sites

Honestly feudalwars,

try to think out of your image processing box. It seems that your thinking is totally fixed on that approach.

I see some more problems with your latest idea when you're dealing with editing existing maps.

 

+ JPEG? Mid Quality? Not for something you want to edit again. This map is going to be a soup of blurry artifacts.

+ Ignore the image quality for a moment. What did you just build? A layer of processed image tiles. Now you want to edit the map? Congratulations, you have to include them in your map editor as a separate layer, totally isolated and untouchable from the rest of the map editor. Yes you can overdraw them- but nothing more. I can assure you: This will create problems with your node-splitting-grid-algorithm-thing and it will hinder you in creating super cool features for your map editor. This might be a problem with nearly every solution based on processed images.

 

Do not ignore the replay idea I mentioned before. Record and replay all the brush drawings a user did. This creates a huge list of coordinates over time. This is just plain data which allows you to recreate the map every time with the very exact look. It's lossless and instead of a 50mb png monument or hundreds of filthy jpeg tiles you have nothing but plain text data- data that can fit into a zipped json file with let me guess, 500KB for larger maps and less than 10KB for smaller maps? If this file is growing to large you can always try to optimize it. Remove duplicate coordinates, remove overlapping brushes or create a tight binary file format.

 

Good luck!

Regards George

 

Thanks, George. 

Slicing up and saving the textured layer of the canvas actually doesn't limit the user's ability to edit the map in any way, because of how the map editor works. In fact, I need to take a screenshot of the entire visible portion of the layer to use when the game starts anyway, for performance reasons.  That layer becomes extremely messy because after editing for a while, a lot of excess images get thrown on top of each other. It would be difficult to conceptualize this without knowing how the system works.

 

The basic idea is that you have two layers: a brush layer and a top layer. The brush creates a hole (by reducing opacity) in the top layer so you can see the layer underneath. When you want to switch to another texture, the area of the brush layer which you could see through the hole gets sent to the bottom of the top layer (layers are Phaser.Groups with z indexes). A callback is added to that image so you can draw a hole through in the same way you're doing with the existing images in the top layer.  Eventually the top layer becomes overcrowded if you have 5 or 6 different textures in the same area (all executing the same callback at once), so taking a screenshot of the top layer and turning all into one image with one callback only serves to optimize performance and has no drawbacks. Eventually I will do this in realtime while you are drawing to the map (to prevent overcrowding in the top layer) but my point is this: slicing up the visible portion only serves to optimize, absolutely no drawbacks in terms of your ability to edit the map after that.

 

As far as image quality goes, I only mentioned mid-quality JPEGs as a starting point. I will definitely increase the quality if a loss is noticeable. 

 

But I haven't ignored the replay idea altogether and you're right, it would be the most ideal, perfect solution with really small files being saved on the client side as opposed to fairly large files needed to be processed on the server side and sent back. The difference is huge. I just don't see it working. Regenerating the map from a record of user inputs, that is. Like I mentioned, callback functions literally execute several times in once second so there's the potential that a map could have tens of thousands of functions that would need to be executed in a short period of time to recreate the map. In addition, there's a lot of stuff going on in the background. For example, when the map editor loads, all of the images you see are tiled orthogonally from JPEGs. They're not bitmap data and they only convert into bitmap data when you apply a texture to them. I did this because it would be impossible to load hundreds of large bitmap data objects at once.

 

I realize I could put some kind of limit on callbacks and execute them only twice per second but even then, there's the potential for thousands of actions needing to be performed in a short period of time. If they were simple calculations, it would be different but we're talking about bitmap manipulations here which are expensive operations.   

 

I did explore the idea I came up with last night of slicing everything up with a grid and it's working quite well so far. With this methodology, the browser is able to save very large portions of the map by looping through the grid nodes, finding the ones that are changed, converting them to bitmap data and then to base64s. I've gotten to the step where I've got all of my base64s stored neatly in an array - from there I can do whatever I want with them. The next step is to figure out the best format to convert for sending to a server for processing. I'll probably use something like this

 

If this all works out I'll write a detailed post on my dev blog explaining the solution I come up with (with source code) in case anyone else has a need to save very large portions of the canvas with Phaser. 

Link to comment
Share on other sites

Well folks, I was able to have my cake and eat it too.

 

I did what I described above except I was able to skip the server-side part and save directly to the client in a single neatly packed JSON file. Check it out: 

 

 

Inside the JSON file is various general info about the map (size, base tile, etc) along with cutouts of each customized node (which represent changed areas of the canvas) in base64 strings. My base64 strings with JPEG mime types are quite compact. Or at least good enough for my purposes: about 300KB per 1000-square pixel area. I'm saving them at 60 percent quality but as you can see from the video, there is no noticeable loss. Even if I did want to make them higher quality, size isn't much of a concern anymore since the file is being saved directly to the client (i.e. no bandwidth repercussions). 

 

The big advantage here is that I'm only 'taking pictures' (if you will) of parts of the canvas that have been customized and can't be regenerated procedurally (from the base tiles). Of course it all depends on how much of the map the user edits, but I'm estimating most maps will be under 5MB uncompressed. 

Link to comment
Share on other sites

Yeah, congratulations! Looks promising so far. There is definitely room to improve but it's at least a working solution for the beginning so you can focus on other tasks to get the whole thing running. Good job and thanks for describing your solution.

 

Regards George

Link to comment
Share on other sites

Yeah, congratulations! Looks promising so far. There is definitely room to improve but it's at least a working solution for the beginning so you can focus on other tasks to get the whole thing running. Good job and thanks for describing your solution.

 

Regards George

Thanks. One of the things I could do to improve would be to have the option to host the images at an external source. If images were hosted at an external source, the file sizes will be 10x smaller, like under 10KB. The disadvantage though is that the map files aren't self-containing and if the external image moved, they would no longer work. I suppose I could offer this as an option though, host the images on S3 or something like that. 

 

The other thing is client-size compression

Link to comment
Share on other sites

Hey,

you can't compress already compressed data (think of the large jpg component). This won't help.

S3 is an option. You can perform client side uploads straight to the S3 Server. You only have to create the signature and policy for each s3 upload on your server- so nobody can use it for arbitrary files. The self-containing argument is important so yes, only optional or until you find a file format with a smaller payload.

Link to comment
Share on other sites

Hey,

you can't compress already compressed data (think of the large jpg component). This won't help.

S3 is an option. You can perform client side uploads straight to the S3 Server. You only have to create the signature and policy for each s3 upload on your server- so nobody can use it for arbitrary files. The self-containing argument is important so yes, only optional or until you find a file format with a smaller payload.

Why is it then when I zip a JPEG, it's could be as much as 10% smaller? 

Link to comment
Share on other sites

Please, just don't take me literally. Of course there is some entropy left to remove as the jpeg is not as specialized as the zip algorithm. You can pack your you data even smaller with algorithms like gzip or bzip2 - but the more compression the higher the duration to compress or decompress. Those 10% you got? This is premature optimization. You should work on other problems. That's why I chose that simplification.

Link to comment
Share on other sites

  • 4 weeks later...

base64 would be fine, but personally I'd just save it as a PNG and load that into the other games. You can save BitmapData.canvas as a PNG, or game.canvas, whatever you need. There's actually some code to do it in the phaser-examples repo. Look in the examples/wip folder for a folder called "spritesheet" (or something like that!) inside you'll find a sprite sheet tool I made, but the important bits you need are the files like canvasToBlob.js and FileSaver.js which will turn a canvas into a PNG saved to your local file system.

 

Hi Rich, so I checked the example. 

Im planning to generate a PNG image from a phaser group object. And then upload that PNG image to a server. (The game I am making allows the user to do some creations on screen, but I need to create the image just from what the user creates, not the entire canvas).

 

Do you think I can use your : Blob.js, CanvasToBlob.js and FileSaver.js 

1- Create a PNG image from a group object

bmd = game.make.bitmapData(500, 500);

bmd = game.make.bitmapData(500, 500);bmd.draw(myPhaserGroup, 0, 0);bmd.update();

2- Save to Disk (is this even possible ?) 

bmd.canvas.toBlob(function(blob) {            saveAs(blob, 'userImage.png');        });

3- Take that userImage.png from disk some how and upload it to a webservice using JQuery ?

This is probably not the way... but might be a clue. This is just an example I found online, this one takes the image from a HTML image element. But in my case I will use mmm the file I saved ? or is there other way to use the  'bmd' object base64 data. as a note I heard canvas.toDataURL() -  'sends a base64 encoded png file which has some additional headers in front so it's probably useless' ( I guess thats what the dataURL.replace(/^data:image\/(png|jpg);base64,/, "") is use for in this example)

var imgElem = document.getElementById('img');$('#urlText').keyup(function(){   $('#img').attr('src',$('#urlText').val());});   $('#sendData').click(function(){var imgData = JSON.stringify(getBase64Image(imgElem));  $.ajax({  url: 'http://url.com/rest/api',  dataType: 'json',  data: imgData,  type: 'POST',  success: function(data) {    console.log(data);    }  });});function getBase64Image(imgElem) {// imgElem must be on the same server otherwise a cross-origin error will be thrown "SECURITY_ERR: DOM Exception 18"    var canvas = document.createElement("canvas");    canvas.width = imgElem.clientWidth;    canvas.height = imgElem.clientHeight;    var ctx = canvas.getContext("2d");    ctx.drawImage(imgElem, 0, 0);    var dataURL = canvas.toDataURL("image/png");    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");}

Sorry with the mixed code... 

Any suggestions on how I can accomplish this ? this would be really appreciated. Again, I prefer to take the image from a group object and not the entire Canvas that contains some other UI and stuff that I don't need.

 

Thanks

Link to comment
Share on other sites

  • 2 weeks later...

okay so it was too difficult, so I ended up doing this.

 

Phaser Game  

var image64 = this.game.canvas.toDataURL('image/png');        // console.log(image64);        $.ajax({            url: 'http://localhost:3000/kente',            dataType: 'json',            type: 'post',            contentType: 'application/json',            data: JSON.stringify( { "image64": image64}),            processData: false,            success: function( data, textStatus, jQxhr ){                console.log(JSON.stringify( data ) );            },            error: function( jqXhr, textStatus, errorThrown ){                console.log( errorThrown );            }        });

Server Running Nodejs + Express + MongoDB

app.route('/kente') //standard response    .post(function(req,res, next){        console.log("::: Receiving base64 Image") // form files        //console.log(req.body.image64);        if(req.body.image64 != undefined){	        var base64Data = req.body.image64.replace(/^data:image\/png;base64,/, "");	        var buff = new Buffer(base64Data, 'base64');	        var filename = Date.now();	        fs.writeFile("public/community_uploads/"+filename+".png", buff, function(err) {	          if(err == null){		          //SAVING IN DATA BASE		          var thePattern = new PatternModel({	                    url: filename + ".png" 	                    });	                thePattern.save(function(err){	                    if(!err){	                        console.log(">Pattern saved");	                        var pttrn = {id:thePattern.id,	                        	url:thePattern.url,	                        	first_color: null,	                        	second_color: null,	                        	created_at: thePattern.created_at};	                        io.emit('patternSaved', pttrn);	                        return sendErrorResponse(res, 200, 'Pattern Saved !');  	                    } else {	                        return sendErrorResponse(res, 400, err);	                    }	                });            	}else console.log("Error Saving to Disk Image: "+ err);	        });    }else{    	return sendErrorResponse(res, 400, 'Missing base 64 image'); //custom return function    }    });
Link to comment
Share on other sites

  • 1 month later...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...