npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ugo-formats

v1.1.0

Published

JavaScript API for parsing and rendering the proprietary image and menu formats used by Flipnote Hatena

Downloads

15

Readme

This JavaScript library provides APIs to parse all of the proprietary formats used by the DSi portion of Flipnote Hatena (or "Ugomemo Theatre" in Japan).

Supported formats:

  • ntft images
  • nbf images
  • npf images
  • tmb thumbnail images (and ppm too)
  • ugo menu format

Why?

A few people were interested in rendering Flipnote Hatena pages in modern web browsers, so hopefully this will help! Besides, I already made a Flipnote player in JavaScript, so why not have a complete set? \ o /

Notes

At the moment, the image bitmaps don't support transparency, I think this can be fixed by using a more up-to-date DIB header format though (atm I'm using BITMAPINFOHEADER).

Also, it's worth pointing out that these parsers are implemented from reverse-engineered specs. I'm pretty certain we've discovered any possible quirks at this point, but if you spot any some behaviour, please raise an issue and be sure to include the file you were having trouble with. Thanks!

Usage

For Images:

There's a class available for each image type, they all work the same way:

ugoFormats.NtftImage
ugoFormats.NpfImage
ugoFormats.NbfImage
ugoFormats.TmbImage

To create a new class instance, pass it data as an ArrayBuffer:

var ntft = new ugoFormats.NtftImage( buffer );

You can also load an image using the class' fetch utility, which retruns a Promise object. When it loads, the promise is resolved and the image is passed as a class instance:

ugoFormats.NtftImage.fetch("./example.ntft").then(ntft => {
	// do something with the ntft instance...
});

Each image class provides methods to convert the image into a bitmap:

  • getImage( width, height ) - returns the bitmap as an Image object
  • getImageUrl( width, height ) - returns the bitmap as a Data URL
  • getImageBlob( width, height ) - returns the bitmap as a File Blob

These image formats don't contain any width of height values themselves, so you have to provide those in order to display them. The only exception is TMB images, as they're always 64 x 48.

Now to put it together:

// fetch example.ntft from a url:
ugoFormats.NtftImage.fetch("./example.ntft").then(ntft => {
  // when the image has loaded, convert to a bitmap
  // getImage() returns a HTML image element:
  var img = ntft.getImage(218, 32);
  // now we can just insert the image into the page:
  document.body.appendChild(img);
});

For Ugomenus:

The UgoMenu class can be used to parse an ugomenu from an ArrayBuffer:

var ugomenu = new ugoFormats.UgoMenu( buffer );

And like the image classes, there's also a fetch utility which retruns a Promise when it loads:

ugoFormats.UgoMenu.fetch("./example.ugo").then(ugomenu => {
	// do something with the ugomenu instance...
});

To understand ugomenus, it's highly recommended that you look at their documentation.

UgoMenu instances have a couple of properties:

  • contents - array of menu items
  • layoutType - menu layout
  • embeds - array of embeded images (if there are any), will be either TmbImage or NtftImage instances depending on the menu layout type

Example usage:

// fetch example.ugo from a url:
ugoFormats.UgoMenu.fetch("./example.ugo").then(ugomenu => {
	// when the ugomenu has loaded, get the list of embeds
    ugomenu.embeds.forEach(embed => {
		// get the embed as a HTML image element, 
        // you dont have to provide the size for embeds:
        var img = embed.getImage();
        // insert the image into the page:
        document.body.appendChild(img);
	});
});

Acknowledgments

  • PBSDS for creating Hatena Tools, and for giving me some notes regarding areas where the documentation fell short.
  • JSA for performing packet captures of Flipnote Hatena before it shut down, without them reverse-engineering the app in general would have been a huge pain.
  • Nintendo for creating the Flipnote Studio application.
  • Hatena for creating Flipnote Hatena, the now-defunct online service for sharing Flipnote Studio creations.