Code Monkey home page Code Monkey logo

upng.js's Introduction

photopea-logo

Photopea.com is a free online tool for editing raster and vector graphics with support for PSD, AI, and Sketch files.

Since Photopea is not fully open-source, this repository serves as a place for bug reports, feature requests, and general discussion.


Supported Formats

  • Complex: PSD, AI, INDD, XCF, Sketch, XD, FIG, KRI, CLIP, PXD, PXZ, CDR, UFO, Fireworks PNG, AFPHOTO, SVG, EPS, PDF, PDN, WMF, EMF.
  • Raster: PNG (APNG), JPG, GIF, WebP, ICO, ICNS, BMP, AVIF, HEIC, JXL, PPM/PGM/PBM, TIFF, DDS, IFF, ANIM, TGA.
  • Raw: DNG, NEF, CR2, CR3, ARW, RW2, RAF, ORF, GPR, 3FR, FFF.

Where You Can Find Us

Other

upng.js's People

Contributors

controversial avatar photopea avatar qq2423200363 avatar scimonster 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

upng.js's Issues

making an official release

We would very much like to use UPNG in one of our projects. However we can't officially use any FOSS code that isn't versioned with a release. Is there some way I can help in creating a release for the current UPNG.js?

Issues with quant and 256 colors

Your library works really good however the quanitizer seems to have an issue I could really not figure why. See this sample gif image which contains exactly 256 colors:

gif-input

Trying to compress this with UPNG into a palette of 256 colors actually produces 252 colors palette only and seems to have some white gaps ? along the line:

gif-output

Also around yellow you can see its not perfect. Doing the same but giving the compress palette of zero so he manually gets all colors produces the exact 256 colors and also gives a better optical result:

gif-output

any idea? @photopea I assume you might know how to improve especially the white artifact issue?

Incorrect decompression of iTXt compressed chunk

The included image contains an iTXt chunk with compressed text. The text as included in the image is below (between ---8<---), but the text reported by UPNG.js is truncated.

---8<---
{"type":"MM","v":0,"lllat":37.82935664523393,"lllon":2.1654982957988977,"latstep":1.1820609867402251E-4,"lonstep":2.0685191139404875E-4,"lastbucket":1600439000999999,"bucketspan":43200.0,"bucketcount":2000,"gts":406,"positions":144622,"infos":[{"id":"???"},{"id":"227384750"},{"id":"377777000"},{"id":"247322400"},{"id":"1001"},{"id":"247235360"},{"id":"???"},{"id":"215185000"},{"id":"247013600"},{"id":"2470071"},{"id":"???"},{"id":"???"},{"id":"232010683"},{"id":"???"},{"id":"247325140"},{"id":"271000768"},{"id":"247138800"},{"id":"247374100"},{"id":"???"},{"id":"227655820"},{"id":"???"},{"id":"636015530"},{"id":"227776070"},{"id":"215959000"},{"id":"227830030"},{"id":"667001840"},{"id":"232022513"},{"id":"254276000"},{"id":"247415100"},{"id":"???"},{"id":"247362700"},{"id":"247211900"},{"id":"???"},{"id":"247373600"},{"id":"???"},{"id":"255912870"},{"id":"247329820"},{"id":"247067930"},{"id":"215595000"},{"id":"???"},{"id":"227886810"},{"id":"???"},{"id":"247621000"},{"id":"229490000"},{"id":"247178700"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"247279000"},{"id":"219024903"},{"id":"???"},{"id":"247229310"},{"id":"304214000"},{"id":"???"},{"id":"???"},{"id":"247214200"},{"id":"319068400"},{"id":"227126610"},{"id":"247327610"},{"id":"211670510"},{"id":"232019268"},{"id":"563096100"},{"id":"???"},{"id":"215426000"},{"id":"227208570"},{"id":"???"},{"id":"2288238"},{"id":"???"},{"id":"247130700"},{"id":"2470069"},{"id":"???"},{"id":"247219400"},{"id":"???"},{"id":"247278400"},{"id":"227779610"},{"id":"319096300"},{"id":"???"},{"id":"???"},{"id":"227184000"},{"id":"255806058"},{"id":"247208920"},{"id":"227665340"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"319053100"},{"id":"247086400"},{"id":"339446000"},{"id":"215121000"},{"id":"???"},{"id":"247121100"},{"id":"???"},{"id":"319025900"},{"id":"???"},{"id":"211411390"},{"id":"247036100"},{"id":"227060730"},{"id":"247149250"},{"id":"227986950"},{"id":"247370100"},{"id":"428042000"},{"id":"???"},{"id":"229953000"},{"id":"218024000"},{"id":"247372500"},{"id":"304416000"},{"id":"319064900"},{"id":"247150350"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"227873090"},{"id":"247106500"},{"id":"235011110"},{"id":"354298000"},{"id":"247391200"},{"id":"???"},{"id":"538001665"},{"id":"100265"},{"id":"111247103"},{"id":"247044300"},{"id":"319609000"},{"id":"269053000"},{"id":"2288237"},{"id":"247238500"},{"id":"205936130"},{"id":"???"},{"id":"319560000"},{"id":"227909190"},{"id":"???"},{"id":"215587000"},{"id":"247101800"},{"id":"???"},{"id":"228009700"},{"id":"???"},{"id":"374499000"},{"id":"672747000"},{"id":"247144800"},{"id":"227691460"},{"id":"247035390"},{"id":"235077715"},{"id":"247160170"},{"id":"247192100"},{"id":"247183200"},{"id":"538006592"},{"id":"378113355"},{"id":"247101100"},{"id":"354854000"},{"id":"605086020"},{"id":"???"},{"id":"226280000"},{"id":"215599000"},{"id":"227288820"},{"id":"???"},{"id":"247319800"},{"id":"211758910"},{"id":"378112621"},{"id":"247228600"},{"id":"248553000"},{"id":"227582180"},{"id":"227452730"},{"id":"255805606"},{"id":"???"},{"id":"???"},{"id":"235085866"},{"id":"228081000"},{"id":"247015400"},{"id":"636018142"},{"id":"239989000"},{"id":"247252410"},{"id":"247482000"},{"id":"???"},{"id":"215065000"},{"id":"???"},{"id":"304628000"},{"id":"227245460"},{"id":"227545850"},{"id":"228078900"},{"id":"???"},{"id":"232029964"},{"id":"???"},{"id":"247056100"},{"id":"227020210"},{"id":"211286290"},{"id":"247222320"},{"id":"247190200"},{"id":"???"},{"id":"255805844"},{"id":"319253000"},{"id":"211349960"},{"id":"247150870"},{"id":"???"},{"id":"247034200"},{"id":"???"},{"id":"227202000"},{"id":"2470027"},{"id":"255912850"},{"id":"247580000"},{"id":"227732750"},{"id":"???"},{"id":"247131600"},{"id":"247067730"},{"id":"247065500"},{"id":"247044790"},{"id":"227859220"},{"id":"247373200"},{"id":"319137400"},{"id":"???"},{"id":"311000104"},{"id":"247038220"},{"id":"247228650"},{"id":"205728930"},{"id":"227904440"},{"id":"538006783"},{"id":"2470050"},{"id":"247106900"},{"id":"247364270"},{"id":"247051600"},{"id":"???"},{"id":"???"},{"id":"248000749"},{"id":"247151070"},{"id":"???"},{"id":"???"},{"id":"227182000"},{"id":"247057100"},{"id":"247356500"},{"id":"235703000"},{"id":"247086200"},{"id":"???"},{"id":"232031099"},{"id":"227568170"},{"id":"247320400"},{"id":"227020300"},{"id":"247154490"},{"id":"215300000"},{"id":"???"},{"id":"???"},{"id":"247046800"},{"id":"???"},{"id":"???"},{"id":"269112430"},{"id":"256001151"},{"id":"2288242"},{"id":"228372900"},{"id":"???"},{"id":"235080934"},{"id":"248258000"},{"id":"???"},{"id":"277373000"},{"id":"247083700"},{"id":"247205000"},{"id":"227392140"},{"id":"???"},{"id":"247343200"},{"id":"???"},{"id":"247069980"},{"id":"269113270"},{"id":"203245426"},{"id":"211812560"},{"id":"538080084"},{"id":"235021357"},{"id":"227425840"},{"id":"247388600"},{"id":"247076570"},{"id":"???"},{"id":"247110700"},{"id":"247225210"},{"id":"???"},{"id":"256565000"},{"id":"247388800"},{"id":"228004550"},{"id":"215000824"},{"id":"218615000"},{"id":"247186700"},{"id":"247225880"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"225981613"},{"id":"227119730"},{"id":"227461070"},{"id":"211706890"},{"id":"247243600"},{"id":"???"},{"id":"2470042"},{"id":"???"},{"id":"247220130"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"228358800"},{"id":"227120990"},{"id":"247337300"},{"id":"247385700"},{"id":"235231000"},{"id":"235770000"},{"id":"227233780"},{"id":"247319500"},{"id":"???"},{"id":"310783000"},{"id":"???"},{"id":"247061700"},{"id":"256121000"},{"id":"2288236"},{"id":"???"},{"id":"249720000"},{"id":"247458000"},{"id":"229459000"},{"id":"218820000"},{"id":"???"},{"id":"247121200"},{"id":"247271100"},{"id":"111247501"},{"id":"???"},{"id":"319835000"},{"id":"247065580"},{"id":"227960860"},{"id":"???"},{"id":"247407000"},{"id":"247132400"},{"id":"247436000"},{"id":"2288241"},{"id":"247159350"},{"id":"???"},{"id":"247013400"},{"id":"228390600"},{"id":"229045000"},{"id":"254523000"},{"id":"356879000"},{"id":"???"},{"id":"???"},{"id":"310763000"},{"id":"???"},{"id":"319094900"},{"id":"???"},{"id":"232002797"},{"id":"???"},{"id":"???"},{"id":"211649470"},{"id":"247380050"},{"id":"247045600"},{"id":"247046600"},{"id":"227878310"},{"id":"???"},{"id":"???"},{"id":"???"},{"id":"211292200"},{"id":"227834780"},{"id":"???"},{"id":"247066220"},{"id":"227807140"},{"id":"247616000"},{"id":"???"},{"id":"???"},{"id":"2288231"},{"id":"310079000"},{"id":"???"},{"id":"215469000"},{"id":"235100652"},{"id":"???"},{"id":"227908470"},{"id":"247140560"},{"id":"577203000"},{"id":"???"},{"id":"247094000"},{"id":"538071072"},{"id":"???"},{"id":"269113200"},{"id":"???"},{"id":"229706000"},{"id":"235010730"},{"id":"247037120"},{"id":"247297200"},{"id":"314397000"},{"id":"227101320"},{"id":"247063240"},{"id":"227914470"},{"id":"247220050"},{"id":"227593840"},{"id":"227245000"},{"id":"247378700"},{"id":"227414980"},{"id":"578000800"},{"id":"247092950"},{"id":"247089500"},{"id":"???"},{"id":"227569780"},{"id":"???"},{"id":"2470038"},{"id":"236647000"},{"id":"247259540"},{"id":"247209100"},{"id":"211527530"},{"id":"???"},{"id":"354972000"},{"id":"???"},{"id":"247257320"},{"id":"???"},{"id":"247063450"},{"id":"2470052"},{"id":"227331290"},{"id":"247664000"}]}]
---8<---

i

use Rec. 709 component coefficients for color distance

hey @photopea

i ran some visual tests and it seems that using the coefficients yields a noticeable improvement in quality across a diverse set of images. for now, i only tested at the default 255 colors setting of http://upng.photopea.com/

UPNG.quantize.dist = function(q,   r,g,b,a) {  var d0=r-q[0], d1=g-q[1], d2=b-q[2], d3=a-q[3];  return d0*d0*.2126+d1*d1*.7152+d2*d2*.0722+d3*d3;  }

the coeffs could probably be re-scaled to avoid one of the mults.

  • gradients have smoother, more pleasant transitions
  • color shifting is reduced
  • slight increase in resulting filesize.
  • perf seemed unchanged or even slightly improved.

i tested for all the images here: https://github.com/leeoniya/RgbQuant.js/tree/master/demo/img

plus these:

pixel3
nightshot
artificial

Block scoped declarations

/usr/local/lib/node_modules/moneda-cli/index.js:32
let cliOptions = helpers.cleanUpCommandLineOptions(options);
^^^

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:141:18)
    at node.js:933:3

Support es6 modules.

Please support es6 modules. They are supported, sometimes behind a flag, by all modern browsers. However, the strategy used to be non-trivial, but now is much easier with Rollup:
https://medium.com/@backspaces/es6-modules-part-1-migration-strategy-a48de0b7f112

The idea is simple: make your repo es6 module based. Then use rollup to convert to the legacy module formats: iife, cjs (node) and so on.

I converted my repo, basically following Three.js's lead, and have never looked back.

Ghost pixels on animated png

Hi,

I've noticed an issue when encoding an APNG file with default params:
test
I can't pinpoint what's wrong exactly, but I have a feeling it's related to blending.
Replacing the regular encode call with the following code fixed the issue (huge thanks for exposing the internal methods btw):

var nimg = UPNG.encode.compress(bufs, w, h, ps, [true, false, false, 0, false]);
UPNG.encode.compressPNG(nimg, -1);
UPNG.encode._main(nimg, w, h, dels);

test-ok

Is it possible to reverse PNG compression?

πŸ‘‹ Hi! First and foremost, thanks for creating and sharing this library. It's the only high quality PNG web encoder/decoder I've been able to find, and it's enabling us (and I'm sure many others) to do great things ^_^

Where I'm at

I have an input image that, uncompressed, decodes with the following information:
~140kb

{
    ctype: 0,
    data: Uint8Array [],
    depth: 16,
    frames: [],
    height: 512,
    tabs: {tEXt: {…}},
    width: 512,
}

And I'm able to follow the steps you've laid out in this thread to convert the original image's data to a Uint16Array[]. Which I then use in cornerstonejs to display and manipulate medical images (it supports Uint8Array[] and Uint16Array[] pixel data for it's WebGL implementation; using individual pixel values as intensities to render)

The problem

When I run it through http://upng.photopea.com/, at the highest quality (lossless), it decodes with:
~3.8kb

{
    ctype: 3,
    data: Uint8Array [],
    depth: 2,
    frames: [],
    height: 512,
    tabs: {PLTE: Array(12)},
    width: 512,
}

So the compression works great! When we're talking over a few petabytes of data, and many, many thousands of images, that really adds up for us. What I'm having trouble figuring out is how to reverse the compression, or use the decoded information from the compressed image, to provide a Uint8Array[] or Uint16Array[] the library I'm using can work with.

I'm not sure why the color type changed, or how it impacts things. When attempting to use the same logic that worked for the original image with the decoded image, I see it rendered as "repeating" 8 times. I assume this is related to the change in depth.

I will continue to play around, and I'll post my findings here. Any/all help is appreciated. If you feel that this is not the appropriate place for issues of this nature, please feel free to close my question.

code style

the source code is really difficult to read, should we change another code style?

Encoding returns empty image

Decoding TIFF file G31D.TIF from TIFF samples and encoding it with UPNG returns empty image.

        // read TIFF
        const ifds = UTIF.decode(tiffBuffer);
        UTIF.decodeImages(tiffBuffer, ifds);
        const page = ifds[0];
        const rgba = UTIF.toRGBA8(page);

        // write PNG
        const pngBuffer = UPNG.encode([rgba], page.width, page.height);

I was able to fix it using undocumented param for UPNG.encode forbidPlte=true, but it is about two times slower than pngjs.

quantizer

@photopea Thx for the great quantizer! It is really fast and shows very good results. Currently I am trying to use it for my SIXEL encoding package (this PR jerch/node-sixel#16).

A few questions/remarks:

  • Your exact color matching is quite slow (understandable, since it has to walk parts of the kd tree). I found populating the palette colors in 16x16x16 cubes in the colorspace and doing local brute force searching being almost as fast as your fast approximation, but with much better results (See ColorMatcher class). The search itself is spheric (euclidian distance) and is done on the outer cube sphere first, and for uncertain colors (those outside of an inner subsphere) with a second bigger sphere. The cut-down of the search space works nicely with good palette color distribution, but ofc falls short, if they all aggregate within a few cubes, or the palette is rather big (>1024 colors). For that one could introduce subcubes (again forming an octree), but I have not implemented this (not needed for SIXEL, as the palette should not be >256).
  • The quantizer has issues to build a 512 color palette for this image: https://github.com/jerch/node-sixel/blob/master/palette.png, it always stops at 503 colors. Maybe you want to have a look at it.
  • Is there a way to strip down the quantizer in terms of channel resolution and channels being used? SIXEL only allows RGB values in full percent limiting the color space to ~1M colors, also alpha is not supported (beside marking one palette entry as fully transparent). Thus I started to wonder, if the calculation can be simplified with those restrictions in mind. This might not work, as you calc most things in float internally, not sure if a partial rewrite with discrete integer calcs is worth the shot (JS also makes this really hard).
  • As already mentioned in the other issue - could you update the npm package somehow? Directly pulling source code from repos is cumbersome 😸.

Edit: I also implemented a very small dithering with forward error diffusion, with does not penalize image size and runtime alot, but helps to remove most obvious bandings.

[BUG]This image whose data length is not 1024

1

When I decode this png, the data is in Uint8Array and the length is 1025. The length should be 1024. This image is 256 x 1. If I use RGBA, the total length should be 256 x 4 1024

Use browser console to run this code

const arrayBuffer = fetch("https://user-images.githubusercontent.com/5212215/81272862-edab9200-9002-11ea-956e-5bbeb910a4ab.png")
      .then(res => res.blob())
      .then(blob => blob.arrayBuffer())
      .then(decode)
      // .then(toRGBA8)
      .then(console.log);

Add support for 8-bit data export

Hi,

Currently, decoding a PNG only returns a true color buffer, even if the file content is palette indexed.

It would be great to be able to optionally decide to get an array of color indices instead of an RGB array when there is a palette. And also get the Related palette of course!

It is important for me to keep the file intact when opening/saving back. Keeping depth etc.

Would this be possible?

Thanks!
Chris

CLI support

Missing for me CLI API for using with nodejs as microservice in Docker for example. Can be written as script in package.json.

How to convert data to same format as native ImageData.data format?

I'm working in an environment where Canvas and ImageData types are not available. This class looks like it does what I need but the library I'm using is expecting pixel data in the same format as the ImageData data property.

ImageData.data Read only
Is a Uint8ClampedArray representing a one-dimensional array containing the data in the RGBA order, with integer values between 0 and 255 (inclusive).

Here is my related question:
https://stackoverflow.com/questions/58465010/how-to-supply-the-correct-data-when-imagedata-is-not-available?noredirect=1#comment103265587_58465010

I'm having issues converting it to the correct format.

Using with Angular

When using this library with Angular5, it works great during development, but the build process using angular-cli strips it (tree shaking). I am not an expert at all of the different module types, but I forked the project and made it work for Angular and I am sure my brute force change will cause issues with other module systems... Wanted to give you a heads up in case you want to document it or make it Angular friendly. Thanks!

These are the changes I made to get it work in Angular 5 production

(function (factory) {
  window['UPNG'] = factory();
})(function () {

var UPNG = {};

// // Make available for import by `require()`
// var pako;
// if (typeof module == "object") {module.exports = UPNG;}  else {window.UPNG = UPNG;}
// if (typeof require == "function") {pako = require("pako");}  else {pako = window.pako;}
// function log() { if (typeof process=="undefined" || process.env.NODE_ENV=="development") console.log.apply(console, arguments);  }
// (function(UPNG, pako){

	
...... library .....


  return UPNG;
});

PNG Encoding sometimes fails

PNG encoding sometimes fails... This is an example that frequently fails:
var bin = UPNG.encode([newData.data], w, h, 0);

Using 256 colors instead of 0 (unlimited) mostly works, but not always.

This is an example that failed with 0 (unlimited colors) - resulting PNG at:
https://x1.gatherworks.com:443/doc/572BD2A2CCA63DBA5EB3C21DE115908B/ffa002be102547399238a7af4a8b3e6f.png

Attaching a screen shot of the application window that was PNG encoded.
2018-04-03_04-12-30

I am not sure what the best way is to give you a recreatable example since it depends on the contents of the buffer... but it frequently happens when using 0 (unlimited colors). Encoding mostly works when using this instead (but not always):
var bin = UPNG.encode([newData.data], w, h, 0, null, true);

Typo

Hi,

There's a typo in here: https://github.com/photopea/UPNG.js/blob/master/UPNG.js#L672

It should be

p32 = new Uint32Array(pimg.buffer)

Otherwise the diff for the changed region doesn't work at all and always returns 0,0,maxWidth,maxHeight

I fixed it locally for me and I can now generate GIFs correctly with changed regions, however I can now see artificacts any idea why? When I dismiss the region using your UPNG.compress function and always set 0,0,maxWidth,maxHeight in my gif it works perfectly?

data array of wrong size

Hi,
When I decode a png, the object given by UPNG has a wrong sized data array. I made a test image here (it is VERY small):
damier2_alpha
and here is the screen capture from Chome's console:
upng2

The image is 12 pixels wide, 7 pixels high and has 4 components. This should give a data array of size 336 but instead gives a larger array (size 343).

I made other tests with other images and every time, the final array size is : w*h*nc + h instead of just w*h*nc , where nc is the number of components per pixel.
I checked with other images and the issue is always here. The last h numbers of the array seem to be fake data, only 0, 1, 255, and 254.

In case someone is interested, here is the workaround I use:

var pngData = png.decode( inputBuffer );
var ncpp = Math.round(pngData.data.length / (pngData.width*pngData.height) );
var croppedArray = new pngData.data.constructor( pngData.data.buffer, 0, pngData.width * pngData.height * ncpp);

Cheers.

Update: the method UPNG.decode._inflate just calls pako.inflate, and Pako seems to be responsible for the wrong size...

node.js buffer

If I want to use UPNG.decode(buffer) in node.js,can I use the following writing?

fs.readFile(file.path, function(err, stat) { const buffer = UPNG.decode(stat) }

can I deliver node.js buffer to the method? If I can't, how should I do it in node.js?

Infinite loop if I decode a abnormal arraybuffer

UPNG.js/UPNG.js

Lines 350 to 387 in c62ddc8

while(true) {
used=[]; plte=[];
var msk = 0xff - ((1<<pr)-1), add = ((1<<pr))>>1;
for(var i=0; i<area; i++) { var qi=i<<2; var r=nimg[qi],g=nimg[qi+1],b=nimg[qi+2],a=nimg[qi+3];
var nr=(r&msk)+add, ng=(g&msk)+add, nb=(b&msk)+add, na=(a&msk)+add, key=(na<<24)|(nb<<16)|(ng<<8)|nr;
if(used[key]) { var pv=plte[used[key]]; pv.occ++; }
else { used[key]=plte.length; plte.push( {occ:1, r:nr,g:ng,b:nb,a:na} ); }
if(plte.length>plim) break;
}
if(plte.length>plim) { pr++; continue; }
break;
}
if(pr==0 && plte.length<=ps) return bufs;
plte.sort(function(a,b) {return b.occ-a.occ;});
ps = Math.min(ps, plte.length);
var nplte = new Uint8Array(ps*4);
for(var i=0; i<ps; i++) { var qi=i<<2,c=plte[i]; nplte[qi]=c.r; nplte[qi+1]=c.g; nplte[qi+2]=c.b; nplte[qi+3]=c.a; }
plte = nplte; //*/
var icnt = Math.max(1, Math.min(10, Math.floor(1024/ps)));
var pind = new Uint16Array(area);
for(var it=0; it<icnt; it++)
{
UPNG.quantize.kMeans(nimg, plte, pind, ps, true);
}
UPNG.quantize.applyPalette(nimg, plte, pind);
// remap remaining frames according to palette
for(var i=1; i<imgs.length; i++) {
UPNG.quantize.kMeans(imgs[i], plte, pind, ps, false); // "classify" into pind
UPNG.quantize.applyPalette(imgs[i], plte, pind); // remap according to pind
}
//UPNG.quantize.dither(nimg, w,h, pind,plte, ps); // I think that (current) dithering is not worth it
for(var i=0; i<bufs.length; i++) imgs[i] = imgs[i].buffer;
return imgs;
}

Above code would run infinite loop if I decode a abnormal arraybuffer, which block main JS thread, and will crash page.
Consider using setTimeout or web worker, and I think it's better to apply decode timeout.

Incorrect data length returned by UPNG.decode

When calling UPNG.decode, it returns an imageObject. However, it seems the length doesn't correspond to height*width*channels*bytesPerChannel.

For example, I have an image 512x512x3 8-bit RGB image, the expected imgObj.data should have 786,432 length, however, the one I got is 786,944 (with a tail of 512 bytes).

Unused variable in UPNG.toRGBA8()

At lines 47 to 51:

if(depth== 1) for(var i=0; i<area; i++) {  var qi=i<<2, gr=255*((data[i>>3]>>(7 -((i&7)   )))& 1), al=(gr==tr*255)?0:255;  bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr;  }
if(depth== 2) for(var i=0; i<area; i++) {  var qi=i<<2, gr= 85*((data[i>>2]>>(6 -((i&3)<<1)))& 3), al=(gr==tr* 85)?0:255;  bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr;  }
if(depth== 4) for(var i=0; i<area; i++) {  var qi=i<<2, gr= 17*((data[i>>1]>>(4 -((i&1)<<2)))&15), al=(gr==tr* 17)?0:255;  bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr;  }
if(depth== 8) for(var i=0; i<area; i++) {  var qi=i<<2, gr=data[i  ] , al=(gr           ==tr)?0:255;  bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr;  }
if(depth==16) for(var i=0; i<area; i++) {  var qi=i<<2, gr=data[i<<1], al=(rs(data,i<<1)==tr)?0:255;  bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr;  }

The variable qi is set to i<<2 and never used!

Use dithering

It's important for colorful images.

Source image [174285 B]
firefox-512

After upng, web interface [69927 B]
firefox-512 upng

Result of pngquant looks better. [69932 B]
firefox-512 pngquant

Feature request: NPM module

Could you create an NPM module of UPNG.js? Samples on how to use it in a Node.js or browser context would also be very helpful.

pako is not defined

use method 'UPNG.encode' get error:
"pako is not defined"
in UPNG.js line 789.
image

UPNG.toRGBA8() output appears to be incorrect for certain PNGs

Hello @photopea and friends!

I'm looking to use upng-js as the PNG decoding library for pdf-lib. However, I ran into an issue when testing the output of UPNG.toRGBA8() on the basi0g01 image from the interlaced PNG test suite linked to in the README.

When I run basi0g01 through UPNG.toRGBA8() and draw the output to an HTML canvas, I see the following:

Screen Shot 2020-02-17 at 6 50 47 PM

The correct rendering is shown below:

Screen Shot 2020-02-17 at 6 50 39 PM

I've attached the basi0g01 image for your convenience: basi0g01.png

Here's a simple self-contained HTML file you can view in your browser to reproduce the issue:

<html>
  <head>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/[email protected]/dist/pako.min.js"></script>
    <script src="https://unpkg.com/[email protected]/UPNG.js"></script>
  </head>

  <body>
    <canvas id="canvas" style="width: 100%; height: 100%;"></iframe>
  </body>

  <script>
    (async () => {
      const upng = UPNG.decode(getImageData());
      const frames = UPNG.toRGBA8(upng);

      const rgbaClamped = new Uint8ClampedArray(frames[0]);
      const imageData = new ImageData(rgbaClamped, upng.width, upng.height);

      const canvas = document.getElementById('canvas');
      const ctx = canvas.getContext('2d');
      ctx.putImageData(imageData, 0, 0);
    })();

    // Inline data for `basi0g01.png`
    function getImageData() {
      return Uint8Array.from([
        0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
        0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
        0x01, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x06, 0x77, 0xcf, 0x00, 0x00, 0x00,
        0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, 0xa0, 0x31, 0xe8, 0x96,
        0x5f, 0x00, 0x00, 0x00, 0x90, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0x2d,
        0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x0c, 0x45, 0xdf, 0xc6, 0x82, 0xc4, 0x15,
        0x18, 0x7a, 0x00, 0xa4, 0x2e, 0x19, 0x7a, 0xb8, 0x1e, 0x83, 0xb1, 0x27,
        0xe0, 0x0c, 0x56, 0x39, 0x00, 0x13, 0x63, 0xa5, 0x80, 0xd8, 0x58, 0x2c,
        0x65, 0xc9, 0x10, 0x35, 0x7c, 0x4b, 0x78, 0xb0, 0xbf, 0xbf, 0xdf, 0x4f,
        0x70, 0x16, 0x8c, 0x19, 0xe7, 0xac, 0xb9, 0x70, 0xa3, 0xf2, 0xd1, 0xde,
        0xd9, 0x69, 0x5c, 0xe5, 0xbf, 0x59, 0x63, 0xdf, 0xd9, 0x2a, 0xaf, 0x4c,
        0x9f, 0xd9, 0x27, 0xea, 0x44, 0x9e, 0x64, 0x87, 0xdf, 0x5b, 0x9c, 0x36,
        0xe7, 0x99, 0xb9, 0x1b, 0xdf, 0x08, 0x2b, 0x4d, 0x4b, 0xd4, 0x01, 0x4f,
        0xe4, 0x01, 0x4b, 0x01, 0xab, 0x7a, 0x17, 0xae, 0xe6, 0x94, 0xd2, 0x8d,
        0x32, 0x8a, 0x2d, 0x63, 0x83, 0x7a, 0x70, 0x45, 0x1e, 0x16, 0x48, 0x70,
        0x2d, 0x9a, 0x9f, 0xf4, 0xa1, 0x1d, 0x2f, 0x7a, 0x51, 0xaa, 0x21, 0xe5,
        0xa1, 0x8c, 0x7f, 0xfd, 0x00, 0x94, 0xe3, 0x51, 0x1d, 0x66, 0x18, 0x22,
        0xf2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
        0x82
      ]);
    }
  </script>
</html>

Note that I obtained the inline image by running the following NodeJS script:

const img = fs.readFileSync('basi0g01.png')
console.log(
  Array
    .from(x)
    .toString(16)
    .split(/(\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,)/g)
    .map(line => line.split(',').filter(Boolean).map(n => Number(n).toString(16))
    .map(n => `0x${n.padStart(2, '0')}`).join(', '))
    .filter(Boolean)
    .join(',\n        '),
)

Lest you suspect that the issue is simply due to a bug in my script code, I should mention that I first encountered the issue when reading the image data directly from the PNG file. I just thought it would be helpful to create a self-contained HTML file to make reproducing the issue as easy as possible.

Finally, I found that by exporting the PNG image in Mac's Preview app (essentially rewriting it as a different PNG type) I was able to successfully decode and draw it on the canvas. Here's the rewritten image I created: basi0g01_rewritten.png. And here's an alternative version of the getImageData function you can swap out in the example I shared to use the rewritten version:

// Inline data for `basi0g01_rewritten.png`
function getImageData() {
  return Uint8Array.from([
    0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
    0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
    0x08, 0x00, 0x00, 0x00, 0x01, 0x21, 0x16, 0x15, 0xbe, 0x00, 0x00, 0x00,
    0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, 0xa0, 0x31, 0xe8, 0x96,
    0x5f, 0x00, 0x00, 0x00, 0xd0, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43,
    0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x18, 0x95,
    0x63, 0x60, 0x60, 0xac, 0x48, 0x2c, 0x28, 0xc8, 0x61, 0x12, 0x60, 0x60,
    0xc8, 0xcd, 0x2b, 0x29, 0x72, 0x0f, 0x72, 0x8c, 0x8c, 0x88, 0x8c, 0x52,
    0x60, 0xbf, 0xca, 0xc0, 0xce, 0xc0, 0xc8, 0x00, 0x06, 0x89, 0xc9, 0xc5,
    0x05, 0x8e, 0x01, 0x01, 0x3e, 0x0c, 0x38, 0xc1, 0xb7, 0x6b, 0x10, 0xb5,
    0x97, 0x75, 0x41, 0x66, 0xe1, 0x56, 0x87, 0x15, 0xb0, 0xa4, 0xa4, 0x16,
    0x27, 0x03, 0xe9, 0x2d, 0x40, 0x5c, 0x9a, 0x5c, 0x50, 0x54, 0xc2, 0xc0,
    0xc0, 0xa8, 0x03, 0x64, 0xab, 0x97, 0x97, 0x14, 0x80, 0xd8, 0x21, 0x40,
    0xb6, 0x48, 0x76, 0x48, 0x90, 0x33, 0x90, 0x9d, 0x01, 0x64, 0xf3, 0x41,
    0xd5, 0x83, 0x80, 0xb4, 0x73, 0x62, 0x4e, 0x66, 0x52, 0x51, 0x62, 0x49,
    0x6a, 0x8a, 0x82, 0x7b, 0x51, 0x62, 0xa5, 0x82, 0x73, 0x7e, 0x4e, 0x7e,
    0x51, 0x71, 0x41, 0x62, 0x72, 0x2a, 0x89, 0xae, 0x20, 0x02, 0x94, 0xa4,
    0x56, 0x94, 0x80, 0x68, 0xe7, 0xfc, 0x82, 0xca, 0xa2, 0xcc, 0xf4, 0x8c,
    0x12, 0x05, 0x47, 0xa0, 0x6f, 0x53, 0x81, 0x76, 0xe6, 0x16, 0x94, 0x96,
    0xa4, 0x16, 0xe9, 0x28, 0x78, 0xe6, 0x25, 0xeb, 0x31, 0x30, 0x80, 0xc2,
    0x0f, 0xa2, 0xe3, 0x73, 0x20, 0x38, 0x5c, 0x18, 0xc5, 0xce, 0x24, 0x97,
    0x16, 0x95, 0x41, 0x8d, 0x61, 0x04, 0x09, 0x01, 0x00, 0x10, 0xc0, 0x34,
    0x91, 0x8a, 0x29, 0xae, 0x33, 0x00, 0x00, 0x00, 0x44, 0x65, 0x58, 0x49,
    0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x01,
    0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x87,
    0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x20, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x66, 0xf6, 0xf7,
    0x5d, 0x00, 0x00, 0x01, 0x59, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c,
    0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78,
    0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d,
    0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a,
    0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a,
    0x6d, 0x65, 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70,
    0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65,
    0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20,
    0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c,
    0x6e, 0x73, 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70,
    0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72,
    0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32,
    0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d,
    0x6e, 0x73, 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
    0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f,
    0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a,
    0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
    0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f,
    0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22,
    0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
    0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61,
    0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66,
    0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
    0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64,
    0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
    0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a,
    0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70,
    0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x4c, 0xc2, 0x27, 0x59, 0x00, 0x00,
    0x01, 0x01, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0x95, 0x93, 0xdb, 0x12,
    0xc2, 0x20, 0x0c, 0x44, 0xc1, 0xf1, 0xff, 0x7f, 0x19, 0xf7, 0x92, 0x0d,
    0x50, 0xc7, 0x07, 0xe9, 0x58, 0x48, 0x72, 0x48, 0x36, 0x50, 0xe7, 0x1a,
    0x18, 0x0b, 0xcf, 0x58, 0x5c, 0xf2, 0x37, 0xe5, 0xd3, 0xba, 0x7c, 0x8c,
    0xf2, 0x81, 0xe9, 0xe0, 0x1c, 0xe3, 0x45, 0x52, 0x56, 0xe1, 0xbd, 0x4f,
    0x21, 0x44, 0xc7, 0x24, 0xc3, 0x79, 0xe7, 0xd2, 0x06, 0xd8, 0xde, 0x4e,
    0x3f, 0x18, 0xda, 0x18, 0x5f, 0x79, 0xec, 0x56, 0x1a, 0x22, 0x85, 0xcd,
    0x39, 0xde, 0x80, 0xcb, 0xb2, 0x37, 0x92, 0x1b, 0x02, 0xa1, 0x01, 0x8a,
    0x69, 0xb5, 0x45, 0xb3, 0xdd, 0x78, 0x93, 0x48, 0x0e, 0x3b, 0x53, 0x3f,
    0xc8, 0x4e, 0x6a, 0x4f, 0xda, 0xe9, 0x78, 0xb4, 0x47, 0x98, 0xbb, 0x4a,
    0x58, 0xd9, 0x75, 0x02, 0x3b, 0x8e, 0x92, 0x38, 0x42, 0x10, 0x16, 0x45,
    0x14, 0x84, 0x8e, 0xbf, 0xd5, 0x74, 0xd9, 0xa8, 0xab, 0x53, 0xdc, 0x6a,
    0xab, 0xb9, 0xca, 0x83, 0xc9, 0x84, 0x79, 0xdd, 0x89, 0x88, 0xda, 0xaf,
    0x82, 0x24, 0xca, 0xf6, 0xad, 0x81, 0x88, 0x8d, 0xfa, 0x5c, 0x3e, 0xdb,
    0xa7, 0xb8, 0x6b, 0xb4, 0xb0, 0xcb, 0xdb, 0x46, 0xce, 0xb8, 0x1d, 0xf7,
    0x82, 0x25, 0x4a, 0x96, 0x2b, 0xcd, 0xab, 0xa2, 0xc5, 0x54, 0x67, 0xd4,
    0x76, 0xcb, 0x89, 0xd6, 0x06, 0xbe, 0x93, 0xdb, 0x63, 0x91, 0xc1, 0x2b,
    0x49, 0x4c, 0x22, 0xd5, 0x05, 0x0b, 0xa4, 0xc8, 0x19, 0x6e, 0x60, 0x17,
    0xb8, 0xc3, 0xd5, 0xc5, 0xef, 0xf0, 0x03, 0xc8, 0xee, 0x53, 0xca, 0xd1,
    0x45, 0xc2, 0x92, 0x86, 0xd7, 0xd2, 0x87, 0xdd, 0xc0, 0x19, 0xae, 0x2b,
    0x92, 0xab, 0x80, 0x3b, 0xec, 0x2b, 0x3d, 0x32, 0x3c, 0xc3, 0x67, 0x06,
    0xff, 0xdf, 0x77, 0x1b, 0xff, 0xaf, 0x3e, 0xe2, 0x3a, 0x3f, 0x78, 0x53,
    0xff, 0x69, 0x96, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
    0x42, 0x60, 0x82
  ]);
}

Any idea what's going on here? Am I doing something incorrectly? Or is this a bug in the UPNG.toRGBA8() method?

Error in `UPNG.encode.compress` when encoding RGBA images

I tried to create a Node.js module from UPNG.js. To do so I added

var pako = require("pako");

as the first line and

module.exports = UPNG;

as the last line in UPNG.js.

Then I loaded pug.png from the samples page at https://blog.photopea.com/png-minifier-inside-photopea.html. The following code was used (running in Node.js):

"use strict";
var UPNG = require("./UPNG");
var FS = require("fs");
var input = FS.readFileSync('pug.png');
var decoded = UPNG.decode(input);
var encoded = new Uint8Array(UPNG.encode(decoded.data, decoded.width, decoded.height, 0));
FS.writeFileSync('test.png', encoded);

I receive the following error:

/Users/.../JS/UPNG.js/UPNG.js:119
	var img32 = new Uint32Array(img.buffer);
	            ^

RangeError: byte length of Uint32Array should be a multiple of 4
    at new Uint32Array (native)
    at Function.UPNG.encode.compress (/Users/.../JS/UPNG.js/UPNG.js:119:14)
    at Object.UPNG.encode (/Users/.../JS/UPNG.js/UPNG.js:66:25)
    at Object.<anonymous> (/Users/.../JS/UPNG.js/UPNG-cli.js:13:20)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:

With another test file (attached zip) I get:

unknown chunk type sBIT 3

and the resulting file has scrambled content.

Archive.zip

Calling UPNG.encode with fractions for width and height causes an issue

This is probably something that should only be documented.

We are scaling images and the calculated width and heights are fractions. When passing these fractions to UPNG.encode, the resulting image is broken and only contains a few lines. The fix is to round the width and height the whole numbers. This could be done in the UPNG library or documented in the API call.

Thanks for a great library!

New package version

Hey,

Would you consider publishing an up-to-date version of this package to npm? The latest version is 3 years old, and doesn't reflect the current state of the project.

Generate png and retrieve the exact pixel value in canvas

Hi,
I'm trying to encode a raw pixel buffer and later retrieve those exact pixel values on canvas.

let data = new Uint8Array(16* 16* 4);

for (var x = 0; x < data.length; x += 4) {
    data[x] = 1;
    data[x + 1] = 2;
    data[x + 2] = 3;
    data[x + 3] = 4;
}
let imageBuffer = UPNG.encode([data.buffer], 16, 16, 0);

However, I get the pixels compressed when I load the file in canvas(except the alpha which is always correct).

image = document.querySelector('img')    
canvas = document.createElement('canvas');
canvas.height = image.height;
canvas.width = image.width;
context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
data = context.getImageData(0, 0, canvas.width, canvas.height).data;
console.log(data);

UPNG.encode for RGB PNG

It would be nice to create a PNG file that does not use the alpha channel (every pixel has a color and alpha is always 255). Since I know that there is no alpha channel, it seems like a lot of wasted space to encode an alpha channel that is always 255.

Thanks!

Encode 16bit image

Hi,
Thanks for the nice png library. It's great that it support 16bit image decoding, will 16-bit encoding be supported? Thank you.

Cannot create a .png from UPNG.encode()

I'm currently trying to retrieve a .tiff image from desk, converting it to a .png and writing the .png to a file on desk.

The following code produces a .png that when I try to open it produces the following error, 'It may be damaged or use a file format that Preview doesn’t recognise.'

let fs = require('fs');
let UTIF = require('utif');
let UPNG = require('upng-js');

let contents = fs.readFileSync('img.tiff');
let ifd = UTIF.decode(contents);
let height = ifd[0].t270['REAL_HEIGHT'];
let width = ifd[0].t270['REAL_LENGTH'];

UTIF.decodeImage(contents, ifd[0]);
let rgba = UTIF.toRGBA8(ifd[0]);
let png = UPNG.encode([rgba], width, height);


 fs.writeFile('f.png',  Buffer.from(png), (err) => {
    if (err) throw err;
    console.log('It\'s saved!');
});

RangeError: attempting to construct out-of-bounds TypedArray on ArrayBuffer

Hello! I'm trying to use UPNG.js to optimise the PNG image returned by Canvas, like this:

function OpenOptimisedImage(canvas) {
    canvas.toBlob((imageBlob) => {
        const fileReader = new FileReader();

        fileReader.onloadend = (canvasConvertedToArrayBuffer) => {
            var img  = window.UPNG.decode(
                // 0 = losslessly.
                window.UPNG.encode([canvasConvertedToArrayBuffer.target.result], canvas.width, canvas.height, 0)
            );
            var rgba = window.UPNG.toRGBA8(img)[0];
            var blob = new Blob([rgba], {type:'application/octet-binary'});

            var reader = new FileReader();

            reader.onloadend = (optimisedBlobConvertedToBase64) => {
                window.open(optimisedBlobConvertedToBase64.target.result);
            };
            reader.readAsDataURL(blob);
        };

        fileReader.readAsArrayBuffer(imageBlob);
    });
}

I get an error "RangeError: attempting to construct out-of-bounds TypedArray on ArrayBuffer" on line

UPNG.encode.compress [..]
var img32 = new Uint32Array(bufs[j]), ilen = img32.length;

if I use the 2.1 version from npm install or https://cdnjs.cloudflare.com/ajax/libs/upng-js/2.1.0/UPNG.js, or on line

UPNG.encode.framize [..]
var cimg = new Uint8Array(bufs[j]), cimg32 = new Uint32Array(cimg.buffer);

if I'm using the latest UPNG.js as it is in the repository now.

It seems that Uint8Array can be created, but not Uint32Array.

Only once I got past the first UPNG.encode call, and I'm not sure why the error didn't happen then.

What is the problem?

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.