Code Monkey home page Code Monkey logo

toucan's Introduction

Toucan: Fabulous Image Processing in Swift

Build Status CocoaPods Carthage compatible

Toucan is a Swift library that provides a clean, quick API for processing images. It greatly simplifies the production of images, supporting resizing, cropping and stylizing your images.

Features

  • Easy and smart resizing
  • Elliptical and rounded rect masking
  • Mask with custom images
  • Chainable image processing stages

Requirements

  • Xcode 10.0+
  • iOS 11.0+

Setup

  • Install using CocoaPods: https://cocoapods.org/pods/Toucan
  • or manually include the Toucan framework by dragging it into your project and import the library in your code using import Toucan

Toucan Usage

Toucan provides two methods of interaction - either through wrapping an single image within a Toucan instance, or through the static functions, providing an image for each invocation. This allows for some very flexible usage.

Create an instance wrapper for easy method chaining:

let resizedAndMaskedImage = Toucan(image: myImage).resize(CGSize(width: 100, height: 150)).maskWithEllipse().image

Or, using static methods when you need a single operation:

let resizedImage = Toucan.Resize.resizeImage(myImage, size: CGSize(width: 100, height: 150))
let resizedAndMaskedImage = Toucan.maskWithEllipse(resizedImage)

Typically, the instance version is a bit cleaner to use, and the one you want.

Resizing

Resize the contained image to the specified size. Depending on what fitMode is supplied, the image may be clipped, cropped or scaled.

Toucan(image: myImage).resize(size: CGSize, fitMode: Toucan.Resize.FitMode)

Fit Mode

FitMode drives the resizing process to determine what to do with an image to make it fit the given size bounds.

Example Mode
Clip Clip Mode
Toucan.Resize.FitMode.Clip
Resizes the image to fit within the width and height boundaries without cropping or distorting the image.

Toucan(image: portraitImage).resize(CGSize(width: 500, height: 500), fitMode: Toucan.Resize.FitMode.Clip).image
Crop Crop Mode
Toucan.Resize.FitMode.crop
Resizes the image to fill the width and height boundaries and crops any excess image data.

Toucan(image: portraitImage).resize(CGSize(width: 500, height: 500), fitMode: Toucan.Resize.FitMode.Crop).image
Scale Scale Mode
Toucan.Resize.FitMode.scale
Scales the image to fit the constraining dimensions exactly.

Toucan(image: portraitImage).resize(CGSize(width: 500, height: 500), fitMode: Toucan.Resize.FitMode.Scale).image

Masking

Alter the original image with a mask; supports ellipse, rounded rect and image masks.

Ellipse Mask

Example Function
Ellipse Mask Mask the given image with an ellipse. Allows specifying an additional border to draw on the clipped image. For a circle, ensure the image width and height are equal!

Toucan(image: myImage).maskWithEllipse().image
Ellipse Mask w. Border When specifying a border width, it is draw on the clipped image.

Toucan(image: myImage).maskWithEllipse(borderWidth: 10, borderColor: UIColor.yellowColor()).image

Path Mask

Example Function
Path Mask Mask the given image with a path. The path will be scaled to fit the image correctly!

path.moveToPoint(CGPointMake(0, 50))
path.addLineToPoint(CGPointMake(50, 0))
path.addLineToPoint(CGPointMake(100, 50))
path.addLineToPoint(CGPointMake(50, 100))
path.closePath()
Toucan(image: myImage).maskWithPath(path: path).image
Path Mask w. Closure Mask the given image with a path provided via a closure. This allows you to construct your path relative to the bounds of the image!

Toucan(image: myImage).maskWithPathClosure(path: (rect: CGRect) -> (UIBezierPath)).image

Rounded Rect Mask

Example Function
Rounded Rect Mask Mask the given image with a rounded rectangle border. Allows specifying an additional border to draw on the clipped image.

Toucan(image: myImage).maskWithRoundedRect(cornerRadius: 30).image
Rounded Rect Mask w. Border When specifying a border width, it is draw on the clipped rounded rect.

Toucan(image: myImage).maskWithRoundedRect(cornerRadius: 30, borderWidth: 10, borderColor: UIColor.purpleColor()).image

Image Mask

Example Function
Image Mask Mask the given image with another image mask. Note that the areas in the original image that correspond to the black areas of the mask show through in the resulting image. The areas that correspond to the white areas of the mask aren’t painted. The areas that correspond to the gray areas in the mask are painted using an intermediate alpha value that’s equal to 1 minus the image mask sample value.

Toucan(image: myImage).maskWithImage(maskImage: octagonMask).image

Example Images

Example images used under Creative Commons with thanks to:

Contributing

  1. Please fork this project
  2. Implement new methods or changes in the Toucan.swift file.
  3. Write tests in the ToucanTests folder.
  4. Write appropriate docs and comments in the README.md
  5. Submit a pull request.

Contact

Raise an Issue or hit me up on Twitter @gavinbunney

License

Toucan is released under an MIT license. See LICENSE for more information.

toucan's People

Contributors

crspybits avatar djtarazona avatar fraserscottmorrison avatar kean avatar l4u avatar marcelofabri avatar marcuscallon avatar natan avatar oogatta avatar philippeauriach avatar phimage avatar readmecritic avatar sakiwei 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  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  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

toucan's Issues

Unable to compile Toucan (installed via Cocoapods) once main project has migrated to Swift 4.2

Not sure what the desired way to resolve this would be:

  • The current podspec could be updated, with the spec.swift_version property set to '4.0'
  • Wait until Swift 4.2 has been released fully and migrate Toucan accordingly.

In either case, setting the swift_version in the podspec would be a good idea to avoid this sort of thing in the future.

Note that the migrations for Toucan are (so far) very simple, just several instances of

UIImageOrientation has been renamed to UIImage.Orientation.

cannot import Toucan

add Toucan to podfile, pod install runs well, and there isn't any error, but I cannot import Toucan library

screenshot

改变图片大小的时候,是否可以自动计算宽高吗?

改变图片大小的时候是否可以自动的计算宽高? 如只传入宽度,程序可以根据图片的原始尺寸自动计算出改变后图片的高度? 或者只传入高度,自动计算宽度。 只有传入宽高,才按照传入的参数进行裁剪?

Resizing image doubles the scale of the original image

The initial image scale is 1, but when resizing the image using Toucan, the image scale is changed to 2, so when I convert the image to Data and send it to server, the image size is double than the size I used to resize the image.

// Image scale was 1
let resizedImage = Toucan.Resize.resizeImage(image, size: CGSize(width: 500, height: 500))
// Image scale becomes 2
// Convert image to Data
let imageData = UIImageJPEGRepresentation(resizedImage, 0.8)!
// Send to server via HTTP

Is it possible for Toucan to maintain the original image scale?

Snitram

Crash on iOS 11

Hi guys!

I just got a crash CGBitmapContextCreate: invalid data bytes/row: should be at least 12096 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipLast using Toucan(image: image).resize(size, fitMode: .crop).image from an image taken with the camera.

Same build is working in iOS 10.3.3 but is crashing on 11.1.1

Any help?

Toucan Memory Leaks

Hi, I use your library to resize my images in my tableview and I noticed that the memory keeps increasing in my app when I use instruments. It shows your library and I checked out your code and I noticed that theres not memory management handling in your closures. It shows that on line 598 on the Toucan class reaching 200+mb's in the closure. Do you mind if I make a pull request and do a fix on it? I'm using your library for a production app

Not Supported in Swift3.1

Hi,
I need to use the library for swift 3.1. I got a set of warnings. Can u provide a latest version which supports swift 3.1. Thanks for your consideration

Tests: Unit Test

There has been some initial work on unit testing Toucan.

  • TravisCI setup
  • Initial tests for Resizing and Masking done

Areas to look at
Main issue is getting some level of coverage over the rest of the existing features, and expanded the expectations on the existing tests

  • Expand existing tests to check actual image content, not just size attributes
  • Expand masking tests - currently just checks the corner transparency for ellipse only :)
  • Masking rounded rect tests
  • Image mask tests
  • Overlay image layer tests

Use of unresolved identifier 'Toucan'

Hi,

Im using Xcode 9.2 and Swift 4. I've tested both Toucan 1.0.0 and 0.7, Im getting the error "use of unresolved identifier 'Toucan' anyway I try to use the framework... Im I doing something wrong, or is this a bug?

resizeByScaling not working

I have the same code which I use on iPad mini 1 and iPhone 6.
The code takes photo by camera and then applies resizeByScaling:CGSizeMake(128, 128).

For iPad mini 1: it correctly resizes the image to 128x128.
On iPhone 6, it is 256x256.

I think there is something wrong with the function. Perhaps it doesn't factor in retina level????

pod problem

Hi!
I'm trying to install pod by " pod 'Toucan' "
but I got 'Unable to find a specification for Toucan '
Could you tell what exactly should I write in pod file?
Thanks

'UInt32' is not convertible to 'CGBitmapInfo'

I got this error message on line 549.

/Users/MNurdin/Documents/iOS/xxxxx/Pods/Toucan/Source/Toucan.swift:549:53: 'UInt32' is not convertible to 'CGBitmapInfo'

Code

let context : CGContextRef = CGBitmapContextCreate(nil, contextWidth, contextHeight,
                CGImageGetBitsPerComponent(image.CGImage),
                CGImageGetBytesPerRow(image.CGImage),
                CGImageGetColorSpace(image.CGImage),
                CGImageGetBitmapInfo(image.CGImage).rawValue)!;

Please advice. Thanks.

crash with resizing rotated image

I am getting an exception when trying to resize the attached image (I hope the upload won't change the metadata)

Toucan.swift: 549 in Util.CGImageWithCorrectOrientation

: CGBitmapContextCreate: invalid data bytes/row: should be at least 4000 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipLast

I think this is the same issue related to orientation: http://stackoverflow.com/a/11958833

image

crash on selecting image taken by front camera

I got this error when i select image captured by front camera.

let myImage = Toucan.init(image: images[0]).image

This is the error message:

UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
Dec 27 22:56:42  mask It[469] <Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 1920 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipFirst.
fatal error: unexpectedly found nil while unwrapping an Optional value

Can I mask this image?

nail

Can I mask this image?
And if there is a background imageView
How do I get the mask image to crop the current position?

Move Objective-C helper methods to extension?

This library is really well-composed! I did notice that the Objective-C helper functions are peppered, throughout, though. Moving them to an extension (that is scoped by a build parameter or that loads in a CocoaPod subspec) would make it easy for pure Swift apps to disable the redundancy.

Crash in CGImageWithCorrectOrientation

We currently expire crashes in our app, which we "fixed" by removing force unwraps and adding logging to get more insights.

Crashlog

Crashed: com.apple.root.user-interactive-qos
0  Rabbit                         0x104977fc4 specialized static Toucan.Util.CGImageWithCorrectOrientation(UIImage) -> CGImage (Toucan.swift:571)
1  Rabbit                         0x10497871c specialized static Toucan.Resize.resizeImage(UIImage, size : CGSize, fitMode : Toucan.Resize.FitMode) -> UIImage? (Toucan.swift)
2  Rabbit                         0x1049c9100 specialized ThumbnailGenerator.generate(for : UIImage) -> [ThumbnailGenerator.GeneratedThumbnail] (ThumbnailGenerator.swift:61)
3  Rabbit                         0x1049fa134 specialized ContentMetadataFetcher.(generateVisualPreviews(for : Content, image : UIImage, storageController : LocalStorageController, completionHandler : ([VisualPreview]) -> ()) -> ()).(closure #2).(closure #1) (ContentMetadataFetcher+Thumbnails.swift:73)
4  Rabbit                         0x1049fa08c partial apply for ContentMetadataFetcher.(generateVisualPreviews(for : Content, image : UIImage, storageController : LocalStorageController, completionHandler : ([VisualPreview]) -> ()) -> ()).(closure #2).(closure #1) (ContentMetadataFetcher+Thumbnails.swift)
5  Rabbit                         0x10493db00 thunk (ContentCreationController.swift)
6  libdispatch.dylib              0x1851a6a54 _dispatch_call_block_and_release + 24
7  libdispatch.dylib              0x1851a6a14 _dispatch_client_callout + 16
8  libdispatch.dylib              0x1851b3ea4 _dispatch_root_queue_drain + 1032
9  libdispatch.dylib              0x1851b3a38 _dispatch_worker_thread3 + 120
10 libsystem_pthread.dylib        0x18544f06c _pthread_wqthread + 1268
11 libsystem_pthread.dylib        0x18544eb6c start_wqthread + 4

Device and system information

iOS 10 and iOS 11
iPad and iPhone

Known stats from logging

The crash is happening on this line which force unwraps the CGContext. It seems that scenarios exist in which the created context is nil.

After adding a guard and logging in the return statement, we've seen logs like this:

Error Domain=Toucan Code=-3 "width: 3840 height: 5760 bitsPerComponent: 8 bitmapInfo: 5" UserInfo={NSLocalizedDescription=width: 3840 height: 5760 bitsPerComponent: 8 bitmapInfo: 5}
Error Domain=Toucan Code=-3 "width: 120 height: 160 bitsPerComponent: 8 bitmapInfo: 0" UserInfo={NSLocalizedDescription=width: 120 height: 160 bitsPerComponent: 8 bitmapInfo: 0}

I've tried to reproduce the crash by hardcoding these values, but that didn't reproduce the crash. I've also made sure that the cgImage and Colorspace are non nil:

guard let cgImage = image.cgImage else {
    throw NSError(domain: "Toucan", code: -1, userInfo: [NSLocalizedDescriptionKey: "CGImage is nil"])
}

guard let colorSpace = cgImage.colorSpace else {
    throw NSError(domain: "Toucan", code: -2, userInfo: [NSLocalizedDescriptionKey: "Color space is nil"])
}

We've never seen these being logged.

Next steps

We for now prevented this crash from happening again by adding guards and throws instead of force unwrapping. It would be great if we can find the cause of this crash and fix it instead.

Drawing off main thread

Do you have any best practices/guide for using the API in a way that doesn't block the main thread?

let roundImage = Toucan(image: image).maskWithEllipse(borderWidth: 3.0, borderColor: UIColor.white).image

Especially when used in a TableView with lots of rounded images causes quite a bit of main thread activity.

toucan

Is CGImageWithCorrectOrientation really necessary?

Hey! I just noticed that each operation in Toucan starts off with a call to CGImageWithCorrectOrientation function which involves creating a new context and drawing an image into it. So, for example, if I want to crop an image with UIImageOrientation.Left then instead of simply cropping the image (which is extremely fast) Toucan would first physically rotate its bitmap (which is much more expensive then cropping itself) and just then crop the image. It would also change the image orientation to UIImageOrientation.Up.

I understand that it might be tempting to just "fix" an orientation so that all the other functions would only have to deal with images in UIImageOrientation.Up. However, if would be nice if Toucan could add a proper support for images in all orientations.

maskImageWithPath scaling problems

So the issue here is that I'm trying to mask the image with the green path (drawn by user). Because the mask is rescaled, it comes out like so:

screenshot1

I can fix it by commenting out the scaling as seen here below:

        public static func maskImageWithPath(_ image: UIImage,
                                             path: UIBezierPath) -> UIImage {
            
            let imgRef = Util.CGImageWithCorrectOrientation(image)
            let size = CGSize(width: CGFloat(imgRef.width) / image.scale, height: CGFloat(imgRef.height) / image.scale)
            
            return Util.drawImageWithClosure(size: size) { (size: CGSize, context: CGContext) -> () in
                
                let boundSize = path.bounds.size
                
//                let pathRatio = boundSize.width / boundSize.height
//                let imageRatio = size.width / size.height
				
                
//                if pathRatio > imageRatio {
//                    //scale based on width
//                    let scale = size.width / boundSize.width
//                    path.apply(CGAffineTransform(scaleX: scale, y: scale))
//                    path.apply(CGAffineTransform(translationX: 0, y: (size.height - path.bounds.height) / 2.0))
//                } else {
//                    //scale based on height
//                    let scale = size.height / boundSize.height
//                    path.apply(CGAffineTransform(scaleX: scale, y: scale))
//                    path.apply(CGAffineTransform(translationX: (size.width - path.bounds.width) / 2.0, y: 0))
//                }
                
                let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
                
                context.addPath(path.cgPath)
                context.clip()
                image.draw(in: rect)
            }
        }

Here's my code, which runs on gesture recognizer touch ended:

if let shapePath = shapeDrawView_.path {
				
				let newPath = UIBezierPath(cgPath: shapePath)
				
				let maskedImage = Toucan(image: letterImage.image!).resize(letterImage.frame.size, fitMode: .scale).maskWithPath(path: newPath).image

				DispatchQueue.main.async {
					self.shapeDrawView?.clear()
					self.letterImage.image = maskedImage
				}
				
			}

Is there a better way to handle this? Or maybe this could be an enhancement.

Otherwise, I love Toucan!

Border width sharpness

Hello, I am just using this library and I see a little imperfection in the border even when I use it as a rounded image or with corner radius. It isn't as sharp as I expect. So if you look closely into the border you will see that it isn't a beautiful border shape.

What could by wrong?

Thanks

Patrik

Role base Menu

I am using Toucan and adding the feature of Role base menu, but I am unable to work it. I have used the following steps.

  1. Created an Interface for menu
    export interface IMenu { name: string; url: string; icon: string; children: IMenu[] }
  2. Then in types.ts I add updateUserMenu: 'updateUserMenu',
  3. In mutation.ts I add
    updateUserMenu: (state: ICommonState, userMenu: Array<IMenu>) => { let user = Object.assign({}, state.user); user.userMenu = userMenu; state.user = user; }
  4. In action.ts I added
    updateUserMenu: (injectee: ActionContext<ICommonState, any>, userMenu: Array<IMenu>) => { injectee.commit(StoreTypes.updateUserMenu, userMenu); }
  5. and in login.ts I add
    this.repo.getMenu(this.username) .then((value) => this.$store.dispatch(StoreTypes.updateUserMenu, value));
    after
    this.auth.login(credentials) .then((value) => this.$store.dispatch(StoreTypes.updateUser, value)) .then(() => this.$store.dispatch(StoreTypes.updateStatusBar, null)) .then(() => this.$router.push(returnUrl)) .catch((user) => { });
  6. in sidebar.ts I call @State((state: IRootStoreState) => state.common.user) user: IUser;
  7. in sidebar.html I use (item, index) in user.userMenu,

I didn't get any thing, nor calling the API.
Help Me out.

How can I get the Toucan framework?

I found that Toucan framework is not in zip file,so I tried to build and archive the Toucan project.
Finally I got a Toucan.framework,but I found the header file just include:

#import <UIKit/UIKit.h>

//! Project version number for Toucan.
FOUNDATION_EXPORT double ToucanVersionNumber;

//! Project version string for Toucan.
FOUNDATION_EXPORT const unsigned char ToucanVersionString[];

Is anything I did wrong?

Compiler error with Carthage verison `0.3.3`

With the latest version 0.3.3 Carthage won't compile for the following reason:

** BUILD FAILED **


The following build commands failed:
        CompileSwift normal x86_64 /Users/mattesgroeger/Documents/workspaces/idagio/idagio-ios/Carthage/Checkouts/Toucan/Source/Toucan.swift
        CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler
(2 failures)
/Users/mattesgroeger/Documents/workspaces/idagio/idagio-ios/Carthage/Checkouts/Toucan/Source/Toucan.swift:551:41: error: cannot invoke 'CGRectMake' with an argument list of type '(Int, Int, Int, Int)'
A shell task failed with exit code 65:
** BUILD FAILED **


The following build commands failed:
        CompileSwift normal x86_64 /Users/mattesgroeger/Documents/workspaces/idagio/idagio-ios/Carthage/Checkouts/Toucan/Source/Toucan.swift
        CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler
(2 failures)

0.3.2 works fine, though

Resize with FitMode.crop decrease image quality

Hello,

We're using toucan in our app to resize product images using FitMode.crop. This fit mode produce really bad quality image even though the cropped image would maintain same aspect ratio as the original image.

Resize code in UIImageExtension:

Toucan(image: self).resize(CGSize(width: 345, height: 519), fitMode: Toucan.Resize.FitMode.crop).image!

I couldn't find any reason why this is happening. Please help.

0.4.x versions get compile error in Xcode 6.4

hi can you help me with this?
screen shot 2015-08-15 at 10 14 59 am

downgrading to 0.3.x solves the issue

/// 0.3.x code
            let context : CGContextRef = CGBitmapContextCreate(nil, CGImageGetWidth(image.CGImage), CGImageGetWidth(image.CGImage),
                CGImageGetBitsPerComponent(image.CGImage),
                CGImageGetBytesPerRow(image.CGImage),
                CGImageGetColorSpace(image.CGImage),
                CGImageGetBitmapInfo(image.CGImage))!;

How to crop from top left

When using resize and crop mode, it appears to crop the image from the middle. How can we crop from the top left corner? For example, if I have a UIImageView that is 400 x 200 and I want the image to be 400 width but crop anything over 200 high so just the top 200 pixels are visible, how can I do that?

tvOS support

I'm sorry to barge in, but any plans of making Toucan available for tvOS?

Crash

My app keeps crashing at this point when I try to resize an image and add a corner radius mask:

The crash occurs at this point:

        static func drawImageWithClosure(size size: CGSize!, closure: (size: CGSize, context: CGContext) -> ()) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(size, false, 0)
            closure(size: size, context: UIGraphicsGetCurrentContext()!)
            let image : UIImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image
        }

UIGraphicsGetCurrentContext()! ==> fatal error: unexpectedly found nil while unwrapping an Optional value

Carthage Support?

Hi,

What do you think about add option to install this library via Carthage? I would like to use it this way. Thanks

Images are resized to integers not floats

The following code takes the upper bound of 170.6666 (which is 171) when UIScreen.main.scale is 3.0

let size = 512 / UIScreen.main.scale
let image = Toucan(image: item.image!).resize(CGSize(width: size, height: size), fitMode: Toucan.Resize.FitMode.clip).image!

It should have been resized the image according to the float in size. Not the upper bound of it.

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.