GithubHelp home page GithubHelp logo

gifwrap's People

Contributors

artbit avatar dafrok avatar dependabot[bot] avatar fahimk avatar grubba27 avatar jimbly avatar jtlapp avatar p2004a avatar simenb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

gifwrap's Issues

The GifUtil namespace needs unit tests

Write unit tests for the functions in the GifUtil namespace.

A number of unit tests elsewhere make use of them, but we don't have full coverage, and there should be separate tests anyway for purposes of isolating problems.

I have a separate app that makes extensive use of all of GifUtil, so I'm mostly sure they're working at this point. The tests will help with maintenance over time.

UPDATE: Other than color quantization, which has a test suite.

Encoding previously decoded gif results in different looking gif

Here's a minimal example that illustrates this issue. It loads a gif image, decodes it and then immediately encodes it as a new image, which ends up looking completely different from the input image:

var fs = require("fs");
var path = require("path");
var GifCodec = require("gifwrap").GifCodec;

fs.readFile(path.join(__dirname, "./input.gif"), (err, buffer) => {
  if (err) throw err;
  var codec = new GifCodec();
  codec.decodeGif(buffer).then(gif => {
    codec
      .encodeGif(gif.frames, {
        loops: gif.loops,
        colorScope: gif.colorScope
      })
      .then(gif => {
        fs.writeFileSync(path.join(__dirname, "./output.gif"), gif.buffer);
      });
  });
});

input.gif

input.gif

output.gif

output.gif

I have noticed similar behaviour with gifs that have frames with x and/or y offsets.

Editing gif frames with Jimp -> The value of "offset" is out of range

Using this gif with the code below https://media1.giphy.com/media/HnKSuvC39SdOM/source.gif

I am getting this error on GifUtil.write():

RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 43818. Received 43820

Is this a bug or am I doing something wrong? I'm trying to downsize the gif to 160x160px.

var filePath = "pathtofile.gif"

await GifUtil.read(filePath)
.then(async inputGif => {
	//Loop through each frame
	for (var i=0; i<inputGif.frames.length; i++){
		//Modify the frame image buffer with jimp
		var newImgBuffer = await GifUtil.copyAsJimp(jimp, inputGif.frames[i])
		.resize(160, 160) // resize
		.getBufferAsync(jimp.AUTO)

		inputGif.frames[i].bitmap.height = 160
		inputGif.frames[i].bitmap.width = 160
		inputGif.frames[i].bitmap.data = newImgBuffer
	}
	
	//Pass inputGif to write() to preserve the original GIF's specs.
	return GifUtil.write(filePath, inputGif.frames, inputGif)
});

Possible to write to buffer?

Something like this:

const bufferStream = new BufferStream();
await GifUtil.write(bufferStream, frames);
const gifBuffer = bufferStream.getBuffer();

Frame 1 uses more than 256 color indexes

Getting the above error trying to load and save a gif

    return GifUtil.read(downloadedFile)
        .then(inputGif =>
            // Pass inputGif to write() to preserve the original GIF's specs.
             GifUtil.write(outputFileName, inputGif.frames, inputGif))

Tried with a few gifs from the internet with same result. Can use quantize function but that causes massive distortion.

(node:1893) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'getMaxDimensions' of undefined

(node:1893) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'getMaxDimensions' of undefined at GifCodec.encodeGif (/Users/chenshuaihua/gifwrap-guide/node_modules/gifwrap/src/gifcodec.js:99:34) at Object.exports.write (/Users/chenshuaihua/gifwrap-guide/node_modules/gifwrap/src/gifutil.js:232:20) at Object.<anonymous> (/Users/chenshuaihua/gifwrap-guide/index.js:10:9) at Module._compile (internal/modules/cjs/loader.js:689:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10) at Module.load (internal/modules/cjs/loader.js:599:32) at tryModuleLoad (internal/modules/cjs/loader.js:538:12) at Function.Module._load (internal/modules/cjs/loader.js:530:3) at Function.Module.runMain (internal/modules/cjs/loader.js:742:12) at startup (internal/bootstrap/node.js:279:19) (node:1893) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2) (node:1893) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Error: Frame 0 uses more than 256 color indexes

Error: Frame 0 uses more than 256 color indexes

async function fixColors(filepath){
    return new Promise((resolve)=>{
        Jimp.read(filepath, function (err, test) {
            //what can i do here to fix the error?
            test.write(file); 
                 resolve();
        });        
    });
}

question: Any way to bypass the 256 color check in GifCodec#encodeGif?

Hello. It's a-me Mario.

I've been, once again, messing around with GifWrap and well, again managing to reach the limit of colors. This time, I'm fully lost on how it happened, but it did, and it's sad.

So, as the title suggests, are there any ways to bypass the need of quantizing frames?

Thank chu!

EDIT: I am able to make it run on a child process,to quantize without blocking the main thread, but I asking in case there are any other ways.

Error: marker was not found

Error

(node:4428) UnhandledPromiseRejectionWarning: Error: marker was not found
    at decodeScan (gifier\node_modules\jpeg-js\lib\decoder.js:344:15)
    at constructor.parse (gifier\node_modules\jpeg-js\lib\decoder.js:804:29)
    at Object.decode [as image/jpeg] (gifier\node_modules\jpeg-js\lib\decoder.js:1096:11)
    at Jimp.parseBitmap (gifier\node_modules\@jimp\core\dist\utils\image-bitmap.js:196:53)
    at Jimp.parseBitmap (gifier\node_modules\@jimp\core\dist\index.js:431:32)
    at gifier\node_modules\@jimp\core\dist\index.js:373:15
    at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:4428) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:4428) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

code


async function getFileBitmap(file){
    return new Promise((resolve)=>{
        Jimp.read(file)
        .then(image => {
            resolve(image.bitmap.data);
        })
    });
}

async function getGifFrames(file){
    return new Promise((resolve)=>{
        GifUtil.read(file).then(inputGif => {
            resolve(inputGif.frames);
        });         
    });
}

async function mergeThumbnail(baseImage, gifImage, outputImage){
    return new Promise( async (resolve, reject)=>{
        const res = sizeOf(baseImage);
        const width = res.width, height = res.height;
        const frames = [];
        let frame = new GifFrame(width, height, { delayCentisecs: 200 });
        frame.bitmap.data = await getFileBitmap(baseImage);
        frames.push(frame);
        let gif_frames = await getGifFrames(gifImage);
        gif_frames.forEach(frame => {
            frames.push(frame);
        });
        GifUtil.write(outputImage, frames);
        resolve();           
    });
}

function uploadFile(outputImage){
    let serverPath = "images/" + makeid(32) + ".gif";
    return new Promise((resolve, reject)=>{
        let uploader = new Upload();
        uploader.setup('clipdrop-prod', './secure/ClipDropAuth.json', 'clipdrop');
        uploader.logging(this.debug_mode);
        uploader.uploadFile(outputImage, serverPath, (uploaded_filename) => {
            resolve(uploaded_filename);
        });
    });
}

async function getFile(url, file){
    return new Promise((resolve, rject)=>{
        https.get(url, function(response) {
            if(debugMode)console.log("STARTED");
            response.pipe(file);
            if(debugMode)console.log("ENDED");
            resolve();
        });
    });
}


app.post('/merge', async (req, res) => {
    //vars: image, and gif are both localfiles, see provided file urls
    await mergeThumbnail(image, gif, outputImage);
    res.send(JSON.stringify({
        'url': uploaded_file
    }));
})

Files

image: https://www.clipdrop.io/wp-content/assets/unsplash/1.jpg
gif: https://storage.googleapis.com/clipdrop/images/MncnmFkx3dF4CbK6q0iiwVD7H5MdQzDp.gif

Example of decoding Gif frames into PNGs.

Hi, we are migrating to using gifwrap to extract Gif frames, and we seem to be having a lot of trouble getting a correct frame.
Would it be possible to provide some simple sample code that shows how to handle using the frame bitmap to generate a sequence of Pngs. One for each frame.

This is the result we get now. After decoding a few frames we get extensive tearing, indicating we have something incorrect.

image

Invalid settings when resizing Jimp image created from a BitmapImage.

I had an issue with your BitmapImage class. Jimp images created from it would not resize.

var width  = 30;
var height = 1;
var images = [];

GifUtil.read(path.join(__dirname + "/../images/default.gif")).then(inputGif => {
	for (var frame = 0; frame<inputGif.frames.length; frame++){
		images[frame] = new Jimp(1, 1 ,0);
		images[frame].bitmap =  new BitmapImage(inputGif.frames[frame]);
		images[frame].resize(width, height); // ERROR INVALID RESIZE SETTINGS
	}
});

I simply am not using it now, instead opting for the following method, which works.

var width  = 30;
var height = 1;
var images = [];

GifUtil.read(path.join(__dirname + "/../images/default.gif")).then(inputGif => {
	images = [];
	for (var frame = 0; frame<inputGif.frames.length; frame++){
		images[frame] = new Jimp(inputGif.frames[frame].bitmap.width, inputGif.frames[frame].bitmap.height ,0);
		images[frame].bitmap.data = inputGif.frames[frame].bitmap.data;
		images[frame].resize(width, height); // WORKS
	}
});

default.gif

Hello from jimp!

Hey! I maintain jimp and think this project is pretty cool and a nice addition to the jimp toolbelt.

I know maintaining open source project on your own can be taxing, I've experienced this with jimp.

Recently I got back into maintaining and and a few other have joined. I created https://github.com/jimp-dev to house the jimp repo going forward to facilitate collaboration and the long term health of the project. I've also moved a few of my jimp related project there.

Would you be interested in moving this repo and it's development there? We also started a dicord for communication and fostering a community.

Transparency Bug

Im trying to create gifs into jimp images then back into gifs. It works fine on some gifs but on some i get this weird bug: https://imgur.com/a/IlRYSLG

This is how I'm doing it:

GifUtil.read(file).then(inputGif => {
    inputGif.frames.forEach((frame, i) => {
        // create a Jimp containing a clone of the frame bitmap
        jimpCopied = GifUtil.copyAsJimp(Jimp, frame);

        Promise.all([jimpCopied, maskP]).then(function(images) {
            var lenna = images[0];
            //var mask = images[1];

            //lenna
            //.greyscale()
            //.mask(mask, 0, 0);
            const fCopied = new GifFrame(new BitmapImage(lenna.bitmap))
            frames.push(fCopied);
            GifUtil.write("my-creation.gif", frames, {
                loops: 0
            }).then(gif => {
                console.log("written");
            });

        });

    })

})

Sorry if its some limitation i missed.

Rework for revised omggif with buffer allocation

omggif now fixes the few issues I had. I also learned that I'm not managing memory allocation properly for omggif. This shouldn't result in errors with the current gifwrap, but I'd like to be able to rely on the external omggif package and get bug fixes for free.

TODO: Revise buffer allocation strategy and make sure everything works with the new omggif package. If so, remove omggif.js from the distribution and depend on the package itself.

RangeError

Hello I'm getting this error:
(node:44132) UnhandledPromiseRejectionWarning: RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 24091. Received 24092

at code encodeGif function

const codec = new GifCodec()
codec.encodeGif(frames).then(gif => {

frames:

obrázok

How can i fix it?

Question: Any way to resolve "writing interlaced GIFs is not supported" / Bypass the encoder

Hello! It's me again :P

This time I have a question. I have this gif (https://cdn.discordapp.com/emojis/422087870464131082.gif), and I'd like to resize it, then save the buffer. The problem is that codec.encodeGif throws an error about the "interlaced GIFs". Is there any way for me to bypass the need of the encoder? Is there anything else I could try that would solve the issue?

Thanks :)

Anyone willing to take over maintenance of this repo?

Hi everyone,

I am no longer using this package and haven't been able to find the time to maintain it. Would anyone like to take over responsibility for doing so? Please point me to other repos of yours to help me decide whether selecting you would actually solve the problem.

My apologies to everyone. I know how much it frustrates me to rely on a repo that isn't being maintained.

Reframing is broken

When calling reframe with xOffset larger or equal to width, or yOffset larger or equal to height, the following error occurs:

(node:3647) UnhandledPromiseRejectionWarning: Error: copy exceeds width of source bitmap
    at BitmapImage.blit (./node_modules/gifwrap/src/bitmapimage.js:91:19)
    at GifFrame.reframe (./node_modules/gifwrap/src/bitmapimage.js:227:15)
    at sourceGif.frames.forEach.frame (./server.js:9:27)
    at Array.forEach (<anonymous>)
    at GifUtil.read.then.sourceGif (./server.js:7:22)
    at <anonymous>
(node:3647) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3647) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

In other cases, the resulting image is empty.

Some gif seems strange

Use this gif

Image

with the demo code:

const { GifUtil } = require('gifwrap');

const content = fs.readFileSync("Image.gif");
GifUtil.read(content).then(inputGif => {
    Array.from(inputGif.frames).forEach(frame => {

        const buf = frame.bitmap.data;
        frame.scanAllCoords((x, y, bi) => {

            // Halve all grays on right half of image.

            if (x > inputGif.width / 2) {
                const r = buf[bi];
                const g = buf[bi + 1];
                const b = buf[bi + 2];
                const a = buf[bi + 3];
                if (r === g && r === b && a === 0xFF) {
                    buf[bi] /= 2;
                    buf[bi + 1] /= 2;
                    buf[bi + 2] /= 2;
                }
            }
        });
    });

    // Pass inputGif to write() to preserve the original GIF's specs.
    return GifUtil.write("modified.gif", inputGif.frames, inputGif).then(outputGif => {
        console.log("modified");
    });
});

The modified.gif seems very strange:

modified

Change transparency from alpha != 255 to alpha == 0

I'm noticing that color processing packages have to treat anything with non-zero alpha as if it were colored. gifwrap currently only treats 0xFF alpha as colored.

To be consistent with other packages, so that less effort is needed to convert gifwrap images to formats needed by other packages, I'll need to make this change.

It'll be a breaking change for anyone using any alpha value other than 0x00 and 0xFF.

Extend to support APNG -- animated PNGs

I find myself needing more than 256 colors per frame, so I need the same code to be able to output to either GIF or APNG format.

TODO: Extend gifwrap to support the APNG format to be able to read and write animated PNGs as well as GIFs, through the same encoder/decoder interface. The dev should only have to choose the encoder or decoder to select between GIF and APNG.

Hmm. That would leave the package name gifwrapa bit deceiving. It might need a more generic name. This might also mean making changes that aren't backward-compatible.

Unknown gif block: 0x4

Purpose of code

The following code does 1 thing only, it loads an image, and a gif, then it merges the image to the start of the gif.
the image should be displayed for 2 seconds

Error

Unknown gif block: 0x4

input files:

baseImage: https://www.clipdrop.io/wp-content/assets/unsplash/1.jpg
gifImage: https://storage.googleapis.com/clipdrop/images/MncnmFkx3dF4CbK6q0iiwVD7H5MdQzDp.gif

code


const { GifFrame, GifUtil, GifCodec } = require('gifwrap');
const Jimp = require('jimp');
const sizeOf = require('image-size');


async function getFileBitmap(file){
    return new Promise((resolve)=>{
        Jimp.read(file)
        .then(image => {
            resolve(image.bitmap.data);
        })
    });
}

async function getGifFrames(file){
    return new Promise((resolve)=>{
        GifUtil.read("fancy.gif").then(inputGif => {
            resolve(inputGif.frames);
        });         
    });
}


async function mergeThumbnail(baseImage, gifImage, outputImage){
    return new Promise( async (resolve, reject)=>{
        const res = sizeOf(baseImage);
        const width = res.width, height = res.height;
        const frames = [];
        let frame = new GifFrame(width, height, { delayCentisecs: 200 });
        frame.bitmap.data = await getFileBitmap(baseImage);
        frames.push(frame);
        let gif_frames = await getGifFrames(gifImage);
        gif_frames.forEach(frame => {
            frames.push(frame);
        });
        GifUtil.write(outputImage, frames);
        resolve();           
    });
}

app.post('/merge', async (req, res) => {
    let outputImage = "storage/" + makeid(12) + ".gif";
    if(debugMode)console.log(req.body.baseImage);
    if(debugMode)console.log(req.body.gifImage);

    let url = new URL(req.body.baseImage);
    let filename = path.basename(url.pathname);
    if(debugMode)console.log(filename);
    const file = fs.createWriteStream("storage/" + filename);
    const request = await getFile(req.body.baseImage, file);
    if(debugMode)console.log("File downloaded");

    let url2 = new URL(req.body.gifImage);
    let filename2 = path.basename(url.pathname);
    if(debugMode)console.log(filename2);
    const file2 = fs.createWriteStream("storage/" + filename2);
    const request2 = await getFile(req.body.gifImage, file2);
    if(debugMode)console.log("File downloaded");

    await mergeThumbnail("storage/" + filename, "storage/" + filename2, outputImage);
    if(debugMode)console.log("File converted");

    let uploaded_file = await uploadFile(outputImage);
    if(debugMode)console.log(uploaded_file);

    fs.unlinkSync("storage/" + filename);
    fs.unlinkSync("storage/" + filename2);
    fs.unlinkSync(outputImage);
    res.send(JSON.stringify({
        'url': uploaded_file
    }));
})

GifError: Invalid block size

Hi, occasionally I'm getting this error, i think it had to do with GifUtil

GifError: Invalid block size
at new GifReader (/var/www/gifier/node_modules/omggif/omggif.js:489:41)
at GifCodec.decodeGif (/var/www/gifier/node_modules/gifwrap/src/gifcodec.js:55:26)
at /var/www/gifier/node_modules/gifwrap/src/gifutil.js:222:24

here is my code blocks

getGifFrames

async function getGifFrames(file){
    return new Promise((resolve)=>{
        GifUtil.read(file).then(inputGif => {
            resolve(inputGif.frames);
        });         
    });
}

mergeThumbnail

async function mergeThumbnail(text, gifImage, outputImage, playIcon){
    return new Promise( async (resolve, reject)=>{
        const font = await Jimp.loadFont(Jimp.FONT_SANS_32_BLACK);
        const font2 = await Jimp.loadFont(Jimp.FONT_SANS_32_WHITE);
        const res = sizeOf(gifImage);
        const width = res.width, height = res.height;
        let frames = [];
        let gif_frames = [];
        try {
        gif_frames = await getGifFrames(gifImage);        
        } catch(e13){
            reject(false);
        }
        const sec_img = (await Jimp.read(playIcon)).resize(48, 48);  
        let w = (width / 2) - (sec_img.bitmap.width / 2);
        let h = (height / 2) - (sec_img.bitmap.height / 2);
        let x = 0;
        let y = height - 56;
        let maxWidth = 320;    
        
        gif_frames.forEach((frame) => {
            let image = new Jimp(frame.bitmap.width, frame.bitmap.height);
            image.bitmap = frame.bitmap;            
            image.blit(sec_img, 136, 156, 0, 0, 48, 48); 
            // do stuff here (shortned)
            GifUtil.quantizeDekker(image);
            
            frames.push(new GifFrame(new BitmapImage(image.bitmap)));
        });        

        GifUtil.write(outputImage, frames);
        resolve(outputImage);           
    });
}

question: Is there any reason we can't use floats like 1.5 on scale?

I've recently messed around with this module and a few animated emojis on Discord. And while having a blast, I couldn't help but notice we can't scale with numbers like 1.5

Is there any reason for this? Is it just because floats can do weird stuff, or is this a limitation?

Either way this module is dumb easy to use, and its amazing. Thank you for making a module like this.
Now for me to discover how i can stitch 3 gifs and make one giant one, if you want to help, that would be awesome, :P

Frame 0 uses more than 256 color indexes

I am not sure how or why this is happening. I am loading an existing Gif, resizing it one frame at a time with Jimp and then saving the output gif in a file.

I am not sure at which point or why the palette changes since my source image is indeed a GIF.

This is my code:

GifUtil.read("org.gif").then(inputGif => {
    images = [];
    
	for (var frame = 0; frame<inputGif.frames.length; frame++){
		var j = new Jimp(inputGif.frames[frame].bitmap.width, inputGif.frames[frame].bitmap.height , 0);
        j.bitmap.data = inputGif.frames[frame].bitmap.data;
        j.resize(width, height);
       
        images[frame] = new GifFrame(j.bitmap);
    }

    inputGif.frames = images;
   

    return GifUtil.write("modified.gif", inputGif.frames, inputGif).then(outputGif => {
        console.log("modified");
    });
});

How do I prevent it from up-scaling the color palette? or how can I quantize the frame?

Using all ram

I am using the following function to try and create a thumbnail of a gif with a mask. icon.data is a buffer containing the gif data. The addMask function works with JIMP variables and works. even if I comment out the line that manipulates the frame it uses up all the ram and crashes with a FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

            let sourceGif=await codec.decodeGif(icon.data);
            for (let i in sourceGif.frames) {
                let frameImage = GifUtil.copyAsJimp(Jimp, sourceGif.frames[i]);
                //frameImage=await addMask(frameImage,icon); //function that resizes a frame and adds a mask to the frame 
                sourceGif.frames[i]=new GifFrame(frameImage.bitmap);
            }
            GifUtil.quantizeDekker(sourceGif.frames, 256);

            // The encoder determines GIF size from the frames, not the provided spec (sourceGif).
            outputBuffer=codec.encodeGif(sourceGif.frames, sourceGif);

After some more checks I find that it is the GifUtil.quantizeDekker function causing the problem.

GIMP -> Filters -> Animation -> Unoptimize

Is there a method in the API to convert all the frames to unoptimized frames so it is easier to edit them and not deal with strange animation sequence artifacts?

e.g. A method in which ALL (excluding the first) frames are converted full width/height dimensions and contain duplicate pixel RGBA values for any preceding layer where otherwise it may have been transparent with a combined disposal method, to be changed to replace disposal method, etc.

For example see: https://graphicdesign.stackexchange.com/questions/55311/how-can-i-modify-a-gif-that-uses-cumulative-layers

Also see: https://www.npmjs.com/package/imagemin-giflossy
unoptimize

Type: boolean
Default: false

Unoptimize GIF animations into an easy-to-edit form.
e.g.:

imageminGiflossy({ unoptimize: true });

edit/update: As a technicality, it is possible to create GIF images where the first frame/layer is not the full dimensions of the image.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.