GithubHelp home page GithubHelp logo

apng's Introduction

APNG golang library

This apng package provides methods for decoding and encoding APNG files. It is based upon the work in the official "image/png" package.

See apngr for an APNG extraction and combination tool using this library.

NOTE: The decoder should work for most anything you throw at it. Malformed PNGs should result in an error message. The encoder currently doesn't handle differences of Image formats and similar and has not been tested as thoroughly.

If a regular PNG file is read, the first Frame of the APNG returned by DecodeAll(*File) will be the PNG data.

Types

APNG

The APNG type contains the frames of a decoded .apng file, along with any important properties. It may also be created and used for Encoding.

Signature Description
Frames []Frame The stored frames of the APNG.
LoopCount uint The number of times an animation should be restarted during display. A value of 0 means to loop forever.

Frame

The Frame type contains an individual frame of an APNG. The following table provides the important properties and methods.

Signature Description
Image image.Image Frame image data.
IsDefault bool Indicates if this frame is a default image that should not be included as part of the animation frames. May only be true for the first Frame.
XOffset int Returns the x offset of the frame.
YOffset int Returns the y offset of the frame.
DelayNumerator int Returns the delay numerator.
DelayDenominator int Returns the delay denominator.
DisposeOp byte Returns the frame disposal operation. May be apng.DISPOSE_OP_NONE, apng.DISPOSE_OP_BACKGROUND, or apng.DISPOSE_OP_PREVIOUS. See the APNG Specification for more information.
BlendOp byte Returns the frame blending operation. May be apng.BLEND_OP_SOURCE or apng.BLEND_OP_OVER. See the APNG Specification for more information.

Methods

DecodeAll(io.Reader) (APNG, error)

This method returns an APNG type containing the frames and associated data within the passed file.

Example

package main

import (
  "log"
  "os"
  "github.com/kettek/apng"
)

func main() {
  // Open our animated PNG file
  f, err := os.Open("animation.png")
  if err != nil {
    panic(err)
  }
  defer f.Close()
  // Decode all frames into an APNG
  a, err := apng.DecodeAll(f)
  if err != nil {
    panic(err)
  }
  // Print some information on the APNG
  log.Printf("Found %d frames\n", len(a.Frames))
  for i, frame := range a.Frames {
    b := frame.Image.Bounds()
    log.Printf("Frame %d: %dx%d\n", i, b.Max.X, b.Max.Y)
  }
}

Decode(io.Reader) (image.Image, error)

This method returns the Image of the default frame of an APNG file.

Encode(io.Writer, APNG) error

This method writes the passed APNG object to the given io.Writer as an APNG binary file.

Example

package main

import (
  "image/png"
  "os"
  "github.com/kettek/apng"
)

func main() {
  // Define our variables
  output := "animation.png"
  images := [4]string{"0.png", "1.png", "2.png", "3.png"}
  a := apng.APNG{
    Frames: make([]apng.Frame, len(images)),
  }
  // Open our file for writing
  out, err := os.Create(output)
  if err != nil {
    panic(err)
  }
  defer out.Close()
  // Assign each decoded PNG's Image to the appropriate Frame Image
  for i, s := range images {
    in, err := os.Open(s)
    if err != nil {
      panic(err)
    }
    defer in.Close()
    m, err := png.Decode(in)
    if err != nil {
      panic(err)
    }
    a.Frames[i].Image = m
  }
  // Write APNG to our output file
  apng.Encode(out, a)
}

Custom Compression

A custom compression writer can be used instead of the default zlib writer. This can be done by creating a specific apng Encoder and assigning a construction function to the CompressionWriter field:

enc := apng.Encoder{
	CompressionWriter: func(w io.Writer) (apng.CompressionWriter, error) {
		return NewCustomZlibWriter(w)
	},
}
enc.Encode(out, a)

apng's People

Contributors

kettek avatar nathanbaulch avatar tengattack 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

Watchers

 avatar  avatar  avatar

apng's Issues

Can't decode seemingly fine apngs

Hi there,

thanks for making this library. Picking it up and including it into my PR was pretty simple.

However I can't get most of my test images to decode. They're working fine in Firefox and Chromium but your library throws me: apng: invalid format: not enough pixel data

A working example is the bouncing ball from the Wikipedia site about apng. I had no issues with it.

Everything else I tested isn't working, some examples:

Since I don't really know the internals of apng and this library I'm a bit lost why they're not working while they're playing fine in the browser. Are the examples just malformed apngs or is it something in the library?

Encoding RGBA Frames is opaque

Following from #1, the encoding of frames that are RGBA turn opaque if the first frame is considered as opaque. This is due to how the standard PNG library detected RGBA vs RGB colors by checking to see if any pixels in the image were not opaque and marking it as such. If they were all opaque, then the image was to be considered as non-alpha. This can be seen in @Lucki's re-encoded image here.

Pending further testing, fixes have been implemented and will be committed shortly.

image.Image doesn't work

If frame is type of image.Image, it encodes a still png.

// dc.Image() returns type image.Image
apngImage.Frames[i].Image = dc.Image()
package main

import (
	"fmt"
	"image"
	"image/draw"
	"math/rand"
	"os"
	"reflect"

	"github.com/fogleman/gg"
	"github.com/kettek/apng"
)

const frames = 4
const w, h int = 256, 256

func main() {
	dc := gg.NewContext(w, h)
	apngRgba := apng.APNG{Frames: make([]apng.Frame, frames)}
	apngNrgba := apng.APNG{Frames: make([]apng.Frame, frames)}
	apngImage := apng.APNG{Frames: make([]apng.Frame, frames)}
	for i := 0; i < frames; i++ {
		dc.SetRGB(rand.Float64(), rand.Float64(), rand.Float64())
		dc.Clear()
		dc.DrawRectangle(0, 0, 300, 300)

		apngImage.Frames[i].Image = dc.Image()               //static apng
		apngNrgba.Frames[i].Image = ImageToNRGBA(dc.Image()) //animation works
		apngRgba.Frames[i].Image = ImageToRGBA(dc.Image())   //animation works

		// dc.SavePNG("frames/" + "0" + strconv.Itoa(i) + "a.png")
	}
	fmt.Println(reflect.TypeOf(apngImage.Frames[0].Image)) //*image.RGBA
	fmt.Println(reflect.TypeOf(apngNrgba.Frames[0].Image)) //*image.NRGBA
	fmt.Println(reflect.TypeOf(apngRgba.Frames[0].Image))  //*image.RGBA

	WriteApng("apngImage.png", apngImage)
	WriteApng("apngNrgba.png", apngNrgba)
	WriteApng("apngRgba.png", apngRgba)
}

// WriteApng write apng
func WriteApng(filename string, a apng.APNG) {
	file, err := os.Create(filename)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	apng.Encode(file, a)
}

// ImageToNRGBA convert image.Image to image.NRGBA
func ImageToNRGBA(im image.Image) *image.NRGBA {
	dst := image.NewNRGBA(im.Bounds())
	draw.Draw(dst, im.Bounds(), im, im.Bounds().Min, draw.Src)
	return dst
}

// ImageToRGBA convert image.Image to image.RGBA
func ImageToRGBA(im image.Image) *image.RGBA {
	dst := image.NewRGBA(im.Bounds())
	draw.Draw(dst, im.Bounds(), im, im.Bounds().Min, draw.Src)
	return dst
}

Source files

04-gg-apng.zip

Check if file is apng

It would be nice if theres a simple function to check if a file is actually an apng?

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.