Giter Club home page Giter Club logo

imgp's Introduction

imgp

Latest release Availability PyPI Build Status License

imgp_asciicast

Watch imgp resize a directory of images in lightning speed!

imgp is a command line image resizer and rotator for JPEG and PNG images. It can resize (or thumbnail) and rotate thousands of images in a go, at lightning speed, while saving significantly on storage.

Powered by multiprocessing, SIMD parallelism (thanks to the Pillow-SIMD library), an intelligent adaptive algorithm, recursive operations, shell completion scripts, EXIF preservation (and more), imgp is a very flexible utility with well-documented easy to use options.

imgp intends to be a stronger replacement of the Nautilus Image Converter extension, not tied to any file manager and way faster. On desktop environments (like Xfce or LxQt) which do not integrate Nautilus, imgp will save your day. File manager nnn provides a script to batch resize images with imgp.

Table of Contents

Features

  • resize by percentage or resolution
  • rotate clockwise by specified angle
  • adaptive resize considering orientation
  • brute force to a resolution
  • optimize images to save more space
  • limit processing by minimum image size
  • convert PNG to JPEG
  • erase exif metadata
  • specify output JPEG image quality
  • force smaller to larger resize
  • process directories recursively
  • overwrite source image option
  • completion scripts for bash, fish, zsh
  • minimal dependencies

Adaptive mode

  • If the specified and image orientations are same [(H >= V and h > v) or (H < V and h < v)], the image is resized with the longer specified side as reference.
  • In case of cross orientation [(H >= V and h <= v) or (H < V and h >= v)], the image is resized with the shorter specified side as reference. Same as non-adaptive.

For example, if an image has a resolution of 2048x1365 and is being resized to 1366x768:

  • In regular mode (default), output image resolution will be 1152x768
  • In adaptive mode, output image resolution will be 1366x910

Performance

imgp could resize 8823 images (approx. 4.5GB in size) of mixed resolutions (high to regular) stored in a USB 2.0 external hard disk at an adaptive resolution of 1366x1000 in around 8 minutes. The resulting size was 897MB (approx. 20%).

imgp uses Python PIL/Pillow library. Nautilus Image Converter calls the convert utility from ImageMagick. For a comparative benchmark, head here.

Installation

Dependencies

imgp requires Python 3.8 or later.

To install PIL library on Ubuntu, run:

sudo apt-get install python3-pil

or, using pip3:

sudo pip3 install pillow

pillow can be replaced by pillow-simd on SIMD processors.

From a package manager

Install imgp from your package manager. If the version available is dated try an alternative installation method.

Packaging status (expand)


Packaging status

Unlisted packagers:


Homebrew TAP (brew install jarun/imgp/imgp)
PyPI (pip3 install imgp)
Source Mage (cast imgp)

Release packages

Packages for Arch Linux, CentOS, Debian, Fedora, openSUSE Leap and Ubuntu are available with the latest stable release.

From source

If you have git installed, clone this repository. Otherwise download the latest stable release or development version (risky).

Install to default location (/usr/local):

sudo make install

To remove, run:

sudo make uninstall

PREFIX is supported, in case you want to install to a different location.

Running standalone

imgp is a standalone utility. From the containing directory, run:

./imgp

Shell completion

Shell completion scripts for Bash, Fish and Zsh can be found in respective subdirectories of auto-completion/. Please refer to your shell's manual for installation instructions.

Usage

cmdline options

usage: imgp [-h] [-x res] [-o deg] [-a] [-c] [-e] [-f] [-H] [-i] [-k] [-m] [-M res]
            [-n] [-N] [-O] [-P] [-q N] [-r] [-s byte] [-w] [-d] [PATH [PATH ...]]

Resize, rotate JPEG and PNG images.

positional arguments:
  PATH                  source file or dir [default: current dir]

optional arguments:
  -h, --help            show this help message and exit
  -x res, --res res     output resolution in HxV or percentage
  -o deg, --rotate deg  rotate clockwise by angle (in degrees)
  -a, --adapt           adapt to resolution by orientation [default: off]
  -c, --convert         convert PNG to JPG format [default: off]
  -e, --eraseexif       erase exif metadata [default: off]
  -f, --force           force to exact specified resolution [default: off]
  -H, --hidden          include hidden (dot) files [default: off]
  -i, --includeimgp     re-process _IMGP files. * RISKY: refer to docs
  -k, --keep            skip (honors -c or --pr) images matching specified
                        H or V or --res=100 [default: off]
  -m, --mute            operate silently [default: informative]
  -M res, --minres res  min resolution in HxV or percentage of --res to resize
  -n, --enlarge         enlarge smaller images [default: off]
  -N, --nearest         use nearest neighbour interpolation for PNG [default: antialias]
  -O, --optimize        optimize the output images [default: off]
  -P, --progressive     save JPEG images as progressive [default: off]
  -q N, --quality N     quality factor (N=1-95, JPEG only) [default: 75]
  -r, --recurse         process non-symbolic dirs recursively [default: off]
  -s byte, --size byte  minimum size to process an image [default: 1024]
  -w, --overwrite       overwrite source images [default: off]
  -d, --debug           enable debug logs [default: off]

Operational notes

  • Multiple files and directories can be specified as source. If PATH is omitted, the current directory is processed.
  • Output image names are appended with _IMGP if --overwrite option is not used. By default _IMGP files are not processed. Doing so may lead to potential race conditions when --overwrite option is used.
  • PNG files with lower target hres/vres are not converted (even if --convert is used). Run imgp --convert (*.png) separately to convert those.
  • Resize and rotate are lossy operations. For additional reductions in size try --optimize and --eraseexif options.
  • Option --optimize is slower, the encoder makes an extra pass over the image in order to select optimal encoder settings.
  • Progressive JPEG images are saved as progressive.

Examples

  1. Convert some images and directories:

    $ imgp -x 1366x768 ~/ ~/Pictures/image3.png ~/Downloads/
    /home/testuser/image1.png
    3840x2160 -> 1365x768
    11104999 bytes -> 1486426 bytes
    
    /home/testuser/image2.jpg
    2048x1365 -> 1152x768
    224642 bytes -> 31421 bytes
    
    /home/testuser/Pictures/image3.png
    1920x1080 -> 1365x768
    2811155 bytes -> 1657474 bytes
    
    /home/testuser/Downloads/image4
    2048x1365 -> 1152x768
    224642 bytes -> 31421 bytes
    
  2. Scale an image by 75% and overwrite the source image:

    $ imgp -x 75 -w ~/image.jpg
    /home/testuser/image.jpg
    1366x767 -> 1025x575
    120968 bytes -> 45040 bytes
    
  3. Rotate an image clockwise by 90 degrees:

    $ imgp -o 90  ~/image.jpg
    120968 bytes -> 72038 bytes
    
  4. Adapt the images in the current directory to 1366x1000 resolution. Visit all directories recursively, overwrite source images, ignore images with matching hres or vres but convert PNG images to JPEG.

    $ imgp -x 1366x1000 -wrack
    
  5. Set hres=800 and adapt vres maintaining the ratio.

    $ imgp -x 800x0
    Source omitted. Processing current directory...
    
    ./image1.jpg
    1366x911 -> 800x534
    69022 bytes -> 35123 bytes
    
    ./image2.jpg
    1050x1400 -> 800x1067
    458092 bytes -> 78089 bytes
    
  6. Process images greater than 50KiB only:

    $ imgp -wrackx 1366x1000 -s 51200
    
  7. Generate a 64px adaptive thumbnail of the last modified file in the current dir:

    #!/usr/bin/env sh
    
    thumb64 ()
    {
        pop=$(ls -1t | head -1)
        imgp -acx 64x64 "$pop"
    }
    

Developers

  1. Copyright © 2016-2023 Arun Prakash Jana
  2. Ananya Jana

imgp's People

Contributors

ananyajana avatar dslackw avatar jarun avatar kianmeng avatar sinjax avatar szlin avatar yzhs avatar zach-adams 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

imgp's Issues

Hello there!

Hello Jarun,

I'm sorry to contact you here but there is unfortunately no PM on Github.

I ended up on your package as I'm also trying to resize image using PIL and Multiprocessing Pool with Python 3.

And I was wondering: have you ever 'lost' images? By that I mean that some processes fail to resize and save the new resized image.

It happen to me on my project quite randomly and I can't figure out what is the problem. I always use the same images to run my test but it's not always the same which are missing. It's quite weird...

If by any chance you have any idea why I would gladly hear your advice (I'm new to Python).

I wish you a very nice day.

Pierre

Be lossless when possible

For JPEG for example, the command jpegtran is able to losslessly perform several operations like flip, rotate by a multiple of 90 degrees and others.
From its man page:

jpegtran works by rearranging the compressed data (DCT coefficients), without ever fully decoding the image. Therefore, its transformations are lossless: there is no image degradation at all, which would not be true if you used djpeg followed by cjpeg to accomplish the same conversion.

non-retention of some EXIF metadata

  • Fresh install of Ubuntu 19.04 (actually, running off live USB)
  • Installed version 2.6 via apt-get install imgp after checking the “Community-maintained free and open-sourced software (universe)” box in Software & Updates.
  • Ran imgp -x 1200x800 -r -z /path/to/input/ (The -z switch was useless as I do not konw where the log went.)
  • Got reduced size versions blazingly fast (yay!)
  • BUT quite a few of the EXIF fields were lost.
  • See attached files for list of original EXIF fields and those in resulting _IMGP file, and a diff -y between them that has been modified to be easier to read.
  • Also ran quick test running v. 2.6 from the repository with ./GITCLONED_imgp/imgp -x 1200x800 -r /path/to/input/; only checked “Attribution Name” field, but it was missing. I presume the rest were, too.

TSTJPEG_orig_exif_fields.txt
TSTJPEG_IMGP_exif_fields.txt
TSTJPEG_exif_field_diff.txt

Feature Request: Rename Flag

Hey, this is a great utility, thank you for writing it!

I'm using imgp to resize images for a blog, and I need to produce several different resolutions of the same image with consistent naming, eg myimage-1080.jpg myimage-720.jpg etc.

Currently this is possible using the separate posix rename utility, but it would be nice to be able to change _IMGP to a custom string, possible with a flag such as --rename my-text-goes-here with imgp itself.

Upload imgd to pypi

First of all, thanks for making such an convenient tool for image processing. I noticed that imgd is not on pypi yet, why not making it so? Thus people could using pip install imgd to install it directly.

If you approve this, I can send a pull request of the essential code to register imgd to pypi.

anyway to determine a suggestion on how much to rotate an image?

This is great, I'll be trying it out on a few current projects.

If i have a scanned image of English characters (A form of some sort) I'd like to use this to pre-process and re-align the page. This will give Apache Tika/Tesseract a better chance at high quality OCR.

Do you have any tips on how i can programmatically "guess" at the right % of rotation required?

Any tips appreciated.

Homebrew tap

Here's the formula file:

https://gist.githubusercontent.com/anonymous/9afa5f317d3db9f1473f5cfe106eb55e/raw/afc707cf9c7f774ba2387646390b6a78a8329db7/imgp.rb

As usual, create a repository jarun/homebrew-imgp, place imgp.rb in there, and tada. The installation command is

brew install jarun/imgp/imgp

Of course you can use a central repository jarun/homebrew-blah to host multiple formulae if you'd like to. In that case, brew install jarun/blah/imgp.

Note that I'm assuming an upstream wheel of Pillow here, which means it probably won't work with Linuxbrew.

resolution param not work

the log is here:

➜ 123 imgp -x 1366x0
Source omitted. Processing current directory...

./20210725_144420.jpg
4032x3024 -> 4032x3024
1445180 bytes -> 838738 bytes

./20210725_144350.jpg
4032x3024 -> 4032x3024
1838832 bytes -> 946717 bytes

./20210725_144408.jpg
4032x3024 -> 4032x3024
1926639 bytes -> 957304 bytes

./20210725_144339.jpg
4032x3024 -> 4032x3024
2691680 bytes -> 892383 bytes

./20210725_144345.jpg
4032x3024 -> 4032x3024
6153433 bytes -> 981851 bytes

5 processed in 0.7151 seconds.
/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/resource_tracker.py:216: UserWarning: resource_tracker: There appear to be 12 leaked semaphore objects to clean up at shutdown
warnings.warn('resource_tracker: There appear to be %d '

No PNG to JPG conversion on MacOs

Hi Arun! First of all thank you for such a great tool!

I tried to install it on Sierra and ran into the PNG to JPG conversion problem. Everything works as it has to but it simply ignores the PNG files. I have correctly installed python 3.6.1, Pillow and made the make installation as you instructed. All the paths look right, imagemagick is also present. I used different combination of arguments but no luck.

I know you have no MacOs mention in readme file but maybe you can make a Brew package so we can use all options on Mac.

Also I've notice significant colour saturation change, is there any option to manually set the parameters?

Some JPGs are not being recognized as JPGs

When I throw a JPG from my camera at imgp, it says it is not a JPG (but it is):

$ ~/dev/imgp/imgp -x 1920x1920 -p -z P1010670.JPG 
P1010670.JPG: not JPEG or PNG image
$ file P1010670.JPG 
P1010670.JPG: JPEG image data, Exif standard: [TIFF image data, little-endian, direntries=13, manufacturer=Panasonic, model=DMC-GX80, orientation=upper-left, xresolution=190, yresolution=198, resolutionunit=2, software=Ver.1.2  , datetime=2017:10:31 12:59:19], baseline, precision 8, 4592x3448, frames 3

Here is an image so you can try it for yourself: [removed]

Some arguments ignored on Windows

Hello,

I just tried running master (v2.9) on Windows and it mostly works, but some arguments seem to be ignored? -r is heeded and -x is processed but ignored while -d, -m and -w have no effect. However, the flags appears to be set properly internally, per the output from this basic debug.patch:

D:\Tools\>c:\Progra~1\Python\python -V
Python 3.9.1
D:\Tools\>c:\Progra~1\Python\python imgp-master\imgp --mute --quality 90 -x 800x800 --overwrite -r imgp
90
True
True

Non-flag heeding invocation output pre-debug patch (identical with short or long-form parameters):

D:\Tools\>c:\Progra~1\Python\python imgp-master\imgp --mute --quality 90 -x 800x800 --overwrite -r imgp.test
imgp.test\10_PHOTO1\R_12fwK7duntjbSI9_IMG_0145.jpg
1280x960 -> 1280x960
396696 bytes -> 173783 bytes

Any ideas?

--JAPH

Error -a/--adapt: ignored explicit argument 'сkx'

Hello. I'm trying to download images, convert PNG to JPG and make JPG progressive. But I'm getting an error and can't figure out what I'm doing wrong.

imgp -wraсkx 300x0 ./public/thumbnails/
imgp: error: argument -a/--adapt: ignored explicit argument 'сkx'
Error: Process completed with exit code 2.

-q N, more explanations.

Hello,

Thank you for this tool. Could you explain how to use the -q N option? What is N?

-q N, --quality N quality factor (N=1-95, JPEG only) [default: 75]

save as

Hi. while using imgp i needed to save processed images as a specific file name but I couldn't find this option. i would appreciate your help.

Picture example of the adaptive mode

The adaptive mode is a cool feature and is documented well in the README file. But as they say, a picture is worth thousands of words. I think it might be clearer for readers if there are corresponding picture examples to recognize what will happen. Just a suggestion, might be a "Good First Issue".

Some images color saturation is reduced after running the image through imgp.

I was using imgp to resize a bunch of product images, and found that one or two lost it's luster (i.e. the color saturation was reduced). I've included an example of the original and new image - curious if there's any improvement to the tool that could solve for this - or if there was a setting I missed.

140174_campaign copy_imgp
140174_campaign copy

image.jpg: not JPEG or PNG image (when it actually is)

Hi,
While looking for a fast image resizer for a low power project, I found and installed your awesome tool on a RaspberryPi ZeroW machine running the latest version of Raspbian (Stretch).

Finding the error mentioned in the subject line, while testing an IMGP resize on one of my images, I downloaded a couple of alternative images from the Internet as comparison tests. One PNG and one JPEG picked at random. IMGP worked fine on those files.

The unidentifiable jpg of mine (attached below) was shot by a Canon Powershot camera and transferred to the machine using CHDK-PTP (Canon Hackers Development Kit)

I attach the image in the hope that it may shed some light on the issue.
Thanks

still-2017_11_09___09_57

Warning when installing v2.7.tar.gz

Description

$ brew install jarun/imgp/imgp
...
Warning: You are using macOS 11.0.
We do not provide support for this released but not yet supported version.
...
Please create pull requests instead of asking for help on Homebrew's GitHub,
...
Error: Your CLT does not support macOS 11.0.

New release?

Most rolling distros ship Pillow 10+ now, which leaves imgp broken because of #49.

Maybe it makes sense to bump the release so it gets updated, e.g. in AUR?

(Feature Request) Print Total Space Saved at End of Job

Hi @jarun,

Thanks for this tool. It's been extremely useful and has the best compression settings w.r.t quality out of the box and is also super performant!

It would be very useful (and also showcase the tool better) if the program could print out the total amount of space saved (in MB preferably)

cannot convert PNG files in palette mode')

Hi,

When i convert many files in a folder, i got error message:"cannot convert PNG files in palette mode".
I found it is because my png file need to be converted.
Can we add some function to fix it ?

Thanks.

Feature idea: flag to ignore (or not exit(1) on) erroneous input files in batch usage

imgp is real handy for my mass-resizing needs, thanks a bunch! This is just a little idea for future users, I have a workaround, so feel free to close it =)

With 1000s of comic books (100000s of pages) to down-size, it happens that one encounters occasional corrupt jpgs. My bash script after extractions and other preps ultimately call imgp -m -x 75 -q 66 -w ./*.jpg. The latter part likely gets expanded by bash into all the jpgs matched in current dir.

Anyway, one way or another imgp is called once and works through multiple files. Now just 0.01% of those may cause your PIL open or resize or other calls to fail, in my case as follows:

Traceback (most recent call last):
  File "/bin/imgp", line 676, in <module>
    main()
  File "/bin/imgp", line 653, in main
    if resize_image(path):
  File "/bin/imgp", line 302, in resize_image
    img = img.resize((_hres, _vres), antialias)
  File "/usr/lib/python3.9/site-packages/PIL/Image.py", line 1916, in resize
    self.load()
  File "/usr/lib/python3.9/site-packages/PIL/ImageFile.py", line 259, in load
    raise OSError(
OSError: image file is truncated (1 bytes not processed)

Not to worry about that particular error, just would be neat to have a flag such that when imgp processes multiple files and just one of them is problematic, it continues processing the other ones and exits with success code 0. It might still warn on stderr or something.

I'll work around it for now by looping over the jpg files in the dir and doing one imgp call for each file individually.

Thank You

Hello,
This is not an issue, I just wanted to say thank you for this great tool. It has been a huge time saver.
Thank you.

'PIL.Image.DecompressionBombError' when resizing large image

I have a large 5.2MB image that I'd like to resize.

When I run imgp I get an error:

➜  imgp -x 50 i.png
Traceback (most recent call last):
  File "/home/linuxbrew/.linuxbrew/bin/imgp", line 676, in <module>
    main()
  File "/home/linuxbrew/.linuxbrew/bin/imgp", line 653, in main
    if resize_image(path):
  File "/home/linuxbrew/.linuxbrew/bin/imgp", line 223, in resize_image
    img = Image.open(src)
  File "/home/linuxbrew/.linuxbrew/Cellar/imgp/2.8/libexec/lib/python3.9/site-packages/PIL/Image.py", line 3009, in open
    im = _open_core(fp, filename, prefix, formats)
  File "/home/linuxbrew/.linuxbrew/Cellar/imgp/2.8/libexec/lib/python3.9/site-packages/PIL/Image.py", line 2996, in _open_core
    _decompression_bomb_check(im.size)
  File "/home/linuxbrew/.linuxbrew/Cellar/imgp/2.8/libexec/lib/python3.9/site-packages/PIL/Image.py", line 2905, in _decompression_bomb_check
    raise DecompressionBombError(
PIL.Image.DecompressionBombError: Image size (255553344 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.
  • Debian 10 (WSL)
  • imgp 2.8 (installed with homebrew).

DeprecationWarning: ANTIALIAS is deprecated and will be removed in Pillow 10

debian10
Python 3.7.3
install PIL library sudo apt-get install python3-pil

hi, how can i ignore this message?

root@kubectl-master:/public# imgp -x 800x0 -s 307200 -rewm
/usr/bin/imgp:54: DeprecationWarning: ANTIALIAS is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.LANCZOS instead.
  png_ip = PIL.Image.ANTIALIAS  # default interpolation for PNG

Progressive jpeg

More of a question than an issue..
I generate and upload lots of 5K images to a web gallery and would like to present them progressively.
I use imgp and love it's speed but I can't find any reference to progressive mode.
Is it on the road map?
Thanks
Sdack

Add option to auto-rotate image

Some devices save the image data in one orientation, but add EXIF data indicating the true orientation of the image. An option to automatically apply this would be handy, so that one might do something like -o auto -x 800x600 -e

Resolution not changed when converting directory

Hi, thanks for this amazing tool!

When i use imgp on a specific file, it changes it's resolution

imgp -x 800x0 IMG_20210507_123728.jpg
IMG_20210507_123728.jpg
4000x3000 -> 800x600
6040630 bytes -> 70771 bytes

But when i run it on a current directory, resolution of files its not changed, but the size of the each file is decreased

imgp -x 800x0
Source omitted. Processing current directory...

./IMG_20210507_123728.jpg
4000x3000 -> 4000x3000
6040630 bytes -> 986332 bytes

./IMG_20210507_124739.jpg
4000x3000 -> 4000x3000
6494707 bytes -> 1185653 bytes

./IMG_20210507_131250.jpg
4000x3000 -> 4000x3000
5782602 bytes -> 1490968 bytes

Here, as you see the resolution isn't changed 4000x3000 -> 4000x3000 6040630 bytes -> 986332 bytes, but only the size

Converting images to max 350KB

I have a folder with images of different size and try to convert the images that are greater then 350KB into something around 350KB. I know I can't set output file size but I tried with specifying the min file size before processing and to limit the resolution in order to get to my requirements. The problem is that I get the following output if I try to run it in the image folder:

imgp -akx 1600 -s 358400
> use --enlarge is to scale > 100%

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.