{ "info": { "author": "Warren Weckesser", "author_email": "", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], "description": "numpngw\n=======\n\nThis python package defines the function ``write_png`` that writes a\nnumpy array to a PNG file, and the function ``write_apng`` that writes\na sequence of arrays to an animated PNG (APNG) file. Also included\nis the class ``AnimatedPNGWriter`` that can be used to save a Matplotlib\nanimation as an animated PNG file; see Example 8 for an example.\n\nCapabilities of ``write_png`` include:\n\n* creation of 8-bit and 16-bit RGB files;\n* creation of 1-bit, 2-bit, 4-bit, 8-bit and 16-bit grayscale files;\n* creation of RGB and grayscale images with an alpha channel;\n* setting a transparent color;\n* automatic creation of a palette for an indexed PNG file;\n* inclusion of ``tEXt``, ``tIME``, ``bKGD``, ``pHYs``, ``gAMA``, ``cHRM``\n and ``iCCP`` chunks.\n\nThe package is written in pure python. The only external dependencies\nare numpy and setuptools.\n\nThe package has a suite of unit tests, but it should still be considered\nprototype-quality software. There may be backwards-incompatible API changes\nbetween releases.\n\nThis software is released under the BSD 2-clause license.\n\nFor packages with more features (including functions for *reading* PNG files),\ntake a look at:\n\n* pypng (https://pypi.python.org/pypi/pypng) or\n* imageio (https://pypi.python.org/pypi/imageio).\n\nThe following examples show some PNG and animated PNG files created with\nnumpy and numpngw. To see the animations in Examples 5 - 8, you must view\nthis file with a browser that supports animated PNG files. Currently (as\nof the writing of this file), Firefox, Safari 10 and recent versions of\nChromium support animated PNG. Opera requires an extension.\n\nExample 1\n---------\n\nThe following script creates this PNG file, an 8-bit RGB image.\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example1.png\n :alt: Example 1\n :align: center\n\nThe script::\n\n import numpy as np\n from numpngw import write_png\n\n\n # Example 1\n #\n # Create an 8-bit RGB image.\n\n img = np.zeros((80, 128, 3), dtype=np.uint8)\n\n grad = np.linspace(0, 255, img.shape[1])\n\n img[:16, :, :] = 127\n img[16:32, :, 0] = grad\n img[32:48, :, 1] = grad[::-1]\n img[48:64, :, 2] = grad\n img[64:, :, :] = 127\n\n write_png('example1.png', img)\n\n\nExample 2\n---------\n\nThe following script creates this PNG file, a 1-bit grayscale image.\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example2.png\n :alt: Example 2\n :align: center\n\nThe script::\n\n import numpy as np\n from numpngw import write_png\n\n # Example 2\n #\n # Create a 1-bit grayscale image.\n\n mask = np.zeros((48, 48), dtype=np.uint8)\n mask[:2, :] = 1\n mask[:, -2:] = 1\n mask[4:6, :-4] = 1\n mask[4:, -6:-4] = 1\n mask[-16:, :16] = 1\n mask[-32:-16, 16:32] = 1\n\n write_png('example2.png', mask, bitdepth=1)\n\n\nExample 3\n---------\n\nThe following script creates this PNG file, a 16-bit RGB file in which\nthe value (0, 0, 0) is transparent. It might not be obvious, but the\ntwo squares are transparent.\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example3.png\n :alt: Example 3\n :align: center\n\nThe script::\n\n import numpy as np\n from numpngw import write_png\n\n # Example 3\n #\n # Create a 16-bit RGB image, with (0, 0, 0) indicating a transparent pixel.\n\n # Create some interesting data.\n w = 32\n nrows = 3*w\n ncols = 5*w\n kernel = np.exp(-np.linspace(-2, 2, 35)**2)\n kernel = kernel/kernel.sum()\n np.random.seed(123)\n x = np.random.randn(nrows, ncols, 3)\n x = np.apply_along_axis(lambda z: np.convolve(z, kernel, mode='same'), 0, x)\n x = np.apply_along_axis(lambda z: np.convolve(z, kernel, mode='same'), 1, x)\n\n # Convert to 16 bit unsigned integers.\n z = (65535*((x - x.min())/x.ptp())).astype(np.uint16)\n\n # Create two squares containing (0, 0, 0).\n z[w:2*w, w:2*w] = 0\n z[w:2*w, -2*w:-w] = 0\n\n # Write the PNG file, and indicate that (0, 0, 0) should be transparent.\n write_png('example3.png', z, transparent=(0, 0, 0))\n\n\nExample 4\n---------\n\nThe following script uses the option ``use_palette=True`` to create this 8-bit\nindexed RGB file.\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example4.png\n :alt: Example 4\n :align: center\n\nThe script::\n\n import numpy as np\n from numpngw import write_png\n\n\n # Example 4\n #\n # Create an 8-bit indexed RGB image that uses a palette.\n\n img_width = 300\n img_height = 200\n img = np.zeros((img_height, img_width, 3), dtype=np.uint8)\n\n np.random.seed(222)\n for _ in range(40):\n width = np.random.randint(5, img_width // 5)\n height = np.random.randint(5, img_height // 5)\n row = np.random.randint(5, img_height - height - 5)\n col = np.random.randint(5, img_width - width - 5)\n color = np.random.randint(80, 256, size=2)\n img[row:row+height, col:col+width, 1:] = color\n\n write_png('example4.png', img, use_palette=True)\n\n\nExample 5\n---------\n\nThis animated PNG\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example5.png\n :alt: Example 5\n :align: center\n\nis created by the following script. As in the other examples, most of the\nscript is code that generates the data to be saved. The line that creates\nthe PNG file is simply::\n\n write_apng(\"example5.png\", seq, delay=50, use_palette=True)\n\nThe script::\n\n import numpy as np\n from numpngw import write_apng\n\n # Example 5\n #\n # Create an 8-bit RGB animated PNG file.\n\n height = 20\n width = 200\n t = np.linspace(0, 10*np.pi, width)\n seq = []\n for phase in np.linspace(0, 2*np.pi, 25, endpoint=False):\n y = 150*0.5*(1 + np.sin(t - phase))\n a = np.zeros((height, width, 3), dtype=np.uint8)\n a[:, :, 0] = y\n a[:, :, 2] = y\n seq.append(a)\n\n write_apng(\"example5.png\", seq, delay=50, use_palette=True)\n\n\nExample 6\n---------\n\nAnother animated RGB PNG. In this example, the argument ``seq``\nthat is passed to ``write_apng`` is a numpy array with shape\n``(num_frames, height, width, 3)``.\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example6.png\n :alt: Example 6\n :align: center\n\nThe script::\n\n import numpy as np\n from numpngw import write_apng\n\n # Example 6\n #\n # Create an 8-bit RGB animated PNG file.\n\n def smoother(w):\n # Return the periodic convolution of w with a 3-d Gaussian kernel.\n r = np.linspace(-3, 3, 21)\n X, Y, Z = np.meshgrid(r, r, r)\n kernel = np.exp(-0.25*(X*X + Y*Y + Z*Z)**2)\n fw = np.fft.fftn(w)\n fkernel = np.fft.fftn(kernel, w.shape)\n v = np.fft.ifftn(fw*fkernel).real\n return v\n\n height = 40\n width = 250\n num_frames = 30\n np.random.seed(12345)\n w = np.random.randn(num_frames, height, width, 3)\n for k in range(3):\n w[..., k] = smoother(w[..., k])\n\n seq = (255*(w - w.min())/w.ptp()).astype(np.uint8)\n\n write_apng(\"example6.png\", seq, delay=40)\n\n\nExample 7\n---------\n\nCreate an animated PNG with different display times for each frame.\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example7.png\n :alt: Example 7\n :align: center\n\nThe script::\n\n import numpy as np\n from numpngw import write_apng\n\n # Example 7\n #\n # Create an animated PNG file with nonuniform display times\n # of the frames.\n\n bits1 = np.array([\n [0,0,1,0,0],\n [0,1,1,0,0],\n [0,0,1,0,0],\n [0,0,1,0,0],\n [0,0,1,0,0],\n [0,0,1,0,0],\n [0,1,1,1,0],\n ])\n\n bits2 = np.array([\n [0,1,1,1,0],\n [1,0,0,0,1],\n [0,0,0,0,1],\n [0,1,1,1,0],\n [1,0,0,0,0],\n [1,0,0,0,0],\n [1,1,1,1,1],\n ])\n\n bits3 = np.array([\n [0,1,1,1,0],\n [1,0,0,0,1],\n [0,0,0,0,1],\n [0,0,1,1,0],\n [0,0,0,0,1],\n [1,0,0,0,1],\n [0,1,1,1,0],\n ])\n\n bits_box1 = np.array([\n [0,0,0,0,0],\n [1,1,1,1,1],\n [1,0,0,0,1],\n [1,0,0,0,1],\n [1,0,0,0,1],\n [1,1,1,1,1],\n [0,0,0,0,0],\n ])\n\n bits_box2 = np.array([\n [0,0,0,0,0],\n [0,0,0,0,0],\n [0,1,1,1,0],\n [0,1,0,1,0],\n [0,1,1,1,0],\n [0,0,0,0,0],\n [0,0,0,0,0],\n ])\n\n bits_dot = np.array([\n [0,0,0,0,0],\n [0,0,0,0,0],\n [0,0,0,0,0],\n [0,0,1,0,0],\n [0,0,0,0,0],\n [0,0,0,0,0],\n [0,0,0,0,0],\n ])\n\n bits_zeros = np.zeros((7, 5), dtype=bool)\n bits_ones = np.ones((7, 5), dtype=bool)\n\n\n def bits_to_image(bits, blocksize=32, color=None):\n bits = np.asarray(bits, dtype=np.bool)\n if color is None:\n color = np.array([255, 0, 0], dtype=np.uint8)\n else:\n color = np.asarray(color, dtype=np.uint8)\n\n x = np.linspace(-1, 1, blocksize)\n X, Y = np.meshgrid(x, x)\n Z = np.sqrt(np.maximum(1 - (X**2 + Y**2), 0))\n # The \"on\" image:\n img1 = (Z.reshape(blocksize, blocksize, 1)*color)\n # The \"off\" image:\n img0 = 0.2*img1\n\n data = np.where(bits[:, None, :, None, None],\n img1[:, None, :], img0[:, None, :])\n img = data.reshape(bits.shape[0]*blocksize, bits.shape[1]*blocksize, 3)\n return img.astype(np.uint8)\n\n # Create `seq` and `delay`, the sequence of images and the\n # corresponding display times.\n\n color = np.array([32, 48, 255])\n blocksize = 24\n # Images...\n im3 = bits_to_image(bits3, blocksize=blocksize, color=color)\n im2 = bits_to_image(bits2, blocksize=blocksize, color=color)\n im1 = bits_to_image(bits1, blocksize=blocksize, color=color)\n im_all = bits_to_image(bits_ones, blocksize=blocksize, color=color)\n im_none = bits_to_image(bits_zeros, blocksize=blocksize, color=color)\n im_box1 = bits_to_image(bits_box1, blocksize=blocksize, color=color)\n im_box2 = bits_to_image(bits_box2, blocksize=blocksize, color=color)\n im_dot = bits_to_image(bits_dot, blocksize=blocksize, color=color)\n\n # The sequence of images:\n seq = [im3, im2, im1, im_all, im_none, im_all, im_none, im_all, im_none,\n im_box1, im_box2, im_dot, im_none]\n # The time duration to display each image, in milliseconds:\n delay = [1000, 1000, 1000, 333, 250, 333, 250, 333, 500,\n 167, 167, 167, 1000]\n\n # Create the animated PNG file.\n write_apng(\"example7.png\", seq, delay=delay, default_image=im_all,\n use_palette=True)\n\n\nExample 8\n---------\n\nThis example shows how a Matplotlib animation can be saved as\nan animated PNG file with `numpngw.AnimatedPNGWriter`. (Be careful\nwith this class--it can easily create very large PNG files.)\n\n.. image:: https://raw.githubusercontent.com/WarrenWeckesser/numpngw/master/examples/example8.png\n :alt: Example 8\n :align: center\n\nThe script::\n\n import numpy as np\n from scipy.integrate import odeint\n from scipy.fftpack import diff as psdiff\n\n import matplotlib.pyplot as plt\n from matplotlib import animation\n from numpngw import AnimatedPNGWriter\n\n\n def kdv_exact(x, c):\n \"\"\"\n Profile of the exact solution to the KdV for a single soliton\n on the real line.\n \"\"\"\n u = 0.5*c*np.cosh(0.5*np.sqrt(c)*x)**(-2)\n return u\n\n\n def kdv(u, t, L):\n \"\"\"\n Differential equations for the KdV equation, discretized in x.\n \"\"\"\n # Compute the x derivatives using the pseudo-spectral method.\n ux = psdiff(u, period=L)\n uxxx = psdiff(u, period=L, order=3)\n\n # Compute du/dt.\n dudt = -6*u*ux - uxxx\n\n return dudt\n\n\n def kdv_solution(u0, t, L):\n \"\"\"\n Use odeint to solve the KdV equation on a periodic domain.\n\n `u0` is initial condition, `t` is the array of time values at which\n the solution is to be computed, and `L` is the length of the periodic\n domain.\n \"\"\"\n sol = odeint(kdv, u0, t, args=(L,), mxstep=5000)\n return sol\n\n\n def update_line(num, x, data, line):\n \"\"\"\n Animation \"call back\" function for each frame.\n \"\"\"\n line.set_data(x, data[num, :])\n return line,\n\n\n # Set the size of the domain, and create the discretized grid.\n L = 80.0\n N = 256\n dx = L / (N - 1.0)\n x = np.linspace(0, (1-1.0/N)*L, N)\n\n # Set the initial conditions.\n # Not exact for two solitons on a periodic domain, but close enough...\n u0 = kdv_exact(x-0.15*L, 0.8) + kdv_exact(x-0.4*L, 0.4)\n\n # Set the time sample grid.\n T = 260\n t = np.linspace(0, T, 225)\n\n print(\"Computing the solution.\")\n sol = kdv_solution(u0, t, L)\n\n print(\"Generating the animated PNG file.\")\n\n fig = plt.figure(figsize=(7.5, 1.5))\n ax = fig.gca(title=\"Korteweg de Vries interacting solitons in a periodic \"\n \"domain (L = 80)\")\n\n # Plot the initial condition. lineplot is reused in the animation.\n lineplot, = ax.plot(x, u0, 'c-', linewidth=3)\n plt.tight_layout()\n\n ani = animation.FuncAnimation(fig, update_line, frames=len(t),\n init_func=lambda : None,\n fargs=(x, sol, lineplot))\n writer = AnimatedPNGWriter(fps=12)\n ani.save('kdv.png', dpi=60, writer=writer)\n\n plt.close(fig)", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/WarrenWeckesser/numpngw", "keywords": "numpy png matplotlib animation", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "numpngw", "package_url": "https://pypi.org/project/numpngw/", "platform": "", "project_url": "https://pypi.org/project/numpngw/", "project_urls": { "Homepage": "https://github.com/WarrenWeckesser/numpngw" }, "release_url": "https://pypi.org/project/numpngw/0.0.8/", "requires_dist": null, "requires_python": "", "summary": "Write numpy array(s) to a PNG or animated PNG file.", "version": "0.0.8" }, "last_serial": 5436526, "releases": { "0.0.2": [ { "comment_text": "", "digests": { "md5": "bb827dc5b757e2c2963ee52c7fd5d14c", "sha256": "77947d831d67c9da612bf4c88c95c12f80adcaeeb47290eeba332689bd679c44" }, "downloads": -1, "filename": "numpngw-0.0.2.tar.gz", "has_sig": false, "md5_digest": "bb827dc5b757e2c2963ee52c7fd5d14c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13831, "upload_time": "2015-11-13T18:04:09", "url": "https://files.pythonhosted.org/packages/62/e9/2d169cf490e8d188bd847796428e42c57c6cbade7d9574b589f080e8ae26/numpngw-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "570a203ab2da8f138ac4c293d56e27b0", "sha256": "bb4bb2b2e4465f3ea7a7dedd63d2ce42e9215392eccd1bbc60fb61e897ee704d" }, "downloads": -1, "filename": "numpngw-0.0.3.tar.gz", "has_sig": false, "md5_digest": "570a203ab2da8f138ac4c293d56e27b0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20923, "upload_time": "2015-12-02T01:32:31", "url": "https://files.pythonhosted.org/packages/79/2f/709e881ccdcf408d66dfb2ddd2eb5b530fd2c326b0f77bb92bf45e6614e8/numpngw-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "84bed08388f771a3caabc9c27c562394", "sha256": "5ea1109505888091dba2453cf4a5b1c3099a955d2f4547592c9feeb8f33bf15e" }, "downloads": -1, "filename": "numpngw-0.0.4.tar.gz", "has_sig": false, "md5_digest": "84bed08388f771a3caabc9c27c562394", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22889, "upload_time": "2015-12-03T02:11:56", "url": "https://files.pythonhosted.org/packages/89/22/c4634958c422e0dd4dcf38d44cc5fc8358a93060d93df2ef82bd8bcdba88/numpngw-0.0.4.tar.gz" } ], "0.0.5": [], "0.0.6": [ { "comment_text": "", "digests": { "md5": "2cd2edaa62034b445de39acf60a66631", "sha256": "89d18f0ab461838b781edf4e3c0f209678ba83669f0e65eb264e4c14abd1f779" }, "downloads": -1, "filename": "numpngw-0.0.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2cd2edaa62034b445de39acf60a66631", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 22726, "upload_time": "2015-12-30T22:25:06", "url": "https://files.pythonhosted.org/packages/4f/d4/b2cbb13e20620d4699b17b1c22b46f3db7bfcaea1c1088e596a5cf1fc2f2/numpngw-0.0.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c9f3cb20055a73ea3931e40a8427aaa5", "sha256": "847797d51d899edaa1b81af5025661a6d14347373d931effcc8e3cefa1e7c4b2" }, "downloads": -1, "filename": "numpngw-0.0.6.tar.gz", "has_sig": false, "md5_digest": "c9f3cb20055a73ea3931e40a8427aaa5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22663, "upload_time": "2015-12-30T02:34:49", "url": "https://files.pythonhosted.org/packages/fc/08/3a9cde3cc80aad28c8c94c7aebea34ebb9dadbd2bd5b5d2da9673c00214e/numpngw-0.0.6.tar.gz" } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "6e294370c6a164e224b74b587baffcf9", "sha256": "995405fb1fc5cb7e2d9288b43ebd4b984e1dca31b8d7b1781123cd9ce6805014" }, "downloads": -1, "filename": "numpngw-0.0.7-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6e294370c6a164e224b74b587baffcf9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 22810, "upload_time": "2018-07-15T00:59:58", "url": "https://files.pythonhosted.org/packages/56/29/c308adeac5c8b43e7b583dbae89482c12b9e281490dca3efb45260901d37/numpngw-0.0.7-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1cb25506a65b7694b50d06fbe8a6e802", "sha256": "502743f8cae69c67c5e1a3315d5fe1e15e35f757ea9e4580a093916b9a993b82" }, "downloads": -1, "filename": "numpngw-0.0.7.tar.gz", "has_sig": false, "md5_digest": "1cb25506a65b7694b50d06fbe8a6e802", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22716, "upload_time": "2018-07-15T00:59:28", "url": "https://files.pythonhosted.org/packages/7f/a1/cd55870fd5f414cf59c7225144a96a6696fba91d8ce46f33c08428550030/numpngw-0.0.7.tar.gz" } ], "0.0.8": [ { "comment_text": "", "digests": { "md5": "6700c641f9ed165002936adf708bc805", "sha256": "311209b06dfbcf5fd16654f5f6690d5ca88252b2d800ecfcd136ea02dd8cd2a9" }, "downloads": -1, "filename": "numpngw-0.0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "6700c641f9ed165002936adf708bc805", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21209, "upload_time": "2019-06-23T07:02:40", "url": "https://files.pythonhosted.org/packages/48/99/a2482bbf4d3a663042f496e9a23fb68b068e8768baf0183293f3e5f9aaad/numpngw-0.0.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "22b2596eaaea9ae79f9adda1e0ecefce", "sha256": "385b431762cc27ff7e73c657a157dd24b3437d72c39638f8b40b543a4a42b989" }, "downloads": -1, "filename": "numpngw-0.0.8.tar.gz", "has_sig": false, "md5_digest": "22b2596eaaea9ae79f9adda1e0ecefce", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25521, "upload_time": "2019-06-23T07:02:20", "url": "https://files.pythonhosted.org/packages/25/37/6852c341dc5105aed5d237b3f51baa87407b4684347de861d348851e6108/numpngw-0.0.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6700c641f9ed165002936adf708bc805", "sha256": "311209b06dfbcf5fd16654f5f6690d5ca88252b2d800ecfcd136ea02dd8cd2a9" }, "downloads": -1, "filename": "numpngw-0.0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "6700c641f9ed165002936adf708bc805", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21209, "upload_time": "2019-06-23T07:02:40", "url": "https://files.pythonhosted.org/packages/48/99/a2482bbf4d3a663042f496e9a23fb68b068e8768baf0183293f3e5f9aaad/numpngw-0.0.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "22b2596eaaea9ae79f9adda1e0ecefce", "sha256": "385b431762cc27ff7e73c657a157dd24b3437d72c39638f8b40b543a4a42b989" }, "downloads": -1, "filename": "numpngw-0.0.8.tar.gz", "has_sig": false, "md5_digest": "22b2596eaaea9ae79f9adda1e0ecefce", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25521, "upload_time": "2019-06-23T07:02:20", "url": "https://files.pythonhosted.org/packages/25/37/6852c341dc5105aed5d237b3f51baa87407b4684347de861d348851e6108/numpngw-0.0.8.tar.gz" } ] }