[roll] Update third-party dart packages

Updated:
Change-Id: Ic0f7001c3a9ba8ee0e68fec553590d9b79a82d07
diff --git a/image/.gitignore b/image/.gitignore
old mode 100644
new mode 100755
index a5eb6db..db51464
--- a/image/.gitignore
+++ b/image/.gitignore
@@ -1,29 +1,29 @@
-pubspec.lock
-example/packages/
-example/res/packages/
-packages/
-example/res/out-alpha_edge.jpg
-example/res/out-trees.jpg
-example/res/thumbnail-cat-eye04.jpg
-example/res/out-alpha_edge.png
-example/res/thumbnail-diamond_plate_texture.jpg
-test/out/
-lib/docs/
-example/webp_viewer.dart.js
-example/webp_viewer.dart.js.deps
-example/webp_viewer.dart.js.map
-example/webp_viewer.dart.precompiled.js
-example/test_formats.dart.js
-example/test_formats.dart.js.deps
-example/test_formats.dart.js.map
-example/test_formats.dart.precompiled.js
-build/
-packages
-psd_to_html/out/
-.idea/
-.packages
-.pub/
-add.png
-out
-.dart_tool/
-example/thumbnail.png
+pubspec.lock

+example/packages/

+example/res/packages/

+packages/

+example/res/out-alpha_edge.jpg

+example/res/out-trees.jpg

+example/res/thumbnail-cat-eye04.jpg

+example/res/out-alpha_edge.png

+example/res/thumbnail-diamond_plate_texture.jpg

+test/out/

+lib/docs/

+example/webp_viewer.dart.js

+example/webp_viewer.dart.js.deps

+example/webp_viewer.dart.js.map

+example/webp_viewer.dart.precompiled.js

+example/test_formats.dart.js

+example/test_formats.dart.js.deps

+example/test_formats.dart.js.map

+example/test_formats.dart.precompiled.js

+build/

+packages

+psd_to_html/out/

+.idea/

+.packages

+.pub/

+add.png

+out

+.dart_tool/

+example/thumbnail.png

diff --git a/image/.travis.yml b/image/.travis.yml
old mode 100644
new mode 100755
index 2729fa2..ce6d653
--- a/image/.travis.yml
+++ b/image/.travis.yml
@@ -1,16 +1,16 @@
-language: dart
-sudo: false
-dart:
-  - dev
-
-dart_task:
-  - test
-  - dartanalyzer
-
-# Only building master means that we don't run two builds for each pull request.
-branches:
-  only: [master]
-
-cache:
-  directories:
-  - $HOME/.pub-cache
+language: dart

+sudo: false

+dart:

+  - dev

+

+dart_task:

+  - test

+  - dartanalyzer

+

+# Only building master means that we don't run two builds for each pull request.

+branches:

+  only: [master]

+

+cache:

+  directories:

+  - $HOME/.pub-cache

diff --git a/image/BUILD.gn b/image/BUILD.gn
index 0897701..fc13501 100644
--- a/image/BUILD.gn
+++ b/image/BUILD.gn
@@ -1,4 +1,4 @@
-# This file is generated by importer.py for image-2.0.7
+# This file is generated by importer.py for image-2.0.8
 
 import("//build/dart/dart_library.gni")
 
diff --git a/image/CHANGELOG.md b/image/CHANGELOG.md
old mode 100644
new mode 100755
index f90901e..9ed3af9
--- a/image/CHANGELOG.md
+++ b/image/CHANGELOG.md
@@ -1,141 +1,149 @@
-## 2.0.7 - February 5, 2019
-
-- Improve JPEG decoding performance.
-- Decode and encode ICC profile data from PNG images.
-
-## 2.0.6 - January 26, 2019
-
-- bakeOrientation will clear the image's exif orientation properties.
-- copyResize will correctly maintain the image's orientation.
-
-## 2.0.5 - December 1, 2018
-
-- Added APNG (animated PNG) encoding.
-- Optimized drawString function.
-
-## 2.0.3 - June 6, 2018
-
-- copyResize can maintain aspect ratio when resizing height by using -1 for the width.
-- Added example for loading and processing images in an isolate.
-
-## 2.0.2 - June 1, 2018
-
-- Re-added decoding of orientation exif value from jpeg images.
-- Added bake_orientation function, which will rotate an image so that it physically matches its orientation exif value,
-useful for rotating an image prior to exporting it to a format that doesn't support exif data.
-
-## 2.0.1 - May 28, 2018
-
-Fix for bad jpeg files when encoding EXIF data.
-
-## 2.0.0 - May 22, 2018
-
-Remove the use of Dart 1 upper-case constants.
-Update SDK dependency to a 2.0 development release.
-
-## 1.1.33 - May 16, 2018
-
-  Maintain EXIF data from JPEG images.
-
-## 1.1.32 - May 9, 2018
-
-  Remove the use of `part` and `part of` in the main library.
-
-## 1.1.30 - March 10, 2018
-
-  Update pubspec to account for the new version of xml package that has been
-  published.
-
-## 1.1.29 - September 18, 2017
-
-- Add fixes for strong mode support.
-
-## 1.1.28 - May 27, 2017
-
-- Update pubspec to fix recent pub issues.
-- Rename changelog.txt to CHANGELOG.md.
-- Fix for 8-bit PNG decoding.
-
-## 1.1.27 - May 14, 2017
-
-- Fix crash decoding some jpeg images.
-
-
-## 1.1.24 - January 23, 2015
-
-- PVR encoding/decoding
-- Fix 16-bit tiff decoding
-
-
-## 1.1.23 - September 15, 2014
-
-- Fix alpha for PSD images.
-
-
-## 1.1.22 - July 31, 2014
-
-- Various bug fixes
-
-
-## 1.1.21 - June 19, 2014
-
-- Add drawImage function
-- Update XML dependency to 2.0.0
-
-
-## 1.1.20 - April 26, 2014
-
-- Fix OpenEXR decoder for dart2js
-
-
-## 1.1.19 - April 15, 2014
-
-- OpenEXR fixes.
-
-
-## 1.1.18 - April 06, 2014
-
-- Added OpenEXR format docoder.
-
-
-## 1.1.17 - April 02, 2014
-
-- Add Photoshop PSD format decoder
-
-
-## 1.1.16 - March 24, 2014
-
-- Fix JPEG encoder for compression quality < 100.
-
-
-## 1.1.15 - March 10, 2014
-
-- Update to new version of archive.
-
-
-## 1.1.14 - February 26, 2014
-
-- Optimizations
-
-
-## 1.1.13 - February 16, 2014
-
-- Added TIFF decoder
-
-
-## 1.1.10 - February 11, 2014
-
-- Added APNG animated PNG decoding support.
-- Improved JPEG decoding performance
-- Various bug fixes
-
-
-## 1.1.8 - February 01, 2014
-
-- Added GIF decoding support, including animated gifs.
-
-
-## 1.1.7 - January 28, 2014
-
-- Added WebP decoding support, included animated WebP.
-
+## 2.0.8 - May 8, 2019

+

+- Add ability to quantize an image to any number of colors.

+- Optimizations for the JPEG decoder.

+- Use #AARRGGBB for colors instead of ##AABBGGRR, to be compatible with Flutter image class.

+- Add floodfill drawing function.

+- CopyRectify to transform an arbitrary quad to the full image.

+- Improve performance of CopyResize.

+

+## 2.0.7 - February 5, 2019

+

+- Improve JPEG decoding performance.

+- Decode and encode ICC profile data from PNG images.

+

+## 2.0.6 - January 26, 2019

+

+- bakeOrientation will clear the image's exif orientation properties.

+- copyResize will correctly maintain the image's orientation.

+

+## 2.0.5 - December 1, 2018

+

+- Added APNG (animated PNG) encoding.

+- Optimized drawString function.

+

+## 2.0.3 - June 6, 2018

+

+- copyResize can maintain aspect ratio when resizing height by using -1 for the width.

+- Added example for loading and processing images in an isolate.

+

+## 2.0.2 - June 1, 2018

+

+- Re-added decoding of orientation exif value from jpeg images.

+- Added bake_orientation function, which will rotate an image so that it physically matches its orientation exif value,

+useful for rotating an image prior to exporting it to a format that doesn't support exif data.

+

+## 2.0.1 - May 28, 2018

+

+Fix for bad jpeg files when encoding EXIF data.

+

+## 2.0.0 - May 22, 2018

+

+Remove the use of Dart 1 upper-case constants.

+Update SDK dependency to a 2.0 development release.

+

+## 1.1.33 - May 16, 2018

+

+  Maintain EXIF data from JPEG images.

+

+## 1.1.32 - May 9, 2018

+

+  Remove the use of `part` and `part of` in the main library.

+

+## 1.1.30 - March 10, 2018

+

+  Update pubspec to account for the new version of xml package that has been

+  published.

+

+## 1.1.29 - September 18, 2017

+

+- Add fixes for strong mode support.

+

+## 1.1.28 - May 27, 2017

+

+- Update pubspec to fix recent pub issues.

+- Rename changelog.txt to CHANGELOG.md.

+- Fix for 8-bit PNG decoding.

+

+## 1.1.27 - May 14, 2017

+

+- Fix crash decoding some jpeg images.

+

+

+## 1.1.24 - January 23, 2015

+

+- PVR encoding/decoding

+- Fix 16-bit tiff decoding

+

+

+## 1.1.23 - September 15, 2014

+

+- Fix alpha for PSD images.

+

+

+## 1.1.22 - July 31, 2014

+

+- Various bug fixes

+

+

+## 1.1.21 - June 19, 2014

+

+- Add drawImage function

+- Update XML dependency to 2.0.0

+

+

+## 1.1.20 - April 26, 2014

+

+- Fix OpenEXR decoder for dart2js

+

+

+## 1.1.19 - April 15, 2014

+

+- OpenEXR fixes.

+

+

+## 1.1.18 - April 06, 2014

+

+- Added OpenEXR format docoder.

+

+

+## 1.1.17 - April 02, 2014

+

+- Add Photoshop PSD format decoder

+

+

+## 1.1.16 - March 24, 2014

+

+- Fix JPEG encoder for compression quality < 100.

+

+

+## 1.1.15 - March 10, 2014

+

+- Update to new version of archive.

+

+

+## 1.1.14 - February 26, 2014

+

+- Optimizations

+

+

+## 1.1.13 - February 16, 2014

+

+- Added TIFF decoder

+

+

+## 1.1.10 - February 11, 2014

+

+- Added APNG animated PNG decoding support.

+- Improved JPEG decoding performance

+- Various bug fixes

+

+

+## 1.1.8 - February 01, 2014

+

+- Added GIF decoding support, including animated gifs.

+

+

+## 1.1.7 - January 28, 2014

+

+- Added WebP decoding support, included animated WebP.

diff --git a/image/LICENSE b/image/LICENSE
old mode 100644
new mode 100755
index 0e2b6e5..d605f93
--- a/image/LICENSE
+++ b/image/LICENSE
@@ -1,156 +1,156 @@
- Copyright 2013 Brendan Duncan
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-Parts of the Image library were ported from the following sources:
-   
-==============================================================================   
- 
- The JPEG encoder/decoder code is derived from the following:
-   https://github.com/notmasteryet/jpgjs
-   Copyright (C) 2011 notmasteryet
-
-   Contributors: Yury Delendik <ydelendik@mozilla.com>
-                 Brendan Dahl <bdahl@mozilla.com>
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-==============================================================================
-
-The WebP encoder/decoder code is derived from the following:
-  http://git.chromium.org/gitweb/?p=webm/libwebp.git
-  Copyright (c) 2010, Google Inc. All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions are
-  met:
-  
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-  
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in
-      the documentation and/or other materials provided with the
-      distribution.
-  
-    * Neither the name of Google nor the names of its contributors may
-      be used to endorse or promote products derived from this software
-      without specific prior written permission.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-==============================================================================  
-
-The TIFF decoder code is derived from the following:
-  Apache Batik
-  http://svn.apache.org/repos/asf/xmlgraphics/batik/trunk
-  Copyright 1999-2007 The Apache Software Foundation
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-  
-       http://www.apache.org/licenses/LICENSE-2.0
-  
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-==============================================================================
-   
-The OpenEXR decoder is derived in part from the OpenEXR library:
-
-Copyright (c) 2002-2011, Industrial Light & Magic, a division of 
-Lucasfilm Entertainment Company Ltd. All rights reserved. 
-
-Redistribution and use in source and binary forms, with or without 
-modification, are permitted provided that the following conditions are met:
-
-
-Redistributions of source code must retain the above copyright notice, this 
-list of conditions and the following disclaimer.
-Redistributions in binary form must reproduce the above copyright notice, this 
-list of conditions and the following disclaimer in the documentation and/or 
-other materials provided with the distribution.
-Neither the name of Industrial Light & Magic nor the names of its contributors 
-may be used to endorse or promote products derived from this software without 
-specific prior written permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-===============================================================================
-
-The PVRTC compression and decompression code is ported from Jeffrey Lam's
-PvrTcCompressor:
-
-https://bitbucket.org/jthlim/pvrtccompressor
-
-===============================================================================
-
-The pvr container format decoder is derived from the QuickPVR project:
-QuickPVR is Copyright (C) 2010 Limbic Software, Inc.
-http://www.limbicsoftware.com/quickpvr.html
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions are met:
-      * Redistributions of source code must retain the above copyright
-        notice, this list of conditions and the following disclaimer.
-      * Redistributions in binary form must reproduce the above copyright
-        notice, this list of conditions and the following disclaimer in the
-        documentation and/or other materials provided with the distribution.
-      * Neither the name of the Limbic Software, Inc. nor the
-        names of its contributors may be used to endorse or promote products
-        derived from this software without specific prior written permission.
-  
-  THIS SOFTWARE IS PROVIDED BY LIMBIC SOFTWARE, INC. ''AS IS'' AND ANY
-  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-  DISCLAIMED. IN NO EVENT SHALL LIMBIC SOFTWARE, INC. BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Copyright 2013 Brendan Duncan

+

+ Licensed under the Apache License, Version 2.0 (the "License");

+ you may not use this file except in compliance with the License.

+ You may obtain a copy of the License at

+

+     http://www.apache.org/licenses/LICENSE-2.0

+

+ Unless required by applicable law or agreed to in writing, software

+ distributed under the License is distributed on an "AS IS" BASIS,

+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ See the License for the specific language governing permissions and

+ limitations under the License.

+

+

+

+Parts of the Image library were ported from the following sources:

+   

+==============================================================================   

+ 

+ The JPEG encoder/decoder code is derived from the following:

+   https://github.com/notmasteryet/jpgjs

+   Copyright (C) 2011 notmasteryet

+

+   Contributors: Yury Delendik <ydelendik@mozilla.com>

+                 Brendan Dahl <bdahl@mozilla.com>

+

+   Licensed under the Apache License, Version 2.0 (the "License");

+   you may not use this file except in compliance with the License.

+   You may obtain a copy of the License at

+

+       http://www.apache.org/licenses/LICENSE-2.0

+

+   Unless required by applicable law or agreed to in writing, software

+   distributed under the License is distributed on an "AS IS" BASIS,

+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+   See the License for the specific language governing permissions and

+   limitations under the License.

+

+==============================================================================

+

+The WebP encoder/decoder code is derived from the following:

+  http://git.chromium.org/gitweb/?p=webm/libwebp.git

+  Copyright (c) 2010, Google Inc. All rights reserved.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions are

+  met:

+  

+    * Redistributions of source code must retain the above copyright

+      notice, this list of conditions and the following disclaimer.

+  

+    * Redistributions in binary form must reproduce the above copyright

+      notice, this list of conditions and the following disclaimer in

+      the documentation and/or other materials provided with the

+      distribution.

+  

+    * Neither the name of Google nor the names of its contributors may

+      be used to endorse or promote products derived from this software

+      without specific prior written permission.

+  

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+==============================================================================  

+

+The TIFF decoder code is derived from the following:

+  Apache Batik

+  http://svn.apache.org/repos/asf/xmlgraphics/batik/trunk

+  Copyright 1999-2007 The Apache Software Foundation

+   Licensed under the Apache License, Version 2.0 (the "License");

+   you may not use this file except in compliance with the License.

+   You may obtain a copy of the License at

+  

+       http://www.apache.org/licenses/LICENSE-2.0

+  

+   Unless required by applicable law or agreed to in writing, software

+   distributed under the License is distributed on an "AS IS" BASIS,

+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+   See the License for the specific language governing permissions and

+   limitations under the License.

+

+==============================================================================

+   

+The OpenEXR decoder is derived in part from the OpenEXR library:

+

+Copyright (c) 2002-2011, Industrial Light & Magic, a division of 

+Lucasfilm Entertainment Company Ltd. All rights reserved. 

+

+Redistribution and use in source and binary forms, with or without 

+modification, are permitted provided that the following conditions are met:

+

+

+Redistributions of source code must retain the above copyright notice, this 

+list of conditions and the following disclaimer.

+Redistributions in binary form must reproduce the above copyright notice, this 

+list of conditions and the following disclaimer in the documentation and/or 

+other materials provided with the distribution.

+Neither the name of Industrial Light & Magic nor the names of its contributors 

+may be used to endorse or promote products derived from this software without 

+specific prior written permission.

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+===============================================================================

+

+The PVRTC compression and decompression code is ported from Jeffrey Lam's

+PvrTcCompressor:

+

+https://bitbucket.org/jthlim/pvrtccompressor

+

+===============================================================================

+

+The pvr container format decoder is derived from the QuickPVR project:

+QuickPVR is Copyright (C) 2010 Limbic Software, Inc.

+http://www.limbicsoftware.com/quickpvr.html

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions are met:

+      * Redistributions of source code must retain the above copyright

+        notice, this list of conditions and the following disclaimer.

+      * Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution.

+      * Neither the name of the Limbic Software, Inc. nor the

+        names of its contributors may be used to endorse or promote products

+        derived from this software without specific prior written permission.

+  

+  THIS SOFTWARE IS PROVIDED BY LIMBIC SOFTWARE, INC. ''AS IS'' AND ANY

+  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+  DISCLAIMED. IN NO EVENT SHALL LIMBIC SOFTWARE, INC. BE LIABLE FOR ANY

+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

   
\ No newline at end of file
diff --git a/image/README.md b/image/README.md
old mode 100644
new mode 100755
index be38dbc..c642532
--- a/image/README.md
+++ b/image/README.md
@@ -1,57 +1,57 @@
-# image
-
-[![Build Status](https://travis-ci.org/brendan-duncan/image.svg?branch=master)](https://travis-ci.org/brendan-duncan/image)
-
-## Overview
-
-A Dart library providing the ability to load, save and manipulate images in a variety of different file formats.
-
-The library has no reliance on `dart:io`, so it can be used for both server and
-web applications. 
-
-**Supported Image Formats:**
-
-Read/Write:
-
-- PNG / Animated APNG
-- JPEG
-- Targa
-- GIF / Animated GIF
-- PVR(PVRTC)
-
-Read Only:
-
-- WebP / Animated WebP
-- TIFF
-- Photoshop PSD
-- OpenEXR
-
-
-## [Documentation](https://github.com/brendan-duncan/image/wiki)
-
-## [API](https://www.dartdocs.org/documentation/image/latest/)
-
-## [Examples](https://github.com/brendan-duncan/image/wiki/Examples)
-
-## [Format Decoding Functions](https://github.com/brendan-duncan/image/wiki#format-decoding-functions)
-
-## Samples
-
-Load an image, resize it, and save it as a png:
-
-    import 'dart:io' as Io;
-    import 'package:image/image.dart';
-    void main() {
-      // Read an image from file (webp in this case).
-      // decodeImage will identify the format of the image and use the appropriate
-      // decoder.
-      Image image = decodeImage(new Io.File('test.webp').readAsBytesSync());
-
-      // Resize the image to a 120x? thumbnail (maintaining the aspect ratio).
-      Image thumbnail = copyResize(image, 120);
-    
-      // Save the thumbnail as a PNG.
-      new Io.File('thumbnail.png')
-            ..writeAsBytesSync(encodePng(thumbnail));
-    }
-
+# image

+

+[![Build Status](https://travis-ci.org/brendan-duncan/image.svg?branch=master)](https://travis-ci.org/brendan-duncan/image)

+

+## Overview

+

+A Dart library providing the ability to load, save and manipulate images in a variety of different file formats.

+

+The library has no reliance on `dart:io`, so it can be used for both server and

+web applications. 

+

+**Supported Image Formats:**

+

+Read/Write:

+

+- PNG / Animated APNG

+- JPEG

+- Targa

+- GIF / Animated GIF

+- PVR(PVRTC)

+

+Read Only:

+

+- WebP / Animated WebP

+- TIFF

+- Photoshop PSD

+- OpenEXR

+

+

+## [Documentation](https://github.com/brendan-duncan/image/wiki)

+

+## [API](https://www.dartdocs.org/documentation/image/latest/)

+

+## [Examples](https://github.com/brendan-duncan/image/wiki/Examples)

+

+## [Format Decoding Functions](https://github.com/brendan-duncan/image/wiki#format-decoding-functions)

+

+## Samples

+

+Load an image, resize it, and save it as a png:

+

+    import 'dart:io' as Io;

+    import 'package:image/image.dart';

+    void main() {

+      // Read an image from file (webp in this case).

+      // decodeImage will identify the format of the image and use the appropriate

+      // decoder.

+      Image image = decodeImage(new Io.File('test.webp').readAsBytesSync());

+

+      // Resize the image to a 120x? thumbnail (maintaining the aspect ratio).

+      Image thumbnail = copyResize(image, 120);

+    

+      // Save the thumbnail as a PNG.

+      new Io.File('thumbnail.png')

+            ..writeAsBytesSync(encodePng(thumbnail));

+    }

+

diff --git a/image/analysis_options.yaml b/image/analysis_options.yaml
old mode 100644
new mode 100755
index 2e6cdca..0ecbeea
--- a/image/analysis_options.yaml
+++ b/image/analysis_options.yaml
@@ -1 +1 @@
-analyzer:
+analyzer:

diff --git a/image/example/example.dart b/image/example/example.dart
old mode 100644
new mode 100755
index 3472525..eac0c88
--- a/image/example/example.dart
+++ b/image/example/example.dart
@@ -1,14 +1,14 @@
-import 'dart:io';
-import 'package:image/image.dart';
-void main() {
-  // Read an image from file (webp in this case).
-  // decodeImage will identify the format of the image and use the appropriate
-  // decoder.
-  Image image = decodeImage(new File('test.webp').readAsBytesSync());
-
-  // Resize the image to a 120x? thumbnail (maintaining the aspect ratio).
-  Image thumbnail = copyResize(image, 120);
-
-  // Save the thumbnail as a PNG.
-  new File('thumbnail.png').writeAsBytesSync(encodePng(thumbnail));
-}
+import 'dart:io';

+import 'package:image/image.dart';

+void main() {

+  // Read an image from file (webp in this case).

+  // decodeImage will identify the format of the image and use the appropriate

+  // decoder.

+  Image image = decodeImage(new File('test.webp').readAsBytesSync());

+

+  // Resize the image to a 120x? thumbnail (maintaining the aspect ratio).

+  Image thumbnail = copyResize(image, 120);

+

+  // Save the thumbnail as a PNG.

+  new File('thumbnail.png').writeAsBytesSync(encodePng(thumbnail));

+}

diff --git a/image/example/image_isolate.dart b/image/example/image_isolate.dart
old mode 100644
new mode 100755
index 28c56a0..8070694
--- a/image/example/image_isolate.dart
+++ b/image/example/image_isolate.dart
@@ -1,33 +1,33 @@
-import 'dart:io';
-import 'dart:isolate';
-import 'package:image/image.dart';
-
-class DecodeParam {
-  final File file;
-  final SendPort sendPort;
-  DecodeParam(this.file, this.sendPort);
-}
-
-void decode(DecodeParam param) {
-  // Read an image from file (webp in this case).
-  // decodeImage will identify the format of the image and use the appropriate
-  // decoder.
-  Image image = decodeImage(param.file.readAsBytesSync());
-  // Resize the image to a 120x? thumbnail (maintaining the aspect ratio).
-  Image thumbnail = gaussianBlur(copyResize(image, 120), 5);
-  param.sendPort.send(thumbnail);
-}
-
-// Decode and process an image file in a separate thread (isolate) to avoid
-// stalling the main UI thread.
-void main() async {
-  ReceivePort receivePort = new ReceivePort();
-
-  await Isolate.spawn(decode,
-      new DecodeParam(new File('test.webp'), receivePort.sendPort));
-
-  // Get the processed image from the isolate.
-  Image image = await receivePort.first;
-
-  new File('thumbnail.png').writeAsBytesSync(encodePng(image));
-}
+import 'dart:io';

+import 'dart:isolate';

+import 'package:image/image.dart';

+

+class DecodeParam {

+  final File file;

+  final SendPort sendPort;

+  DecodeParam(this.file, this.sendPort);

+}

+

+void decode(DecodeParam param) {

+  // Read an image from file (webp in this case).

+  // decodeImage will identify the format of the image and use the appropriate

+  // decoder.

+  Image image = decodeImage(param.file.readAsBytesSync());

+  // Resize the image to a 120x? thumbnail (maintaining the aspect ratio).

+  Image thumbnail = gaussianBlur(copyResize(image, 120), 5);

+  param.sendPort.send(thumbnail);

+}

+

+// Decode and process an image file in a separate thread (isolate) to avoid

+// stalling the main UI thread.

+void main() async {

+  ReceivePort receivePort = ReceivePort();

+

+  await Isolate.spawn(decode,

+      new DecodeParam(new File('test.webp'), receivePort.sendPort));

+

+  // Get the processed image from the isolate.

+  Image image = await receivePort.first;

+

+  new File('thumbnail.png').writeAsBytesSync(encodePng(image));

+}

diff --git a/image/example/test.webp b/image/example/test.webp
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/lib/image.dart b/image/lib/image.dart
old mode 100644
new mode 100755
index 9303773..b8ccc4f
--- a/image/lib/image.dart
+++ b/image/lib/image.dart
@@ -13,6 +13,7 @@
 export 'src/draw/draw_string.dart';

 export 'src/draw/fill.dart';

 export 'src/draw/fill_rect.dart';

+export 'src/draw/fill_flood.dart';

 

 export 'src/effects/drop_shadow.dart';

 

@@ -138,6 +139,7 @@
 export 'src/transform/bake_orientation.dart';

 export 'src/transform/copy_crop.dart';

 export 'src/transform/copy_into.dart';

+export 'src/transform/copy_rectify.dart';

 export 'src/transform/copy_resize.dart';

 export 'src/transform/copy_rotate.dart';

 export 'src/transform/flip.dart';

@@ -149,6 +151,7 @@
 export 'src/util/min_max.dart';

 export 'src/util/neural_quantizer.dart';

 export 'src/util/output_buffer.dart';

+export 'src/util/point.dart';

 export 'src/util/random.dart';

 

 export 'src/animation.dart';

diff --git a/image/lib/src/animation.dart b/image/lib/src/animation.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/bitmap_font.dart b/image/lib/src/bitmap_font.dart
old mode 100644
new mode 100755
index 213f480..4360e83
--- a/image/lib/src/bitmap_font.dart
+++ b/image/lib/src/bitmap_font.dart
@@ -75,7 +75,7 @@
    * .fnt font definition and associated PNG images.

    */

   BitmapFont.fromZip(List<int> fileData) {

-    Archive arc = new ZipDecoder().decodeBytes(fileData);

+    Archive arc = ZipDecoder().decodeBytes(fileData);

 

     ArchiveFile font_file;

     for (int i = 0; i < arc.numberOfFiles(); ++i) {

@@ -89,7 +89,7 @@
       throw new ImageException('Invalid font archive');

     }

 

-    String font_str = new String.fromCharCodes(font_file.content);

+    String font_str = String.fromCharCodes(font_file.content);

     XML.XmlDocument xml;

 

     if (font_str.startsWith('<font>')) {

@@ -222,7 +222,7 @@
                                        '$filename');

             }

 

-            Image image = new PngDecoder().decodeImage(imageFile.content);

+            Image image = PngDecoder().decodeImage(imageFile.content);

 

             fontPages[id] = image;

           }

@@ -262,7 +262,7 @@
 

           Image fontImage = fontPages[page];

 

-          BitmapFontCharacter ch = new BitmapFontCharacter(id, width, height,

+          BitmapFontCharacter ch = BitmapFontCharacter(id, width, height,

               xoffset, yoffset, xadvance, page, chnl);

 

           characters[id] = ch;

@@ -300,17 +300,17 @@
       switch (tk[0]) {

         case 'info':

           var attrs = _parseParameters(tk);

-          var info = new XML.XmlElement(new XML.XmlName('info'), attrs, []);

+          var info = XML.XmlElement(new XML.XmlName('info'), attrs, []);

           children.add(info);

           break;

         case 'common':

           var attrs = _parseParameters(tk);

-          var node = new XML.XmlElement(new XML.XmlName('common'), attrs, []);

+          var node = XML.XmlElement(new XML.XmlName('common'), attrs, []);

           children.add(node);

           break;

         case 'page':

           var attrs = _parseParameters(tk);

-          var page = new XML.XmlElement(new XML.XmlName('page'), attrs, []);

+          var page = XML.XmlElement(new XML.XmlName('page'), attrs, []);

           pageList.add(page);

           break;

         case 'chars':

@@ -318,7 +318,7 @@
           break;

         case 'char':

           var attrs = _parseParameters(tk);

-          var node = new XML.XmlElement(new XML.XmlName('char'), attrs, []);

+          var node = XML.XmlElement(new XML.XmlName('char'), attrs, []);

           charList.add(node);

           break;

         case 'kernings':

@@ -326,31 +326,31 @@
           break;

         case 'kerning':

           var attrs = _parseParameters(tk);

-          var node = new XML.XmlElement(new XML.XmlName('kerning'), attrs, []);

+          var node = XML.XmlElement(new XML.XmlName('kerning'), attrs, []);

           kerningList.add(node);

           break;

       }

     }

 

     if (charsAttrs != null || charList.isNotEmpty) {

-      var node = new XML.XmlElement(new XML.XmlName('chars'), charsAttrs,

+      var node = XML.XmlElement(new XML.XmlName('chars'), charsAttrs,

           charList);

       children.add(node);

     }

 

     if (kerningsAttrs != null || kerningList.isNotEmpty) {

-      var node = new XML.XmlElement(new XML.XmlName('kernings'), kerningsAttrs,

+      var node = XML.XmlElement(new XML.XmlName('kernings'), kerningsAttrs,

           kerningList);

       children.add(node);

     }

 

     if (pageList.isNotEmpty) {

-      var pages = new XML.XmlElement(new XML.XmlName('pages'), [], pageList);

+      var pages = XML.XmlElement(new XML.XmlName('pages'), [], pageList);

       children.add(pages);

     }

 

-    var xml = new XML.XmlElement(new XML.XmlName('font'), [], children);

-    var doc = new XML.XmlDocument([xml]);

+    var xml = XML.XmlElement(new XML.XmlName('font'), [], children);

+    var doc = XML.XmlDocument([xml]);

 

     return doc;

   }

@@ -369,7 +369,7 @@
       // Remove all " characters

       atk[1] = atk[1].replaceAll('"', '');

 

-      var a = new XML.XmlAttribute(new XML.XmlName(atk[0]), atk[1]);

+      var a = XML.XmlAttribute(new XML.XmlName(atk[0]), atk[1]);

       params.add(a);

     }

     return params;

@@ -404,7 +404,7 @@
                       this.channel) :

     this.width = width,

     this.height = height,

-    image = new Image(width, height);

+    image = Image(width, height);

 

   String toString() {

     Map x = {'id': id, 'width': width, 'height': height, 'xoffset': xoffset,

diff --git a/image/lib/src/color.dart b/image/lib/src/color.dart
old mode 100644
new mode 100755
index 59ea428..233daa1
--- a/image/lib/src/color.dart
+++ b/image/lib/src/color.dart
@@ -60,15 +60,37 @@
     var rgb = labToRGB(L, a, b);

     return getColor(rgb[0], rgb[1], rgb[2]);

   }

+

+  /**

+   * Compare colors from a 3 or 4 dimensional color space

+   */

+  static double distance(List<double> c1, List<double> c2, bool compareAlpha) {

+    double d1 = c1[0] - c2[0];

+    double d2 = c1[1] - c2[1];

+    double d3 = c1[2] - c2[2];

+    if (compareAlpha) {

+      double dA = c1[3] - c2[3];

+      return Math.sqrt(

+        Math.max(d1*d1, (d1-dA)*(d1-dA)) +

+        Math.max(d2*d2, (d2-dA)*(d2-dA)) +

+        Math.max(d3*d3, (d3-dA)*(d3-dA))

+      );

+    } else {

+      return Math.sqrt(

+        d1*d1 +

+        d2*d2 +

+        d3*d3);

+    }

+  }

 }

 

 

-/// Red channel of a color.

-const int RED = 0;

+/// Blue channel of a color.

+const int BLUE = 0;

 /// Green channel of a color.

 const int GREEN = 1;

-/// Blue channel of a color.

-const int BLUE = 2;

+/// Red channel of a color.

+const int RED = 2;

 /// Alpha channel of a color.

 const int ALPHA = 3;

 /// Luminance of a color.

@@ -82,17 +104,17 @@
  */

 int getColor(int r, int g, int b, [int a = 255]) =>

     (clamp255(a) << 24) |

-    (clamp255(b) << 16) |

+    (clamp255(r) << 16) |

     (clamp255(g) << 8) |

-    clamp255(r);

+    (clamp255(b));

 

 /**

  * Get the [channel] from the [color].

  */

 int getChannel(int color, int channel) =>

-    channel == 0 ? getRed(color) :

-    channel == 1 ? getGreen(color) :

-    channel == 2 ? getBlue(color) :

+    channel == RED ? getRed(color) :

+    channel == GREEN ? getGreen(color) :

+    channel == BLUE ? getBlue(color) :

     getAlpha(color);

 

 /**

@@ -100,22 +122,22 @@
  * replaced with the given [value].

  */

 int setChannel(int color, int channel, int value) =>

-    channel == 0 ? setRed(color, value) :

-    channel == 1 ? setGreen(color, value) :

-    channel == 2 ? setBlue(color, value) :

+    channel == RED ? setRed(color, value) :

+    channel == GREEN ? setGreen(color, value) :

+    channel == BLUE ? setBlue(color, value) :

     setAlpha(color, value);

 

 /**

- * Get the red channel from the [color].

+ * Get the blue channel from the [color].

  */

-int getRed(int color) =>

+int getBlue(int color) =>

     (color) & 0xff;

 

 /**

- * Returns a new color where the red channel of [color] has been replaced

+ * Returns a new color where the blue channel of [color] has been replaced

  * by [value].

  */

-int setRed(int color, int value) =>

+int setBlue(int color, int value) =>

     (color & 0xffffff00) | (clamp255(value));

 

 /**

@@ -132,16 +154,16 @@
     (color & 0xffff00ff) | (clamp255(value) << 8);

 

 /**

- * Get the blue channel from the [color].

+ * Get the red channel from the [color].

  */

-int getBlue(int color) =>

+int getRed(int color) =>

     (color >> 16) & 0xff;

 

 /**

- * Returns a new color where the blue channel of [color] has been replaced

+ * Returns a new color where the red channel of [color] has been replaced

  * by [value].

  */

-int setBlue(int color, int value) =>

+int setRed(int color, int value) =>

     (color & 0xff00ffff) | (clamp255(value) << 16);

 

 /**

@@ -460,3 +482,86 @@
           (G * 255.0).toInt().clamp(0,  255),

           (B * 255.0).toInt().clamp(0,  255)];

 }

+

+/**

+ * Convert a RGB color to XYZ.

+ */

+List<double> rgbToXYZ(num r, num g, num b) {

+  r = r / 255.0;

+  g = g / 255.0;

+  b = b / 255.0;

+

+  if ( r > 0.04045 ) r = Math.pow((r + 0.055) / 1.055, 2.4);

+  else               r = r / 12.92;

+  if ( g > 0.04045 ) g = Math.pow((g + 0.055) / 1.055, 2.4);

+  else               g = g / 12.92;

+  if ( b > 0.04045 ) b = Math.pow((b + 0.055) / 1.055, 2.4);

+  else               b = b / 12.92;

+

+  r = r * 100.0;

+  g = g * 100.0;

+  b = b * 100.0;

+

+  return [r * 0.4124 + g * 0.3576 + b * 0.1805,

+          r * 0.2126 + g * 0.7152 + b * 0.0722,

+          r * 0.0193 + g * 0.1192 + b * 0.9505];

+}

+

+/**

+ * Convert a XYZ color to CIE-L*ab.

+ */

+List<double> xyzToLab(num x, num y, num z) {

+  x = x / 95.047;

+  y = y / 100.0;

+  z = z / 108.883;

+

+  if (x > 0.008856) x = Math.pow(x, 1/3.0);

+  else              x = (7.787 * x) + (16 / 116.0);

+  if (y > 0.008856) y = Math.pow(y, 1/3.0);

+  else              y = (7.787 * y) + (16 / 116.0);

+  if (z > 0.008856) z = Math.pow(z, 1/3.0);

+  else              z = (7.787 * z) + (16 / 116.0);

+

+  return [(116.0 * y) - 16,

+          500.0 * (x - y),

+          200.0 * (y - z)];

+}

+

+/**

+ * Convert a RGB color to CIE-L*ab.

+ */

+List<double> rgbToLab(num r, num g, num b) {

+  r = r / 255.0;

+  g = g / 255.0;

+  b = b / 255.0;

+

+  if ( r > 0.04045 ) r = Math.pow((r + 0.055) / 1.055, 2.4);

+  else               r = r / 12.92;

+  if ( g > 0.04045 ) g = Math.pow((g + 0.055) / 1.055, 2.4);

+  else               g = g / 12.92;

+  if ( b > 0.04045 ) b = Math.pow((b + 0.055) / 1.055, 2.4);

+  else               b = b / 12.92;

+

+  r = r * 100.0;

+  g = g * 100.0;

+  b = b * 100.0;

+

+  double x = r * 0.4124 + g * 0.3576 + b * 0.1805;

+  double y = r * 0.2126 + g * 0.7152 + b * 0.0722;

+  double z = r * 0.0193 + g * 0.1192 + b * 0.9505;

+

+  x = x / 95.047;

+  y = y / 100.0;

+  z = z / 108.883;

+

+  if (x > 0.008856) x = Math.pow(x, 1/3.0);

+  else              x = (7.787 * x) + (16 / 116.0);

+  if (y > 0.008856) y = Math.pow(y, 1/3.0);

+  else              y = (7.787 * y) + (16 / 116.0);

+  if (z > 0.008856) z = Math.pow(z, 1/3.0);

+  else              z = (7.787 * z) + (16 / 116.0);

+

+  return [(116.0 * y) - 16,

+          500.0 * (x - y),

+          200.0 * (y - z)];

+}

diff --git a/image/lib/src/draw/draw_char.dart b/image/lib/src/draw/draw_char.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/draw/draw_circle.dart b/image/lib/src/draw/draw_circle.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/draw/draw_image.dart b/image/lib/src/draw/draw_image.dart
old mode 100644
new mode 100755
index 1229ba5..5a07d2f
--- a/image/lib/src/draw/draw_image.dart
+++ b/image/lib/src/draw/draw_image.dart
@@ -1,51 +1,51 @@
-import '../image.dart';
-import 'draw_pixel.dart';
-
-/**
- * Draw the image [src] onto the image [dst].
- *
- * In other words, copyInto will take an rectangular area from src of
- * width [src_w] and height [src_h] at position ([src_x],[src_y]) and place it
- * in a rectangular area of [dst] of width [dst_w] and height [dst_h] at
- * position ([dst_x],[dst_y]).
- *
- * If the source and destination coordinates and width and heights differ,
- * appropriate stretching or shrinking of the image fragment will be performed.
- * The coordinates refer to the upper left corner. This function can be used to
- * copy regions within the same image (if [dst] is the same as [src])
- * but if the regions overlap the results will be unpredictable.
- */
-Image drawImage(Image dst, Image src,
-                {int dstX, int dstY, int srcX, int srcY,
-                 int srcW, int srcH, bool blend: true}) {
-  if (dstX == null) {
-    dstX = 0;
-  }
-  if (dstY == null) {
-    dstY = 0;
-  }
-  if (srcX == null) {
-    srcX = 0;
-  }
-  if (srcY == null) {
-    srcY = 0;
-  }
-  if (srcW == null) {
-    srcW = src.width;
-  }
-  if (srcH == null) {
-    srcH = src.height;
-  }
-
-  for (int y = 0; y < srcH; ++y) {
-    for (int x = 0; x < srcW; ++x) {
-      if (blend) {
-        drawPixel(dst, dstX + x, dstY + y, src.getPixel(srcX + x, srcY + y));
-      } else {
-        dst.setPixel(dstX + x, dstY + y, src.getPixel(srcX + x, srcY + y));
-      }
-    }
-  }
-
-  return dst;
-}
+import '../image.dart';

+import 'draw_pixel.dart';

+

+/**

+ * Draw the image [src] onto the image [dst].

+ *

+ * In other words, copyInto will take an rectangular area from src of

+ * width [src_w] and height [src_h] at position ([src_x],[src_y]) and place it

+ * in a rectangular area of [dst] of width [dst_w] and height [dst_h] at

+ * position ([dst_x],[dst_y]).

+ *

+ * If the source and destination coordinates and width and heights differ,

+ * appropriate stretching or shrinking of the image fragment will be performed.

+ * The coordinates refer to the upper left corner. This function can be used to

+ * copy regions within the same image (if [dst] is the same as [src])

+ * but if the regions overlap the results will be unpredictable.

+ */

+Image drawImage(Image dst, Image src,

+                {int dstX, int dstY, int srcX, int srcY,

+                 int srcW, int srcH, bool blend: true}) {

+  if (dstX == null) {

+    dstX = 0;

+  }

+  if (dstY == null) {

+    dstY = 0;

+  }

+  if (srcX == null) {

+    srcX = 0;

+  }

+  if (srcY == null) {

+    srcY = 0;

+  }

+  if (srcW == null) {

+    srcW = src.width;

+  }

+  if (srcH == null) {

+    srcH = src.height;

+  }

+

+  for (int y = 0; y < srcH; ++y) {

+    for (int x = 0; x < srcW; ++x) {

+      if (blend) {

+        drawPixel(dst, dstX + x, dstY + y, src.getPixel(srcX + x, srcY + y));

+      } else {

+        dst.setPixel(dstX + x, dstY + y, src.getPixel(srcX + x, srcY + y));

+      }

+    }

+  }

+

+  return dst;

+}

diff --git a/image/lib/src/draw/draw_line.dart b/image/lib/src/draw/draw_line.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/draw/draw_pixel.dart b/image/lib/src/draw/draw_pixel.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/draw/draw_rect.dart b/image/lib/src/draw/draw_rect.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/draw/draw_string.dart b/image/lib/src/draw/draw_string.dart
old mode 100644
new mode 100755
index 3440cf6..6604f25
--- a/image/lib/src/draw/draw_string.dart
+++ b/image/lib/src/draw/draw_string.dart
@@ -4,10 +4,10 @@
 import '../image.dart';

 import 'draw_pixel.dart';

 

-var _r_lut = new Uint8List(256);

-var _g_lut = new Uint8List(256);

-var _b_lut = new Uint8List(256);

-var _a_lut = new Uint8List(256);

+var _r_lut = Uint8List(256);

+var _g_lut = Uint8List(256);

+var _b_lut = Uint8List(256);

+var _a_lut = Uint8List(256);

 

 /**

  * Draw a string horizontally into [image] horizontally into [image] at position

diff --git a/image/lib/src/draw/fill.dart b/image/lib/src/draw/fill.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/draw/fill_flood.dart b/image/lib/src/draw/fill_flood.dart
new file mode 100755
index 0000000..a613a02
--- /dev/null
+++ b/image/lib/src/draw/fill_flood.dart
@@ -0,0 +1,143 @@
+import 'dart:math' as Math;

+import 'dart:typed_data';

+

+import '../color.dart';

+import '../image.dart';

+

+typedef TestPixel = bool Function(int y, int x);

+typedef MarkPixel = void Function(int y, int x);

+

+/**

+ * Fill the 4-connected shape containing [x],[y] in the image [src] with the given [color]

+ */

+

+Image fillFlood(Image src, int x, int y, int color, {num threshold=0.0, bool compareAlpha=false}) {

+  int srcColor = src.getPixel(x, y);

+  if (!compareAlpha) srcColor = setAlpha(srcColor, 0);

+

+  TestPixel array;

+  if (threshold > 0) {

+    List<double> lab = rgbToLab(getRed(srcColor), getGreen(srcColor), getBlue(srcColor));

+    if (compareAlpha) lab.add(getAlpha(srcColor).toDouble());

+    array = (int y, int x) => _testPixelLabColorDistance(src, x, y, lab, threshold);

+  } else if (!compareAlpha) {

+    array = (int y, int x) => setAlpha(src.getPixel(x, y), 0) != srcColor;

+  } else {

+    array = (int y, int x) => src.getPixel(x, y) != srcColor;

+  }

+

+  MarkPixel mark = (int y, int x) => src.setPixel(x, y, color);

+  _fill4(src, x, y, array, mark);

+  return src;

+}

+

+/**

+ * Create a mask describing the 4-connected shape containing [x],[y] in the image [src]

+ */

+

+Uint8List maskFlood(Image src, int x, int y, {num threshold=0.0, bool compareAlpha=false, int fillValue=255}) {

+  int srcColor = src.getPixel(x, y);

+  if (!compareAlpha) srcColor = setAlpha(srcColor, 0);

+  Uint8List ret = Uint8List(src.width * src.height);

+

+  TestPixel array;

+  if (threshold > 0) {

+    List<double> lab = rgbToLab(getRed(srcColor), getGreen(srcColor), getBlue(srcColor));

+    if (compareAlpha) lab.add(getAlpha(srcColor).toDouble());

+    array = (int y, int x) => ret[y * src.width + x] != 0 || _testPixelLabColorDistance(src, x, y, lab, threshold);

+  } else if (!compareAlpha) {

+    array = (int y, int x) => ret[y * src.width + x] != 0 || setAlpha(src.getPixel(x, y), 0) != srcColor;

+  } else {

+    array = (int y, int x) => ret[y * src.width + x] != 0 || src.getPixel(x, y) != srcColor;

+  }

+

+  MarkPixel mark = (int y, int x) => ret[y * src.width + x] = fillValue;

+  _fill4(src, x, y, array, mark);

+  return ret;

+}

+

+bool _testPixelLabColorDistance(Image src, int x, int y, List<double> refColor, num threshold) {

+  int pixel = src.getPixel(x, y);

+  bool compareAlpha = refColor.length > 3;

+  List<double> pixelColor = rgbToLab(getRed(pixel), getGreen(pixel), getBlue(pixel));

+  if (compareAlpha) pixelColor.add(getAlpha(pixel).toDouble());

+  return Color.distance(pixelColor, refColor, compareAlpha) > threshold;

+}

+

+/**

+ * Adam Milazzo (2015). A More Efficient Flood Fill.

+ * http://www.adammil.net/blog/v126_A_More_Efficient_Flood_Fill.html

+ */

+

+void _fill4(Image src, int x, int y, TestPixel array, MarkPixel mark) {

+

+  // at this point, we know array(y,x) is clear, and we want to move as far as possible to the upper-left. moving

+  // up is much more important than moving left, so we could try to make this smarter by sometimes moving to

+  // the right if doing so would allow us to move further up, but it doesn't seem worth the complexity

+  while(true)

+  {

+    int ox = x, oy = y;

+    while (y != 0 && !array(y-1, x)) y--;

+    while (x != 0 && !array(y, x-1)) x--;

+    if (x == ox && y == oy) break;

+  }

+  _fill4Core(src, x, y, array, mark);

+}

+

+void _fill4Core(Image src, int x, int y, TestPixel array, MarkPixel mark) {

+  // at this point, we know that array(y,x) is clear, and array(y-1,x) and array(y,x-1) are set.

+  // we'll begin scanning down and to the right, attempting to fill an entire rectangular block

+  int lastRowLength = 0; // the number of cells that were clear in the last row we scanned

+

+  do {

+    int rowLength = 0, sx = x; // keep track of how long this row is. sx is the starting x for the main scan below

+    // now we want to handle a case like |***|, where we fill 3 cells in the first row and then after we move to

+    // the second row we find the first  | **| cell is filled, ending our rectangular scan. rather than handling

+    // this via the recursion below, we'll increase the starting value of 'x' and reduce the last row length to

+    // match. then we'll continue trying to set the narrower rectangular block

+    if (lastRowLength != 0 && array(y, x)) { // if this is not the first row and the leftmost cell is filled...

+      do {

+        if (--lastRowLength == 0) return; // shorten the row. if it's full, we're done

+      } while (array(y, ++x)); // otherwise, update the starting point of the main scan to match

+      sx = x;

+    } else {

+      // we also want to handle the opposite case, | **|, where we begin scanning a 2-wide rectangular block and

+      // then find on the next row that it has     |***| gotten wider on the left. again, we could handle this

+      // with recursion but we'd prefer to adjust x and lastRowLength instead

+      for (; x != 0 && !array(y, x-1); rowLength++, lastRowLength++) {

+        mark(y, --x); // to avoid scanning the cells twice, we'll fill them and update rowLength here

+        // if there's something above the new starting point, handle that recursively. this deals with cases

+        // like |* **| when we begin filling from (2,0), move down to (2,1), and then move left to (0,1).

+        // the  |****| main scan assumes the portion of the previous row from x to x+lastRowLength has already

+        // been filled. adjusting x and lastRowLength breaks that assumption in this case, so we must fix it

+        if (y != 0 && !array(y-1, x)) _fill4(src, x, y-1, array, mark); // use _Fill since there may be more up and left

+      }

+    }

+

+    // now at this point we can begin to scan the current row in the rectangular block. the span of the previous

+    // row from x (inclusive) to x+lastRowLength (exclusive) has already been filled, so we don't need to

+    // check it. so scan across to the right in the current row

+    for (; sx < src.width && !array(y, sx); rowLength++, sx++) mark(y, sx);

+    // now we've scanned this row. if the block is rectangular, then the previous row has already been scanned,

+    // so we don't need to look upwards and we're going to scan the next row in the next iteration so we don't

+    // need to look downwards. however, if the block is not rectangular, we may need to look upwards or rightwards

+    // for some portion of the row. if this row was shorter than the last row, we may need to look rightwards near

+    // the end, as in the case of |*****|, where the first row is 5 cells long and the second row is 3 cells long.

+    // we must look to the right  |*** *| of the single cell at the end of the second row, i.e. at (4,1)

+    if (rowLength < lastRowLength) {

+      for (int end=x+lastRowLength; ++sx < end; ) // 'end' is the end of the previous row, so scan the current row to

+      {                                           // there. any clear cells would have been connected to the previous

+        if (!array(y, sx)) _fill4Core(src, sx, y, array, mark); // row. the cells up and left must be set so use FillCore

+      }

+    }

+    // alternately, if this row is longer than the previous row, as in the case |*** *| then we must look above

+    // the end of the row, i.e at (4,0)                                         |*****|

+    else if (rowLength > lastRowLength && y != 0) // if this row is longer and we're not already at the top...

+    {

+      for (int ux=x+lastRowLength; ++ux<sx; ) { // sx is the end of the current row

+        if (!array(y-1, ux)) _fill4(src, ux, y-1, array, mark); // since there may be clear cells up and left, use _Fill

+      }

+    }

+    lastRowLength = rowLength; // record the new row length

+  } while (lastRowLength != 0 && ++y < src.height); // if we get to a full row or to the bottom, we're done

+}

diff --git a/image/lib/src/draw/fill_rect.dart b/image/lib/src/draw/fill_rect.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/effects/drop_shadow.dart b/image/lib/src/effects/drop_shadow.dart
old mode 100644
new mode 100755
index fe69f50..f86b0d7
--- a/image/lib/src/effects/drop_shadow.dart
+++ b/image/lib/src/effects/drop_shadow.dart
@@ -44,7 +44,7 @@
     newImageHeight = shadowHeight + shadowOffsetY + vShadow;

   }

 

-  Image dst = new Image(newImageWidth, newImageHeight);

+  Image dst = Image(newImageWidth, newImageHeight);

   dst.fill(0x00ffffff);

 

   copyInto(dst, src, dstX: shadowOffsetX, dstY: shadowOffsetY);

diff --git a/image/lib/src/exif_data.dart b/image/lib/src/exif_data.dart
old mode 100644
new mode 100755
index 78f5e56..1b8cc10
--- a/image/lib/src/exif_data.dart
+++ b/image/lib/src/exif_data.dart
@@ -1,35 +1,35 @@
-import 'dart:typed_data';
-
-/**
- * Exif data stored with an image.
- */
-class ExifData {
-  static const int CAMERA_MAKE = 0x010F; // string
-  static const int CAMERA_MODEL = 0x0110; // string
-  static const int DATE_TIME = 0x0132; // string
-  static const int ORIENTATION = 0x0112; // int
-
-  List<Uint8List> rawData;
-  Map<int, dynamic> data;
-
-  ExifData()
-    : data = new Map<int, dynamic>();
-
-  ExifData.from(ExifData other)
-    : data = (other == null) ?
-              new Map<int, dynamic>() :
-              new Map<int, dynamic>.from(other.data) {
-    if (other != null && other.rawData != null) {
-      rawData = new List<Uint8List>(other.rawData.length);
-      for (int i = 0; i < other.rawData.length; ++i) {
-        rawData[i] = new Uint8List.fromList(other.rawData[i]);
-      }
-    }
-  }
-
-  bool get hasRawData => rawData != null && rawData.isNotEmpty;
-
-  bool get hasOrientation => data.containsKey(ORIENTATION);
-  int get orientation => data[ORIENTATION];
-  set orientation(int value) => data[ORIENTATION] = value;
-}
+import 'dart:typed_data';

+

+/**

+ * Exif data stored with an image.

+ */

+class ExifData {

+  static const int CAMERA_MAKE = 0x010F; // string

+  static const int CAMERA_MODEL = 0x0110; // string

+  static const int DATE_TIME = 0x0132; // string

+  static const int ORIENTATION = 0x0112; // int

+

+  List<Uint8List> rawData;

+  Map<int, dynamic> data;

+

+  ExifData()

+    : data = Map<int, dynamic>();

+

+  ExifData.from(ExifData other)

+    : data = (other == null) ?

+              new Map<int, dynamic>() :

+              new Map<int, dynamic>.from(other.data) {

+    if (other != null && other.rawData != null) {

+      rawData = List<Uint8List>(other.rawData.length);

+      for (int i = 0; i < other.rawData.length; ++i) {

+        rawData[i] = Uint8List.fromList(other.rawData[i]);

+      }

+    }

+  }

+

+  bool get hasRawData => rawData != null && rawData.isNotEmpty;

+

+  bool get hasOrientation => data.containsKey(ORIENTATION);

+  int get orientation => data[ORIENTATION];

+  set orientation(int value) => data[ORIENTATION] = value;

+}

diff --git a/image/lib/src/filter/adjust_color.dart b/image/lib/src/filter/adjust_color.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/brightness.dart b/image/lib/src/filter/brightness.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/bump_to_normal.dart b/image/lib/src/filter/bump_to_normal.dart
old mode 100644
new mode 100755
index da81d12..41c5dcb
--- a/image/lib/src/filter/bump_to_normal.dart
+++ b/image/lib/src/filter/bump_to_normal.dart
@@ -11,7 +11,7 @@
  * the strength of the normal image.

  */

 Image bumpToNormal(Image src, {double strength: 2.0}) {

-  Image dest = new Image.from(src);

+  Image dest = Image.from(src);

 

   for (var y = 0; y < src.height; ++y) {

     for (var x = 0; x < src.width; ++x) {

diff --git a/image/lib/src/filter/color_offset.dart b/image/lib/src/filter/color_offset.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/contrast.dart b/image/lib/src/filter/contrast.dart
old mode 100644
new mode 100755
index 311bc4c..3188b1e
--- a/image/lib/src/filter/contrast.dart
+++ b/image/lib/src/filter/contrast.dart
@@ -23,7 +23,7 @@
 

     contrast = contrast / 100.0;

     contrast = contrast * contrast;

-    _contrast = new Uint8List(256);

+    _contrast = Uint8List(256);

     for (int i = 0; i < 256; ++i) {

       _contrast[i] =

           clamp255((((((i / 255.0) - 0.5) * contrast) + 0.5) * 255.0).toInt());

diff --git a/image/lib/src/filter/convolution.dart b/image/lib/src/filter/convolution.dart
old mode 100644
new mode 100755
index bcb7802..4008e7f
--- a/image/lib/src/filter/convolution.dart
+++ b/image/lib/src/filter/convolution.dart
@@ -12,7 +12,7 @@
  */

 Image convolution(Image src, List<num> filter,

                   [num filterDiv = 1.0, num offset = 0.0]) {

-  Image tmp = new Image.from(src);

+  Image tmp = Image.from(src);

 

   for (int y = 0; y < src.height; ++y) {

     for (int x = 0; x < src.width; ++x) {

diff --git a/image/lib/src/filter/emboss.dart b/image/lib/src/filter/emboss.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/gaussian_blur.dart b/image/lib/src/filter/gaussian_blur.dart
old mode 100644
new mode 100755
index 0679e24..5bc657d
--- a/image/lib/src/filter/gaussian_blur.dart
+++ b/image/lib/src/filter/gaussian_blur.dart
@@ -25,7 +25,7 @@
     double sigma = radius * (2.0 / 3.0);

     double s = 2.0 * sigma * sigma;

 

-    kernel = new SeperableKernel(radius);

+    kernel = SeperableKernel(radius);

 

     double sum = 0.0;

     for (int x = -radius; x <= radius; ++x) {

diff --git a/image/lib/src/filter/grayscale.dart b/image/lib/src/filter/grayscale.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/invert.dart b/image/lib/src/filter/invert.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/noise.dart b/image/lib/src/filter/noise.dart
old mode 100644
new mode 100755
index e5cca94..dd4d8ef
--- a/image/lib/src/filter/noise.dart
+++ b/image/lib/src/filter/noise.dart
@@ -24,7 +24,7 @@
 Image noise(Image image, double sigma, {int type: NOISE_GAUSSIAN,

   Math.Random random}) {

   if (random == null) {

-    random = new Math.Random();

+    random = Math.Random();

   }

 

   double nsigma = sigma;

diff --git a/image/lib/src/filter/normalize.dart b/image/lib/src/filter/normalize.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/pixelate.dart b/image/lib/src/filter/pixelate.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/quantize.dart b/image/lib/src/filter/quantize.dart
old mode 100644
new mode 100755
index a92645d..39278bc
--- a/image/lib/src/filter/quantize.dart
+++ b/image/lib/src/filter/quantize.dart
@@ -1,11 +1,27 @@
+import 'package:image/src/util/octree_quantizer.dart';

+

 import '../image.dart';

 import '../util/neural_quantizer.dart';

 

+enum QuantizeMethod {

+  neuralNet,

+  octree

+}

+

 /**

  * Quantize the number of colors in image to 256.

  */

-Image quantize(Image src) {

-  NeuralQuantizer quant = new NeuralQuantizer(src);

+Image quantize(Image src, {int numberOfColors=256,

+               QuantizeMethod method=QuantizeMethod.neuralNet}) {

+  if (method == QuantizeMethod.octree || numberOfColors < 4) {

+    OctreeQuantizer oct = OctreeQuantizer(src, numberOfColors: numberOfColors);

+    for (int i = 0, len = src.length; i < len; ++i) {

+      src[i] = oct.getQuantizedColor(src[i]);

+    }

+    return src;

+  }

+

+  NeuralQuantizer quant = NeuralQuantizer(src, numberOfColors: numberOfColors);

   for (int i = 0, len = src.length; i < len; ++i) {

     src[i] = quant.getQuantizedColor(src[i]);

   }

diff --git a/image/lib/src/filter/remap_colors.dart b/image/lib/src/filter/remap_colors.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/scale_rgba.dart b/image/lib/src/filter/scale_rgba.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/seperable_convolution.dart b/image/lib/src/filter/seperable_convolution.dart
old mode 100644
new mode 100755
index 1099b45..6ff5a5a
--- a/image/lib/src/filter/seperable_convolution.dart
+++ b/image/lib/src/filter/seperable_convolution.dart
@@ -9,7 +9,7 @@
  */

 Image seperableConvolution(Image src, SeperableKernel kernel) {

   // Apply the filter horizontally

-  Image tmp = new Image.from(src);

+  Image tmp = Image.from(src);

   kernel.apply(src, tmp, horizontal: true);

 

   // Apply the filter vertically, applying back to the original image.

diff --git a/image/lib/src/filter/seperable_kernel.dart b/image/lib/src/filter/seperable_kernel.dart
old mode 100644
new mode 100755
index d254c22..db0b39e
--- a/image/lib/src/filter/seperable_kernel.dart
+++ b/image/lib/src/filter/seperable_kernel.dart
@@ -12,7 +12,7 @@
    * Create a seperable convolution kernel for the given [radius].

    */

   SeperableKernel(int radius) :

-    coefficients = new List<double>(2 * radius + 1),

+    coefficients = List<double>(2 * radius + 1),

     this.size = radius;

 

   /**

diff --git a/image/lib/src/filter/sepia.dart b/image/lib/src/filter/sepia.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/smooth.dart b/image/lib/src/filter/smooth.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/sobel.dart b/image/lib/src/filter/sobel.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/filter/vignette.dart b/image/lib/src/filter/vignette.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/fonts/arial_14.dart b/image/lib/src/fonts/arial_14.dart
old mode 100644
new mode 100755
index 2437404..288ee3c
--- a/image/lib/src/fonts/arial_14.dart
+++ b/image/lib/src/fonts/arial_14.dart
@@ -3,7 +3,7 @@
 /**

  * 14px Arial font for use with [drawString] and [drawChar].

  */

-final BitmapFont arial_14 = new BitmapFont.fromZip(_ARIAL_14);

+final BitmapFont arial_14 = BitmapFont.fromZip(_ARIAL_14);

 

 const List<int> _ARIAL_14 = const [

   80, 75, 3, 4, 20, 0, 0, 8, 8, 0, 184, 182, 42, 68, 36, 55, 216, 103, 135, 15, 0, 0, 133, 15, 0, 0, 12, 0, 0, 0, 97, 114, 105, 97, 108, 95, 49, 52, 46, 112,

diff --git a/image/lib/src/fonts/arial_24.dart b/image/lib/src/fonts/arial_24.dart
old mode 100644
new mode 100755
index 338adb0..b838e04
--- a/image/lib/src/fonts/arial_24.dart
+++ b/image/lib/src/fonts/arial_24.dart
@@ -3,7 +3,7 @@
 /**

  * 24px Arial font for use with [drawString] and [drawChar].

  */

-final BitmapFont arial_24 = new BitmapFont.fromZip(_ARIAL_24);

+final BitmapFont arial_24 = BitmapFont.fromZip(_ARIAL_24);

 

 const List<int> _ARIAL_24 = const [

 80, 75, 3, 4, 20, 0, 0, 8, 8, 0, 131, 182, 42, 68, 22, 124, 124, 222, 0, 29, 0, 0, 62, 29, 0, 0, 12, 0, 0, 0, 97, 114, 105, 97, 108, 95, 50, 52, 46, 112, 110, 103, 141, 121, 103, 80, 19, 80, 179, 118, 18, 66, 143, 180, 208, 155, 128, 64, 164, 67, 232, 16, 122, 239, 85, 5, 68, 64, 122, 83, 58, 132, 158, 0, 130, 244, 142, 160, 16, 170, 2, 138, 72, 87, 164, 5, 165, 119, 4, 233, 66, 144, 222, 36, 116, 233, 215, 119, 190, 31, 223, 251, 235, 206, 61, 179, 115, 102, 127, 236, 236, 60, 115, 102, 207, 238, 179, 243, 196, 27, 27, 106, 221, 33, 99, 38, 3, 0, 0, 119, 116, 180, 213, 77, 1, 0, 48, 230, 159, 207, 66, 66, 244, 239, 86, 224, 212, 200, 0, 0, 216, 8, 117, 212, 85, 204, 145, 115, 123, 79, 18, 211, 75, 229, 234, 49, 16, 18, 52, 21, 109, 148, 42, 7, 248, 159, 189, 80, 38, 137, 81, 38, 129, 130, 56, 101, 192, 240, 191, 1, 163, 11, 81, 191, 2, 91, 10, 85, 79, 145, 206, 63, 31, 84, 43, 184, 120, 42, 107, 111, 79, 79, 83, 134, 135, 73, 184, 79, 86, 152, 148, 106, 38, 51, 75, 254, 239, 206, 120, 234, 219, 124, 191, 179, 37, 151, 235, 165, 219, 155, 51, 82, 165, 219, 107, 33, 177, 142, 219, 72, 254, 176, 135, 183, 75, 46, 156, 24, 73, 186, 5, 129, 136, 228, 149, 157, 144, 117, 89, 241, 144, 158, 139, 37, 23, 137, 133, 32, 141, 105, 194, 245, 217, 191, 65, 91, 30, 194, 163, 183, 29, 112, 219, 5, 201, 73, 249, 208, 253, 212, 72, 202, 222, 75, 73, 37, 100, 120, 251, 34, 233, 16, 95, 196, 6, 112, 145, 197, 230, 72, 242, 110, 151, 28, 241, 83, 202, 145, 174, 253, 254, 19, 85, 7, 195, 205, 215, 107, 30, 85, 3, 236, 172, 203, 45, 249, 163, 178, 55, 161, 206, 139, 46, 191, 123, 2, 194, 148, 76, 17, 101, 73, 60, 198, 97, 239, 62, 242, 213, 198, 126, 94, 49, 218, 189, 121, 23, 113, 239, 73, 208, 208, 10, 195, 179, 33, 214, 136, 189, 239, 44, 127, 31, 15, 68, 242, 209, 76, 231, 47, 237, 111, 96, 190, 194, 3, 143, 17, 57, 247, 207, 57, 90, 61, 114, 166, 200, 71, 149, 14, 170, 88, 44, 46, 153, 218, 203, 189, 63, 165, 167, 119, 12, 30, 60, 217, 96, 37, 88, 140, 28, 191, 100, 7, 189, 253, 230, 145, 121, 120, 67, 41, 7, 108, 85, 251, 148, 164, 224, 238, 23, 182, 16, 199, 18, 217, 208, 55, 44, 112, 166, 124, 233, 193, 199, 70, 32, 182, 159, 232, 179, 43, 237, 116, 199, 172, 255, 82, 252, 194, 205, 249, 244, 208, 24, 93, 206, 123, 47, 210, 16, 100, 68, 151, 76, 144, 186, 246, 197, 86, 34, 201, 169, 200, 191, 216, 199, 203, 118, 109, 152, 107, 17, 112, 233, 228, 179, 59, 72, 104, 75, 240, 71, 252, 254, 213, 167, 63, 27, 71, 65, 218, 27, 254, 113, 138, 181, 3, 231, 121, 227, 42, 133, 147, 75, 146, 243, 153, 191, 227, 162, 2, 18, 105, 148, 172, 130, 205, 235, 226, 244, 130, 89, 230, 37, 50, 10, 40, 214, 185, 153, 144, 2, 98, 97, 117, 198, 82, 45, 13, 188, 41, 141, 74, 103, 186, 37, 187, 125, 9, 97, 185, 159, 170, 199, 161, 199, 159, 190, 244, 38, 213, 181, 149, 31, 51, 172, 37, 230, 159, 213, 42, 218, 90, 138, 79, 41, 202, 252, 13, 110, 192, 87, 113, 144, 131, 66, 22, 25, 62, 106, 42, 176, 22, 132, 5, 70, 31, 14, 226, 4, 70, 99, 110, 182, 89, 247, 103, 10, 61, 18, 167, 220, 94, 133, 133, 185, 71, 138, 237, 228, 19, 222, 69, 136, 182, 71, 120, 177, 134, 210, 134, 197, 99, 103, 152, 196, 55, 28, 162, 66, 133, 181, 219, 185, 119, 114, 25, 35, 121, 73, 67, 207, 50, 158, 232, 47, 115, 79, 94, 216, 166, 27, 76, 202, 89, 214, 100, 168, 217, 124, 98, 95, 186, 124, 206, 153, 102, 114, 97, 231, 186, 204, 32, 68, 136, 161, 0, 214, 146, 251, 193, 229, 246, 181, 200, 14, 28, 84, 185, 231, 146, 40, 190, 233, 176, 213, 26, 47, 132, 122, 34, 35, 22, 217, 144, 81, 223, 162, 131, 203, 9, 153, 172, 210, 2, 191, 140, 67, 206, 66, 168, 184, 227, 80, 191, 20, 118, 156, 144, 35, 154, 98, 0, 184, 175, 216, 199, 40, 84, 247, 165, 189, 51, 68, 58, 37, 202, 78, 59, 210, 230, 95, 54, 116, 23, 179, 132, 221, 117, 160, 230, 185, 112, 66, 253, 156, 216, 145, 246, 8, 65, 14, 11, 241, 168, 247, 142, 146, 206, 0, 187, 117, 75, 105, 104, 10, 171, 5, 122, 202, 65, 146, 81, 122, 119, 206, 70, 66, 91, 26, 40, 179, 205, 24, 172, 182, 55, 168, 55, 16, 235, 199, 216, 14, 69, 250, 182, 70, 230, 96, 103, 131, 136, 49, 50, 99, 149, 52, 248, 6, 150, 136, 187, 73, 30, 140, 186, 104, 216, 142, 213, 67, 240, 99, 25, 204, 38, 74, 63, 180, 91, 70, 61, 248, 41, 184, 183, 55, 136, 0, 131, 210, 111, 2, 137, 177, 53, 166, 98, 49, 185, 66, 87, 156, 178, 78, 249, 213, 170, 77, 253, 101, 140, 3, 171, 54, 90, 82, 47, 223, 139, 160, 158, 47, 240, 87, 21, 208, 33, 7, 116, 169, 62, 240, 227, 193, 168, 88, 179, 212, 103, 63, 88, 239, 158, 205, 72, 166, 189, 4, 126, 225, 77, 94, 250, 4, 50, 138, 123, 130, 157, 229, 209, 193, 217, 158, 109, 188, 2, 25, 221, 163, 190, 10, 101, 198, 59, 222, 17, 4, 133, 138, 231, 236, 6, 83, 34, 201, 10, 142, 51, 69, 170, 226, 161, 125, 103, 140, 108, 112, 222, 87, 224, 55, 36, 44, 17, 47, 176, 153, 61, 143, 101, 210, 116, 8, 87, 71, 47, 161, 138, 72, 202, 240, 167, 223, 92, 32, 68, 111, 156, 92, 174, 94, 216, 205, 208, 168, 164, 223, 254, 17, 35, 117, 208, 142, 197, 197, 12, 10, 63, 188, 234, 111, 164, 199, 59, 230, 14, 174, 174, 13, 59, 24, 129, 63, 215, 2, 210, 126, 176, 56, 73, 208, 130, 248, 140, 107, 69, 180, 255, 82, 62, 92, 153, 6,

diff --git a/image/lib/src/fonts/arial_48.dart b/image/lib/src/fonts/arial_48.dart
old mode 100644
new mode 100755
index 34d42a6..a156382
--- a/image/lib/src/fonts/arial_48.dart
+++ b/image/lib/src/fonts/arial_48.dart
@@ -3,7 +3,7 @@
 /**

  * 48px Arial font for use with [drawString] and [drawChar].

  */

-final BitmapFont arial_48 = new BitmapFont.fromZip(_ARIAL_48);

+final BitmapFont arial_48 = BitmapFont.fromZip(_ARIAL_48);

 

 const List<int> _ARIAL_48 = const

 [80, 75, 3, 4, 20, 0, 0, 8, 8, 0, 187, 182, 42, 68, 95, 169, 84, 175, 60, 66, 0, 0, 49, 67, 0, 0, 12, 0, 0, 0, 97, 114, 105, 97, 108, 95, 52, 56, 46, 112, 110, 103, 164, 187, 85, 80, 92, 77, 224, 237, 59, 131, 187, 7, 201, 64, 112, 11, 110, 131, 133, 224, 238, 16, 130, 59, 9, 131, 12, 4, 6, 215, 193, 33, 193, 157, 96, 131, 36, 192, 135, 195, 224, 26, 66, 176, 32, 67, 66, 128, 76, 112, 39, 184, 219, 0, 55, 255, 115, 238, 173, 243, 112, 30, 239, 170, 93, 187, 118, 213, 126, 233, 174, 213, 221, 235, 183, 30, 58, 193, 64, 79, 157, 148, 232, 41, 17, 0, 0, 32, 213, 212, 80, 49, 2, 0, 8, 160, 255, 190, 69, 8, 240, 254, 189, 93, 253, 135, 138, 1, 0, 165, 107, 77, 21, 197, 87, 1, 232, 3, 235, 164, 198, 242, 246, 186, 34, 18, 130, 8, 138, 255, 247, 249, 194, 74, 129, 197, 74, 49, 16, 173, 64, 192, 141, 35, 26, 16, 118, 181, 160, 125, 36, 202, 168, 153, 237, 244, 27, 37, 103, 100, 50, 247, 250, 128, 177, 95, 254, 118, 206, 249, 102, 78, 136, 251, 255, 183, 42, 30, 13, 18, 27, 31, 167, 132, 48, 219, 109, 15, 203, 143, 247, 203, 158, 251, 254, 24, 221, 156, 128, 185, 172, 219, 247, 103, 185, 13, 210, 33, 143, 143, 143, 152, 161, 71, 204, 71, 162, 117, 130, 28, 9, 130, 241, 237, 222, 97, 73, 246, 245, 226, 190, 71, 57, 152, 213, 242, 145, 45, 220, 95, 104, 56, 55, 120, 72, 22, 125, 228, 203, 53, 52, 143, 237, 118, 50, 85, 143, 87, 172, 177, 28, 154, 200, 180, 80, 223, 53, 20, 104, 222, 150, 246, 117, 27, 63, 37, 252, 209, 82, 59, 4, 6, 15, 88, 9, 120, 22, 10, 22, 41, 74, 94, 73, 224, 140, 243, 164, 94, 15, 157, 104, 163, 28, 249, 244, 86, 183, 249, 124, 168, 196, 182, 74, 194, 83, 240, 212, 247, 153, 115, 58, 119, 178, 243, 208, 217, 53, 185, 57, 35, 189, 163, 91, 178, 8, 142, 195, 163, 210, 103, 61, 65, 87, 177, 202, 237, 71, 177, 184, 250, 239, 125, 2, 99, 129, 252, 243, 193, 112, 207, 196, 113, 255, 214, 254, 249, 237, 68, 231, 63, 223, 123, 15, 165, 221, 136, 119, 190, 201, 251, 56, 38, 181, 168, 94, 74, 230, 52, 249, 72, 9, 31, 105, 236, 46, 144, 188, 212, 163, 114, 136, 226, 254, 112, 2, 184, 125, 195, 26, 242, 53, 107, 79, 217, 105, 60, 144, 187, 87, 104, 118, 186, 81, 56, 52, 165, 122, 237, 42, 232, 91, 47, 56, 46, 148, 148, 176, 239, 177, 165, 45, 42, 186, 158, 103, 209, 126, 223, 118, 56, 125, 185, 230, 166, 199, 81, 31, 236, 148, 50, 252, 116, 47, 127, 109, 206, 243, 222, 25, 83, 40, 194, 41, 159, 42, 216, 16, 191, 73, 182, 76, 178, 96, 25, 195, 56, 145, 120, 221, 209, 247, 29, 108, 181, 175, 236, 216, 29, 39, 167, 156, 18, 205, 248, 39, 191, 138, 185, 45, 189, 245, 180, 33, 13, 27, 70, 58, 148, 169, 111, 245, 83, 143, 82, 4, 226, 123, 111, 61, 214, 230, 240, 183, 32, 141, 126, 56, 251, 164, 22, 215, 124, 239, 245, 77, 175, 244, 133, 160, 70, 189, 249, 150, 16, 5, 232, 87, 197, 90, 92, 181, 190, 147, 48, 153, 95, 129, 177, 162, 31, 214, 122, 112, 101, 136, 121, 205, 132, 73, 107, 205, 156, 108, 75, 95, 180, 7, 137, 134, 71, 137, 228, 194, 157, 77, 153, 190, 180, 155, 207, 70, 187, 210, 128, 250, 228, 4, 181, 249, 93, 154, 236, 6, 159, 245, 37, 52, 160, 146, 233, 125, 94, 183, 153, 40, 153, 238, 55, 192, 214, 9, 251, 133, 167, 149, 52, 205, 70, 186, 197, 78, 215, 194, 9, 75, 43, 119, 230, 76, 240, 156, 149, 207, 24, 121, 215, 117, 248, 98, 189, 150, 79, 99, 190, 155, 82, 216, 148, 248, 230, 223, 93, 170, 214, 149, 125, 110, 243, 161, 152, 97, 140, 58, 7, 183, 124, 206, 49, 161, 208, 205, 21, 76, 48, 20, 255, 218, 191, 107, 231, 97, 214, 108, 238, 28, 221, 55, 87, 83, 165, 90, 27, 251, 190, 54, 15, 220, 90, 226, 138, 80, 123, 169, 172, 62, 99, 150, 179, 126, 7, 197, 149, 163, 16, 191, 125, 138, 34, 254, 118, 22, 83, 17, 106, 78, 32, 135, 206, 106, 104, 140, 237, 94, 230, 58, 6, 54, 15, 210, 25, 205, 12, 153, 82, 47, 201, 68, 187, 170, 70, 62, 19, 149, 250, 82, 240, 83, 86, 1, 100, 64, 5, 215, 194, 192, 136, 29, 99, 215, 9, 19, 7, 182, 4, 233, 31, 203, 233, 127, 142, 92, 15, 85, 242, 172, 69, 76, 110, 125, 144, 198, 77, 174, 139, 2, 83, 40, 135, 122, 197, 59, 15, 221, 134, 91, 103, 237, 92, 117, 229, 221, 181, 41, 135, 0, 146, 182, 45, 241, 9, 2, 214, 180, 41, 94, 181, 13, 191, 224, 12, 114, 73, 131, 99, 11, 186, 201, 184, 164, 139, 22, 4, 178, 104, 106, 64, 38, 176, 169, 142, 163, 7, 159, 157, 39, 248, 126, 140, 151, 176, 137, 14, 114, 206, 156, 207, 254, 185, 16, 172, 29, 248, 100, 108, 218, 215, 211, 191, 108, 208, 78, 127, 100, 131, 13, 53, 106, 152, 193, 136, 87, 180, 8, 239, 99, 160, 144, 118, 167, 63, 42, 166, 87, 221, 225, 109, 75, 141, 173, 129, 154, 206, 255, 254, 238, 117, 139, 191, 81, 8, 3, 6, 167, 154, 148, 143, 181, 152, 44, 191, 24, 250, 117, 148, 154, 50, 176, 33, 166, 141, 38, 47, 156, 93, 106, 88, 242, 196, 70, 143, 28, 223, 169, 18, 114, 224, 67, 43, 247, 73, 136, 27, 12, 189, 67, 243, 48, 104, 134, 48, 103, 19, 56, 120, 164, 188, 130, 171, 177, 92, 3, 225, 163, 196, 252, 151, 60, 152, 53, 243, 55, 21, 146, 30, 158, 230, 188, 217, 182, 109, 86, 210, 192, 214, 144, 229, 24, 59, 174, 199, 224, 134, 90, 130, 86, 20, 225, 160, 21, 102, 189, 111, 223, 232, 192, 109, 155, 197, 224, 180, 73, 167, 150, 182, 31, 67, 136, 233, 132, 35, 158, 104, 167, 118, 155, 129, 231, 73, 3, 61, 21, 28, 198, 123, 54, 194, 216, 90, 29, 123, 53, 147, 155, 20, 64, 210, 47, 34, 14, 38, 22, 17, 164, 159, 61, 172, 36, 94, 4, 22, 85, 59, 21, 165, 151, 158, 248, 119, 15, 143, 175, 98, 210, 108, 103, 57, 182, 133, 142, 24, 72, 174, 184, 40, 94, 146, 91, 50, 75, 65, 214, 29, 21, 65, 236, 111, 181, 151, 128, 200, 180, 221, 184, 199, 180, 40, 1, 194, 149, 84, 128, 8, 92, 98, 31, 230, 171, 8, 236, 223, 128, 64, 251, 244, 130, 66, 133, 222, 72, 102, 158, 248, 219, 141, 4, 11, 207, 72, 124, 70, 144, 218, 203, 189, 1, 31, 83, 62, 154, 125, 143, 78, 130, 70, 75, 44, 152, 62, 11, 166, 74, 116, 102, 185, 164, 45, 45, 65, 60, 27, 25, 149, 62, 151, 56, 139, 193, 50, 15, 57, 24, 61, 230, 64, 13, 81, 70, 213, 40, 201, 10, 63, 223, 159, 250, 175, 113, 207, 104, 200, 220, 155, 154, 201, 63, 10, 76, 165, 53, 203, 113, 98, 69, 133, 244, 74, 12, 55, 73, 46, 134, 54, 144, 125, 54, 18, 123, 60, 193, 124, 126, 23, 137, 135, 15, 157, 135, 131, 105, 186, 123, 251, 104, 120, 168, 27, 96, 161, 173, 101, 5, 87, 81, 220, 226, 122, 167, 35, 0, 119, 72, 161, 167, 209, 42, 27, 2, 191, 234, 217, 134, 159, 18, 253, 147, 51, 51, 14, 4, 233, 150, 133, 68, 252, 11, 183, 185, 0, 251, 241, 208, 39, 50, 153, 156, 138, 32, 168, 135, 157, 23, 169, 30, 188, 223, 15, 5, 80, 38, 88, 114, 163, 113, 123, 65, 216, 43, 194, 231, 116, 172, 238, 93, 49, 132, 126, 73, 129, 108, 164, 232, 172, 16, 105, 197, 167, 21, 231, 189, 255, 239, 219, 202, 159, 81, 9, 94, 113, 103, 218, 134, 11, 79, 28, 168, 70, 100, 195, 130, 132, 31, 74, 77, 186, 127, 8, 91, 1, 212, 60, 45, 249, 84, 247, 7, 250, 121, 71, 169, 38, 66, 35, 234, 156, 49, 188, 93, 201, 126, 133, 239, 111, 231, 185, 142, 196, 182, 109, 21, 4, 73, 48, 103, 39, 140, 250, 52, 202, 49, 109, 139, 135, 134, 176, 62, 147, 152, 117, 131, 106, 21, 179, 226, 38, 40, 158, 212, 78, 190, 95, 38, 8, 237, 120, 7, 124, 86, 191, 96, 56, 132, 38, 29, 40, 189, 138, 62, 238, 86, 245, 207, 143, 200, 207, 9, 97, 71, 169, 189, 102, 60, 225, 64, 197, 54, 244, 55, 60, 223, 80, 88, 120, 163, 108, 36, 158, 77, 155, 238, 29, 136, 97, 171, 150, 22, 249, 235, 211, 120, 68, 154, 37, 191, 114, 26, 31, 5, 126, 73, 139, 108, 116, 104, 221, 24, 69, 36, 41, 63, 214, 227, 102, 135, 37, 189, 233, 12, 110, 140, 160, 55, 12, 164, 122, 220, 88, 14, 217, 131, 111, 206, 240, 174, 245, 201, 36, 252, 52, 177, 172, 170, 79, 191, 108, 51, 176, 106, 124, 138, 110, 22, 74, 134, 78, 77, 124, 157, 193, 131, 66, 246, 233, 125, 142, 37, 185, 245, 181, 70, 219, 79, 237, 232, 101, 201, 89, 43, 195, 255, 115, 171, 161, 234, 195, 93, 107, 6, 173, 29, 22, 149, 40, 35, 91, 46, 14, 9, 17, 73, 241, 254, 171, 212, 119, 167, 67, 190, 189, 1, 53, 80, 62, 251, 2, 184, 52, 161, 134, 91, 74, 33, 159, 112, 139, 2, 40, 97, 96, 189, 229, 201, 95, 83, 143, 129, 74, 28, 72, 148, 193, 107, 3, 190, 185, 74, 95, 63, 156, 228, 164, 202, 254, 239, 43, 25, 139, 138, 160, 155, 127, 35, 235, 151, 252, 180, 202, 148, 165, 229, 198, 94, 112, 85, 175, 99, 167, 202, 46, 96, 21, 18, 158, 193, 78, 141, 85, 214, 8, 60, 154, 95, 43, 54, 77, 229, 31, 121, 65, 167, 42, 186, 219, 226, 113, 182, 123, 47, 54, 19, 155, 67, 140, 182, 147, 146, 229, 243, 79, 34, 92, 20, 18, 196, 225, 99, 140, 118, 64, 144, 170, 60, 106, 82, 171, 184, 105, 21, 195, 2, 143, 79, 199, 235, 4, 84, 8, 3, 122, 21, 247, 109, 185, 125, 74, 131, 183, 208, 27, 117, 7, 209, 243, 198, 19, 83, 50, 246, 133, 174, 186, 146, 79, 255, 68, 177, 141, 58, 169, 57, 216, 75, 98, 46, 245, 78, 44, 86, 187, 151, 125, 126, 6, 201, 147, 33, 41, 113, 173, 27, 107, 176, 44, 241, 161, 78, 216, 224, 75, 30, 217, 14, 3, 82, 164, 189, 137, 198, 39, 140, 49, 23, 132, 189, 109, 132, 19, 11, 74, 255, 228, 111, 248, 117, 198, 201, 179, 119, 32, 109, 117, 16, 23, 108, 230, 76, 61, 253, 222, 182, 138, 118, 62, 145, 17, 46, 69, 8, 49, 64, 81, 63, 57, 126, 228, 66, 225, 165, 213, 55, 236, 239, 99, 31, 88, 127, 7, 248, 65, 124, 100, 179, 156, 126, 249, 220, 131, 56, 78, 148, 196, 247, 253, 34, 56, 20, 51, 110, 219, 6, 37, 120, 85, 148, 90, 187, 12, 147, 249, 21, 64, 29, 34, 99, 142, 255, 78, 39, 155, 131, 134, 54, 57, 163, 119, 133, 226, 103, 153, 147, 105, 95, 63, 240, 246, 69, 187, 88, 130, 7, 36, 15, 169, 246, 126, 99, 123, 47, 60, 223, 112, 224, 56, 87, 202, 126, 25, 64, 37, 13, 97, 39, 70, 54, 58, 182, 110, 84, 33, 146, 70, 246, 142, 91, 57, 235, 212, 53, 111, 6, 63, 139, 178, 2, 29, 172, 124, 216, 219, 238, 14, 17, 241, 39, 38, 214, 79, 216, 72, 71, 126, 218, 0, 9, 111, 192, 178, 202, 115, 22, 62, 29, 7, 212, 221, 194, 92, 253, 207, 247, 219, 233, 19, 194, 235, 58, 190, 131, 211, 30, 55, 182, 156, 185, 147, 221, 89, 122, 103, 234, 54, 146, 98, 248, 214, 41, 165, 25, 99, 103, 130, 253, 92, 150, 158, 84, 219, 18, 253, 213, 204, 111, 36, 51, 227, 177, 44, 13, 93, 18, 181, 213, 184, 158, 149, 133, 77, 244, 135, 40, 125, 89, 80, 229, 3, 100, 105, 98, 218, 102, 236, 223, 235, 217, 5, 247, 114, 56, 254, 139, 130, 114, 88, 160, 159, 131, 244, 85, 210, 44, 0, 74, 161, 57, 153, 53, 223, 175, 216, 3, 193, 85, 0, 165, 174, 133, 250, 10, 179, 108, 49, 138, 227, 237, 61, 135, 111, 239, 105, 211, 79, 53, 205, 73, 139, 162, 25, 127, 173, 80, 43,

diff --git a/image/lib/src/formats/decode_info.dart b/image/lib/src/formats/decode_info.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/decoder.dart b/image/lib/src/formats/decoder.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/encoder.dart b/image/lib/src/formats/encoder.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/exr/exr_attribute.dart b/image/lib/src/formats/exr/exr_attribute.dart
old mode 100644
new mode 100755
index 5510f33..5daa2e9
--- a/image/lib/src/formats/exr/exr_attribute.dart
+++ b/image/lib/src/formats/exr/exr_attribute.dart
@@ -1,10 +1,10 @@
-import '../../util/input_buffer.dart';
-
-class ExrAttribute {
-  String name;
-  String type;
-  int size;
-  InputBuffer data;
-
-  ExrAttribute(this.name, this.type, this.size, this.data);
-}
+import '../../util/input_buffer.dart';

+

+class ExrAttribute {

+  String name;

+  String type;

+  int size;

+  InputBuffer data;

+

+  ExrAttribute(this.name, this.type, this.size, this.data);

+}

diff --git a/image/lib/src/formats/exr/exr_b44_compressor.dart b/image/lib/src/formats/exr/exr_b44_compressor.dart
old mode 100644
new mode 100755
index 07daf1a..a7e3842
--- a/image/lib/src/formats/exr/exr_b44_compressor.dart
+++ b/image/lib/src/formats/exr/exr_b44_compressor.dart
@@ -1,36 +1,36 @@
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../internal/internal.dart';
-import '../../util/input_buffer.dart';
-import 'exr_compressor.dart';
-import 'exr_part.dart';
-
-abstract class ExrB44Compressor extends ExrCompressor {
-  factory ExrB44Compressor(ExrPart header, int maxScanLineSize, int numScanLines,
-                           bool optFlatFields) = InternalExrB44Compressor;
-}
-
-@internal
-class InternalExrB44Compressor extends InternalExrCompressor implements ExrB44Compressor {
-  InternalExrB44Compressor(ExrPart header, int maxScanLineSize, this._numScanLines,
-                           bool optFlatFields) :
-    super(header) {
-  }
-
-  int numScanLines() => _numScanLines;
-
-  Uint8List compress(InputBuffer inPtr, int x, int y,
-                     [int width, int height]) {
-    throw new ImageException('B44 compression not yet supported.');
-  }
-
-  Uint8List uncompress(InputBuffer inPtr, int x, int y,
-                       [int width, int height]) {
-    throw new ImageException('B44 compression not yet supported.');
-  }
-
-  //int _maxScanLineSize;
-  int _numScanLines;
-  //bool _optFlatFields;
-}
+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../internal/internal.dart';

+import '../../util/input_buffer.dart';

+import 'exr_compressor.dart';

+import 'exr_part.dart';

+

+abstract class ExrB44Compressor extends ExrCompressor {

+  factory ExrB44Compressor(ExrPart header, int maxScanLineSize, int numScanLines,

+                           bool optFlatFields) = InternalExrB44Compressor;

+}

+

+@internal

+class InternalExrB44Compressor extends InternalExrCompressor implements ExrB44Compressor {

+  InternalExrB44Compressor(ExrPart header, int maxScanLineSize, this._numScanLines,

+                           bool optFlatFields) :

+    super(header) {

+  }

+

+  int numScanLines() => _numScanLines;

+

+  Uint8List compress(InputBuffer inPtr, int x, int y,

+                     [int width, int height]) {

+    throw new ImageException('B44 compression not yet supported.');

+  }

+

+  Uint8List uncompress(InputBuffer inPtr, int x, int y,

+                       [int width, int height]) {

+    throw new ImageException('B44 compression not yet supported.');

+  }

+

+  //int _maxScanLineSize;

+  int _numScanLines;

+  //bool _optFlatFields;

+}

diff --git a/image/lib/src/formats/exr/exr_channel.dart b/image/lib/src/formats/exr/exr_channel.dart
old mode 100644
new mode 100755
index 3a751f8..19ee809
--- a/image/lib/src/formats/exr/exr_channel.dart
+++ b/image/lib/src/formats/exr/exr_channel.dart
@@ -1,76 +1,76 @@
-import '../../image_exception.dart';
-import '../../hdr/hdr_image.dart';
-import '../../util/input_buffer.dart';
-
-class ExrChannel {
-  static const int TYPE_UINT = HdrImage.UINT;
-  static const int TYPE_HALF = HdrImage.HALF;
-  static const int TYPE_FLOAT = HdrImage.FLOAT;
-
-  // Channel Names
-
-  /// Luminance
-  static const String Y = 'Y';
-  /// Chroma RY
-  static const String RY = 'RY';
-  /// Chroma BY
-  static const String BY = 'BY';
-  /// Red for colored mattes
-  static const String AR = 'AR';
-  /// Green for colored mattes
-  static const String AG = 'AG';
-  /// Blue for colored mattes
-  static const String AB = 'AB';
-  /// Distance of the front of a sample from the viewer
-  static const String Z = 'Z';
-  /// Distance of the back of a sample from the viewer
-  static const String ZBack = 'ZBack';
-  /// Alpha/opacity
-  static const String A = 'A';
-  /// Red value of a sample
-  static const String R = 'R';
-  /// Green value of a sample
-  static const String G = 'G';
-  /// Blue value of a sample
-  static const String B = 'B';
-  /// A numerical identifier for the object represented by a sample.
-  static const String ID = 'id';
-
-  String name;
-  int type;
-  int size;
-  bool pLinear;
-  int xSampling;
-  int ySampling;
-
-  ExrChannel(InputBuffer input) {
-    name = input.readString();
-    if (name == null || name.isEmpty) {
-      name = null;
-      return;
-    }
-    type = input.readUint32();
-    int i = input.readByte();
-    assert(i == 0 || i == 1);
-    pLinear = i == 1;
-    input.skip(3);
-    xSampling = input.readUint32();
-    ySampling = input.readUint32();
-
-    switch (type) {
-      case TYPE_UINT:
-        size = 4;
-        break;
-      case TYPE_HALF:
-        size = 2;
-        break;
-      case TYPE_FLOAT:
-        size = 4;
-        break;
-      default:
-        throw new ImageException('EXR Invalid pixel type: $type');
-    }
-  }
-
-  bool get isValid => name != null;
-}
+import '../../image_exception.dart';

+import '../../hdr/hdr_image.dart';

+import '../../util/input_buffer.dart';

+

+class ExrChannel {

+  static const int TYPE_UINT = HdrImage.UINT;

+  static const int TYPE_HALF = HdrImage.HALF;

+  static const int TYPE_FLOAT = HdrImage.FLOAT;

+

+  // Channel Names

+

+  /// Luminance

+  static const String Y = 'Y';

+  /// Chroma RY

+  static const String RY = 'RY';

+  /// Chroma BY

+  static const String BY = 'BY';

+  /// Red for colored mattes

+  static const String AR = 'AR';

+  /// Green for colored mattes

+  static const String AG = 'AG';

+  /// Blue for colored mattes

+  static const String AB = 'AB';

+  /// Distance of the front of a sample from the viewer

+  static const String Z = 'Z';

+  /// Distance of the back of a sample from the viewer

+  static const String ZBack = 'ZBack';

+  /// Alpha/opacity

+  static const String A = 'A';

+  /// Red value of a sample

+  static const String R = 'R';

+  /// Green value of a sample

+  static const String G = 'G';

+  /// Blue value of a sample

+  static const String B = 'B';

+  /// A numerical identifier for the object represented by a sample.

+  static const String ID = 'id';

+

+  String name;

+  int type;

+  int size;

+  bool pLinear;

+  int xSampling;

+  int ySampling;

+

+  ExrChannel(InputBuffer input) {

+    name = input.readString();

+    if (name == null || name.isEmpty) {

+      name = null;

+      return;

+    }

+    type = input.readUint32();

+    int i = input.readByte();

+    assert(i == 0 || i == 1);

+    pLinear = i == 1;

+    input.skip(3);

+    xSampling = input.readUint32();

+    ySampling = input.readUint32();

+

+    switch (type) {

+      case TYPE_UINT:

+        size = 4;

+        break;

+      case TYPE_HALF:

+        size = 2;

+        break;

+      case TYPE_FLOAT:

+        size = 4;

+        break;

+      default:

+        throw new ImageException('EXR Invalid pixel type: $type');

+    }

+  }

+

+  bool get isValid => name != null;

+}

diff --git a/image/lib/src/formats/exr/exr_compressor.dart b/image/lib/src/formats/exr/exr_compressor.dart
old mode 100644
new mode 100755
index b0b0e5f..71e99b3
--- a/image/lib/src/formats/exr/exr_compressor.dart
+++ b/image/lib/src/formats/exr/exr_compressor.dart
@@ -1,103 +1,103 @@
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../internal/internal.dart';
-import '../../util/input_buffer.dart';
-import 'exr_b44_compressor.dart';
-import 'exr_part.dart';
-import 'exr_piz_compressor.dart';
-import 'exr_pxr24_compressor.dart';
-import 'exr_rle_compressor.dart';
-import 'exr_zip_compressor.dart';
-
-abstract class ExrCompressor {
-  static const int NO_COMPRESSION = 0;
-  static const int RLE_COMPRESSION = 1;
-  static const int ZIPS_COMPRESSION = 2;
-  static const int ZIP_COMPRESSION = 3;
-  static const int PIZ_COMPRESSION = 4;
-  static const int PXR24_COMPRESSION = 5;
-  static const int B44_COMPRESSION = 6;
-  static const int B44A_COMPRESSION = 7;
-
-  int decodedWidth = 0;
-  int decodedHeight = 0;
-
-  factory ExrCompressor(int type, ExrPart hdr, int maxScanLineSize,
-                        [int numScanLines]) {
-    switch (type) {
-      case RLE_COMPRESSION:
-        return new ExrRleCompressor(hdr, maxScanLineSize);
-      case ZIPS_COMPRESSION:
-        return new ExrZipCompressor(hdr, maxScanLineSize,
-                                    numScanLines == null ? 1 : numScanLines);
-      case ZIP_COMPRESSION:
-        return new ExrZipCompressor(hdr, maxScanLineSize,
-                                    numScanLines == null ? 16 : numScanLines);
-      case PIZ_COMPRESSION:
-        return new ExrPizCompressor(hdr, maxScanLineSize,
-                                    numScanLines == null ? 32 : numScanLines);
-      case PXR24_COMPRESSION:
-        return new ExrPxr24Compressor(hdr, maxScanLineSize,
-                                     numScanLines == null ? 16 : numScanLines);
-      case B44_COMPRESSION:
-        return new ExrB44Compressor(hdr, maxScanLineSize,
-                              numScanLines == null ? 32 : numScanLines, false);
-      case B44A_COMPRESSION:
-        return new ExrB44Compressor(hdr, maxScanLineSize,
-                              numScanLines == null ? 32 : numScanLines, true);
-      default:
-        throw new ImageException('Invalid compression type: $type');
-    }
-  }
-
-  factory ExrCompressor.tile(int type, int tileLineSize, int numTileLines,
-                             ExrPart hdr) {
-    switch (type) {
-      case RLE_COMPRESSION:
-        return new ExrRleCompressor(hdr, (tileLineSize * numTileLines));
-      case ZIPS_COMPRESSION:
-      case ZIP_COMPRESSION:
-        return new ExrZipCompressor(hdr, tileLineSize, numTileLines);
-      case PIZ_COMPRESSION:
-        return new ExrPizCompressor(hdr, tileLineSize, numTileLines);
-      case PXR24_COMPRESSION:
-        return new ExrPxr24Compressor(hdr, tileLineSize, numTileLines);
-      case B44_COMPRESSION:
-        return new ExrB44Compressor(hdr, tileLineSize, numTileLines, false);
-      case B44A_COMPRESSION:
-        return new ExrB44Compressor(hdr, tileLineSize, numTileLines, true);
-      default:
-        throw new ImageException('Invalid compression type: $type');
-    }
-  }
-
-  ExrCompressor._(this._header);
-
-  int numScanLines();
-
-  Uint8List compress(InputBuffer inPtr, int x, int y,
-                     [int width, int height]) {
-    throw new ImageException('Unsupported compression type');
-  }
-
-  Uint8List uncompress(InputBuffer inPtr, int x, int y,
-                       [int width, int height]) {
-    throw new ImageException('Unsupported compression type');
-  }
-
-  ExrPart _header;
-}
-
-@internal
-abstract class InternalExrCompressor extends ExrCompressor {
-  InternalExrCompressor(InternalExrPart header) : super._(header);
-
-  InternalExrPart get header => _header;
-
-  int numSamples(int s, int a, int b) {
-    int a1 = a ~/ s;
-    int b1 = b ~/ s;
-    return  b1 - a1 + ((a1 * s < a) ? 0: 1);
-  }
-}
+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../internal/internal.dart';

+import '../../util/input_buffer.dart';

+import 'exr_b44_compressor.dart';

+import 'exr_part.dart';

+import 'exr_piz_compressor.dart';

+import 'exr_pxr24_compressor.dart';

+import 'exr_rle_compressor.dart';

+import 'exr_zip_compressor.dart';

+

+abstract class ExrCompressor {

+  static const int NO_COMPRESSION = 0;

+  static const int RLE_COMPRESSION = 1;

+  static const int ZIPS_COMPRESSION = 2;

+  static const int ZIP_COMPRESSION = 3;

+  static const int PIZ_COMPRESSION = 4;

+  static const int PXR24_COMPRESSION = 5;

+  static const int B44_COMPRESSION = 6;

+  static const int B44A_COMPRESSION = 7;

+

+  int decodedWidth = 0;

+  int decodedHeight = 0;

+

+  factory ExrCompressor(int type, ExrPart hdr, int maxScanLineSize,

+                        [int numScanLines]) {

+    switch (type) {

+      case RLE_COMPRESSION:

+        return new ExrRleCompressor(hdr, maxScanLineSize);

+      case ZIPS_COMPRESSION:

+        return new ExrZipCompressor(hdr, maxScanLineSize,

+                                    numScanLines == null ? 1 : numScanLines);

+      case ZIP_COMPRESSION:

+        return new ExrZipCompressor(hdr, maxScanLineSize,

+                                    numScanLines == null ? 16 : numScanLines);

+      case PIZ_COMPRESSION:

+        return new ExrPizCompressor(hdr, maxScanLineSize,

+                                    numScanLines == null ? 32 : numScanLines);

+      case PXR24_COMPRESSION:

+        return new ExrPxr24Compressor(hdr, maxScanLineSize,

+                                     numScanLines == null ? 16 : numScanLines);

+      case B44_COMPRESSION:

+        return new ExrB44Compressor(hdr, maxScanLineSize,

+                              numScanLines == null ? 32 : numScanLines, false);

+      case B44A_COMPRESSION:

+        return new ExrB44Compressor(hdr, maxScanLineSize,

+                              numScanLines == null ? 32 : numScanLines, true);

+      default:

+        throw new ImageException('Invalid compression type: $type');

+    }

+  }

+

+  factory ExrCompressor.tile(int type, int tileLineSize, int numTileLines,

+                             ExrPart hdr) {

+    switch (type) {

+      case RLE_COMPRESSION:

+        return new ExrRleCompressor(hdr, (tileLineSize * numTileLines));

+      case ZIPS_COMPRESSION:

+      case ZIP_COMPRESSION:

+        return new ExrZipCompressor(hdr, tileLineSize, numTileLines);

+      case PIZ_COMPRESSION:

+        return new ExrPizCompressor(hdr, tileLineSize, numTileLines);

+      case PXR24_COMPRESSION:

+        return new ExrPxr24Compressor(hdr, tileLineSize, numTileLines);

+      case B44_COMPRESSION:

+        return new ExrB44Compressor(hdr, tileLineSize, numTileLines, false);

+      case B44A_COMPRESSION:

+        return new ExrB44Compressor(hdr, tileLineSize, numTileLines, true);

+      default:

+        throw new ImageException('Invalid compression type: $type');

+    }

+  }

+

+  ExrCompressor._(this._header);

+

+  int numScanLines();

+

+  Uint8List compress(InputBuffer inPtr, int x, int y,

+                     [int width, int height]) {

+    throw new ImageException('Unsupported compression type');

+  }

+

+  Uint8List uncompress(InputBuffer inPtr, int x, int y,

+                       [int width, int height]) {

+    throw new ImageException('Unsupported compression type');

+  }

+

+  ExrPart _header;

+}

+

+@internal

+abstract class InternalExrCompressor extends ExrCompressor {

+  InternalExrCompressor(InternalExrPart header) : super._(header);

+

+  InternalExrPart get header => _header;

+

+  int numSamples(int s, int a, int b) {

+    int a1 = a ~/ s;

+    int b1 = b ~/ s;

+    return  b1 - a1 + ((a1 * s < a) ? 0: 1);

+  }

+}

diff --git a/image/lib/src/formats/exr/exr_huffman.dart b/image/lib/src/formats/exr/exr_huffman.dart
old mode 100644
new mode 100755
index b90c415..b5a0d3e
--- a/image/lib/src/formats/exr/exr_huffman.dart
+++ b/image/lib/src/formats/exr/exr_huffman.dart
@@ -1,345 +1,345 @@
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-
-class ExrHuffman {
-  static void uncompress(InputBuffer compressed, int nCompressed,
-                         Uint16List raw, int nRaw) {
-    if (nCompressed == 0) {
-      if (nRaw != 0) {
-        throw new ImageException('Incomplete huffman data');
-      }
-
-      return;
-    }
-
-    int start = compressed.offset;
-
-    int im = compressed.readUint32();
-    int iM = compressed.readUint32();
-    compressed.skip(4); // tableLength
-    int nBits = compressed.readUint32();
-
-    if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) {
-      throw new ImageException('Invalid huffman table size');
-    }
-
-    compressed.skip(4);
-
-    List<int> freq = new List<int>(HUF_ENCSIZE);
-    freq.fillRange(0, HUF_ENCSIZE, 0);
-
-    List<ExrHufDec> hdec = new List<ExrHufDec>(HUF_DECSIZE);
-    for (int i = 0; i < HUF_DECSIZE; ++i) {
-      hdec[i] = new ExrHufDec();
-    }
-
-    unpackEncTable(compressed, nCompressed - 20, im, iM, freq);
-
-    if (nBits > 8 * (nCompressed - (compressed.offset - start))) {
-      throw new ImageException("Error in header for Huffman-encoded data "
-                               "(invalid number of bits).");
-    }
-
-    buildDecTable(freq, im, iM, hdec);
-    decode(freq, hdec, compressed, nBits, iM, nRaw, raw);
-  }
-
-  static void decode(List<int> hcode, List<ExrHufDec> hdecod,
-                     InputBuffer input, int ni, int rlc, int no,
-                     Uint16List out) {
-    List<int> c_lc = [0, 0];
-    int ie = input.offset + (ni + 7) ~/ 8; // input byte size
-    int oi = 0;
-
-    // Loop on input bytes
-
-    while (input.offset < ie) {
-      getChar(c_lc, input);
-
-      // Access decoding table
-      while (c_lc[1] >= HUF_DECBITS) {
-        ExrHufDec pl = hdecod[(c_lc[0] >> (c_lc[1] - HUF_DECBITS)) & HUF_DECMASK];
-
-        if (pl.len != 0) {
-          // Get short code
-          c_lc[1] -= pl.len;
-          oi = getCode(pl.lit, rlc, c_lc, input, out, oi, no);
-        } else {
-          if (pl.p == null) {
-            throw new ImageException("Error in Huffman-encoded data "
-                                     "(invalid code).");
-          }
-
-          // Search long code
-          int j;
-          for (j = 0; j < pl.lit; j++) {
-            int l = hufLength(hcode[pl.p[j]]);
-
-            while (c_lc[1] < l && input.offset < ie) { // get more bits
-              getChar(c_lc, input);
-            }
-
-            if (c_lc[1] >= l) {
-              if (hufCode(hcode[pl.p[j]]) ==
-                  ((c_lc[0] >> (c_lc[1] - l)) & ((1 << l) - 1))) {
-                // Found : get long code
-                c_lc[1] -= l;
-                oi = getCode(pl.p[j], rlc, c_lc, input, out, oi, no);
-                break;
-              }
-            }
-          }
-
-          if (j == pl.lit) {
-            throw new ImageException("Error in Huffman-encoded data "
-                                     "(invalid code).");
-          }
-        }
-      }
-    }
-
-    // Get remaining (short) codes
-    int i = (8 - ni) & 7;
-    c_lc[0] >>= i;
-    c_lc[1] -= i;
-
-    while (c_lc[1] > 0) {
-      ExrHufDec pl = hdecod[(c_lc[0] << (HUF_DECBITS - c_lc[1])) & HUF_DECMASK];
-
-      if (pl.len != 0) {
-        c_lc[1] -= pl.len;
-        oi = getCode(pl.lit, rlc, c_lc, input, out, oi, no);
-      } else {
-        throw new ImageException("Error in Huffman-encoded data "
-                                 "(invalid code).");
-      }
-    }
-
-    if (oi != no) {
-      throw new ImageException("Error in Huffman-encoded data "
-                               "(decoded data are shorter than expected).");
-    }
-  }
-
-  static int getCode(int po, int rlc, List<int> c_lc, InputBuffer input,
-                     Uint16List out, int oi, int oe) {
-    if (po == rlc) {
-      if (c_lc[1] < 8) {
-        getChar(c_lc, input);
-      }
-
-      c_lc[1] -= 8;
-
-      int cs = (c_lc[0] >> c_lc[1]) & 0xff;
-
-      if (oi + cs > oe) {
-        throw new ImageException("Error in Huffman-encoded data "
-                                 "(decoded data are longer than expected).");
-      }
-
-      int s = out[oi - 1];
-
-      while (cs-- > 0) {
-        out[oi++] = s;
-      }
-    } else if (oi < oe) {
-      out[oi++] = po;
-    } else {
-      throw new ImageException("Error in Huffman-encoded data "
-                               "(decoded data are longer than expected).");
-    }
-    return oi;
-  }
-
-
-  static void buildDecTable(List<int> hcode, int im, int iM,
-                            List<ExrHufDec> hdecod) {
-    // Init hashtable & loop on all codes.
-    // Assumes that hufClearDecTable(hdecod) has already been called.
-    for (; im <= iM; im++) {
-      int c = hufCode(hcode[im]);
-      int l = hufLength(hcode[im]);
-
-      if (c >> l != 0) {
-        // Error: c is supposed to be an l-bit code,
-        // but c contains a value that is greater
-        // than the largest l-bit number.
-        throw new ImageException("Error in Huffman-encoded data "
-                                 "(invalid code table entry).");
-      }
-
-      if (l > HUF_DECBITS) {
-        // Long code: add a secondary entry
-        ExrHufDec pl = hdecod[(c >> (l - HUF_DECBITS))];
-
-        if (pl.len != 0) {
-          // Error: a short code has already
-          // been stored in table entry *pl.
-          throw new ImageException("Error in Huffman-encoded data "
-                                   "(invalid code table entry).");
-        }
-
-        pl.lit++;
-
-        if (pl.p != null) {
-          List<int> p = pl.p;
-          pl.p = new List<int>(pl.lit);
-
-          for (int i = 0; i < pl.lit - 1; ++i) {
-            pl.p[i] = p[i];
-          }
-        } else {
-          pl.p = [0];
-        }
-
-        pl.p[pl.lit - 1] = im;
-      } else if (l != 0) {
-        // Short code: init all primary entries
-        int pi = (c << (HUF_DECBITS - l));
-        ExrHufDec pl = hdecod[pi];
-
-        for (int i = 1 << (HUF_DECBITS - l); i > 0; i--, pi++) {
-          pl = hdecod[pi];
-          if (pl.len != 0 || pl.p != null) {
-            // Error: a short code or a long code has
-            // already been stored in table entry *pl.
-            throw new ImageException("Error in Huffman-encoded data "
-                                     "(invalid code table entry).");
-          }
-
-          pl.len = l;
-          pl.lit = im;
-        }
-      }
-    }
-  }
-
-  static void unpackEncTable(InputBuffer p, int ni, int im, int iM,
-                             List<int> hcode) {
-    int pcode = p.offset;
-    List<int> c_lc = [0, 0];
-
-    for (; im <= iM; im++) {
-      if (p.offset - pcode > ni) {
-        throw new ImageException("Error in Huffman-encoded data "
-                                 "(unexpected end of code table data).");
-      }
-
-      int l = hcode[im] = getBits(6, c_lc, p); // code length
-
-      if (l == LONG_ZEROCODE_RUN) {
-        if (p.offset - pcode > ni) {
-          throw new ImageException("Error in Huffman-encoded data "
-                                   "(unexpected end of code table data).");
-        }
-
-        int zerun = getBits(8, c_lc, p) + SHORTEST_LONG_RUN;
-
-        if (im + zerun > iM + 1) {
-          throw new ImageException("Error in Huffman-encoded data "
-                                   "(code table is longer than expected).");
-        }
-
-        while (zerun-- != 0) {
-          hcode[im++] = 0;
-        }
-
-        im--;
-      } else if (l >= SHORT_ZEROCODE_RUN) {
-        int zerun = l - SHORT_ZEROCODE_RUN + 2;
-
-        if (im + zerun > iM + 1) {
-          throw new ImageException("Error in Huffman-encoded data "
-                                   "(code table is longer than expected).");
-        }
-
-        while (zerun-- != 0) {
-          hcode[im++] = 0;
-        }
-
-        im--;
-      }
-    }
-
-    canonicalCodeTable(hcode);
-  }
-
-  static int hufLength(int code) => code & 63;
-
-  static int hufCode(int code) => code >> 6;
-
-  static void canonicalCodeTable(List<int> hcode) {
-    List<int> n = new List<int>(59);
-    n.fillRange(0, 59, 0);
-
-    // For each i from 0 through 58, count the
-    // number of different codes of length i, and
-    // store the count in n[i].
-
-    for (int i = 0; i < HUF_ENCSIZE; ++i) {
-      n[hcode[i]] += 1;
-    }
-
-    // For each i from 58 through 1, compute the
-    // numerically lowest code with length i, and
-    // store that code in n[i].
-
-    int c = 0;
-
-    for (int i = 58; i > 0; --i) {
-      int nc = ((c + n[i]) >> 1);
-      n[i] = c;
-      c = nc;
-    }
-
-    // hcode[i] contains the length, l, of the
-    // code for symbol i.  Assign the next available
-    // code of length l to the symbol and store both
-    // l and the code in hcode[i].
-
-    for (int i = 0; i < HUF_ENCSIZE; ++i) {
-      int l = hcode[i];
-      if (l > 0) {
-        hcode[i] = l | (n[l]++ << 6);
-      }
-    }
-  }
-
-  static void getChar(List<int> c_lc, InputBuffer input) {
-    c_lc[0] = ((c_lc[0] << 8) | input.readByte()) & MASK_64;
-    c_lc[1] = (c_lc[1] + 8) & MASK_32;
-  }
-
-  static int getBits(int nBits, List<int> c_lc, InputBuffer input) {
-    while (c_lc[1] < nBits) {
-      c_lc[0] = ((c_lc[0] << 8) | input.readByte()) & MASK_64;
-      c_lc[1] = (c_lc[1] + 8) & MASK_32;
-    }
-
-    c_lc[1] -= nBits;
-
-    return (c_lc[0] >> c_lc[1]) & ((1 << nBits) - 1);
-  }
-
-  static const int MASK_32 = (1 << 32) - 1;
-  static const int MASK_64 = (1 << 64) - 1;
-  static const int HUF_ENCBITS = 16;     // literal (value) bit length
-  static const int HUF_DECBITS = 14;     // decoding bit size (>= 8)
-
-  static const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1; // encoding table size
-  static const int HUF_DECSIZE =  1 << HUF_DECBITS;  // decoding table size
-  static const int HUF_DECMASK = HUF_DECSIZE - 1;
-
-  static const int SHORT_ZEROCODE_RUN = 59;
-  static const int LONG_ZEROCODE_RUN = 63;
-  static const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
-  static const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN;
-}
-
-class ExrHufDec {
-  int len = 0;
-  int lit = 0;
-  List<int> p;
-}
+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+

+class ExrHuffman {

+  static void uncompress(InputBuffer compressed, int nCompressed,

+                         Uint16List raw, int nRaw) {

+    if (nCompressed == 0) {

+      if (nRaw != 0) {

+        throw new ImageException('Incomplete huffman data');

+      }

+

+      return;

+    }

+

+    int start = compressed.offset;

+

+    int im = compressed.readUint32();

+    int iM = compressed.readUint32();

+    compressed.skip(4); // tableLength

+    int nBits = compressed.readUint32();

+

+    if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) {

+      throw new ImageException('Invalid huffman table size');

+    }

+

+    compressed.skip(4);

+

+    List<int> freq = List<int>(HUF_ENCSIZE);

+    freq.fillRange(0, HUF_ENCSIZE, 0);

+

+    List<ExrHufDec> hdec = List<ExrHufDec>(HUF_DECSIZE);

+    for (int i = 0; i < HUF_DECSIZE; ++i) {

+      hdec[i] = ExrHufDec();

+    }

+

+    unpackEncTable(compressed, nCompressed - 20, im, iM, freq);

+

+    if (nBits > 8 * (nCompressed - (compressed.offset - start))) {

+      throw new ImageException("Error in header for Huffman-encoded data "

+                               "(invalid number of bits).");

+    }

+

+    buildDecTable(freq, im, iM, hdec);

+    decode(freq, hdec, compressed, nBits, iM, nRaw, raw);

+  }

+

+  static void decode(List<int> hcode, List<ExrHufDec> hdecod,

+                     InputBuffer input, int ni, int rlc, int no,

+                     Uint16List out) {

+    List<int> c_lc = [0, 0];

+    int ie = input.offset + (ni + 7) ~/ 8; // input byte size

+    int oi = 0;

+

+    // Loop on input bytes

+

+    while (input.offset < ie) {

+      getChar(c_lc, input);

+

+      // Access decoding table

+      while (c_lc[1] >= HUF_DECBITS) {

+        ExrHufDec pl = hdecod[(c_lc[0] >> (c_lc[1] - HUF_DECBITS)) & HUF_DECMASK];

+

+        if (pl.len != 0) {

+          // Get short code

+          c_lc[1] -= pl.len;

+          oi = getCode(pl.lit, rlc, c_lc, input, out, oi, no);

+        } else {

+          if (pl.p == null) {

+            throw new ImageException("Error in Huffman-encoded data "

+                                     "(invalid code).");

+          }

+

+          // Search long code

+          int j;

+          for (j = 0; j < pl.lit; j++) {

+            int l = hufLength(hcode[pl.p[j]]);

+

+            while (c_lc[1] < l && input.offset < ie) { // get more bits

+              getChar(c_lc, input);

+            }

+

+            if (c_lc[1] >= l) {

+              if (hufCode(hcode[pl.p[j]]) ==

+                  ((c_lc[0] >> (c_lc[1] - l)) & ((1 << l) - 1))) {

+                // Found : get long code

+                c_lc[1] -= l;

+                oi = getCode(pl.p[j], rlc, c_lc, input, out, oi, no);

+                break;

+              }

+            }

+          }

+

+          if (j == pl.lit) {

+            throw new ImageException("Error in Huffman-encoded data "

+                                     "(invalid code).");

+          }

+        }

+      }

+    }

+

+    // Get remaining (short) codes

+    int i = (8 - ni) & 7;

+    c_lc[0] >>= i;

+    c_lc[1] -= i;

+

+    while (c_lc[1] > 0) {

+      ExrHufDec pl = hdecod[(c_lc[0] << (HUF_DECBITS - c_lc[1])) & HUF_DECMASK];

+

+      if (pl.len != 0) {

+        c_lc[1] -= pl.len;

+        oi = getCode(pl.lit, rlc, c_lc, input, out, oi, no);

+      } else {

+        throw new ImageException("Error in Huffman-encoded data "

+                                 "(invalid code).");

+      }

+    }

+

+    if (oi != no) {

+      throw new ImageException("Error in Huffman-encoded data "

+                               "(decoded data are shorter than expected).");

+    }

+  }

+

+  static int getCode(int po, int rlc, List<int> c_lc, InputBuffer input,

+                     Uint16List out, int oi, int oe) {

+    if (po == rlc) {

+      if (c_lc[1] < 8) {

+        getChar(c_lc, input);

+      }

+

+      c_lc[1] -= 8;

+

+      int cs = (c_lc[0] >> c_lc[1]) & 0xff;

+

+      if (oi + cs > oe) {

+        throw new ImageException("Error in Huffman-encoded data "

+                                 "(decoded data are longer than expected).");

+      }

+

+      int s = out[oi - 1];

+

+      while (cs-- > 0) {

+        out[oi++] = s;

+      }

+    } else if (oi < oe) {

+      out[oi++] = po;

+    } else {

+      throw new ImageException("Error in Huffman-encoded data "

+                               "(decoded data are longer than expected).");

+    }

+    return oi;

+  }

+

+

+  static void buildDecTable(List<int> hcode, int im, int iM,

+                            List<ExrHufDec> hdecod) {

+    // Init hashtable & loop on all codes.

+    // Assumes that hufClearDecTable(hdecod) has already been called.

+    for (; im <= iM; im++) {

+      int c = hufCode(hcode[im]);

+      int l = hufLength(hcode[im]);

+

+      if (c >> l != 0) {

+        // Error: c is supposed to be an l-bit code,

+        // but c contains a value that is greater

+        // than the largest l-bit number.

+        throw new ImageException("Error in Huffman-encoded data "

+                                 "(invalid code table entry).");

+      }

+

+      if (l > HUF_DECBITS) {

+        // Long code: add a secondary entry

+        ExrHufDec pl = hdecod[(c >> (l - HUF_DECBITS))];

+

+        if (pl.len != 0) {

+          // Error: a short code has already

+          // been stored in table entry *pl.

+          throw new ImageException("Error in Huffman-encoded data "

+                                   "(invalid code table entry).");

+        }

+

+        pl.lit++;

+

+        if (pl.p != null) {

+          List<int> p = pl.p;

+          pl.p = List<int>(pl.lit);

+

+          for (int i = 0; i < pl.lit - 1; ++i) {

+            pl.p[i] = p[i];

+          }

+        } else {

+          pl.p = [0];

+        }

+

+        pl.p[pl.lit - 1] = im;

+      } else if (l != 0) {

+        // Short code: init all primary entries

+        int pi = (c << (HUF_DECBITS - l));

+        ExrHufDec pl = hdecod[pi];

+

+        for (int i = 1 << (HUF_DECBITS - l); i > 0; i--, pi++) {

+          pl = hdecod[pi];

+          if (pl.len != 0 || pl.p != null) {

+            // Error: a short code or a long code has

+            // already been stored in table entry *pl.

+            throw new ImageException("Error in Huffman-encoded data "

+                                     "(invalid code table entry).");

+          }

+

+          pl.len = l;

+          pl.lit = im;

+        }

+      }

+    }

+  }

+

+  static void unpackEncTable(InputBuffer p, int ni, int im, int iM,

+                             List<int> hcode) {

+    int pcode = p.offset;

+    List<int> c_lc = [0, 0];

+

+    for (; im <= iM; im++) {

+      if (p.offset - pcode > ni) {

+        throw new ImageException("Error in Huffman-encoded data "

+                                 "(unexpected end of code table data).");

+      }

+

+      int l = hcode[im] = getBits(6, c_lc, p); // code length

+

+      if (l == LONG_ZEROCODE_RUN) {

+        if (p.offset - pcode > ni) {

+          throw new ImageException("Error in Huffman-encoded data "

+                                   "(unexpected end of code table data).");

+        }

+

+        int zerun = getBits(8, c_lc, p) + SHORTEST_LONG_RUN;

+

+        if (im + zerun > iM + 1) {

+          throw new ImageException("Error in Huffman-encoded data "

+                                   "(code table is longer than expected).");

+        }

+

+        while (zerun-- != 0) {

+          hcode[im++] = 0;

+        }

+

+        im--;

+      } else if (l >= SHORT_ZEROCODE_RUN) {

+        int zerun = l - SHORT_ZEROCODE_RUN + 2;

+

+        if (im + zerun > iM + 1) {

+          throw new ImageException("Error in Huffman-encoded data "

+                                   "(code table is longer than expected).");

+        }

+

+        while (zerun-- != 0) {

+          hcode[im++] = 0;

+        }

+

+        im--;

+      }

+    }

+

+    canonicalCodeTable(hcode);

+  }

+

+  static int hufLength(int code) => code & 63;

+

+  static int hufCode(int code) => code >> 6;

+

+  static void canonicalCodeTable(List<int> hcode) {

+    List<int> n = List<int>(59);

+    n.fillRange(0, 59, 0);

+

+    // For each i from 0 through 58, count the

+    // number of different codes of length i, and

+    // store the count in n[i].

+

+    for (int i = 0; i < HUF_ENCSIZE; ++i) {

+      n[hcode[i]] += 1;

+    }

+

+    // For each i from 58 through 1, compute the

+    // numerically lowest code with length i, and

+    // store that code in n[i].

+

+    int c = 0;

+

+    for (int i = 58; i > 0; --i) {

+      int nc = ((c + n[i]) >> 1);

+      n[i] = c;

+      c = nc;

+    }

+

+    // hcode[i] contains the length, l, of the

+    // code for symbol i.  Assign the next available

+    // code of length l to the symbol and store both

+    // l and the code in hcode[i].

+

+    for (int i = 0; i < HUF_ENCSIZE; ++i) {

+      int l = hcode[i];

+      if (l > 0) {

+        hcode[i] = l | (n[l]++ << 6);

+      }

+    }

+  }

+

+  static void getChar(List<int> c_lc, InputBuffer input) {

+    c_lc[0] = ((c_lc[0] << 8) | input.readByte()) & MASK_64;

+    c_lc[1] = (c_lc[1] + 8) & MASK_32;

+  }

+

+  static int getBits(int nBits, List<int> c_lc, InputBuffer input) {

+    while (c_lc[1] < nBits) {

+      c_lc[0] = ((c_lc[0] << 8) | input.readByte()) & MASK_64;

+      c_lc[1] = (c_lc[1] + 8) & MASK_32;

+    }

+

+    c_lc[1] -= nBits;

+

+    return (c_lc[0] >> c_lc[1]) & ((1 << nBits) - 1);

+  }

+

+  static const int MASK_32 = (1 << 32) - 1;

+  static const int MASK_64 = (1 << 64) - 1;

+  static const int HUF_ENCBITS = 16;     // literal (value) bit length

+  static const int HUF_DECBITS = 14;     // decoding bit size (>= 8)

+

+  static const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1; // encoding table size

+  static const int HUF_DECSIZE =  1 << HUF_DECBITS;  // decoding table size

+  static const int HUF_DECMASK = HUF_DECSIZE - 1;

+

+  static const int SHORT_ZEROCODE_RUN = 59;

+  static const int LONG_ZEROCODE_RUN = 63;

+  static const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;

+  static const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN;

+}

+

+class ExrHufDec {

+  int len = 0;

+  int lit = 0;

+  List<int> p;

+}

diff --git a/image/lib/src/formats/exr/exr_image.dart b/image/lib/src/formats/exr/exr_image.dart
old mode 100644
new mode 100755
index c250589..4c431e3
--- a/image/lib/src/formats/exr/exr_image.dart
+++ b/image/lib/src/formats/exr/exr_image.dart
@@ -15,7 +15,7 @@
   List<InternalExrPart> _parts = [];

 

   ExrImage(List<int> bytes) {

-    InputBuffer input = new InputBuffer(bytes);

+    InputBuffer input = InputBuffer(bytes);

     int magic = input.readUint32();

     if (magic != MAGIC) {

       throw new ImageException('File is not an OpenEXR image file.');

@@ -33,13 +33,13 @@
     }

 

     if (!_isMultiPart()) {

-      ExrPart part = new InternalExrPart(_isTiled(), input);

+      ExrPart part = InternalExrPart(_isTiled(), input);

       if (part.isValid) {

         _parts.add(part);

       }

     } else {

       while (true) {

-        ExrPart part = new InternalExrPart(_isTiled(), input);

+        ExrPart part = InternalExrPart(_isTiled(), input);

         if (!part.isValid) {

           break;

         }

@@ -66,7 +66,7 @@
    * Parse just enough of the file to identify that it's an EXR image.

    */

   static bool isValidFile(List<int> bytes) {

-    InputBuffer input = new InputBuffer(bytes);

+    InputBuffer input = InputBuffer(bytes);

 

     int magic = input.readUint32();

     if (magic != MAGIC) {

@@ -137,9 +137,9 @@
     HdrImage framebuffer = part.framebuffer;

     ExrCompressor compressor = part.compressor;

     List<Uint32List> offsets = part.offsets;

-    //Uint32List fbi = new Uint32List(part.channels.length);

+    //Uint32List fbi = Uint32List(part.channels.length);

 

-    InputBuffer imgData = new InputBuffer.from(input);

+    InputBuffer imgData = InputBuffer.from(input);

     for (int ly = 0, l = 0; ly < part.numYLevels; ++ly) {

       for (int lx = 0; lx < part.numXLevels; ++lx, ++l) {

         for (int ty = 0, oi = 0; ty < part.numYTiles[ly]; ++ty) {

@@ -234,13 +234,13 @@
     //int minY = part.top;

     //int maxY = minY + part.linesInBuffer - 1;

 

-    Uint32List fbi = new Uint32List(part.channels.length);

+    Uint32List fbi = Uint32List(part.channels.length);

     //int total = 0;

 

     //int xx = 0;

     int yy = 0;

 

-    InputBuffer imgData = new InputBuffer.from(input);

+    InputBuffer imgData = InputBuffer.from(input);

     for (int offset in offsets) {

       imgData.offset = offset;

 

diff --git a/image/lib/src/formats/exr/exr_part.dart b/image/lib/src/formats/exr/exr_part.dart
old mode 100644
new mode 100755
index 0917076..e0d7416
--- a/image/lib/src/formats/exr/exr_part.dart
+++ b/image/lib/src/formats/exr/exr_part.dart
@@ -1,384 +1,384 @@
-import 'dart:math' as Math;
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../internal/internal.dart';
-import '../../hdr/hdr_image.dart';
-import '../../util/input_buffer.dart';
-import 'exr_attribute.dart';
-import 'exr_channel.dart';
-import 'exr_compressor.dart';
-
-class ExrPart {
-  /// The framebuffer for this exr part.
-  HdrImage framebuffer = new HdrImage();
-  /// The channels present in this part.
-  List<ExrChannel> channels = [];
-  /// The extra attributes read from the part header.
-  Map<String, ExrAttribute> attributes = {};
-  /// The display window (see the openexr documentation).
-  List<int> displayWindow;
-  /// The data window (see the openexr documentation).
-  List<int> dataWindow;
-  /// width of the data window
-  int width;
-  /// Height of the data window
-  int height;
-  double pixelAspectRatio = 1.0;
-  double screenWindowCenterX = 0.0;
-  double screenWindowCenterY = 0.0;
-  double screenWindowWidth = 1.0;
-  Float32List chromaticities;
-
-  ExrPart(this._tiled, InputBuffer input) {
-    //_type = _tiled ? ExrPart.TYPE_TILE : ExrPart.TYPE_SCANLINE;
-
-    while (true) {
-      String name = input.readString();
-      if (name == null || name.isEmpty) {
-        break;
-      }
-
-      String type = input.readString();
-      int size = input.readUint32();
-      InputBuffer value = input.readBytes(size);
-
-      attributes[name] = new ExrAttribute(name, type, size, value);
-
-      switch (name) {
-        case 'channels':
-          while (true) {
-            ExrChannel channel = new ExrChannel(value);
-            if (!channel.isValid) {
-              break;
-            }
-            channels.add(channel);
-          }
-          break;
-        case 'chromaticities':
-          chromaticities = new Float32List(8);
-          chromaticities[0] = value.readFloat32();
-          chromaticities[1] = value.readFloat32();
-          chromaticities[2] = value.readFloat32();
-          chromaticities[3] = value.readFloat32();
-          chromaticities[4] = value.readFloat32();
-          chromaticities[5] = value.readFloat32();
-          chromaticities[6] = value.readFloat32();
-          chromaticities[7] = value.readFloat32();
-          break;
-        case 'compression':
-          _compressionType = value.readByte();
-          if (_compressionType > 7) {
-            throw new ImageException('EXR Invalid compression type');
-          }
-          break;
-        case 'dataWindow':
-          dataWindow = [value.readInt32(), value.readInt32(),
-                        value.readInt32(), value.readInt32()];
-          width = (dataWindow[2] - dataWindow[0]) + 1;
-          height = (dataWindow[3] - dataWindow[1]) + 1;
-          break;
-        case 'displayWindow':
-          displayWindow = [value.readInt32(), value.readInt32(),
-                           value.readInt32(), value.readInt32()];
-          break;
-        case 'lineOrder':
-          //_lineOrder = value.readByte();
-          break;
-        case 'pixelAspectRatio':
-          pixelAspectRatio = value.readFloat32();
-          break;
-        case 'screenWindowCenter':
-          screenWindowCenterX = value.readFloat32();
-          screenWindowCenterY = value.readFloat32();
-          break;
-        case 'screenWindowWidth':
-          screenWindowWidth = value.readFloat32();
-          break;
-        case 'tiles':
-          _tileWidth = value.readUint32();
-          _tileHeight = value.readUint32();
-          int mode = value.readByte();
-          _tileLevelMode = mode & 0xf;
-          _tileRoundingMode = (mode >> 4) & 0xf;
-          break;
-        case 'type':
-          String s = value.readString();
-          if (s == 'deepscanline') {
-            //this._type = TYPE_DEEP_SCANLINE;
-          } else if (s == 'deeptile') {
-            //this._type = TYPE_DEEP_TILE;
-          } else {
-            throw new ImageException('EXR Invalid type: $s');
-          }
-          break;
-        default:
-          break;
-      }
-    }
-
-    if (_tiled) {
-      _numXLevels = _calculateNumXLevels(left, right, top, bottom);
-      _numYLevels = _calculateNumYLevels(left, right, top, bottom);
-      if (_tileLevelMode != RIPMAP_LEVELS) {
-        _numYLevels = 1;
-      }
-
-      _numXTiles = new List<int>(_numXLevels);
-      _numYTiles = new List<int>(_numYLevels);
-
-      _calculateNumTiles(_numXTiles, _numXLevels, left, right, _tileWidth,
-                         _tileRoundingMode);
-
-      _calculateNumTiles(_numYTiles, _numYLevels, top, bottom, _tileHeight,
-                         _tileRoundingMode);
-
-      _bytesPerPixel = _calculateBytesPerPixel();
-      _maxBytesPerTileLine = _bytesPerPixel * _tileWidth;
-      //_tileBufferSize = _maxBytesPerTileLine * _tileHeight;
-
-      _compressor = new ExrCompressor(_compressionType, this,
-                                      _maxBytesPerTileLine, _tileHeight);
-
-      _offsets = new List<Uint32List>(_numXLevels * _numYLevels);
-      for (int ly = 0, l = 0; ly < _numYLevels; ++ly) {
-        for (int lx = 0; lx < _numXLevels; ++lx, ++l) {
-          _offsets[l] = new Uint32List(_numXTiles[lx] * _numYTiles[ly]);
-        }
-      }
-    } else {
-      _bytesPerLine = new Uint32List(height + 1);
-      for (ExrChannel ch in channels) {
-        int nBytes = ch.size * width ~/ ch.xSampling;
-        for (int y = 0; y < height; ++y) {
-          if ((y + top) % ch.ySampling == 0) {
-            _bytesPerLine[y] += nBytes;
-          }
-        }
-      }
-
-      int maxBytesPerLine = 0;
-      for (int y = 0; y < height; ++y) {
-        maxBytesPerLine = Math.max(maxBytesPerLine, _bytesPerLine[y]);
-      }
-
-      _compressor = new ExrCompressor(_compressionType, this, maxBytesPerLine);
-
-      _linesInBuffer = _compressor.numScanLines();
-      //_lineBufferSize = maxBytesPerLine * _linesInBuffer;
-
-      _offsetInLineBuffer = new Uint32List(_bytesPerLine.length);
-
-      int offset = 0;
-      for (int i = 0; i <= _bytesPerLine.length - 1; ++i) {
-        if (i % _linesInBuffer == 0) {
-          offset = 0;
-        }
-        _offsetInLineBuffer[i] = offset;
-        offset += _bytesPerLine[i];
-      }
-
-      int numOffsets = ((height + _linesInBuffer) ~/ _linesInBuffer) - 1;
-      _offsets = [new Uint32List(numOffsets)];
-    }
-  }
-
-  int get left => dataWindow[0];
-
-  int get top => dataWindow[1];
-
-  int get right => dataWindow[2];
-
-  int get bottom => dataWindow[3];
-
-  /**
-   * Was this part successfully decoded?
-   */
-  bool get isValid => width != null;
-
-  int _calculateNumXLevels(int minX, int maxX, int minY, int maxY) {
-    int num = 0;
-
-    switch (_tileLevelMode) {
-      case ONE_LEVEL:
-        num = 1;
-        break;
-      case MIPMAP_LEVELS:
-        int w = maxX - minX + 1;
-        int h = maxY - minY + 1;
-        num = _roundLog2(Math.max(w, h), _tileRoundingMode) + 1;
-        break;
-      case RIPMAP_LEVELS:
-        int w = maxX - minX + 1;
-        num = _roundLog2(w, _tileRoundingMode) + 1;
-        break;
-      default:
-        throw new ImageException("Unknown LevelMode format.");
-    }
-
-    return num;
-  }
-
-
-  int _calculateNumYLevels(int minX, int maxX, int minY, int maxY) {
-    int num = 0;
-
-    switch (_tileLevelMode) {
-      case ONE_LEVEL:
-        num = 1;
-        break;
-      case MIPMAP_LEVELS:
-        int w = (maxX - minX) + 1;
-        int h = (maxY - minY) + 1;
-        num = _roundLog2(Math.max(w, h), _tileRoundingMode) + 1;
-        break;
-      case RIPMAP_LEVELS:
-        int h = (maxY - minY) + 1;
-        num = _roundLog2(h, _tileRoundingMode) + 1;
-        break;
-      default:
-        throw new ImageException('Unknown LevelMode format.');
-    }
-
-    return num;
-  }
-
-  int _roundLog2(int x, int rmode) {
-    return (rmode == ROUND_DOWN) ? _floorLog2(x) : _ceilLog2(x);
-  }
-
-  int _floorLog2(int x) {
-    int y = 0;
-
-    while (x > 1) {
-      y +=  1;
-      x >>= 1;
-    }
-
-    return y;
-  }
-
-
-  int _ceilLog2(int x) {
-    int y = 0;
-    int r = 0;
-
-    while (x > 1) {
-      if (x & 1 != 0) {
-        r = 1;
-      }
-
-      y +=  1;
-      x >>= 1;
-    }
-
-    return y + r;
-  }
-
-  int _calculateBytesPerPixel() {
-    int bytesPerPixel = 0;
-
-    for (ExrChannel ch in channels) {
-      bytesPerPixel += ch.size;
-    }
-
-    return bytesPerPixel;
-  }
-
-  void _calculateNumTiles(List<int> numTiles, int numLevels,
-                          int min, int max, int size, int rmode) {
-    for (int i = 0; i < numLevels; i++) {
-      numTiles[i] = (_levelSize(min, max, i, rmode) + size - 1) ~/ size;
-    }
-  }
-
-  int _levelSize(int min, int max, int l, int rmode) {
-    if (l < 0) {
-      throw new ImageException('Argument not in valid range.');
-    }
-
-    int a = (max - min) + 1;
-    int b = (1 << l);
-    int size = a ~/ b;
-
-    if (rmode == ROUND_UP && size * b < a) {
-      size += 1;
-    }
-
-    return Math.max(size, 1);
-  }
-
-  static const int TYPE_SCANLINE = 0;
-  static const int TYPE_TILE = 1;
-  static const int TYPE_DEEP_SCANLINE = 2;
-  static const int TYPE_DEEP_TILE = 3;
-
-  static const int INCREASING_Y = 0;
-  static const int DECREASING_Y = 1;
-  static const int RANDOM_Y = 2;
-
-  static const int ONE_LEVEL = 0;
-  static const int MIPMAP_LEVELS = 1;
-  static const int RIPMAP_LEVELS = 2;
-
-  static const int ROUND_DOWN = 0;
-  static const int ROUND_UP = 1;
-
-  //int _type;
-  //int _lineOrder = INCREASING_Y;
-  int _compressionType = ExrCompressor.NO_COMPRESSION;
-  List<Uint32List> _offsets;
-
-  Uint32List _bytesPerLine;
-  ExrCompressor _compressor;
-  int _linesInBuffer;
-  //int _lineBufferSize;
-  Uint32List _offsetInLineBuffer;
-
-  bool _tiled;
-  int _tileWidth;
-  int _tileHeight;
-  int _tileLevelMode;
-  int _tileRoundingMode;
-  List<int> _numXTiles;
-  List<int> _numYTiles;
-  int _numXLevels;
-  int _numYLevels;
-  int _bytesPerPixel;
-  int _maxBytesPerTileLine;
-  //int _tileBufferSize;
-}
-
-@internal
-class InternalExrPart extends ExrPart {
-  InternalExrPart(bool tiled, InputBuffer input) : super(tiled, input);
-
-  List<Uint32List> get offsets => _offsets;
-
-  ExrCompressor get compressor => _compressor;
-  int get linesInBuffer => _linesInBuffer;
-  Uint32List get offsetInLineBuffer => _offsetInLineBuffer;
-
-  bool get tiled => _tiled;
-  int get tileWidth => _tileWidth;
-  int get tileHeight => _tileHeight;
-  List<int> get numXTiles => _numXTiles;
-  List<int> get numYTiles => _numYTiles;
-  int get numXLevels => _numXLevels;
-  int get numYLevels => _numYLevels;
-
-  void readOffsets(InputBuffer input) {
-    if (_tiled) {
-      for (int i = 0; i < _offsets.length; ++i) {
-        for (int j = 0; j < _offsets[i].length; ++j) {
-          _offsets[i][j] = input.readUint64();
-        }
-      }
-    } else {
-      int numOffsets = _offsets[0].length;
-      for (int i = 0; i < numOffsets; ++i) {
-        _offsets[0][i] = input.readUint64();
-      }
-    }
-  }
-}
+import 'dart:math' as Math;

+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../internal/internal.dart';

+import '../../hdr/hdr_image.dart';

+import '../../util/input_buffer.dart';

+import 'exr_attribute.dart';

+import 'exr_channel.dart';

+import 'exr_compressor.dart';

+

+class ExrPart {

+  /// The framebuffer for this exr part.

+  HdrImage framebuffer = HdrImage();

+  /// The channels present in this part.

+  List<ExrChannel> channels = [];

+  /// The extra attributes read from the part header.

+  Map<String, ExrAttribute> attributes = {};

+  /// The display window (see the openexr documentation).

+  List<int> displayWindow;

+  /// The data window (see the openexr documentation).

+  List<int> dataWindow;

+  /// width of the data window

+  int width;

+  /// Height of the data window

+  int height;

+  double pixelAspectRatio = 1.0;

+  double screenWindowCenterX = 0.0;

+  double screenWindowCenterY = 0.0;

+  double screenWindowWidth = 1.0;

+  Float32List chromaticities;

+

+  ExrPart(this._tiled, InputBuffer input) {

+    //_type = _tiled ? ExrPart.TYPE_TILE : ExrPart.TYPE_SCANLINE;

+

+    while (true) {

+      String name = input.readString();

+      if (name == null || name.isEmpty) {

+        break;

+      }

+

+      String type = input.readString();

+      int size = input.readUint32();

+      InputBuffer value = input.readBytes(size);

+

+      attributes[name] = ExrAttribute(name, type, size, value);

+

+      switch (name) {

+        case 'channels':

+          while (true) {

+            ExrChannel channel = ExrChannel(value);

+            if (!channel.isValid) {

+              break;

+            }

+            channels.add(channel);

+          }

+          break;

+        case 'chromaticities':

+          chromaticities = Float32List(8);

+          chromaticities[0] = value.readFloat32();

+          chromaticities[1] = value.readFloat32();

+          chromaticities[2] = value.readFloat32();

+          chromaticities[3] = value.readFloat32();

+          chromaticities[4] = value.readFloat32();

+          chromaticities[5] = value.readFloat32();

+          chromaticities[6] = value.readFloat32();

+          chromaticities[7] = value.readFloat32();

+          break;

+        case 'compression':

+          _compressionType = value.readByte();

+          if (_compressionType > 7) {

+            throw new ImageException('EXR Invalid compression type');

+          }

+          break;

+        case 'dataWindow':

+          dataWindow = [value.readInt32(), value.readInt32(),

+                        value.readInt32(), value.readInt32()];

+          width = (dataWindow[2] - dataWindow[0]) + 1;

+          height = (dataWindow[3] - dataWindow[1]) + 1;

+          break;

+        case 'displayWindow':

+          displayWindow = [value.readInt32(), value.readInt32(),

+                           value.readInt32(), value.readInt32()];

+          break;

+        case 'lineOrder':

+          //_lineOrder = value.readByte();

+          break;

+        case 'pixelAspectRatio':

+          pixelAspectRatio = value.readFloat32();

+          break;

+        case 'screenWindowCenter':

+          screenWindowCenterX = value.readFloat32();

+          screenWindowCenterY = value.readFloat32();

+          break;

+        case 'screenWindowWidth':

+          screenWindowWidth = value.readFloat32();

+          break;

+        case 'tiles':

+          _tileWidth = value.readUint32();

+          _tileHeight = value.readUint32();

+          int mode = value.readByte();

+          _tileLevelMode = mode & 0xf;

+          _tileRoundingMode = (mode >> 4) & 0xf;

+          break;

+        case 'type':

+          String s = value.readString();

+          if (s == 'deepscanline') {

+            //this._type = TYPE_DEEP_SCANLINE;

+          } else if (s == 'deeptile') {

+            //this._type = TYPE_DEEP_TILE;

+          } else {

+            throw new ImageException('EXR Invalid type: $s');

+          }

+          break;

+        default:

+          break;

+      }

+    }

+

+    if (_tiled) {

+      _numXLevels = _calculateNumXLevels(left, right, top, bottom);

+      _numYLevels = _calculateNumYLevels(left, right, top, bottom);

+      if (_tileLevelMode != RIPMAP_LEVELS) {

+        _numYLevels = 1;

+      }

+

+      _numXTiles = List<int>(_numXLevels);

+      _numYTiles = List<int>(_numYLevels);

+

+      _calculateNumTiles(_numXTiles, _numXLevels, left, right, _tileWidth,

+                         _tileRoundingMode);

+

+      _calculateNumTiles(_numYTiles, _numYLevels, top, bottom, _tileHeight,

+                         _tileRoundingMode);

+

+      _bytesPerPixel = _calculateBytesPerPixel();

+      _maxBytesPerTileLine = _bytesPerPixel * _tileWidth;

+      //_tileBufferSize = _maxBytesPerTileLine * _tileHeight;

+

+      _compressor = ExrCompressor(_compressionType, this,

+                                      _maxBytesPerTileLine, _tileHeight);

+

+      _offsets = List<Uint32List>(_numXLevels * _numYLevels);

+      for (int ly = 0, l = 0; ly < _numYLevels; ++ly) {

+        for (int lx = 0; lx < _numXLevels; ++lx, ++l) {

+          _offsets[l] = Uint32List(_numXTiles[lx] * _numYTiles[ly]);

+        }

+      }

+    } else {

+      _bytesPerLine = Uint32List(height + 1);

+      for (ExrChannel ch in channels) {

+        int nBytes = ch.size * width ~/ ch.xSampling;

+        for (int y = 0; y < height; ++y) {

+          if ((y + top) % ch.ySampling == 0) {

+            _bytesPerLine[y] += nBytes;

+          }

+        }

+      }

+

+      int maxBytesPerLine = 0;

+      for (int y = 0; y < height; ++y) {

+        maxBytesPerLine = Math.max(maxBytesPerLine, _bytesPerLine[y]);

+      }

+

+      _compressor = ExrCompressor(_compressionType, this, maxBytesPerLine);

+

+      _linesInBuffer = _compressor.numScanLines();

+      //_lineBufferSize = maxBytesPerLine * _linesInBuffer;

+

+      _offsetInLineBuffer = Uint32List(_bytesPerLine.length);

+

+      int offset = 0;

+      for (int i = 0; i <= _bytesPerLine.length - 1; ++i) {

+        if (i % _linesInBuffer == 0) {

+          offset = 0;

+        }

+        _offsetInLineBuffer[i] = offset;

+        offset += _bytesPerLine[i];

+      }

+

+      int numOffsets = ((height + _linesInBuffer) ~/ _linesInBuffer) - 1;

+      _offsets = [new Uint32List(numOffsets)];

+    }

+  }

+

+  int get left => dataWindow[0];

+

+  int get top => dataWindow[1];

+

+  int get right => dataWindow[2];

+

+  int get bottom => dataWindow[3];

+

+  /**

+   * Was this part successfully decoded?

+   */

+  bool get isValid => width != null;

+

+  int _calculateNumXLevels(int minX, int maxX, int minY, int maxY) {

+    int num = 0;

+

+    switch (_tileLevelMode) {

+      case ONE_LEVEL:

+        num = 1;

+        break;

+      case MIPMAP_LEVELS:

+        int w = maxX - minX + 1;

+        int h = maxY - minY + 1;

+        num = _roundLog2(Math.max(w, h), _tileRoundingMode) + 1;

+        break;

+      case RIPMAP_LEVELS:

+        int w = maxX - minX + 1;

+        num = _roundLog2(w, _tileRoundingMode) + 1;

+        break;

+      default:

+        throw new ImageException("Unknown LevelMode format.");

+    }

+

+    return num;

+  }

+

+

+  int _calculateNumYLevels(int minX, int maxX, int minY, int maxY) {

+    int num = 0;

+

+    switch (_tileLevelMode) {

+      case ONE_LEVEL:

+        num = 1;

+        break;

+      case MIPMAP_LEVELS:

+        int w = (maxX - minX) + 1;

+        int h = (maxY - minY) + 1;

+        num = _roundLog2(Math.max(w, h), _tileRoundingMode) + 1;

+        break;

+      case RIPMAP_LEVELS:

+        int h = (maxY - minY) + 1;

+        num = _roundLog2(h, _tileRoundingMode) + 1;

+        break;

+      default:

+        throw new ImageException('Unknown LevelMode format.');

+    }

+

+    return num;

+  }

+

+  int _roundLog2(int x, int rmode) {

+    return (rmode == ROUND_DOWN) ? _floorLog2(x) : _ceilLog2(x);

+  }

+

+  int _floorLog2(int x) {

+    int y = 0;

+

+    while (x > 1) {

+      y +=  1;

+      x >>= 1;

+    }

+

+    return y;

+  }

+

+

+  int _ceilLog2(int x) {

+    int y = 0;

+    int r = 0;

+

+    while (x > 1) {

+      if (x & 1 != 0) {

+        r = 1;

+      }

+

+      y +=  1;

+      x >>= 1;

+    }

+

+    return y + r;

+  }

+

+  int _calculateBytesPerPixel() {

+    int bytesPerPixel = 0;

+

+    for (ExrChannel ch in channels) {

+      bytesPerPixel += ch.size;

+    }

+

+    return bytesPerPixel;

+  }

+

+  void _calculateNumTiles(List<int> numTiles, int numLevels,

+                          int min, int max, int size, int rmode) {

+    for (int i = 0; i < numLevels; i++) {

+      numTiles[i] = (_levelSize(min, max, i, rmode) + size - 1) ~/ size;

+    }

+  }

+

+  int _levelSize(int min, int max, int l, int rmode) {

+    if (l < 0) {

+      throw new ImageException('Argument not in valid range.');

+    }

+

+    int a = (max - min) + 1;

+    int b = (1 << l);

+    int size = a ~/ b;

+

+    if (rmode == ROUND_UP && size * b < a) {

+      size += 1;

+    }

+

+    return Math.max(size, 1);

+  }

+

+  static const int TYPE_SCANLINE = 0;

+  static const int TYPE_TILE = 1;

+  static const int TYPE_DEEP_SCANLINE = 2;

+  static const int TYPE_DEEP_TILE = 3;

+

+  static const int INCREASING_Y = 0;

+  static const int DECREASING_Y = 1;

+  static const int RANDOM_Y = 2;

+

+  static const int ONE_LEVEL = 0;

+  static const int MIPMAP_LEVELS = 1;

+  static const int RIPMAP_LEVELS = 2;

+

+  static const int ROUND_DOWN = 0;

+  static const int ROUND_UP = 1;

+

+  //int _type;

+  //int _lineOrder = INCREASING_Y;

+  int _compressionType = ExrCompressor.NO_COMPRESSION;

+  List<Uint32List> _offsets;

+

+  Uint32List _bytesPerLine;

+  ExrCompressor _compressor;

+  int _linesInBuffer;

+  //int _lineBufferSize;

+  Uint32List _offsetInLineBuffer;

+

+  bool _tiled;

+  int _tileWidth;

+  int _tileHeight;

+  int _tileLevelMode;

+  int _tileRoundingMode;

+  List<int> _numXTiles;

+  List<int> _numYTiles;

+  int _numXLevels;

+  int _numYLevels;

+  int _bytesPerPixel;

+  int _maxBytesPerTileLine;

+  //int _tileBufferSize;

+}

+

+@internal

+class InternalExrPart extends ExrPart {

+  InternalExrPart(bool tiled, InputBuffer input) : super(tiled, input);

+

+  List<Uint32List> get offsets => _offsets;

+

+  ExrCompressor get compressor => _compressor;

+  int get linesInBuffer => _linesInBuffer;

+  Uint32List get offsetInLineBuffer => _offsetInLineBuffer;

+

+  bool get tiled => _tiled;

+  int get tileWidth => _tileWidth;

+  int get tileHeight => _tileHeight;

+  List<int> get numXTiles => _numXTiles;

+  List<int> get numYTiles => _numYTiles;

+  int get numXLevels => _numXLevels;

+  int get numYLevels => _numYLevels;

+

+  void readOffsets(InputBuffer input) {

+    if (_tiled) {

+      for (int i = 0; i < _offsets.length; ++i) {

+        for (int j = 0; j < _offsets[i].length; ++j) {

+          _offsets[i][j] = input.readUint64();

+        }

+      }

+    } else {

+      int numOffsets = _offsets[0].length;

+      for (int i = 0; i < numOffsets; ++i) {

+        _offsets[0][i] = input.readUint64();

+      }

+    }

+  }

+}

diff --git a/image/lib/src/formats/exr/exr_piz_compressor.dart b/image/lib/src/formats/exr/exr_piz_compressor.dart
old mode 100644
new mode 100755
index 198e62f..3de8788
--- a/image/lib/src/formats/exr/exr_piz_compressor.dart
+++ b/image/lib/src/formats/exr/exr_piz_compressor.dart
@@ -1,184 +1,184 @@
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../internal/internal.dart';
-import '../../util/input_buffer.dart';
-import '../../util/output_buffer.dart';
-import 'exr_channel.dart';
-import 'exr_compressor.dart';
-import 'exr_huffman.dart';
-import 'exr_part.dart';
-import 'exr_wavelet.dart';
-
-/**
- * Wavelet compression
- */
-abstract class ExrPizCompressor extends ExrCompressor {
-  factory ExrPizCompressor(ExrPart header, int maxScanLineSize,
-                           int numScanLines) = InternalExrPizCompressor;
-}
-
-@internal
-class InternalExrPizCompressor extends InternalExrCompressor implements ExrPizCompressor {
-  InternalExrPizCompressor(ExrPart header, this._maxScanLineSize, this._numScanLines) :
-    super(header) {
-    _channelData = new List<_PizChannelData>(header.channels.length);
-    for (int i = 0; i < _channelData.length; ++i) {
-      _channelData[i] = new _PizChannelData();
-    }
-
-    int tmpBufferSize = (_maxScanLineSize * _numScanLines) ~/ 2;
-    _tmpBuffer = new Uint16List(tmpBufferSize);
-  }
-
-  int numScanLines() => _numScanLines;
-
-  Uint8List compress(InputBuffer inPtr, int x, int y,
-                     [int width, int height]) {
-    throw new ImageException('Piz compression not yet supported.');
-  }
-
-  Uint8List uncompress(InputBuffer inPtr, int x, int y,
-                       [int width, int height]) {
-    if (width == null) {
-      width = header.width;
-    }
-    if (height == null) {
-      height = header.linesInBuffer;
-    }
-
-    int minX = x;
-    int maxX = x + width - 1;
-    int minY = y;
-    int maxY = y + height - 1;
-
-    if (maxX > header.width) {
-      maxX = header.width - 1;
-    }
-    if (maxY > header.height) {
-      maxY = header.height - 1;
-    }
-
-    decodedWidth = (maxX - minX) + 1;
-    decodedHeight = (maxY - minY) + 1;
-
-    int tmpBufferEnd = 0;
-    List<ExrChannel> channels = header.channels;
-    final int numChannels = channels.length;
-
-    for (int i = 0; i < numChannels; ++i) {
-      ExrChannel ch = channels[i];
-      _PizChannelData cd = _channelData[i];
-      cd.start = tmpBufferEnd;
-      cd.end = cd.start;
-
-      cd.nx = numSamples(ch.xSampling, minX, maxX);
-      cd.ny = numSamples(ch.ySampling, minY, maxY);
-      cd.ys = ch.ySampling;
-
-      cd.size = ch.size ~/ 2; //2=size(HALF)
-
-      tmpBufferEnd += cd.nx * cd.ny * cd.size;
-    }
-
-    int minNonZero = inPtr.readUint16();
-    int maxNonZero = inPtr.readUint16();
-
-    if (maxNonZero >= BITMAP_SIZE) {
-      throw new ImageException("Error in header for PIZ-compressed data "
-                               "(invalid bitmap size).");
-    }
-
-    Uint8List bitmap = new Uint8List(BITMAP_SIZE);
-    if (minNonZero <= maxNonZero) {
-      InputBuffer b = inPtr.readBytes(maxNonZero - minNonZero + 1);
-      for (int i = 0, j = minNonZero, len = b.length; i < len; ++i) {
-        bitmap[j++] = b[i];
-      }
-    }
-
-    Uint16List lut = new Uint16List(USHORT_RANGE);
-    int maxValue = _reverseLutFromBitmap(bitmap, lut);
-
-    // Huffman decoding
-    int length = inPtr.readUint32();
-    ExrHuffman.uncompress(inPtr, length, _tmpBuffer, tmpBufferEnd);
-
-    // Wavelet decoding
-    for (int i = 0; i < numChannels; ++i) {
-      _PizChannelData cd = _channelData[i];
-      for (int j = 0; j < cd.size; ++j) {
-        ExrWavelet.decode(_tmpBuffer, cd.start + j, cd.nx, cd.size, cd.ny,
-                          cd.nx * cd.size, maxValue);
-      }
-    }
-
-    // Expand the pixel data to their original range
-    _applyLut(lut, _tmpBuffer, tmpBufferEnd);
-
-    if (_output == null) {
-      _output = new OutputBuffer(size: (_maxScanLineSize * _numScanLines) +
-                                       (65536 + 8192));
-    }
-    _output.rewind();
-
-    //int count = 0;
-    // Rearrange the pixel data into the format expected by the caller.
-    for (int y = minY; y <= maxY; ++y) {
-      for (int i = 0; i < numChannels; ++i) {
-        _PizChannelData cd = _channelData[i];
-
-        if ((y % cd.ys) != 0) {
-          continue;
-        }
-
-        for (int x = cd.nx * cd.size; x > 0; --x) {
-          _output.writeUint16(_tmpBuffer[cd.end++]);
-        }
-      }
-    }
-
-    return _output.getBytes();
-  }
-
-  void _applyLut(List<int> lut, List<int> data, int nData) {
-    for (int i = 0; i < nData; ++i) {
-      data[i] = lut[data[i]];
-    }
-  }
-
-  int _reverseLutFromBitmap(Uint8List bitmap, Uint16List lut) {
-    int k = 0;
-    for (int i = 0; i < USHORT_RANGE; ++i) {
-      if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7))) != 0) {
-        lut[k++] = i;
-      }
-    }
-
-    int n = k - 1;
-
-    while (k < USHORT_RANGE) {
-      lut[k++] = 0;
-    }
-
-    return n;   // maximum k where lut[k] is non-zero,
-  }
-
-  static const int USHORT_RANGE = 1 << 16;
-  static const int BITMAP_SIZE = 8192;
-
-  OutputBuffer _output;
-  int _maxScanLineSize;
-  int _numScanLines;
-  List<_PizChannelData> _channelData;
-  Uint16List _tmpBuffer;
-}
-
-class _PizChannelData {
-  int start;
-  int end;
-  int nx;
-  int ny;
-  int ys;
-  int size;
-}
+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../internal/internal.dart';

+import '../../util/input_buffer.dart';

+import '../../util/output_buffer.dart';

+import 'exr_channel.dart';

+import 'exr_compressor.dart';

+import 'exr_huffman.dart';

+import 'exr_part.dart';

+import 'exr_wavelet.dart';

+

+/**

+ * Wavelet compression

+ */

+abstract class ExrPizCompressor extends ExrCompressor {

+  factory ExrPizCompressor(ExrPart header, int maxScanLineSize,

+                           int numScanLines) = InternalExrPizCompressor;

+}

+

+@internal

+class InternalExrPizCompressor extends InternalExrCompressor implements ExrPizCompressor {

+  InternalExrPizCompressor(ExrPart header, this._maxScanLineSize, this._numScanLines) :

+    super(header) {

+    _channelData = List<_PizChannelData>(header.channels.length);

+    for (int i = 0; i < _channelData.length; ++i) {

+      _channelData[i] = _PizChannelData();

+    }

+

+    int tmpBufferSize = (_maxScanLineSize * _numScanLines) ~/ 2;

+    _tmpBuffer = Uint16List(tmpBufferSize);

+  }

+

+  int numScanLines() => _numScanLines;

+

+  Uint8List compress(InputBuffer inPtr, int x, int y,

+                     [int width, int height]) {

+    throw new ImageException('Piz compression not yet supported.');

+  }

+

+  Uint8List uncompress(InputBuffer inPtr, int x, int y,

+                       [int width, int height]) {

+    if (width == null) {

+      width = header.width;

+    }

+    if (height == null) {

+      height = header.linesInBuffer;

+    }

+

+    int minX = x;

+    int maxX = x + width - 1;

+    int minY = y;

+    int maxY = y + height - 1;

+

+    if (maxX > header.width) {

+      maxX = header.width - 1;

+    }

+    if (maxY > header.height) {

+      maxY = header.height - 1;

+    }

+

+    decodedWidth = (maxX - minX) + 1;

+    decodedHeight = (maxY - minY) + 1;

+

+    int tmpBufferEnd = 0;

+    List<ExrChannel> channels = header.channels;

+    final int numChannels = channels.length;

+

+    for (int i = 0; i < numChannels; ++i) {

+      ExrChannel ch = channels[i];

+      _PizChannelData cd = _channelData[i];

+      cd.start = tmpBufferEnd;

+      cd.end = cd.start;

+

+      cd.nx = numSamples(ch.xSampling, minX, maxX);

+      cd.ny = numSamples(ch.ySampling, minY, maxY);

+      cd.ys = ch.ySampling;

+

+      cd.size = ch.size ~/ 2; //2=size(HALF)

+

+      tmpBufferEnd += cd.nx * cd.ny * cd.size;

+    }

+

+    int minNonZero = inPtr.readUint16();

+    int maxNonZero = inPtr.readUint16();

+

+    if (maxNonZero >= BITMAP_SIZE) {

+      throw new ImageException("Error in header for PIZ-compressed data "

+                               "(invalid bitmap size).");

+    }

+

+    Uint8List bitmap = Uint8List(BITMAP_SIZE);

+    if (minNonZero <= maxNonZero) {

+      InputBuffer b = inPtr.readBytes(maxNonZero - minNonZero + 1);

+      for (int i = 0, j = minNonZero, len = b.length; i < len; ++i) {

+        bitmap[j++] = b[i];

+      }

+    }

+

+    Uint16List lut = Uint16List(USHORT_RANGE);

+    int maxValue = _reverseLutFromBitmap(bitmap, lut);

+

+    // Huffman decoding

+    int length = inPtr.readUint32();

+    ExrHuffman.uncompress(inPtr, length, _tmpBuffer, tmpBufferEnd);

+

+    // Wavelet decoding

+    for (int i = 0; i < numChannels; ++i) {

+      _PizChannelData cd = _channelData[i];

+      for (int j = 0; j < cd.size; ++j) {

+        ExrWavelet.decode(_tmpBuffer, cd.start + j, cd.nx, cd.size, cd.ny,

+                          cd.nx * cd.size, maxValue);

+      }

+    }

+

+    // Expand the pixel data to their original range

+    _applyLut(lut, _tmpBuffer, tmpBufferEnd);

+

+    if (_output == null) {

+      _output = OutputBuffer(size: (_maxScanLineSize * _numScanLines) +

+                                       (65536 + 8192));

+    }

+    _output.rewind();

+

+    //int count = 0;

+    // Rearrange the pixel data into the format expected by the caller.

+    for (int y = minY; y <= maxY; ++y) {

+      for (int i = 0; i < numChannels; ++i) {

+        _PizChannelData cd = _channelData[i];

+

+        if ((y % cd.ys) != 0) {

+          continue;

+        }

+

+        for (int x = cd.nx * cd.size; x > 0; --x) {

+          _output.writeUint16(_tmpBuffer[cd.end++]);

+        }

+      }

+    }

+

+    return _output.getBytes();

+  }

+

+  void _applyLut(List<int> lut, List<int> data, int nData) {

+    for (int i = 0; i < nData; ++i) {

+      data[i] = lut[data[i]];

+    }

+  }

+

+  int _reverseLutFromBitmap(Uint8List bitmap, Uint16List lut) {

+    int k = 0;

+    for (int i = 0; i < USHORT_RANGE; ++i) {

+      if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7))) != 0) {

+        lut[k++] = i;

+      }

+    }

+

+    int n = k - 1;

+

+    while (k < USHORT_RANGE) {

+      lut[k++] = 0;

+    }

+

+    return n;   // maximum k where lut[k] is non-zero,

+  }

+

+  static const int USHORT_RANGE = 1 << 16;

+  static const int BITMAP_SIZE = 8192;

+

+  OutputBuffer _output;

+  int _maxScanLineSize;

+  int _numScanLines;

+  List<_PizChannelData> _channelData;

+  Uint16List _tmpBuffer;

+}

+

+class _PizChannelData {

+  int start;

+  int end;

+  int nx;

+  int ny;

+  int ys;

+  int size;

+}

diff --git a/image/lib/src/formats/exr/exr_pxr24_compressor.dart b/image/lib/src/formats/exr/exr_pxr24_compressor.dart
old mode 100644
new mode 100755
index 6aafd0b..b3cd998
--- a/image/lib/src/formats/exr/exr_pxr24_compressor.dart
+++ b/image/lib/src/formats/exr/exr_pxr24_compressor.dart
@@ -1,135 +1,135 @@
-import 'dart:typed_data';
-
-import 'package:archive/archive.dart';
-
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-import '../../util/output_buffer.dart';
-import 'exr_channel.dart';
-import 'exr_compressor.dart';
-import 'exr_part.dart';
-
-abstract class ExrPxr24Compressor extends ExrCompressor {
-  factory ExrPxr24Compressor(ExrPart header, int maxScanLineSize,
-                             int numScanLines) = InternalExrPxr24Compressor;
-}
-
-class InternalExrPxr24Compressor extends InternalExrCompressor implements ExrPxr24Compressor {
-  InternalExrPxr24Compressor(ExrPart header, this._maxScanLineSize, this._numScanLines) :
-    super(header) {
-  }
-
-  int numScanLines() => _numScanLines;
-
-  Uint8List compress(InputBuffer inPtr, int x, int y,
-                     [int width, int height]) {
-    throw new ImageException('Pxr24 compression not yet supported.');
-  }
-
-  Uint8List uncompress(InputBuffer inPtr, int x, int y,
-                       [int width, int height]) {
-    List<int> data = _zlib.decodeBytes(inPtr.toUint8List());
-    if (data == null) {
-      throw new ImageException('Error decoding pxr24 compressed data');
-    }
-
-    if (_output == null) {
-      _output = new OutputBuffer(size: _numScanLines * _maxScanLineSize);
-    }
-    _output.rewind();
-
-    int tmpEnd = 0;
-    List<int> ptr = [0, 0, 0, 0];
-    Uint32List pixel = new Uint32List(1);
-    Uint8List pixelBytes = new Uint8List.view(pixel.buffer);
-
-    if (width == null) {
-      width = header.width;
-    }
-    if (height == null) {
-      height = header.linesInBuffer;
-    }
-
-    int minX = x;
-    int maxX = x + width - 1;
-    int minY = y;
-    int maxY = y + height - 1;
-
-    if (maxX > header.width) {
-      maxX = header.width - 1;
-    }
-    if (maxY > header.height) {
-      maxY = header.height - 1;
-    }
-
-    decodedWidth = (maxX - minX) + 1;
-    decodedHeight = (maxY - minY) + 1;
-
-    int numChannels = header.channels.length;
-    for (int yi = minY; yi <= maxY; ++yi) {
-
-      for (int ci = 0; ci < numChannels; ++ci) {
-        ExrChannel ch = header.channels[ci];
-        if ((y % ch.ySampling) != 0) {
-          continue;
-        }
-
-        int n = numSamples(ch.xSampling, minX, maxX);
-        pixel[0] = 0;
-
-        switch (ch.type) {
-          case ExrChannel.TYPE_UINT:
-            ptr[0] = tmpEnd;
-            ptr[1] = ptr[0] + n;
-            ptr[2] = ptr[1] + n;
-            tmpEnd = ptr[2] + n;
-            for (int j = 0; j < n; ++j) {
-              int diff = (data[ptr[0]++] << 24) |
-                         (data[ptr[1]++] << 16) |
-                         (data[ptr[2]++] << 8);
-              pixel[0] += diff;
-              for (int k = 0; k < 4; ++k) {
-                _output.writeByte(pixelBytes[k]);
-              }
-            }
-            break;
-          case ExrChannel.TYPE_HALF:
-            ptr[0] = tmpEnd;
-            ptr[1] = ptr[0] + n;
-            tmpEnd = ptr[1] + n;
-            for (int j = 0; j < n; ++j) {
-              int diff = (data[ptr[0]++] << 8) | data[ptr[1]++];
-              pixel[0] += diff;
-
-              for (int k = 0; k < 2; ++k) {
-                _output.writeByte(pixelBytes[k]);
-              }
-            }
-            break;
-          case ExrChannel.TYPE_FLOAT:
-            ptr[0] = tmpEnd;
-            ptr[1] = ptr[0] + n;
-            ptr[2] = ptr[1] + n;
-            tmpEnd = ptr[2] + n;
-            for (int j = 0; j < n; ++j) {
-              int diff = (data[ptr[0]++] << 24) |
-                         (data[ptr[1]++] << 16) |
-                         (data[ptr[2]++] << 8);
-              pixel[0] += diff;
-              for (int k = 0; k < 4; ++k) {
-                _output.writeByte(pixelBytes[k]);
-              }
-            }
-            break;
-        }
-      }
-    }
-
-    return _output.getBytes();
-  }
-
-  ZLibDecoder _zlib = new ZLibDecoder();
-  int _maxScanLineSize;
-  int _numScanLines;
-  OutputBuffer _output;
-}
+import 'dart:typed_data';

+

+import 'package:archive/archive.dart';

+

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+import '../../util/output_buffer.dart';

+import 'exr_channel.dart';

+import 'exr_compressor.dart';

+import 'exr_part.dart';

+

+abstract class ExrPxr24Compressor extends ExrCompressor {

+  factory ExrPxr24Compressor(ExrPart header, int maxScanLineSize,

+                             int numScanLines) = InternalExrPxr24Compressor;

+}

+

+class InternalExrPxr24Compressor extends InternalExrCompressor implements ExrPxr24Compressor {

+  InternalExrPxr24Compressor(ExrPart header, this._maxScanLineSize, this._numScanLines) :

+    super(header) {

+  }

+

+  int numScanLines() => _numScanLines;

+

+  Uint8List compress(InputBuffer inPtr, int x, int y,

+                     [int width, int height]) {

+    throw new ImageException('Pxr24 compression not yet supported.');

+  }

+

+  Uint8List uncompress(InputBuffer inPtr, int x, int y,

+                       [int width, int height]) {

+    List<int> data = _zlib.decodeBytes(inPtr.toUint8List());

+    if (data == null) {

+      throw new ImageException('Error decoding pxr24 compressed data');

+    }

+

+    if (_output == null) {

+      _output = OutputBuffer(size: _numScanLines * _maxScanLineSize);

+    }

+    _output.rewind();

+

+    int tmpEnd = 0;

+    List<int> ptr = [0, 0, 0, 0];

+    Uint32List pixel = Uint32List(1);

+    Uint8List pixelBytes = Uint8List.view(pixel.buffer);

+

+    if (width == null) {

+      width = header.width;

+    }

+    if (height == null) {

+      height = header.linesInBuffer;

+    }

+

+    int minX = x;

+    int maxX = x + width - 1;

+    int minY = y;

+    int maxY = y + height - 1;

+

+    if (maxX > header.width) {

+      maxX = header.width - 1;

+    }

+    if (maxY > header.height) {

+      maxY = header.height - 1;

+    }

+

+    decodedWidth = (maxX - minX) + 1;

+    decodedHeight = (maxY - minY) + 1;

+

+    int numChannels = header.channels.length;

+    for (int yi = minY; yi <= maxY; ++yi) {

+

+      for (int ci = 0; ci < numChannels; ++ci) {

+        ExrChannel ch = header.channels[ci];

+        if ((y % ch.ySampling) != 0) {

+          continue;

+        }

+

+        int n = numSamples(ch.xSampling, minX, maxX);

+        pixel[0] = 0;

+

+        switch (ch.type) {

+          case ExrChannel.TYPE_UINT:

+            ptr[0] = tmpEnd;

+            ptr[1] = ptr[0] + n;

+            ptr[2] = ptr[1] + n;

+            tmpEnd = ptr[2] + n;

+            for (int j = 0; j < n; ++j) {

+              int diff = (data[ptr[0]++] << 24) |

+                         (data[ptr[1]++] << 16) |

+                         (data[ptr[2]++] << 8);

+              pixel[0] += diff;

+              for (int k = 0; k < 4; ++k) {

+                _output.writeByte(pixelBytes[k]);

+              }

+            }

+            break;

+          case ExrChannel.TYPE_HALF:

+            ptr[0] = tmpEnd;

+            ptr[1] = ptr[0] + n;

+            tmpEnd = ptr[1] + n;

+            for (int j = 0; j < n; ++j) {

+              int diff = (data[ptr[0]++] << 8) | data[ptr[1]++];

+              pixel[0] += diff;

+

+              for (int k = 0; k < 2; ++k) {

+                _output.writeByte(pixelBytes[k]);

+              }

+            }

+            break;

+          case ExrChannel.TYPE_FLOAT:

+            ptr[0] = tmpEnd;

+            ptr[1] = ptr[0] + n;

+            ptr[2] = ptr[1] + n;

+            tmpEnd = ptr[2] + n;

+            for (int j = 0; j < n; ++j) {

+              int diff = (data[ptr[0]++] << 24) |

+                         (data[ptr[1]++] << 16) |

+                         (data[ptr[2]++] << 8);

+              pixel[0] += diff;

+              for (int k = 0; k < 4; ++k) {

+                _output.writeByte(pixelBytes[k]);

+              }

+            }

+            break;

+        }

+      }

+    }

+

+    return _output.getBytes();

+  }

+

+  ZLibDecoder _zlib = ZLibDecoder();

+  int _maxScanLineSize;

+  int _numScanLines;

+  OutputBuffer _output;

+}

diff --git a/image/lib/src/formats/exr/exr_rle_compressor.dart b/image/lib/src/formats/exr/exr_rle_compressor.dart
old mode 100644
new mode 100755
index e94cad8..3b537da
--- a/image/lib/src/formats/exr/exr_rle_compressor.dart
+++ b/image/lib/src/formats/exr/exr_rle_compressor.dart
@@ -1,100 +1,100 @@
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-import '../../util/output_buffer.dart';
-import 'exr_compressor.dart';
-import 'exr_part.dart';
-
-abstract class ExrRleCompressor extends ExrCompressor {
-  factory ExrRleCompressor(ExrPart header, int maxScanLineSize) = InternalExrRleCompressor;
-}
-
-class InternalExrRleCompressor extends InternalExrCompressor implements ExrRleCompressor {
-  InternalExrRleCompressor(ExrPart header, int maxScanLineSize) :
-    super(header) {
-  }
-
-  int numScanLines() => 1;
-
-  Uint8List compress(InputBuffer inPtr, int x, int y,
-                     [int width, int height]) {
-    throw new ImageException('Rle compression not yet supported.');
-  }
-
-  Uint8List uncompress(InputBuffer inPtr, int x, int y,
-                       [int width, int height]) {
-    OutputBuffer out = new OutputBuffer(size: inPtr.length * 2);
-
-    if (width == null) {
-      width = header.width;
-    }
-    if (height == null) {
-      height = header.linesInBuffer;
-    }
-
-    int minX = x;
-    int maxX = x + width - 1;
-    int minY = y;
-    int maxY = y + height - 1;
-
-    if (maxX > header.width) {
-      maxX = header.width - 1;
-    }
-    if (maxY > header.height) {
-      maxY = header.height - 1;
-    }
-
-    decodedWidth = (maxX - minX) + 1;
-    decodedHeight = (maxY - minY) + 1;
-
-    while (!inPtr.isEOS) {
-      int n = inPtr.readInt8();
-      if (n < 0) {
-        int count = -n;
-        while (count-- > 0) {
-          out.writeByte(inPtr.readByte());
-        }
-      } else {
-        int count = n;
-        while (count-- >= 0) {
-          out.writeByte(inPtr.readByte());
-        }
-      }
-    }
-
-    Uint8List data = out.getBytes();
-
-    // Predictor
-    for (int i = 1, len = data.length; i < len; ++i) {
-      data[i] = data[i - 1] + data[i] - 128;
-    }
-
-    // Reorder the pixel data
-    if (_outCache == null || _outCache.length != data.length) {
-      _outCache = new Uint8List(data.length);
-    }
-
-    final int len = data.length;
-    int t1 = 0;
-    int t2 = (len + 1) ~/ 2;
-    int si = 0;
-
-    while (true) {
-      if (si < len) {
-        _outCache[si++] = data[t1++];
-      } else {
-        break;
-      }
-      if (si < len) {
-        _outCache[si++] = data[t2++];
-      } else {
-        break;
-      }
-    }
-
-    return _outCache;
-  }
-
-  Uint8List _outCache;
-}
+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+import '../../util/output_buffer.dart';

+import 'exr_compressor.dart';

+import 'exr_part.dart';

+

+abstract class ExrRleCompressor extends ExrCompressor {

+  factory ExrRleCompressor(ExrPart header, int maxScanLineSize) = InternalExrRleCompressor;

+}

+

+class InternalExrRleCompressor extends InternalExrCompressor implements ExrRleCompressor {

+  InternalExrRleCompressor(ExrPart header, int maxScanLineSize) :

+    super(header) {

+  }

+

+  int numScanLines() => 1;

+

+  Uint8List compress(InputBuffer inPtr, int x, int y,

+                     [int width, int height]) {

+    throw new ImageException('Rle compression not yet supported.');

+  }

+

+  Uint8List uncompress(InputBuffer inPtr, int x, int y,

+                       [int width, int height]) {

+    OutputBuffer out = OutputBuffer(size: inPtr.length * 2);

+

+    if (width == null) {

+      width = header.width;

+    }

+    if (height == null) {

+      height = header.linesInBuffer;

+    }

+

+    int minX = x;

+    int maxX = x + width - 1;

+    int minY = y;

+    int maxY = y + height - 1;

+

+    if (maxX > header.width) {

+      maxX = header.width - 1;

+    }

+    if (maxY > header.height) {

+      maxY = header.height - 1;

+    }

+

+    decodedWidth = (maxX - minX) + 1;

+    decodedHeight = (maxY - minY) + 1;

+

+    while (!inPtr.isEOS) {

+      int n = inPtr.readInt8();

+      if (n < 0) {

+        int count = -n;

+        while (count-- > 0) {

+          out.writeByte(inPtr.readByte());

+        }

+      } else {

+        int count = n;

+        while (count-- >= 0) {

+          out.writeByte(inPtr.readByte());

+        }

+      }

+    }

+

+    Uint8List data = out.getBytes();

+

+    // Predictor

+    for (int i = 1, len = data.length; i < len; ++i) {

+      data[i] = data[i - 1] + data[i] - 128;

+    }

+

+    // Reorder the pixel data

+    if (_outCache == null || _outCache.length != data.length) {

+      _outCache = Uint8List(data.length);

+    }

+

+    final int len = data.length;

+    int t1 = 0;

+    int t2 = (len + 1) ~/ 2;

+    int si = 0;

+

+    while (true) {

+      if (si < len) {

+        _outCache[si++] = data[t1++];

+      } else {

+        break;

+      }

+      if (si < len) {

+        _outCache[si++] = data[t2++];

+      } else {

+        break;

+      }

+    }

+

+    return _outCache;

+  }

+

+  Uint8List _outCache;

+}

diff --git a/image/lib/src/formats/exr/exr_wavelet.dart b/image/lib/src/formats/exr/exr_wavelet.dart
old mode 100644
new mode 100755
index a8de536..407daf3
--- a/image/lib/src/formats/exr/exr_wavelet.dart
+++ b/image/lib/src/formats/exr/exr_wavelet.dart
@@ -1,154 +1,154 @@
-import 'dart:typed_data';
-
-import '../../internal/bit_operators.dart';
-
-class ExrWavelet {
-  static void decode(Uint16List input, int si, int nx, int ox, int ny, int oy,
-                     int mx) {
-    bool w14 = (mx < (1 << 14));
-    int n = (nx > ny) ? ny : nx;
-    int p = 1;
-    int p2;
-
-    // Search max level
-    while (p <= n) {
-      p <<= 1;
-    }
-
-    p >>= 1;
-    p2 = p;
-    p >>= 1;
-
-    List<int> a_b = [0, 0];
-
-    // Hierarchical loop on smaller dimension n
-    while (p >= 1) {
-      int py = si;
-      int ey = si + oy * (ny - p2);
-      int oy1 = oy * p;
-      int oy2 = oy * p2;
-      int ox1 = ox * p;
-      int ox2 = ox * p2;
-      int i00, i01, i10, i11;
-
-      // Y loop
-      for (; py <= ey; py += oy2) {
-        int px = py;
-        int ex = py + ox * (nx - p2);
-
-        // X loop
-        for (; px <= ex; px += ox2) {
-          int p01 = px  + ox1;
-          int p10 = px  + oy1;
-          int p11 = p10 + ox1;
-
-          // 2D wavelet decoding
-          if (w14) {
-            wdec14(input[px], input[p10], a_b);
-            i00 = a_b[0];
-            i10 = a_b[1];
-
-            wdec14(input[p01], input[p11], a_b);
-            i01 = a_b[0];
-            i11 = a_b[1];
-
-            wdec14(i00, i01, a_b);
-            input[px] = a_b[0];
-            input[p01] = a_b[1];
-
-            wdec14(i10, i11, a_b);
-            input[p10] = a_b[0];
-            input[p11] = a_b[1];
-          } else {
-            wdec16(input[px],  input[p10], a_b);
-            i00 = a_b[0];
-            i10 = a_b[1];
-
-            wdec16(input[p01], input[p11], a_b);
-            i01 = a_b[0];
-            i11 = a_b[1];
-
-            wdec16(i00, i01, a_b);
-            input[px] = a_b[0];
-            input[p01] = a_b[1];
-
-            wdec16(i10, i11, a_b);
-            input[p10] = a_b[0];
-            input[p11] = a_b[1];
-          }
-        }
-
-        // Decode (1D) odd column (still in Y loop)
-        if (nx & p != 0) {
-          int p10 = px + oy1;
-
-          if (w14) {
-            wdec14(input[px], input[p10], a_b);
-            i00 = a_b[0];
-            input[p10] = a_b[1];
-          } else {
-            wdec16(input[px], input[p10], a_b);
-            i00 = a_b[0];
-            input[p10] = a_b[1];
-          }
-
-          input[px] = i00;
-        }
-      }
-
-      // Decode (1D) odd line (must loop in X)
-      if (ny & p != 0) {
-        int px = py;
-        int ex = py + ox * (nx - p2);
-
-        for (; px <= ex; px += ox2) {
-          int p01 = px + ox1;
-
-          if (w14 != 0) {
-            wdec14(input[px], input[p01], a_b);
-            i00 = a_b[0];
-            input[p01] = a_b[1];
-          } else {
-            wdec16(input[px], input[p01], a_b);
-            i00 = a_b[0];
-            input[p01] = a_b[1];
-          }
-
-          input[px] = i00;
-        }
-      }
-
-      // Next level
-      p2 = p;
-      p >>= 1;
-    }
-  }
-
-  static const int NBITS = 16;
-  static const int A_OFFSET =  1 << (NBITS  - 1);
-  static const int M_OFFSET =  1 << (NBITS  - 1);
-  static const int MOD_MASK = (1 <<  NBITS) - 1;
-
-  static void wdec14(int l, int h, List<int> a_b) {
-    int ls = uint16ToInt16(l);
-    int hs = uint16ToInt16(h);
-
-    int hi = hs;
-    int ai = ls + (hi & 1) + (hi >> 1);
-
-    int as = ai;
-    int bs = ai - hi;
-
-    a_b[0] = as;
-    a_b[1] = bs;
-  }
-
-  static void wdec16(int l, int h, List<int> a_b) {
-    int m = l;
-    int d = h;
-    int bb = (m - (d >> 1)) & MOD_MASK;
-    int aa = (d + bb - A_OFFSET) & MOD_MASK;
-    a_b[1] = bb;
-    a_b[0] = aa;
-  }
-}
+import 'dart:typed_data';

+

+import '../../internal/bit_operators.dart';

+

+class ExrWavelet {

+  static void decode(Uint16List input, int si, int nx, int ox, int ny, int oy,

+                     int mx) {

+    bool w14 = (mx < (1 << 14));

+    int n = (nx > ny) ? ny : nx;

+    int p = 1;

+    int p2;

+

+    // Search max level

+    while (p <= n) {

+      p <<= 1;

+    }

+

+    p >>= 1;

+    p2 = p;

+    p >>= 1;

+

+    List<int> a_b = [0, 0];

+

+    // Hierarchical loop on smaller dimension n

+    while (p >= 1) {

+      int py = si;

+      int ey = si + oy * (ny - p2);

+      int oy1 = oy * p;

+      int oy2 = oy * p2;

+      int ox1 = ox * p;

+      int ox2 = ox * p2;

+      int i00, i01, i10, i11;

+

+      // Y loop

+      for (; py <= ey; py += oy2) {

+        int px = py;

+        int ex = py + ox * (nx - p2);

+

+        // X loop

+        for (; px <= ex; px += ox2) {

+          int p01 = px  + ox1;

+          int p10 = px  + oy1;

+          int p11 = p10 + ox1;

+

+          // 2D wavelet decoding

+          if (w14) {

+            wdec14(input[px], input[p10], a_b);

+            i00 = a_b[0];

+            i10 = a_b[1];

+

+            wdec14(input[p01], input[p11], a_b);

+            i01 = a_b[0];

+            i11 = a_b[1];

+

+            wdec14(i00, i01, a_b);

+            input[px] = a_b[0];

+            input[p01] = a_b[1];

+

+            wdec14(i10, i11, a_b);

+            input[p10] = a_b[0];

+            input[p11] = a_b[1];

+          } else {

+            wdec16(input[px],  input[p10], a_b);

+            i00 = a_b[0];

+            i10 = a_b[1];

+

+            wdec16(input[p01], input[p11], a_b);

+            i01 = a_b[0];

+            i11 = a_b[1];

+

+            wdec16(i00, i01, a_b);

+            input[px] = a_b[0];

+            input[p01] = a_b[1];

+

+            wdec16(i10, i11, a_b);

+            input[p10] = a_b[0];

+            input[p11] = a_b[1];

+          }

+        }

+

+        // Decode (1D) odd column (still in Y loop)

+        if (nx & p != 0) {

+          int p10 = px + oy1;

+

+          if (w14) {

+            wdec14(input[px], input[p10], a_b);

+            i00 = a_b[0];

+            input[p10] = a_b[1];

+          } else {

+            wdec16(input[px], input[p10], a_b);

+            i00 = a_b[0];

+            input[p10] = a_b[1];

+          }

+

+          input[px] = i00;

+        }

+      }

+

+      // Decode (1D) odd line (must loop in X)

+      if (ny & p != 0) {

+        int px = py;

+        int ex = py + ox * (nx - p2);

+

+        for (; px <= ex; px += ox2) {

+          int p01 = px + ox1;

+

+          if (w14 != 0) {

+            wdec14(input[px], input[p01], a_b);

+            i00 = a_b[0];

+            input[p01] = a_b[1];

+          } else {

+            wdec16(input[px], input[p01], a_b);

+            i00 = a_b[0];

+            input[p01] = a_b[1];

+          }

+

+          input[px] = i00;

+        }

+      }

+

+      // Next level

+      p2 = p;

+      p >>= 1;

+    }

+  }

+

+  static const int NBITS = 16;

+  static const int A_OFFSET =  1 << (NBITS  - 1);

+  static const int M_OFFSET =  1 << (NBITS  - 1);

+  static const int MOD_MASK = (1 <<  NBITS) - 1;

+

+  static void wdec14(int l, int h, List<int> a_b) {

+    int ls = uint16ToInt16(l);

+    int hs = uint16ToInt16(h);

+

+    int hi = hs;

+    int ai = ls + (hi & 1) + (hi >> 1);

+

+    int as = ai;

+    int bs = ai - hi;

+

+    a_b[0] = as;

+    a_b[1] = bs;

+  }

+

+  static void wdec16(int l, int h, List<int> a_b) {

+    int m = l;

+    int d = h;

+    int bb = (m - (d >> 1)) & MOD_MASK;

+    int aa = (d + bb - A_OFFSET) & MOD_MASK;

+    a_b[1] = bb;

+    a_b[0] = aa;

+  }

+}

diff --git a/image/lib/src/formats/exr/exr_zip_compressor.dart b/image/lib/src/formats/exr/exr_zip_compressor.dart
old mode 100644
new mode 100755
index edb0053..085aaf9
--- a/image/lib/src/formats/exr/exr_zip_compressor.dart
+++ b/image/lib/src/formats/exr/exr_zip_compressor.dart
@@ -1,88 +1,88 @@
-import 'dart:typed_data';
-
-import 'package:archive/archive.dart';
-
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-import 'exr_compressor.dart';
-import 'exr_part.dart';
-
-abstract class ExrZipCompressor extends ExrCompressor {
-  factory ExrZipCompressor(ExrPart header, int maxScanLineSize,
-                           int numScanLines) = InternalExrZipCompressor;
-}
-
-class InternalExrZipCompressor extends InternalExrCompressor implements ExrZipCompressor {
-  ZLibDecoder zlib = new ZLibDecoder();
-
-  InternalExrZipCompressor(ExrPart header, int maxScanLineSize, this._numScanLines) :
-    super(header) {
-  }
-
-  int numScanLines() => _numScanLines;
-
-  Uint8List compress(InputBuffer input, int x, int y,
-                     [int width, int height]) {
-    throw new ImageException('Zip compression not yet supported');
-  }
-
-  Uint8List uncompress(InputBuffer input, int x, int y,
-                       [int width, int height]) {
-    Uint8List data = zlib.decodeBytes(input.toUint8List());
-
-    if (width == null) {
-      width = header.width;
-    }
-    if (height == null) {
-      height = header.linesInBuffer;
-    }
-
-    int minX = x;
-    int maxX = x + width - 1;
-    int minY = y;
-    int maxY = y + height - 1;
-
-    if (maxX > header.width) {
-      maxX = header.width - 1;
-    }
-    if (maxY > header.height) {
-      maxY = header.height - 1;
-    }
-
-    decodedWidth = (maxX - minX) + 1;
-    decodedHeight = (maxY - minY) + 1;
-
-    // Predictor
-    for (int i = 1, len = data.length; i < len; ++i) {
-      data[i] = data[i - 1] + data[i] - 128;
-    }
-
-    // Reorder the pixel data
-    if (_outCache == null || _outCache.length != data.length) {
-      _outCache = new Uint8List(data.length);
-    }
-
-    final int len = data.length;
-    int t1 = 0;
-    int t2 = (len + 1) ~/ 2;
-    int si = 0;
-
-    while (true) {
-      if (si < len) {
-        _outCache[si++] = data[t1++];
-      } else {
-        break;
-      }
-      if (si < len) {
-        _outCache[si++] = data[t2++];
-      } else {
-        break;
-      }
-    }
-
-    return _outCache;
-  }
-
-  int _numScanLines;
-  Uint8List _outCache;
-}
+import 'dart:typed_data';

+

+import 'package:archive/archive.dart';

+

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+import 'exr_compressor.dart';

+import 'exr_part.dart';

+

+abstract class ExrZipCompressor extends ExrCompressor {

+  factory ExrZipCompressor(ExrPart header, int maxScanLineSize,

+                           int numScanLines) = InternalExrZipCompressor;

+}

+

+class InternalExrZipCompressor extends InternalExrCompressor implements ExrZipCompressor {

+  ZLibDecoder zlib = ZLibDecoder();

+

+  InternalExrZipCompressor(ExrPart header, int maxScanLineSize, this._numScanLines) :

+    super(header) {

+  }

+

+  int numScanLines() => _numScanLines;

+

+  Uint8List compress(InputBuffer input, int x, int y,

+                     [int width, int height]) {

+    throw new ImageException('Zip compression not yet supported');

+  }

+

+  Uint8List uncompress(InputBuffer input, int x, int y,

+                       [int width, int height]) {

+    Uint8List data = zlib.decodeBytes(input.toUint8List());

+

+    if (width == null) {

+      width = header.width;

+    }

+    if (height == null) {

+      height = header.linesInBuffer;

+    }

+

+    int minX = x;

+    int maxX = x + width - 1;

+    int minY = y;

+    int maxY = y + height - 1;

+

+    if (maxX > header.width) {

+      maxX = header.width - 1;

+    }

+    if (maxY > header.height) {

+      maxY = header.height - 1;

+    }

+

+    decodedWidth = (maxX - minX) + 1;

+    decodedHeight = (maxY - minY) + 1;

+

+    // Predictor

+    for (int i = 1, len = data.length; i < len; ++i) {

+      data[i] = data[i - 1] + data[i] - 128;

+    }

+

+    // Reorder the pixel data

+    if (_outCache == null || _outCache.length != data.length) {

+      _outCache = Uint8List(data.length);

+    }

+

+    final int len = data.length;

+    int t1 = 0;

+    int t2 = (len + 1) ~/ 2;

+    int si = 0;

+

+    while (true) {

+      if (si < len) {

+        _outCache[si++] = data[t1++];

+      } else {

+        break;

+      }

+      if (si < len) {

+        _outCache[si++] = data[t2++];

+      } else {

+        break;

+      }

+    }

+

+    return _outCache;

+  }

+

+  int _numScanLines;

+  Uint8List _outCache;

+}

diff --git a/image/lib/src/formats/exr_decoder.dart b/image/lib/src/formats/exr_decoder.dart
old mode 100644
new mode 100755
index ca38ef2..ef5dc4c
--- a/image/lib/src/formats/exr_decoder.dart
+++ b/image/lib/src/formats/exr_decoder.dart
@@ -1,98 +1,98 @@
-import '../animation.dart';
-import '../image.dart';
-import '../hdr/hdr_image.dart';
-import '../hdr/hdr_to_image.dart';
-import 'decode_info.dart';
-import 'decoder.dart';
-import 'exr/exr_image.dart';
-
-/**
- * Decode an OpenEXR formatted image.
- *
- * OpenEXR is a format developed by Industrial Light & Magic, with collaboration
- * from other companies such as Weta and Pixar, for storing hight dynamic
- * range (HDR) images for use in digital visual effects production. It supports
- * a wide range of features, including 16-bit or 32-bit floating-point channels;
- * lossless and lossy data compression; arbitrary image channels for storing
- * any combination of data, such as red, green, blue, alpha, luminance and
- * chroma channels, depth, surface normal, motion vectors, etc. It can also
- * store images in scanline or tiled format; multiple views for stereo images;
- * multiple parts; etc.
- *
- * Because OpenEXR is a high-dynamic-range (HDR) format, it must be converted
- * to a low-dynamic-range (LDR) image for display, or for use as an OpenGL
- * texture (for example). This process is called tone-mapping. Currently only
- * a simple tone-mapping function is provided with a single [exposure]
- * parameter. More tone-mapping functionality will be added.
- */
-class ExrDecoder extends Decoder {
-  ExrImage exrImage;
-  /// Exposure for tone-mapping the hdr image to an [Image], applied during
-  /// [decodeFrame].
-  double exposure;
-  double gamma;
-  bool reinhard;
-  double bloomAmount;
-  double bloomRadius;
-
-  ExrDecoder({this.exposure: 1.0});
-
-  bool isValidFile(List<int> data) {
-    return ExrImage.isValidFile(data);
-  }
-
-  DecodeInfo startDecode(List<int> data) {
-    exrImage = new ExrImage(data);
-    return exrImage;
-  }
-
-  int numFrames() => exrImage != null ? exrImage.parts.length : 0;
-
-  Image decodeFrame(int frame) {
-    if (exrImage == null) {
-      return null;
-    }
-
-    return hdrToImage(exrImage.getPart(frame).framebuffer,
-                      exposure: exposure);
-  }
-
-  HdrImage decodeHdrFrame(int frame) {
-    if (exrImage == null) {
-      return null;
-    }
-    if (frame >= exrImage.parts.length) {
-      return null;
-    }
-    return exrImage.parts[frame].framebuffer;
-  }
-
-  Image decodeImage(List<int> bytes, {int frame: 0}) {
-    if (startDecode(bytes) == null) {
-      return null;
-    }
-
-    return decodeFrame(frame);
-  }
-
-  HdrImage decodeHdrImage(List<int> bytes, {int frame: 0}) {
-    if (startDecode(bytes) == null) {
-      return null;
-    }
-    return decodeHdrFrame(frame);
-  }
-
-  Animation decodeAnimation(List<int> data) {
-    Image image = decodeImage(data);
-    if (image == null) {
-      return null;
-    }
-
-    Animation anim = new Animation();
-    anim.width = image.width;
-    anim.height = image.height;
-    anim.addFrame(image);
-
-    return anim;
-  }
-}
+import '../animation.dart';

+import '../image.dart';

+import '../hdr/hdr_image.dart';

+import '../hdr/hdr_to_image.dart';

+import 'decode_info.dart';

+import 'decoder.dart';

+import 'exr/exr_image.dart';

+

+/**

+ * Decode an OpenEXR formatted image.

+ *

+ * OpenEXR is a format developed by Industrial Light & Magic, with collaboration

+ * from other companies such as Weta and Pixar, for storing hight dynamic

+ * range (HDR) images for use in digital visual effects production. It supports

+ * a wide range of features, including 16-bit or 32-bit floating-point channels;

+ * lossless and lossy data compression; arbitrary image channels for storing

+ * any combination of data, such as red, green, blue, alpha, luminance and

+ * chroma channels, depth, surface normal, motion vectors, etc. It can also

+ * store images in scanline or tiled format; multiple views for stereo images;

+ * multiple parts; etc.

+ *

+ * Because OpenEXR is a high-dynamic-range (HDR) format, it must be converted

+ * to a low-dynamic-range (LDR) image for display, or for use as an OpenGL

+ * texture (for example). This process is called tone-mapping. Currently only

+ * a simple tone-mapping function is provided with a single [exposure]

+ * parameter. More tone-mapping functionality will be added.

+ */

+class ExrDecoder extends Decoder {

+  ExrImage exrImage;

+  /// Exposure for tone-mapping the hdr image to an [Image], applied during

+  /// [decodeFrame].

+  double exposure;

+  double gamma;

+  bool reinhard;

+  double bloomAmount;

+  double bloomRadius;

+

+  ExrDecoder({this.exposure: 1.0});

+

+  bool isValidFile(List<int> data) {

+    return ExrImage.isValidFile(data);

+  }

+

+  DecodeInfo startDecode(List<int> data) {

+    exrImage = ExrImage(data);

+    return exrImage;

+  }

+

+  int numFrames() => exrImage != null ? exrImage.parts.length : 0;

+

+  Image decodeFrame(int frame) {

+    if (exrImage == null) {

+      return null;

+    }

+

+    return hdrToImage(exrImage.getPart(frame).framebuffer,

+                      exposure: exposure);

+  }

+

+  HdrImage decodeHdrFrame(int frame) {

+    if (exrImage == null) {

+      return null;

+    }

+    if (frame >= exrImage.parts.length) {

+      return null;

+    }

+    return exrImage.parts[frame].framebuffer;

+  }

+

+  Image decodeImage(List<int> bytes, {int frame: 0}) {

+    if (startDecode(bytes) == null) {

+      return null;

+    }

+

+    return decodeFrame(frame);

+  }

+

+  HdrImage decodeHdrImage(List<int> bytes, {int frame: 0}) {

+    if (startDecode(bytes) == null) {

+      return null;

+    }

+    return decodeHdrFrame(frame);

+  }

+

+  Animation decodeAnimation(List<int> data) {

+    Image image = decodeImage(data);

+    if (image == null) {

+      return null;

+    }

+

+    Animation anim = Animation();

+    anim.width = image.width;

+    anim.height = image.height;

+    anim.addFrame(image);

+

+    return anim;

+  }

+}

diff --git a/image/lib/src/formats/formats.dart b/image/lib/src/formats/formats.dart
old mode 100644
new mode 100755
index 51aa445..611864e
--- a/image/lib/src/formats/formats.dart
+++ b/image/lib/src/formats/formats.dart
@@ -25,39 +25,39 @@
   // The various decoders will be creating a Uint8List for their InputStream

   // if the data isn't already that type, so do it once here to avoid having to

   // do it multiple times.

-  Uint8List bytes = new Uint8List.fromList(data);

+  Uint8List bytes = Uint8List.fromList(data);

 

-  JpegDecoder jpg = new JpegDecoder();

+  JpegDecoder jpg = JpegDecoder();

   if (jpg.isValidFile(bytes)) {

     return jpg;

   }

 

-  PngDecoder png = new PngDecoder();

+  PngDecoder png = PngDecoder();

   if (png.isValidFile(bytes)) {

     return png;

   }

 

-  GifDecoder gif = new GifDecoder();

+  GifDecoder gif = GifDecoder();

   if (gif.isValidFile(bytes)) {

     return gif;

   }

 

-  WebPDecoder webp = new WebPDecoder();

+  WebPDecoder webp = WebPDecoder();

   if (webp.isValidFile(bytes)) {

     return webp;

   }

 

-  TiffDecoder tiff = new TiffDecoder();

+  TiffDecoder tiff = TiffDecoder();

   if (tiff.isValidFile(bytes)) {

     return tiff;

   }

 

-  PsdDecoder psd = new PsdDecoder();

+  PsdDecoder psd = PsdDecoder();

   if (psd.isValidFile(bytes)) {

     return psd;

   }

 

-  ExrDecoder exr = new ExrDecoder();

+  ExrDecoder exr = ExrDecoder();

   if (exr.isValidFile(bytes)) {

     return exr;

   }

diff --git a/image/lib/src/formats/gif/gif_color_map.dart b/image/lib/src/formats/gif/gif_color_map.dart
old mode 100644
new mode 100755
index 4a5acd3..5325a42
--- a/image/lib/src/formats/gif/gif_color_map.dart
+++ b/image/lib/src/formats/gif/gif_color_map.dart
@@ -10,7 +10,7 @@
 

   GifColorMap(int numColors) :

     this.numColors = numColors,

-    colors = new Uint8List(numColors * 3) {

+    colors = Uint8List(numColors * 3) {

     bitsPerPixel = _bitSize(numColors);

   }

 

diff --git a/image/lib/src/formats/gif/gif_image_desc.dart b/image/lib/src/formats/gif/gif_image_desc.dart
old mode 100644
new mode 100755
index b8b252e..c4b0b88
--- a/image/lib/src/formats/gif/gif_image_desc.dart
+++ b/image/lib/src/formats/gif/gif_image_desc.dart
@@ -25,7 +25,7 @@
     interlaced = (b & 0x40) != 0;

 

     if (b & 0x80 != 0) {

-      colorMap = new GifColorMap(1 << bitsPerPixel);

+      colorMap = GifColorMap(1 << bitsPerPixel);

 

       for (int i = 0; i < colorMap.numColors; ++i) {

         colorMap.setColor(i, input.readByte(), input.readByte(),

diff --git a/image/lib/src/formats/gif/gif_info.dart b/image/lib/src/formats/gif/gif_info.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/gif_decoder.dart b/image/lib/src/formats/gif_decoder.dart
old mode 100644
new mode 100755
index 5eb9e42..57d9f78
--- a/image/lib/src/formats/gif_decoder.dart
+++ b/image/lib/src/formats/gif_decoder.dart
@@ -26,8 +26,8 @@
    * Is the given file a valid Gif image?

    */

   bool isValidFile(List<int> bytes) {

-    _input = new InputBuffer(bytes);

-    info = new GifInfo();

+    _input = InputBuffer(bytes);

+    info = GifInfo();

     return _getInfo();

   }

 

@@ -44,9 +44,9 @@
    * If the file is not a valid Gif image, null is returned.

    */

   GifInfo startDecode(List<int> bytes) {

-    _input = new InputBuffer(bytes);

+    _input = InputBuffer(bytes);

 

-    info = new GifInfo();

+    info = GifInfo();

     if (!_getInfo()) {

       return null;

     }

@@ -167,18 +167,18 @@
       return null;

     }

 

-    Animation anim = new Animation();

+    Animation anim = Animation();

     anim.width = info.width;

     anim.height = info.height;

     anim.loopCount = _repeat;

 

-    Image lastImage = new Image(info.width, info.height);

+    Image lastImage = Image(info.width, info.height);

     for (int i = 0; i < info.numFrames; ++i) {

       //_frame = i;

       if (lastImage == null) {

-        lastImage = new Image(info.width, info.height);

+        lastImage = Image(info.width, info.height);

       } else {

-        lastImage = new Image.from(lastImage);

+        lastImage = Image.from(lastImage);

       }

 

       GifImageDesc frame = info.frames[i];

@@ -211,7 +211,7 @@
     if (_input.isEOS) {

       return null;

     }

-    InternalGifImageDesc gifImage = new InternalGifImageDesc(_input);

+    InternalGifImageDesc gifImage = InternalGifImageDesc(_input);

     _input.skip(1);

     _skipRemainder();

     return gifImage;

@@ -259,8 +259,8 @@
 

     _pixelCount = width * height;

 

-    Image image = new Image(width, height);

-    Uint8List line = new Uint8List(width);

+    Image image = Image(width, height);

+    Uint8List line = Uint8List(width);

 

     if (gifImage.interlaced) {

       int row = gifImage.y;

@@ -314,7 +314,7 @@
 

     // Is there a global color map?

     if (b & 0x80 != 0) {

-      info.globalColorMap = new GifColorMap(1 << bitsPerPixel);

+      info.globalColorMap = GifColorMap(1 << bitsPerPixel);

 

       // Get the global color map:

       for (int i = 0; i < info.globalColorMap.numColors; ++i) {

@@ -581,10 +581,10 @@
   }

 

   void _initDecode() {

-    _buffer = new Uint8List(256);

-    _stack = new Uint8List(LZ_MAX_CODE);

-    _suffix = new Uint8List(LZ_MAX_CODE + 1);

-    _prefix = new Uint32List(LZ_MAX_CODE + 1);

+    _buffer = Uint8List(256);

+    _stack = Uint8List(LZ_MAX_CODE);

+    _suffix = Uint8List(LZ_MAX_CODE + 1);

+    _prefix = Uint32List(LZ_MAX_CODE + 1);

   }

 

   InputBuffer _input;

diff --git a/image/lib/src/formats/gif_encoder.dart b/image/lib/src/formats/gif_encoder.dart
old mode 100644
new mode 100755
index ee62520..bc19f6e
--- a/image/lib/src/formats/gif_encoder.dart
+++ b/image/lib/src/formats/gif_encoder.dart
@@ -15,12 +15,12 @@
 

   void addFrame(Image image, {int duration}) {

     if (output == null) {

-      output = new OutputBuffer();

+      output = OutputBuffer();

 

       if (duration != null) {

         this.delay = duration;

       }

-      _lastColorMap = new NeuralQuantizer(image);

+      _lastColorMap = NeuralQuantizer(image);

       _lastImage = _lastColorMap.getIndexMap(image);

       _width = image.width;

       _height = image.height;

@@ -38,7 +38,7 @@
     if (duration != null) {

       this.delay = duration;

     }

-    _lastColorMap = new NeuralQuantizer(image);

+    _lastColorMap = NeuralQuantizer(image);

     _lastImage = _lastColorMap.getIndexMap(image);

   }

 

@@ -121,13 +121,13 @@
     _curAccum = 0;

     _curBits = 0;

     _blockSize = 0;

-    _block = new Uint8List(256);

+    _block = Uint8List(256);

 

     const int initCodeSize = 8;

     output.writeByte(initCodeSize);

 

-    Int32List hTab = new Int32List(HSIZE);

-    Int32List codeTab = new Int32List(HSIZE);

+    Int32List hTab = Int32List(HSIZE);

+    Int32List codeTab = Int32List(HSIZE);

     int remaining = width * height;

     int curPixel = 0;

 

diff --git a/image/lib/src/formats/jpeg/jpeg.dart b/image/lib/src/formats/jpeg/jpeg.dart
old mode 100644
new mode 100755
index 848af20..73b4da5
--- a/image/lib/src/formats/jpeg/jpeg.dart
+++ b/image/lib/src/formats/jpeg/jpeg.dart
@@ -1,86 +1,86 @@
-class Jpeg {
-  static const List<int> dctZigZag = const [
-      0,  1,  8, 16,  9,  2,  3, 10,
-      17, 24, 32, 25, 18, 11,  4,  5,
-      12, 19, 26, 33, 40, 48, 41, 34,
-      27, 20, 13,  6,  7, 14, 21, 28,
-      35, 42, 49, 56, 57, 50, 43, 36,
-      29, 22, 15, 23, 30, 37, 44, 51,
-      58, 59, 52, 45, 38, 31, 39, 46,
-      53, 60, 61, 54, 47, 55, 62, 63,
-      63, 63, 63, 63, 63, 63, 63, 63, // extra entries for safety in decoder
-      63, 63, 63, 63, 63, 63, 63, 63 ];
-
-  static const int DCTSIZE = 8; // The basic DCT block is 8x8 samples
-  static const int DCTSIZE2 = 64;  // DCTSIZE squared; # of elements in a block
-  static const int NUM_QUANT_TBLS = 4; // Quantization tables are numbered 0..3
-  static const int NUM_HUFF_TBLS = 4; // Huffman tables are numbered 0..3
-  static const int NUM_ARITH_TBLS = 16;  // Arith-coding tables are numbered 0..15
-  static const int MAX_COMPS_IN_SCAN = 4; // JPEG limit on # of components in one scan
-  static const int MAX_SAMP_FACTOR = 4; // JPEG limit on sampling factors
-
-  static const int M_SOF0  = 0xc0;
-  static const int M_SOF1  = 0xc1;
-  static const int M_SOF2  = 0xc2;
-  static const int M_SOF3  = 0xc3;
-
-  static const int M_SOF5  = 0xc5;
-  static const int M_SOF6  = 0xc6;
-  static const int M_SOF7  = 0xc7;
-
-  static const int M_JPG   = 0xc8;
-  static const int M_SOF9  = 0xc9;
-  static const int M_SOF10 = 0xca;
-  static const int M_SOF11 = 0xcb;
-
-  static const int M_SOF13 = 0xcd;
-  static const int M_SOF14 = 0xce;
-  static const int M_SOF15 = 0xcf;
-
-  static const int M_DHT   = 0xc4;
-
-  static const int M_DAC   = 0xcc;
-
-  static const int M_RST0  = 0xd0;
-  static const int M_RST1  = 0xd1;
-  static const int M_RST2  = 0xd2;
-  static const int M_RST3  = 0xd3;
-  static const int M_RST4  = 0xd4;
-  static const int M_RST5  = 0xd5;
-  static const int M_RST6  = 0xd6;
-  static const int M_RST7  = 0xd7;
-
-  static const int M_SOI   = 0xd8;
-  static const int M_EOI   = 0xd9;
-  static const int M_SOS   = 0xda;
-  static const int M_DQT   = 0xdb;
-  static const int M_DNL   = 0xdc;
-  static const int M_DRI   = 0xdd;
-  static const int M_DHP   = 0xde;
-  static const int M_EXP   = 0xdf;
-
-  static const int M_APP0  = 0xe0; // JFIF, JFXX, CIFF, AVI1, Ocad
-  static const int M_APP1  = 0xe1; // EXIF, ExtendedXMP, XMP, QVCI, FLIR
-  static const int M_APP2  = 0xe2; // ICC_Profile, FPXR, MPF, PreviewImage
-  static const int M_APP3  = 0xe3; // Meta, Stim, PreviewImage
-  static const int M_APP4  = 0xe4; // Scalado, FPXR, PreviewImage
-  static const int M_APP5  = 0xe5; // RMETA, PreviewImage
-  static const int M_APP6  = 0xe6; // EPPIM, NITF, HP_TDHD, GoPro
-  static const int M_APP7  = 0xe7; // Pentax, Qualcomm
-  static const int M_APP8  = 0xe8; // SPIFF
-  static const int M_APP9  = 0xe9; // MediaJukebox
-  static const int M_APP10 = 0xea; // Comment
-  static const int M_APP11 = 0xeb; // Jpeg-HDR
-  static const int M_APP12 = 0xec; // PictureInfo, Ducky
-  static const int M_APP13 = 0xed; // Photoshop, Adobe_CM
-  static const int M_APP14 = 0xee; // ADOBE
-  static const int M_APP15 = 0xef; // GraphicConverter
-
-  static const int M_JPG0  = 0xf0;
-  static const int M_JPG13 = 0xfd;
-  static const int M_COM   = 0xfe;
-
-  static const int M_TEM   = 0x01;
-
-  static const int M_ERROR = 0x100;
-}
+class Jpeg {

+  static const dctZigZag = const [

+      0,  1,  8, 16,  9,  2,  3, 10,

+      17, 24, 32, 25, 18, 11,  4,  5,

+      12, 19, 26, 33, 40, 48, 41, 34,

+      27, 20, 13,  6,  7, 14, 21, 28,

+      35, 42, 49, 56, 57, 50, 43, 36,

+      29, 22, 15, 23, 30, 37, 44, 51,

+      58, 59, 52, 45, 38, 31, 39, 46,

+      53, 60, 61, 54, 47, 55, 62, 63,

+      63, 63, 63, 63, 63, 63, 63, 63, // extra entries for safety in decoder

+      63, 63, 63, 63, 63, 63, 63, 63 ];

+

+  static const int DCTSIZE = 8; // The basic DCT block is 8x8 samples

+  static const int DCTSIZE2 = 64;  // DCTSIZE squared; # of elements in a block

+  static const int NUM_QUANT_TBLS = 4; // Quantization tables are numbered 0..3

+  static const int NUM_HUFF_TBLS = 4; // Huffman tables are numbered 0..3

+  static const int NUM_ARITH_TBLS = 16;  // Arith-coding tables are numbered 0..15

+  static const int MAX_COMPS_IN_SCAN = 4; // JPEG limit on # of components in one scan

+  static const int MAX_SAMP_FACTOR = 4; // JPEG limit on sampling factors

+

+  static const int M_SOF0  = 0xc0;

+  static const int M_SOF1  = 0xc1;

+  static const int M_SOF2  = 0xc2;

+  static const int M_SOF3  = 0xc3;

+

+  static const int M_SOF5  = 0xc5;

+  static const int M_SOF6  = 0xc6;

+  static const int M_SOF7  = 0xc7;

+

+  static const int M_JPG   = 0xc8;

+  static const int M_SOF9  = 0xc9;

+  static const int M_SOF10 = 0xca;

+  static const int M_SOF11 = 0xcb;

+

+  static const int M_SOF13 = 0xcd;

+  static const int M_SOF14 = 0xce;

+  static const int M_SOF15 = 0xcf;

+

+  static const int M_DHT   = 0xc4;

+

+  static const int M_DAC   = 0xcc;

+

+  static const int M_RST0  = 0xd0;

+  static const int M_RST1  = 0xd1;

+  static const int M_RST2  = 0xd2;

+  static const int M_RST3  = 0xd3;

+  static const int M_RST4  = 0xd4;

+  static const int M_RST5  = 0xd5;

+  static const int M_RST6  = 0xd6;

+  static const int M_RST7  = 0xd7;

+

+  static const int M_SOI   = 0xd8;

+  static const int M_EOI   = 0xd9;

+  static const int M_SOS   = 0xda;

+  static const int M_DQT   = 0xdb;

+  static const int M_DNL   = 0xdc;

+  static const int M_DRI   = 0xdd;

+  static const int M_DHP   = 0xde;

+  static const int M_EXP   = 0xdf;

+

+  static const int M_APP0  = 0xe0; // JFIF, JFXX, CIFF, AVI1, Ocad

+  static const int M_APP1  = 0xe1; // EXIF, ExtendedXMP, XMP, QVCI, FLIR

+  static const int M_APP2  = 0xe2; // ICC_Profile, FPXR, MPF, PreviewImage

+  static const int M_APP3  = 0xe3; // Meta, Stim, PreviewImage

+  static const int M_APP4  = 0xe4; // Scalado, FPXR, PreviewImage

+  static const int M_APP5  = 0xe5; // RMETA, PreviewImage

+  static const int M_APP6  = 0xe6; // EPPIM, NITF, HP_TDHD, GoPro

+  static const int M_APP7  = 0xe7; // Pentax, Qualcomm

+  static const int M_APP8  = 0xe8; // SPIFF

+  static const int M_APP9  = 0xe9; // MediaJukebox

+  static const int M_APP10 = 0xea; // Comment

+  static const int M_APP11 = 0xeb; // Jpeg-HDR

+  static const int M_APP12 = 0xec; // PictureInfo, Ducky

+  static const int M_APP13 = 0xed; // Photoshop, Adobe_CM

+  static const int M_APP14 = 0xee; // ADOBE

+  static const int M_APP15 = 0xef; // GraphicConverter

+

+  static const int M_JPG0  = 0xf0;

+  static const int M_JPG13 = 0xfd;

+  static const int M_COM   = 0xfe;

+

+  static const int M_TEM   = 0x01;

+

+  static const int M_ERROR = 0x100;

+}

diff --git a/image/lib/src/formats/jpeg/jpeg_adobe.dart b/image/lib/src/formats/jpeg/jpeg_adobe.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/jpeg/jpeg_component.dart b/image/lib/src/formats/jpeg/jpeg_component.dart
old mode 100644
new mode 100755
index 7af35d5..44b8221
--- a/image/lib/src/formats/jpeg/jpeg_component.dart
+++ b/image/lib/src/formats/jpeg/jpeg_component.dart
@@ -1,20 +1,20 @@
-import 'dart:typed_data';
-
-class JpegComponent {
-  int h;
-  int v;
-  final List<Int16List> quantizationTableList;
-  int quantizationIndex;
-  int blocksPerLine;
-  int blocksPerColumn;
-  List blocks;
-  List huffmanTableDC;
-  List huffmanTableAC;
-  int pred;
-
-  JpegComponent(this.h, this.v, this.quantizationTableList,
-      this.quantizationIndex);
-
-  Int16List get quantizationTable =>
-      quantizationTableList[quantizationIndex];
-}
+import 'dart:typed_data';

+

+class JpegComponent {

+  int hSamples;

+  int vSamples;

+  final List<Int16List> quantizationTableList;

+  int quantizationIndex;

+  int blocksPerLine;

+  int blocksPerColumn;

+  List blocks;

+  List huffmanTableDC;

+  List huffmanTableAC;

+  int pred;

+

+  JpegComponent(this.hSamples, this.vSamples, this.quantizationTableList,

+      this.quantizationIndex);

+

+  Int16List get quantizationTable =>

+      quantizationTableList[quantizationIndex];

+}

diff --git a/image/lib/src/formats/jpeg/jpeg_data.dart b/image/lib/src/formats/jpeg/jpeg_data.dart
old mode 100644
new mode 100755
index 73517f1..f32f91f
--- a/image/lib/src/formats/jpeg/jpeg_data.dart
+++ b/image/lib/src/formats/jpeg/jpeg_data.dart
@@ -1,1152 +1,1185 @@
-import 'dart:typed_data';
-
-import '../../exif_data.dart';
-import '../../image_exception.dart';
-import '../../internal/bit_operators.dart';
-import '../../util/input_buffer.dart';
-import 'jpeg.dart';
-import 'jpeg_adobe.dart';
-import 'jpeg_component.dart';
-import 'jpeg_frame.dart';
-import 'jpeg_info.dart';
-import 'jpeg_jfif.dart';
-import 'jpeg_scan.dart';
-
-class JpegData  {
-  InputBuffer input;
-  JpegJfif jfif;
-  JpegAdobe adobe;
-  JpegFrame frame;
-  int resetInterval;
-  ExifData exif = new ExifData();
-  final List<Int16List> quantizationTables = new List(Jpeg.NUM_QUANT_TBLS);
-  final List<JpegFrame> frames = [];
-  final List huffmanTablesAC = [];
-  final List huffmanTablesDC = [];
-  final List<Map> components = [];
-
-  bool validate(List<int> bytes) {
-    input = new InputBuffer(bytes, bigEndian: true);
-
-    int marker = _nextMarker();
-    if (marker != Jpeg.M_SOI) {
-      return false;
-    }
-
-    bool hasSOF = false;
-    bool hasSOS = false;
-
-    marker = _nextMarker();
-    while (marker != Jpeg.M_EOI && !input.isEOS) { // EOI (End of image)
-      _skipBlock();
-      switch (marker) {
-        case Jpeg.M_SOF0: // SOF0 (Start of Frame, Baseline DCT)
-        case Jpeg.M_SOF1: // SOF1 (Start of Frame, Extended DCT)
-        case Jpeg.M_SOF2: // SOF2 (Start of Frame, Progressive DCT)
-          hasSOF = true;
-          break;
-        case Jpeg.M_SOS: // SOS (Start of Scan)
-          hasSOS = true;
-          break;
-        default:
-      }
-
-      marker = _nextMarker();
-    }
-
-    return hasSOF && hasSOS;
-  }
-
-  JpegInfo readInfo(List<int> bytes) {
-    input = new InputBuffer(bytes, bigEndian: true);
-
-    int marker = _nextMarker();
-    if (marker != Jpeg.M_SOI) {
-      return null;
-    }
-
-    JpegInfo info = new JpegInfo();
-
-    bool hasSOF = false;
-    bool hasSOS = false;
-
-    marker = _nextMarker();
-    while (marker != Jpeg.M_EOI && !input.isEOS) { // EOI (End of image)
-      switch (marker) {
-        case Jpeg.M_SOF0: // SOF0 (Start of Frame, Baseline DCT)
-        case Jpeg.M_SOF1: // SOF1 (Start of Frame, Extended DCT)
-        case Jpeg.M_SOF2: // SOF2 (Start of Frame, Progressive DCT)
-          hasSOF = true;
-          _readFrame(marker, _readBlock());
-          break;
-        case Jpeg.M_SOS: // SOS (Start of Scan)
-          hasSOS = true;
-          _skipBlock();
-          break;
-        default:
-          _skipBlock();
-          break;
-      }
-
-      marker = _nextMarker();
-    }
-
-    if (frame != null) {
-      info.width = frame.samplesPerLine;
-      info.height = frame.scanLines;
-    }
-    frame = null;
-    frames.clear();
-
-    return (hasSOF && hasSOS) ? info : null;
-  }
-
-  void read(List<int> bytes) {
-    input = new InputBuffer(bytes, bigEndian: true);
-
-    _read();
-
-    if (frames.length != 1) {
-      throw new ImageException('Only single frame JPEGs supported');
-    }
-
-    for (int i = 0; i < frame.componentsOrder.length; ++i) {
-      /*JpegComponent component =*/ frame.components[frame.componentsOrder[i]];
-    }
-
-    for (int i = 0; i < frame.componentsOrder.length; ++i) {
-      JpegComponent component = frame.components[frame.componentsOrder[i]];
-      components.add({
-        'scaleX': component.h / frame.maxH,
-        'scaleY': component.v / frame.maxV,
-        'lines': _buildComponentData(frame, component)
-      });
-    }
-  }
-
-  int get width => frame.samplesPerLine;
-
-  int get height => frame.scanLines;
-
-  Uint8List getData(int width, int height) {
-    num scaleX = 1;
-    num scaleY = 1;
-    Map component1;
-    Map component2;
-    Map component3;
-    Map component4;
-    Uint8List component1Line;
-    Uint8List component2Line;
-    Uint8List component3Line;
-    Uint8List component4Line;
-    int offset = 0;
-    int Y, Cb, Cr, K, C, M, Ye, R, G, B;
-    bool colorTransform = false;
-    int dataLength = width * height * components.length;
-    Uint8List data = new Uint8List(dataLength);
-
-    switch (components.length) {
-      case 1:
-        component1 = components[0];
-        var lines = component1['lines'];
-        var sy = component1['scaleY'];
-        var sx =  component1['scaleX'];
-        for (int y = 0; y < height; y++) {
-          component1Line = lines[(y * sy * scaleY).toInt()];
-          for (int x = 0; x < width; x++) {
-            Y = component1Line[(x *sx * scaleX).toInt()];
-            data[offset++] = Y;
-          }
-        }
-        break;
-      case 2:
-        // PDF might compress two component data in custom color-space
-        component1 = components[0];
-        component2 = components[1];
-        for (int y = 0; y < height; y++) {
-          component1Line = component1['lines'][(y * component1['scaleY'] * scaleY)];
-          component2Line = component2['lines'][(y * component2['scaleY'] * scaleY)];
-          for (int x = 0; x < width; x++) {
-            Y = component1Line[(x * component1['scaleX'] * scaleX).toInt()];
-            data[offset++] = Y;
-            Y = component2Line[(x * component2['scaleX'] * scaleX).toInt()];
-            data[offset++] = Y;
-          }
-        }
-        break;
-      case 3:
-        // The default transform for three components is true
-        colorTransform = true;
-
-        component1 = components[0];
-        component2 = components[1];
-        component3 = components[2];
-
-        double sy1 = (component1['scaleY'] * scaleY).toDouble();
-        double sy2 = (component2['scaleY'] * scaleY).toDouble();
-        double sy3 = (component3['scaleY'] * scaleY).toDouble();
-        double sx1 = (component1['scaleX'] * scaleX).toDouble();
-        double sx2 = (component2['scaleX'] * scaleX).toDouble();
-        double sx3 = (component3['scaleX'] * scaleX).toDouble();
-
-        List<Uint8List> lines1 = component1['lines'];
-        List<Uint8List> lines2 = component2['lines'];
-        List<Uint8List> lines3 = component3['lines'];
-
-        for (int y = 0; y < height; y++) {
-          component1Line = lines1[(y * sy1).toInt()];
-          component2Line = lines2[(y * sy2).toInt()];
-          component3Line = lines3[(y * sy3).toInt()];
-
-          for (int x = 0; x < width; x++) {
-            if (!colorTransform) {
-              data[offset++] = component1Line[(x * sx1).toInt()];
-              data[offset++] = component2Line[(x * sx2).toInt()];
-              data[offset++] = component3Line[(x * sx3).toInt()];
-            } else {
-              Y =  component1Line[(x * sx1).toInt()] << 8;
-              Cb = component2Line[(x * sx2).toInt()] - 128;
-              Cr = component3Line[(x * sx3).toInt()] - 128;
-
-              R = shiftR((Y + 359 * Cr + 128), 8);
-              G = shiftR((Y - 88 * Cb - 183 * Cr + 128), 8);
-              B = shiftR((Y + 454 * Cb + 128), 8);
-
-              data[offset++] = _clamp8(R);
-              data[offset++] = _clamp8(G);
-              data[offset++] = _clamp8(B);
-            }
-          }
-        }
-        break;
-      case 4:
-        if (adobe == null) {
-          throw new ImageException('Unsupported color mode (4 components)');
-        }
-        // The default transform for four components is false
-        colorTransform = false;
-        // The adobe transform marker overrides any previous setting
-        if (adobe.transformCode != 0) {
-          colorTransform = true;
-        }
-
-        component1 = components[0];
-        component2 = components[1];
-        component3 = components[2];
-        component4 = components[3];
-
-        var sx1 = component1['scaleX'] * scaleX;
-        var sx2 = component2['scaleX'] * scaleX;
-        var sx3 = component3['scaleX'] * scaleX;
-        var sx4 = component4['scaleX'] * scaleX;
-        var sy1 = component1['scaleY'] * scaleY;
-        var sy2 = component2['scaleY'] * scaleY;
-        var sy3 = component3['scaleY'] * scaleY;
-        var sy4 = component4['scaleY'] * scaleY;
-
-        var lines1 = component1['lines'];
-        var lines2 = component2['lines'];
-        var lines3 = component3['lines'];
-        var lines4 = component4['lines'];
-
-        for (int y = 0; y < height; y++) {
-          component1Line = lines1[(y * sy1).toInt()];
-          component2Line = lines2[(y * sy2).toInt()];
-          component3Line = lines3[(y * sy3).toInt()];
-          component4Line = lines4[(y * sy4).toInt()];
-          for (int x = 0; x < width; x++) {
-            if (!colorTransform) {
-              C = component1Line[(x * sx1).toInt()];
-              M = component2Line[(x * sx2).toInt()];
-              Ye = component3Line[(x * sx3).toInt()];
-              K = component4Line[(x * sx4).toInt()];
-            } else {
-              Y = component1Line[(x * sx1).toInt()];
-              Cb = component2Line[(x * sx2).toInt()];
-              Cr = component3Line[(x * sx3).toInt()];
-              K = component4Line[(x * sx4).toInt()];
-
-              C = 255 - _clamp8((Y + 1.402 * (Cr - 128)).toInt());
-              M = 255 - _clamp8((Y - 0.3441363 * (Cb - 128) -
-                                    0.71413636 * (Cr - 128)).toInt());
-              Ye = 255 - _clamp8((Y + 1.772 * (Cb - 128)).toInt());
-            }
-
-            data[offset++] = C;
-            data[offset++] = M;
-            data[offset++] = Ye;
-            data[offset++] = K;
-          }
-        }
-        break;
-      default:
-        throw new ImageException('Unsupported color mode');
-    }
-
-    return data;
-  }
-
-  void _read() {
-    int marker = _nextMarker();
-    if (marker != Jpeg.M_SOI) { // SOI (Start of Image)
-      throw new ImageException('Start Of Image marker not found.');
-    }
-
-    marker = _nextMarker();
-    while (marker != Jpeg.M_EOI && !input.isEOS) {
-      InputBuffer block = _readBlock();
-      switch (marker) {
-        case Jpeg.M_APP0:
-        case Jpeg.M_APP1:
-        case Jpeg.M_APP2:
-        case Jpeg.M_APP3:
-        case Jpeg.M_APP4:
-        case Jpeg.M_APP5:
-        case Jpeg.M_APP6:
-        case Jpeg.M_APP7:
-        case Jpeg.M_APP8:
-        case Jpeg.M_APP9:
-        case Jpeg.M_APP10:
-        case Jpeg.M_APP11:
-        case Jpeg.M_APP12:
-        case Jpeg.M_APP13:
-        case Jpeg.M_APP14:
-        case Jpeg.M_APP15:
-        case Jpeg.M_COM:
-          _readAppData(marker, block);
-          break;
-
-        case Jpeg.M_DQT: // DQT (Define Quantization Tables)
-          _readDQT(block);
-          break;
-
-        case Jpeg.M_SOF0: // SOF0 (Start of Frame, Baseline DCT)
-        case Jpeg.M_SOF1: // SOF1 (Start of Frame, Extended DCT)
-        case Jpeg.M_SOF2: // SOF2 (Start of Frame, Progressive DCT)
-          _readFrame(marker, block);
-          break;
-
-        case Jpeg.M_SOF3:
-        case Jpeg.M_SOF5:
-        case Jpeg.M_SOF6:
-        case Jpeg.M_SOF7:
-        case Jpeg.M_JPG:
-        case Jpeg.M_SOF9:
-        case Jpeg.M_SOF10:
-        case Jpeg.M_SOF11:
-        case Jpeg.M_SOF13:
-        case Jpeg.M_SOF14:
-        case Jpeg.M_SOF15:
-          throw new ImageException('Unhandled frame type ${marker.toRadixString(16)}');
-
-        case Jpeg.M_DHT: // DHT (Define Huffman Tables)
-          _readDHT(block);
-          break;
-
-        case Jpeg.M_DRI: // DRI (Define Restart Interval)
-          _readDRI(block);
-          break;
-
-        case Jpeg.M_SOS: // SOS (Start of Scan)
-          _readSOS(block);
-          break;
-
-        case 0xff: // Fill bytes
-          if (input[0] != 0xff) {
-            input.offset--;
-          }
-          break;
-
-        default:
-          if (input[-3] == 0xff && input[-2] >= 0xc0 && input[-2] <= 0xfe) {
-            // could be incorrect encoding -- last 0xFF byte of the previous
-            // block was eaten by the encoder
-            input.offset -= 3;
-            break;
-          }
-
-          if (marker != 0) {
-            throw new ImageException('Unknown JPEG marker ' +
-                marker.toRadixString(16));
-          }
-          break;
-      }
-
-      marker = _nextMarker();
-    }
-  }
-
-  void _skipBlock() {
-    int length = input.readUint16();
-    if (length < 2) {
-      throw new ImageException('Invalid Block');
-    }
-    input.offset += length - 2;
-  }
-
-  InputBuffer _readBlock() {
-    int length = input.readUint16();
-    if (length < 2) {
-      throw new ImageException('Invalid Block');
-    }
-    return input.readBytes(length - 2);
-  }
-
-  int _nextMarker() {
-    int c = 0;
-    if (input.isEOS) {
-      return c;
-    }
-
-    do {
-      do {
-        c = input.readByte();
-      } while (c != 0xff && !input.isEOS);
-
-      if (input.isEOS) {
-        return c;
-      }
-
-      do {
-        c = input.readByte();
-      } while (c == 0xff && !input.isEOS);
-    } while (c == 0 && !input.isEOS);
-
-    return c;
-  }
-
-  num _readExifValue(InputBuffer block, int format) {
-    const FMT_BYTE = 1;
-    //const FMT_STRING = 2;
-    const FMT_USHORT = 3;
-    const FMT_ULONG = 4;
-    const FMT_URATIONAL = 5;
-    const FMT_SBYTE = 6;
-    //const FMT_UNDEFINED = 7;
-    const FMT_SSHORT = 8;
-    const FMT_SLONG = 9;
-    const FMT_SRATIONAL = 10;
-    const FMT_SINGLE = 11;
-    const FMT_DOUBLE = 12;
-
-    switch (format) {
-      case FMT_SBYTE:
-        return block.readInt8();
-      case FMT_BYTE:
-        return block.readByte();
-      case FMT_USHORT:
-        return block.readUint16();
-      case FMT_ULONG:
-        return block.readUint32();
-      case FMT_URATIONAL:
-      case FMT_SRATIONAL: {
-        int num = block.readInt32();
-        int den = block.readInt32();
-        if (den == 0) {
-          return 0.0;
-        }
-        return num / den;
-      }
-      case FMT_SSHORT:
-        return block.readInt16();
-      case FMT_SLONG:
-        return block.readInt32();
-      // Not sure if this is correct (never seen float used in Exif format)
-      case FMT_SINGLE:
-        return block.readFloat32();
-      case FMT_DOUBLE:
-        return block.readFloat64();
-      default:
-        return 0;
-    }
-  }
-
-  void _readExifDir(InputBuffer block, [int nesting = 0]) {
-    if (nesting > 4) {
-      return; // Maximum Exif directory nesting exceeded (corrupt Exif header)
-    }
-
-    int numDirEntries = block.readUint16();
-
-    const TAG_ORIENTATION = 0x0112;
-    const TAG_INTEROP_OFFSET = 0xA005;
-    const TAG_EXIF_OFFSET = 0x8769;
-    const maxFormats = 12;
-    const bytesPerFormat = const [0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8];
-
-    for (int di = 0; di < numDirEntries; ++di) {
-      int tag = block.readUint16();
-      int format = block.readUint16();
-      int components = block.readUint32();
-
-      if (format - 1 >= maxFormats) {
-        continue;
-      }
-
-      // too many components
-      if (components > 0x10000) {
-        continue;
-      }
-
-      int byteCount = bytesPerFormat[format];
-
-      // If its bigger than 4 bytes, the dir entry contains an offset.
-      if (byteCount > 4) {
-        int offset = block.readUint32();
-        if (offset + byteCount > block.length) {
-          continue; // Bogus pointer offset and / or bytecount value
-        }
-
-        //ValuePtr = OffsetBase+OffsetVal;
-      }
-
-      switch (tag) {
-        case TAG_ORIENTATION: {
-            num orientation = _readExifValue(block, format);
-            exif.orientation = orientation.toInt();
-          }
-          break;
-        case TAG_EXIF_OFFSET:
-        case TAG_INTEROP_OFFSET:
-          break;
-        default:
-          // skip unknown tags
-          break;
-      }
-    }
-  }
-
-  void _readExifData(InputBuffer block) {
-    if (exif.rawData == null) {
-      exif.rawData = new List<Uint8List>();
-    }
-
-    Uint8List rawData = new Uint8List.fromList(block.toUint8List());
-    exif.rawData.add(rawData);
-
-    const EXIF_TAG = 0x45786966; // Exif\0\0
-    if (block.readUint32() != EXIF_TAG) {
-      return;
-    }
-    if (block.readUint16() != 0) {
-      return;
-    }
-
-    bool saveEndian = block.bigEndian;
-
-    // Exif Directory
-    String alignment = block.readString(2);
-    if (alignment == 'II') { // Exif is in Intel order
-      block.bigEndian = false;
-    } else if (alignment == 'MM') { // Exif section in Motorola order
-      block.bigEndian = true;
-    } else {
-      return;
-    }
-
-    block.skip(2);
-
-    int offset = block.readUint32();
-    if (offset < 8 || offset > 16){
-      if (offset > block.length - 16) {
-        // invalid offset for first Exif IFD value ;
-        block.bigEndian = saveEndian;
-        return;
-      }
-    }
-
-    if (offset > 8) {
-      block.skip(offset - 8);
-    }
-
-    _readExifDir(block);
-
-    block.bigEndian = saveEndian;
-  }
-
-  void _readAppData(int marker, InputBuffer block) {
-    InputBuffer appData = block;
-
-    if (marker == Jpeg.M_APP0) {
-      // 'JFIF\0'
-      if (appData[0] == 0x4A && appData[1] == 0x46 &&
-          appData[2] == 0x49 && appData[3] == 0x46 && appData[4] == 0) {
-        jfif = new JpegJfif();
-        jfif.majorVersion = appData[5];
-        jfif.minorVersion = appData[6];
-        jfif.densityUnits = appData[7];
-        jfif.xDensity = shiftL(appData[8], 8) | appData[9];
-        jfif.yDensity = shiftL(appData[10], 8) | appData[11];
-        jfif.thumbWidth = appData[12];
-        jfif.thumbHeight = appData[13];
-        int thumbSize = 3 * jfif.thumbWidth * jfif.thumbHeight;
-        jfif.thumbData = appData.subset(14 + thumbSize, offset: 14);
-      }
-    } else if (marker == Jpeg.M_APP1) {
-      // 'EXIF\0'
-      _readExifData(appData);
-    } else if (marker == Jpeg.M_APP14) {
-      // 'Adobe\0'
-      if (appData[0] == 0x41 && appData[1] == 0x64 &&
-          appData[2] == 0x6F && appData[3] == 0x62 &&
-          appData[4] == 0x65 && appData[5] == 0) {
-        adobe = new JpegAdobe();
-        adobe.version = appData[6];
-        adobe.flags0 = shiftL(appData[7], 8) | appData[8];
-        adobe.flags1 = shiftL(appData[9], 8) | appData[10];
-        adobe.transformCode = appData[11];
-      }
-    } else {
-      //print("!!!! UNHANDLED APP TAG 0x${marker.toRadixString(16)}");
-    }
-  }
-
-  void _readDQT(InputBuffer block) {
-    while (!block.isEOS) {
-      int n = block.readByte();
-      int prec = shiftR(n, 4);
-      n &= 0x0F;
-
-      if (n >= Jpeg.NUM_QUANT_TBLS) {
-        throw new ImageException('Invalid number of quantization tables');
-      }
-
-      if (quantizationTables[n] == null) {
-        quantizationTables[n] = new Int16List(64);
-      }
-
-      Int16List tableData = quantizationTables[n];
-      for (int i = 0; i < Jpeg.DCTSIZE2; i++) {
-        int tmp;
-        if (prec != 0) {
-          tmp = block.readUint16();
-        } else {
-          tmp = block.readByte();
-        }
-
-        tableData[Jpeg.dctZigZag[i]] = tmp;
-      }
-    }
-
-    if (!block.isEOS) {
-      throw new ImageException('Bad length for DQT block');
-    }
-  }
-
-  void _readFrame(int marker, InputBuffer block) {
-    if (frame != null) {
-      throw new ImageException('Duplicate JPG frame data found.');
-    }
-
-    frame = new JpegFrame();
-    frame.extended = (marker == Jpeg.M_SOF1);
-    frame.progressive = (marker == Jpeg.M_SOF2);
-    frame.precision = block.readByte();
-    frame.scanLines = block.readUint16();
-    frame.samplesPerLine = block.readUint16();
-
-    int numComponents = block.readByte();
-
-    for (int i = 0; i < numComponents; i++) {
-      int componentId = block.readByte();
-      int x = block.readByte();
-      int h = shiftR(x, 4) & 15;
-      int v = x & 15;
-      int qId = block.readByte();
-      frame.componentsOrder.add(componentId);
-      frame.components[componentId] =
-          new JpegComponent(h, v, quantizationTables, qId);
-    }
-
-    frame.prepare();
-    frames.add(frame);
-  }
-
-  void _readDHT(InputBuffer block) {
-    while (!block.isEOS) {
-      int index = block.readByte();
-
-      Uint8List bits = new Uint8List(16);
-      int count = 0;
-      for (int j = 0; j < 16; j++) {
-        bits[j] = block.readByte();
-        count += bits[j];
-      }
-
-      Uint8List huffmanValues = new Uint8List(count);
-      for (int j = 0; j < count; j++) {
-        huffmanValues[j] = block.readByte();
-      }
-
-      List ht;
-      if (index & 0x10 != 0) { // AC table definition
-        index -= 0x10;
-        ht = huffmanTablesAC;
-      } else { // DC table definition
-        ht = huffmanTablesDC;
-      }
-
-      if (ht.length <= index) {
-        ht.length = index + 1;
-      }
-
-      ht[index] = _buildHuffmanTable(bits, huffmanValues);
-    }
-  }
-
-  void _readDRI(InputBuffer block) {
-    resetInterval = block.readUint16();
-  }
-
-  void _readSOS(InputBuffer block) {
-    int n = block.readByte();
-    if (n < 1 || n > Jpeg.MAX_COMPS_IN_SCAN) {
-      throw new ImageException('Invalid SOS block');
-    }
-
-    List components = new List(n);
-    for (int i = 0; i < n; i++) {
-      int id = block.readByte();
-      int c = block.readByte();
-
-      if (!frame.components.containsKey(id)) {
-        throw new ImageException('Invalid Component in SOS block');
-      }
-
-      JpegComponent component = frame.components[id];
-      components[i] = component;
-
-      int dc_tbl_no = shiftR(c, 4) & 15;
-      int ac_tbl_no = c & 15;
-
-      if (dc_tbl_no < huffmanTablesDC.length) {
-        component.huffmanTableDC = huffmanTablesDC[dc_tbl_no];
-      }
-      if (ac_tbl_no < huffmanTablesAC.length) {
-        component.huffmanTableAC = huffmanTablesAC[ac_tbl_no];
-      }
-    }
-
-    int spectralStart = block.readByte();
-    int spectralEnd = block.readByte();
-    int successiveApproximation = block.readByte();
-
-    int Ah = shiftR(successiveApproximation, 4) & 15;
-    int Al = successiveApproximation & 15;
-
-    new JpegScan(input, frame, components, resetInterval,
-                  spectralStart, spectralEnd, Ah, Al).decode();
-  }
-
-  List _buildHuffmanTable(Uint8List codeLengths, Uint8List values) {
-    int k = 0;
-    List code = [];
-    int length = 16;
-
-    while (length > 0 && (codeLengths[length - 1] == 0)) {
-      length--;
-    }
-
-    code.add(new _JpegHuffman());
-
-    _JpegHuffman p = code[0];
-    _JpegHuffman q;
-
-    for (int i = 0; i < length; i++) {
-      for (int j = 0; j < codeLengths[i]; j++) {
-        p = code.removeLast();
-        if (p.children.length <= p.index) {
-          p.children.length = p.index + 1;
-        }
-        p.children[p.index] = values[k];
-        while (p.index > 0) {
-          p = code.removeLast();
-        }
-        p.index++;
-        code.add(p);
-        while (code.length <= i) {
-          q = new _JpegHuffman();
-          code.add(q);
-          if (p.children.length <= p.index) {
-            p.children.length = p.index + 1;
-          }
-          p.children[p.index] = q.children;
-          p = q;
-        }
-        k++;
-      }
-
-      if ((i + 1) < length) {
-        // p here points to last code
-        q = new _JpegHuffman();
-        code.add(q);
-        if (p.children.length <= p.index) {
-          p.children.length = p.index + 1;
-        }
-        p.children[p.index] = q.children;
-        p = q;
-      }
-    }
-
-    return code[0].children;
-  }
-
-  List<Uint8List> _buildComponentData(JpegFrame frame,
-                                      JpegComponent component) {
-    final int blocksPerLine = component.blocksPerLine;
-    final int blocksPerColumn = component.blocksPerColumn;
-    int samplesPerLine = shiftL(blocksPerLine, 3);
-    Int32List R = new Int32List(64);
-    Uint8List r = new Uint8List(64);
-    List<Uint8List> lines = new List(blocksPerColumn * 8);
-
-    int l = 0;
-    for (int blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
-      int scanLine = shiftL(blockRow, 3);
-      for (int i = 0; i < 8; i++) {
-        lines[l++] = new Uint8List(samplesPerLine);
-      }
-
-      for (int blockCol = 0; blockCol < blocksPerLine; blockCol++) {
-        _quantizeAndInverse(component.quantizationTable,
-                            component.blocks[blockRow][blockCol],
-                            r, R);
-
-        int offset = 0;
-        int sample = shiftL(blockCol, 3);
-        for (int j = 0; j < 8; j++) {
-          Uint8List line = lines[scanLine + j];
-          for (int i = 0; i < 8; i++) {
-            line[sample + i] = r[offset++];
-          }
-        }
-      }
-    }
-
-    return lines;
-  }
-
-  static int toFix(double val) {
-    const int FIXED_POINT = 20;
-    const int ONE = 1 << FIXED_POINT;
-
-    return (val * ONE).toInt() & 0xffffffff;
-  }
-
-  static int _clamp8(int i) => i < 0 ? 0 : i > 255 ? 255 : i;
-
-  static Uint8List dctClip;
-
-  /**
-   * Quantize the coefficients and apply IDCT.
-   *
-   * A port of poppler's IDCT method which in turn is taken from:
-   * Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
-   * "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
-   * IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, 988-991.
-   */
-  void _quantizeAndInverse(Int16List quantizationTable,
-                           Int32List coefBlock,
-                           Uint8List dataOut,
-                           Int32List dataIn) {
-    Int32List p = dataIn;
-
-    const int dctClipOffset = 256;
-    const int dctClipLength = 768;
-    if (dctClip == null) {
-      dctClip = new Uint8List(dctClipLength);
-      int i;
-      for (i = -256; i < 0; ++i) {
-        dctClip[dctClipOffset + i] = 0;
-      }
-      for (i = 0; i < 256; ++i) {
-        dctClip[dctClipOffset + i] = i;
-      }
-      for (i = 256; i < 512; ++i) {
-        dctClip[dctClipOffset + i] = 255;
-      }
-    }
-
-    // IDCT constants (20.12 fixed point format)
-    const int COS_1 = 4017;  // cos(pi/16)*4096
-    const int SIN_1 = 799;   // sin(pi/16)*4096
-    const int COS_3 = 3406;  // cos(3*pi/16)*4096
-    const int SIN_3 = 2276;  // sin(3*pi/16)*4096
-    const int COS_6 = 1567;  // cos(6*pi/16)*4096
-    const int SIN_6 = 3784;  // sin(6*pi/16)*4096
-    const int SQRT_2 = 5793;  // sqrt(2)*4096
-    const int SQRT_1D2 = 2896; // sqrt(2) / 2
-
-    // de-quantize
-    for (int i = 0; i < 64; i++) {
-      p[i] = (coefBlock[i] * quantizationTable[i]);
-    }
-
-    // inverse DCT on rows
-    int row = 0;
-    for (int i = 0; i < 8; ++i, row += 8) {
-      // check for all-zero AC coefficients
-      if (p[1 + row] == 0 &&
-      p[2 + row] == 0 &&
-      p[3 + row] == 0 &&
-      p[4 + row] == 0 &&
-      p[5 + row] == 0 &&
-      p[6 + row] == 0 &&
-      p[7 + row] == 0) {
-        int t = shiftR((SQRT_2 * p[0 + row] + 512), 10);
-        p[row + 0] = t;
-        p[row + 1] = t;
-        p[row + 2] = t;
-        p[row + 3] = t;
-        p[row + 4] = t;
-        p[row + 5] = t;
-        p[row + 6] = t;
-        p[row + 7] = t;
-        continue;
-      }
-
-      // stage 4
-      int v0 = shiftR((SQRT_2 * p[0 + row] + 128), 8);
-      int v1 = shiftR((SQRT_2 * p[4 + row] + 128), 8);
-      int v2 = p[2 + row];
-      int v3 = p[6 + row];
-      int v4 = shiftR((SQRT_1D2 * (p[1 + row] - p[7 + row]) + 128), 8);
-      int v7 = shiftR((SQRT_1D2 * (p[1 + row] + p[7 + row]) + 128), 8);
-      int v5 = shiftL(p[3 + row], 4);
-      int v6 = shiftL(p[5 + row], 4);
-
-      // stage 3
-      int t = shiftR((v0 - v1 + 1), 1);
-      v0 = shiftR((v0 + v1 + 1), 1);
-      v1 = t;
-      t = shiftR((v2 * SIN_6 + v3 * COS_6 + 128), 8);
-      v2 = shiftR((v2 * COS_6 - v3 * SIN_6 + 128), 8);
-      v3 = t;
-      t = shiftR((v4 - v6 + 1), 1);
-      v4 = shiftR((v4 + v6 + 1), 1);
-      v6 = t;
-      t = shiftR((v7 + v5 + 1), 1);
-      v5 = shiftR((v7 - v5 + 1), 1);
-      v7 = t;
-
-      // stage 2
-      t = shiftR((v0 - v3 + 1), 1);
-      v0 = shiftR((v0 + v3 + 1), 1);
-      v3 = t;
-      t = shiftR((v1 - v2 + 1), 1);
-      v1 = shiftR((v1 + v2 + 1), 1);
-      v2 = t;
-      t = shiftR((v4 * SIN_3 + v7 * COS_3 + 2048), 12);
-      v4 = shiftR((v4 * COS_3 - v7 * SIN_3 + 2048), 12);
-      v7 = t;
-      t = shiftR((v5 * SIN_1 + v6 * COS_1 + 2048), 12);
-      v5 = shiftR((v5 * COS_1 - v6 * SIN_1 + 2048), 12);
-      v6 = t;
-
-      // stage 1
-      p[0 + row] = (v0 + v7);
-      p[7 + row] = (v0 - v7);
-      p[1 + row] = (v1 + v6);
-      p[6 + row] = (v1 - v6);
-      p[2 + row] = (v2 + v5);
-      p[5 + row] = (v2 - v5);
-      p[3 + row] = (v3 + v4);
-      p[4 + row] = (v3 - v4);
-    }
-
-    // inverse DCT on columns
-    for (int i = 0; i < 8; ++i) {
-      int col = i;
-
-      // check for all-zero AC coefficients
-      if (p[1 * 8 + col] == 0 &&
-      p[2 * 8 + col] == 0 &&
-      p[3 * 8 + col] == 0 &&
-      p[4 * 8 + col] == 0 &&
-      p[5 * 8 + col] == 0 &&
-      p[6 * 8 + col] == 0 &&
-      p[7 * 8 + col] == 0) {
-        int t = shiftR((SQRT_2 * dataIn[i] + 8192), 14);
-        p[0 * 8 + col] = t;
-        p[1 * 8 + col] = t;
-        p[2 * 8 + col] = t;
-        p[3 * 8 + col] = t;
-        p[4 * 8 + col] = t;
-        p[5 * 8 + col] = t;
-        p[6 * 8 + col] = t;
-        p[7 * 8 + col] = t;
-        continue;
-      }
-
-      // stage 4
-      int v0 = shiftR((SQRT_2 * p[0 * 8 + col] + 2048), 12);
-      int v1 = shiftR((SQRT_2 * p[4 * 8 + col] + 2048), 12);
-      int v2 = p[2 * 8 + col];
-      int v3 = p[6 * 8 + col];
-      int v4 = shiftR((SQRT_1D2 * (p[1 * 8 + col] - p[7 * 8 + col]) + 2048), 12);
-      int v7 = shiftR((SQRT_1D2 * (p[1 * 8 + col] + p[7 * 8 + col]) + 2048), 12);
-      int v5 = p[3 * 8 + col];
-      int v6 = p[5 * 8 + col];
-
-      // stage 3
-      int t = shiftR((v0 - v1 + 1), 1);
-      v0 = shiftR((v0 + v1 + 1), 1);
-      v1 = t;
-      t = shiftR((v2 * SIN_6 + v3 * COS_6 + 2048), 12);
-      v2 = shiftR((v2 * COS_6 - v3 * SIN_6 + 2048), 12);
-      v3 = t;
-      t = shiftR((v4 - v6 + 1), 1);
-      v4 = shiftR((v4 + v6 + 1), 1);
-      v6 = t;
-      t = shiftR((v7 + v5 + 1), 1);
-      v5 = shiftR((v7 - v5 + 1), 1);
-      v7 = t;
-
-      // stage 2
-      t = shiftR((v0 - v3 + 1), 1);
-      v0 = shiftR((v0 + v3 + 1), 1);
-      v3 = t;
-      t = shiftR((v1 - v2 + 1), 1);
-      v1 = shiftR((v1 + v2 + 1), 1);
-      v2 = t;
-      t = shiftR((v4 * SIN_3 + v7 * COS_3 + 2048), 12);
-      v4 = shiftR((v4 * COS_3 - v7 * SIN_3 + 2048), 12);
-      v7 = t;
-      t = shiftR((v5 * SIN_1 + v6 * COS_1 + 2048), 12);
-      v5 = shiftR((v5 * COS_1 - v6 * SIN_1 + 2048), 12);
-      v6 = t;
-
-      // stage 1
-      p[0 * 8 + col] = (v0 + v7);
-      p[7 * 8 + col] = (v0 - v7);
-      p[1 * 8 + col] = (v1 + v6);
-      p[6 * 8 + col] = (v1 - v6);
-      p[2 * 8 + col] = (v2 + v5);
-      p[5 * 8 + col] = (v2 - v5);
-      p[3 * 8 + col] = (v3 + v4);
-      p[4 * 8 + col] = (v3 - v4);
-    }
-
-    // convert to 8-bit integers
-    for (int i = 0; i < 64; ++i) {
-      dataOut[i] = dctClip[(dctClipOffset + 128 + shiftR((p[i] + 8), 4))];
-    }
-  }
-
-  static const CRR = const [
-    -179, -178, -177, -175, -174, -172, -171, -170, -168, -167, -165, -164, -163,
-    -161, -160, -158, -157, -156, -154, -153, -151, -150, -149, -147, -146, -144, -143,
-    -142, -140, -139, -137, -136, -135, -133, -132, -130, -129, -128, -126, -125,
-    -123, -122, -121, -119, -118, -116, -115, -114, -112, -111, -109, -108, -107,
-    -105, -104, -102, -101, -100, -98, -97, -95, -94, -93, -91, -90, -88, -87, -86,
-    -84, -83, -81, -80, -79, -77, -76, -74, -73, -72, -70, -69, -67, -66, -64, -63,
-    -62, -60, -59, -57, -56, -55, -53, -52, -50, -49, -48, -46, -45, -43, -42, -41,
-    -39, -38, -36, -35, -34, -32, -31, -29, -28, -27, -25, -24, -22, -21, -20, -18,
-    -17, -15, -14, -13, -11, -10, -8, -7, -6, -4, -3, -1, 0, 1, 3, 4, 6, 7, 8, 10,
-    11, 13, 14, 15, 17, 18, 20, 21, 22, 24, 25, 27, 28, 29, 31, 32, 34, 35, 36, 38,
-    39, 41, 42, 43, 45, 46, 48, 49, 50, 52, 53, 55, 56, 57, 59, 60, 62, 63, 64, 66,
-    67, 69, 70, 72, 73, 74, 76, 77, 79, 80, 81, 83, 84, 86, 87, 88, 90, 91, 93, 94,
-    95, 97, 98, 100, 101, 102, 104, 105, 107, 108, 109, 111, 112, 114, 115, 116, 118,
-    119, 121, 122, 123, 125, 126, 128, 129, 130, 132, 133, 135, 136, 137, 139, 140,
-    142, 143, 144, 146, 147, 149, 150, 151, 153, 154, 156, 157, 158, 160, 161, 163,
-    164, 165, 167, 168, 170, 171, 172, 174, 175, 177, 178
-  ];
-
-  static const CRG = const [
-    5990656, 5943854, 5897052, 5850250, 5803448, 5756646, 5709844, 5663042, 5616240,
-    5569438, 5522636, 5475834, 5429032, 5382230, 5335428, 5288626, 5241824, 5195022,
-    5148220, 5101418, 5054616, 5007814, 4961012, 4914210, 4867408, 4820606, 4773804,
-    4727002, 4680200, 4633398, 4586596, 4539794, 4492992, 4446190, 4399388, 4352586,
-    4305784, 4258982, 4212180, 4165378, 4118576, 4071774, 4024972, 3978170, 3931368,
-    3884566, 3837764, 3790962, 3744160, 3697358, 3650556, 3603754, 3556952, 3510150,
-    3463348, 3416546, 3369744, 3322942, 3276140, 3229338, 3182536, 3135734, 3088932,
-    3042130, 2995328, 2948526, 2901724, 2854922, 2808120, 2761318, 2714516, 2667714,
-    2620912, 2574110, 2527308, 2480506, 2433704, 2386902, 2340100, 2293298, 2246496,
-    2199694, 2152892, 2106090, 2059288, 2012486, 1965684, 1918882, 1872080, 1825278,
-    1778476, 1731674, 1684872, 1638070, 1591268, 1544466, 1497664, 1450862, 1404060,
-    1357258, 1310456, 1263654, 1216852, 1170050, 1123248, 1076446, 1029644, 982842,
-    936040, 889238, 842436, 795634, 748832, 702030, 655228, 608426, 561624, 514822,
-    468020, 421218, 374416, 327614, 280812, 234010, 187208, 140406, 93604, 46802, 0,
-    -46802, -93604, -140406, -187208, -234010, -280812, -327614, -374416, -421218,
-    -468020, -514822, -561624, -608426, -655228, -702030, -748832, -795634, -842436,
-    -889238, -936040, -982842, -1029644, -1076446, -1123248, -1170050, -1216852,
-    -1263654, -1310456, -1357258, -1404060, -1450862, -1497664, -1544466, -1591268,
-    -1638070, -1684872, -1731674, -1778476, -1825278, -1872080, -1918882, -1965684,
-    -2012486, -2059288, -2106090, -2152892, -2199694, -2246496, -2293298, -2340100,
-    -2386902, -2433704, -2480506, -2527308, -2574110, -2620912, -2667714, -2714516,
-    -2761318, -2808120, -2854922, -2901724, -2948526, -2995328, -3042130, -3088932,
-    -3135734, -3182536, -3229338, -3276140, -3322942, -3369744, -3416546, -3463348,
-    -3510150, -3556952, -3603754, -3650556, -3697358, -3744160, -3790962, -3837764,
-    -3884566, -3931368, -3978170, -4024972, -4071774, -4118576, -4165378, -4212180,
-    -4258982, -4305784, -4352586, -4399388, -4446190, -4492992, -4539794, -4586596,
-    -4633398, -4680200, -4727002, -4773804, -4820606, -4867408, -4914210, -4961012,
-    -5007814, -5054616, -5101418, -5148220, -5195022, -5241824, -5288626, -5335428,
-    -5382230, -5429032, -5475834, -5522636, -5569438, -5616240, -5663042, -5709844,
-    -5756646, -5803448, -5850250, -5897052, -5943854
-  ];
-
-  static const CBG = const [
-    2919680, 2897126, 2874572, 2852018, 2829464, 2806910, 2784356, 2761802, 2739248, 2716694,
-    2694140, 2671586, 2649032, 2626478, 2603924, 2581370, 2558816, 2536262, 2513708,
-    2491154, 2468600, 2446046, 2423492, 2400938, 2378384, 2355830, 2333276, 2310722,
-    2288168, 2265614, 2243060, 2220506, 2197952, 2175398, 2152844, 2130290, 2107736,
-    2085182, 2062628, 2040074, 2017520, 1994966, 1972412, 1949858, 1927304, 1904750,
-    1882196, 1859642, 1837088, 1814534, 1791980, 1769426, 1746872, 1724318, 1701764,
-    1679210, 1656656, 1634102, 1611548, 1588994, 1566440, 1543886, 1521332, 1498778,
-    1476224, 1453670, 1431116, 1408562, 1386008, 1363454, 1340900, 1318346, 1295792,
-    1273238, 1250684, 1228130, 1205576, 1183022, 1160468, 1137914, 1115360,
-    1092806, 1070252, 1047698, 1025144, 1002590, 980036, 957482, 934928, 912374,
-    889820, 867266, 844712, 822158, 799604, 777050, 754496, 731942, 709388, 686834,
-    664280, 641726, 619172, 596618, 574064, 551510, 528956, 506402, 483848, 461294,
-    438740, 416186, 393632, 371078, 348524, 325970, 303416, 280862, 258308, 235754,
-    213200, 190646, 168092, 145538, 122984, 100430, 77876, 55322, 32768, 10214, -12340,
-    -34894, -57448, -80002, -102556, -125110, -147664, -170218, -192772, -215326,
-    -237880, -260434, -282988, -305542, -328096, -350650, -373204, -395758, -418312,
-    -440866, -463420, -485974, -508528, -531082, -553636, -576190, -598744, -621298,
-    -643852, -666406, -688960, -711514, -734068, -756622, -779176, -801730, -824284,
-    -846838, -869392, -891946, -914500, -937054, -959608, -982162, -1004716, -1027270,
-    -1049824, -1072378, -1094932, -1117486, -1140040, -1162594, -1185148, -1207702,
-    -1230256, -1252810, -1275364, -1297918, -1320472, -1343026, -1365580, -1388134,
-    -1410688, -1433242, -1455796, -1478350, -1500904, -1523458, -1546012, -1568566,
-    -1591120, -1613674, -1636228, -1658782, -1681336, -1703890, -1726444, -1748998,
-    -1771552, -1794106, -1816660, -1839214, -1861768, -1884322, -1906876, -1929430,
-    -1951984, -1974538, -1997092, -2019646, -2042200, -2064754, -2087308, -2109862,
-    -2132416, -2154970, -2177524, -2200078, -2222632, -2245186, -2267740, -2290294,
-    -2312848, -2335402, -2357956, -2380510, -2403064, -2425618, -2448172, -2470726,
-    -2493280, -2515834, -2538388, -2560942, -2583496, -2606050, -2628604, -2651158,
-    -2673712, -2696266, -2718820, -2741374, -2763928, -2786482, -2809036, -2831590
-  ];
-
-  static const CBB = const [
-    -227, -225, -223, -222, -220, -218, -216, -214, -213, -211, -209, -207, -206,
-    -204, -202, -200, -198, -197, -195, -193, -191, -190, -188,
-    -186, -184, -183, -181, -179, -177, -175, -174, -172, -170, -168, -167, -165,
-    -163, -161, -159, -158, -156, -154, -152, -151, -149, -147, -145, -144, -142,
-    -140, -138, -136, -135, -133, -131, -129, -128, -126, -124, -122, -120, -119, -117,
-    -115, -113, -112, -110, -108, -106, -105, -103, -101, -99, -97, -96, -94, -92,
-    -90, -89, -87, -85, -83, -82, -80, -78, -76, -74, -73, -71, -69, -67, -66, -64,
-    -62, -60, -58, -57, -55, -53, -51, -50, -48, -46, -44, -43, -41, -39, -37, -35,
-    -34, -32, -30, -28, -27, -25, -23, -21, -19, -18, -16, -14, -12, -11, -9, -7,
-    -5, -4, -2, 0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, 27, 28, 30, 32,
-    34, 35, 37, 39, 41, 43, 44, 46, 48, 50, 51, 53, 55, 57, 58, 60, 62, 64, 66, 67,
-    69, 71, 73, 74, 76, 78, 80, 82, 83, 85, 87, 89, 90, 92, 94, 96, 97, 99, 101, 103,
-    105, 106, 108, 110, 112, 113, 115, 117, 119, 120, 122, 124, 126, 128, 129, 131,
-    133, 135, 136, 138, 140, 142, 144, 145, 147, 149, 151, 152, 154, 156, 158, 159,
-    161, 163, 165, 167, 168, 170, 172, 174, 175, 177, 179, 181, 183, 184, 186, 188,
-    190, 191, 193, 195, 197, 198, 200, 202, 204, 206, 207, 209, 211, 213, 214, 216,
-    218, 220, 222, 223, 225
-  ];
-}
-
-class _JpegHuffman {
-  List children = [];
-  int index = 0;
-}
-
-/*class _JPEG_HuffTables {
-  bool ac_table = false;
-  Uint32List look_up = new Uint32List(256);
-  Uint32List look_up2 = new Uint32List(256);
-  Uint8List code_size = new Uint8List(256);
-  Uint32List tree = new Uint32List(512);
-}*/
+import 'dart:typed_data';

+

+import '../../exif_data.dart';

+import '../../image_exception.dart';

+import '../../internal/bit_operators.dart';

+import '../../util/input_buffer.dart';

+import 'jpeg.dart';

+import 'jpeg_adobe.dart';

+import 'jpeg_component.dart';

+import 'jpeg_frame.dart';

+import 'jpeg_info.dart';

+import 'jpeg_jfif.dart';

+import 'jpeg_scan.dart';

+

+class JpegData  {

+  InputBuffer input;

+  JpegJfif jfif;

+  JpegAdobe adobe;

+  JpegFrame frame;

+  int resetInterval;

+  ExifData exif = ExifData();

+  final List<Int16List> quantizationTables = List(Jpeg.NUM_QUANT_TBLS);

+  final List<JpegFrame> frames = [];

+  final List huffmanTablesAC = [];

+  final List huffmanTablesDC = [];

+  final List<_ComponentData> components = [];

+

+  bool validate(List<int> bytes) {

+    input = InputBuffer(bytes, bigEndian: true);

+

+    int marker = _nextMarker();

+    if (marker != Jpeg.M_SOI) {

+      return false;

+    }

+

+    bool hasSOF = false;

+    bool hasSOS = false;

+

+    marker = _nextMarker();

+    while (marker != Jpeg.M_EOI && !input.isEOS) { // EOI (End of image)

+      _skipBlock();

+      switch (marker) {

+        case Jpeg.M_SOF0: // SOF0 (Start of Frame, Baseline DCT)

+        case Jpeg.M_SOF1: // SOF1 (Start of Frame, Extended DCT)

+        case Jpeg.M_SOF2: // SOF2 (Start of Frame, Progressive DCT)

+          hasSOF = true;

+          break;

+        case Jpeg.M_SOS: // SOS (Start of Scan)

+          hasSOS = true;

+          break;

+        default:

+      }

+

+      marker = _nextMarker();

+    }

+

+    return hasSOF && hasSOS;

+  }

+

+  JpegInfo readInfo(List<int> bytes) {

+    input = InputBuffer(bytes, bigEndian: true);

+

+    int marker = _nextMarker();

+    if (marker != Jpeg.M_SOI) {

+      return null;

+    }

+

+    JpegInfo info = JpegInfo();

+

+    bool hasSOF = false;

+    bool hasSOS = false;

+

+    marker = _nextMarker();

+    while (marker != Jpeg.M_EOI && !input.isEOS) { // EOI (End of image)

+      switch (marker) {

+        case Jpeg.M_SOF0: // SOF0 (Start of Frame, Baseline DCT)

+        case Jpeg.M_SOF1: // SOF1 (Start of Frame, Extended DCT)

+        case Jpeg.M_SOF2: // SOF2 (Start of Frame, Progressive DCT)

+          hasSOF = true;

+          _readFrame(marker, _readBlock());

+          break;

+        case Jpeg.M_SOS: // SOS (Start of Scan)

+          hasSOS = true;

+          _skipBlock();

+          break;

+        default:

+          _skipBlock();

+          break;

+      }

+

+      marker = _nextMarker();

+    }

+

+    if (frame != null) {

+      info.width = frame.samplesPerLine;

+      info.height = frame.scanLines;

+    }

+    frame = null;

+    frames.clear();

+

+    return (hasSOF && hasSOS) ? info : null;

+  }

+

+  void read(List<int> bytes) {

+    input = InputBuffer(bytes, bigEndian: true);

+

+    _read();

+

+    if (frames.length != 1) {

+      throw new ImageException('Only single frame JPEGs supported');

+    }

+

+    for (int i = 0; i < frame.componentsOrder.length; ++i) {

+      /*JpegComponent component =*/ frame.components[frame.componentsOrder[i]];

+    }

+

+    for (int i = 0; i < frame.componentsOrder.length; ++i) {

+      JpegComponent component = frame.components[frame.componentsOrder[i]];

+      components.add(_ComponentData(component.hSamples, frame.maxHSamples,

+                                    component.vSamples, frame.maxVSamples,

+                                    _buildComponentData(frame, component)));

+    }

+  }

+

+  int get width => frame.samplesPerLine;

+

+  int get height => frame.scanLines;

+

+  Uint8List getData(int width, int height) {

+    num scaleX = 1;

+    num scaleY = 1;

+    _ComponentData component1;

+    _ComponentData component2;

+    _ComponentData component3;

+    _ComponentData component4;

+    Uint8List component1Line;

+    Uint8List component2Line;

+    Uint8List component3Line;

+    Uint8List component4Line;

+    int offset = 0;

+    int Y, Cb, Cr, K, C, M, Ye, R, G, B;

+    bool colorTransform = false;

+    int dataLength = width * height * components.length;

+    Uint8List data = Uint8List(dataLength);

+

+    switch (components.length) {

+      case 1:

+        component1 = components[0];

+        var lines = component1.lines;

+        int hShift1 = component1.hScaleShift;

+        int vShift1 = component1.vScaleShift;

+        for (int y = 0; y < height; y++) {

+          int y1 = y >> vShift1;

+          component1Line = lines[y1];

+          for (int x = 0; x < width; x++) {

+            int x1 = x >> hShift1;

+            Y = component1Line[x1];

+            data[offset++] = Y;

+          }

+        }

+        break;

+      case 2:

+        // PDF might compress two component data in custom color-space

+        component1 = components[0];

+        component2 = components[1];

+        int hShift1 = component1.hScaleShift;

+        int vShift1 = component1.vScaleShift;

+        int hShift2 = component2.hScaleShift;

+        int vShift2 = component2.vScaleShift;

+

+        for (int y = 0; y < height; y++) {

+          int y1 = y >> vShift1;

+          int y2 = y >> vShift2;

+          component1Line = component1.lines[y1];

+          component2Line = component2.lines[y2];

+

+          for (int x = 0; x < width; x++) {

+            int x1 = x >> hShift1;

+            int x2 = x >> hShift2;

+

+            Y = component1Line[x1];

+            data[offset++] = Y;

+

+            Y = component2Line[x2];

+            data[offset++] = Y;

+          }

+        }

+        break;

+      case 3:

+        // The default transform for three components is true

+        colorTransform = true;

+

+        component1 = components[0];

+        component2 = components[1];

+        component3 = components[2];

+

+        var lines1 = component1.lines;

+        var lines2 = component2.lines;

+        var lines3 = component3.lines;

+

+        int hShift1 = component1.hScaleShift;

+        int vShift1 = component1.vScaleShift;

+        int hShift2 = component2.hScaleShift;

+        int vShift2 = component2.vScaleShift;

+        int hShift3 = component3.hScaleShift;

+        int vShift3 = component3.vScaleShift;

+

+        for (int y = 0; y < height; y++) {

+          int y1 = y >> vShift1;

+          int y2 = y >> vShift2;

+          int y3 = y >> vShift3;

+

+          component1Line = lines1[y1];

+          component2Line = lines2[y2];

+          component3Line = lines3[y3];

+

+          for (int x = 0; x < width; x++) {

+            int x1 = x >> hShift1;

+            int x2 = x >> hShift2;

+            int x3 = x >> hShift3;

+

+            if (!colorTransform) {

+              data[offset++] = component1Line[x1];

+              data[offset++] = component2Line[x2];

+              data[offset++] = component3Line[x3];

+            } else {

+              Y = component1Line[x1] << 8;

+              Cb = component2Line[x2] - 128;

+              Cr = component3Line[x3] - 128;

+

+              R = shiftR((Y + 359 * Cr + 128), 8);

+              G = shiftR((Y - 88 * Cb - 183 * Cr + 128), 8);

+              B = shiftR((Y + 454 * Cb + 128), 8);

+

+              data[offset++] = _clamp8(R);

+              data[offset++] = _clamp8(G);

+              data[offset++] = _clamp8(B);

+            }

+          }

+        }

+        break;

+      case 4:

+        if (adobe == null) {

+          throw new ImageException('Unsupported color mode (4 components)');

+        }

+        // The default transform for four components is false

+        colorTransform = false;

+        // The adobe transform marker overrides any previous setting

+        if (adobe.transformCode != 0) {

+          colorTransform = true;

+        }

+

+        component1 = components[0];

+        component2 = components[1];

+        component3 = components[2];

+        component4 = components[3];

+

+        var lines1 = component1.lines;

+        var lines2 = component2.lines;

+        var lines3 = component3.lines;

+        var lines4 = component4.lines;

+

+        int hShift1 = component1.hScaleShift;

+        int vShift1 = component1.vScaleShift;

+        int hShift2 = component2.hScaleShift;

+        int vShift2 = component2.vScaleShift;

+        int hShift3 = component3.hScaleShift;

+        int vShift3 = component3.vScaleShift;

+        int hShift4 = component4.hScaleShift;

+        int vShift4 = component4.vScaleShift;

+

+        for (int y = 0; y < height; y++) {

+          int y1 = y >> vShift1;

+          int y2 = y >> vShift2;

+          int y3 = y >> vShift3;

+          int y4 = y >> vShift4;

+          component1Line = lines1[y1];

+          component2Line = lines2[y2];

+          component3Line = lines3[y3];

+          component4Line = lines4[y4];

+          for (int x = 0; x < width; x++) {

+            int x1 = x >> hShift1;

+            int x2 = x >> hShift2;

+            int x3 = x >> hShift3;

+            int x4 = x >> hShift4;

+            if (!colorTransform) {

+              C = component1Line[x1];

+              M = component2Line[x2];

+              Ye = component3Line[x3];

+              K = component4Line[x4];

+            } else {

+              Y = component1Line[x1];

+              Cb = component2Line[x2];

+              Cr = component3Line[x3];

+              K = component4Line[x4];

+

+              C = 255 - _clamp8((Y + 1.402 * (Cr - 128)).toInt());

+              M = 255 - _clamp8((Y - 0.3441363 * (Cb - 128) -

+                                    0.71413636 * (Cr - 128)).toInt());

+              Ye = 255 - _clamp8((Y + 1.772 * (Cb - 128)).toInt());

+            }

+

+            data[offset++] = C;

+            data[offset++] = M;

+            data[offset++] = Ye;

+            data[offset++] = K;

+          }

+        }

+        break;

+      default:

+        throw new ImageException('Unsupported color mode');

+    }

+

+    return data;

+  }

+

+  void _read() {

+    int marker = _nextMarker();

+    if (marker != Jpeg.M_SOI) { // SOI (Start of Image)

+      throw new ImageException('Start Of Image marker not found.');

+    }

+

+    marker = _nextMarker();

+    while (marker != Jpeg.M_EOI && !input.isEOS) {

+      InputBuffer block = _readBlock();

+      switch (marker) {

+        case Jpeg.M_APP0:

+        case Jpeg.M_APP1:

+        case Jpeg.M_APP2:

+        case Jpeg.M_APP3:

+        case Jpeg.M_APP4:

+        case Jpeg.M_APP5:

+        case Jpeg.M_APP6:

+        case Jpeg.M_APP7:

+        case Jpeg.M_APP8:

+        case Jpeg.M_APP9:

+        case Jpeg.M_APP10:

+        case Jpeg.M_APP11:

+        case Jpeg.M_APP12:

+        case Jpeg.M_APP13:

+        case Jpeg.M_APP14:

+        case Jpeg.M_APP15:

+        case Jpeg.M_COM:

+          _readAppData(marker, block);

+          break;

+

+        case Jpeg.M_DQT: // DQT (Define Quantization Tables)

+          _readDQT(block);

+          break;

+

+        case Jpeg.M_SOF0: // SOF0 (Start of Frame, Baseline DCT)

+        case Jpeg.M_SOF1: // SOF1 (Start of Frame, Extended DCT)

+        case Jpeg.M_SOF2: // SOF2 (Start of Frame, Progressive DCT)

+          _readFrame(marker, block);

+          break;

+

+        case Jpeg.M_SOF3:

+        case Jpeg.M_SOF5:

+        case Jpeg.M_SOF6:

+        case Jpeg.M_SOF7:

+        case Jpeg.M_JPG:

+        case Jpeg.M_SOF9:

+        case Jpeg.M_SOF10:

+        case Jpeg.M_SOF11:

+        case Jpeg.M_SOF13:

+        case Jpeg.M_SOF14:

+        case Jpeg.M_SOF15:

+          throw new ImageException('Unhandled frame type ${marker.toRadixString(16)}');

+

+        case Jpeg.M_DHT: // DHT (Define Huffman Tables)

+          _readDHT(block);

+          break;

+

+        case Jpeg.M_DRI: // DRI (Define Restart Interval)

+          _readDRI(block);

+          break;

+

+        case Jpeg.M_SOS: // SOS (Start of Scan)

+          _readSOS(block);

+          break;

+

+        case 0xff: // Fill bytes

+          if (input[0] != 0xff) {

+            input.offset--;

+          }

+          break;

+

+        default:

+          if (input[-3] == 0xff && input[-2] >= 0xc0 && input[-2] <= 0xfe) {

+            // could be incorrect encoding -- last 0xFF byte of the previous

+            // block was eaten by the encoder

+            input.offset -= 3;

+            break;

+          }

+

+          if (marker != 0) {

+            throw new ImageException('Unknown JPEG marker ' +

+                marker.toRadixString(16));

+          }

+          break;

+      }

+

+      marker = _nextMarker();

+    }

+  }

+

+  void _skipBlock() {

+    int length = input.readUint16();

+    if (length < 2) {

+      throw new ImageException('Invalid Block');

+    }

+    input.offset += length - 2;

+  }

+

+  InputBuffer _readBlock() {

+    int length = input.readUint16();

+    if (length < 2) {

+      throw new ImageException('Invalid Block');

+    }

+    return input.readBytes(length - 2);

+  }

+

+  int _nextMarker() {

+    int c = 0;

+    if (input.isEOS) {

+      return c;

+    }

+

+    do {

+      do {

+        c = input.readByte();

+      } while (c != 0xff && !input.isEOS);

+

+      if (input.isEOS) {

+        return c;

+      }

+

+      do {

+        c = input.readByte();

+      } while (c == 0xff && !input.isEOS);

+    } while (c == 0 && !input.isEOS);

+

+    return c;

+  }

+

+  num _readExifValue(InputBuffer block, int format) {

+    const FMT_BYTE = 1;

+    //const FMT_STRING = 2;

+    const FMT_USHORT = 3;

+    const FMT_ULONG = 4;

+    const FMT_URATIONAL = 5;

+    const FMT_SBYTE = 6;

+    //const FMT_UNDEFINED = 7;

+    const FMT_SSHORT = 8;

+    const FMT_SLONG = 9;

+    const FMT_SRATIONAL = 10;

+    const FMT_SINGLE = 11;

+    const FMT_DOUBLE = 12;

+

+    switch (format) {

+      case FMT_SBYTE:

+        return block.readInt8();

+      case FMT_BYTE:

+        return block.readByte();

+      case FMT_USHORT:

+        return block.readUint16();

+      case FMT_ULONG:

+        return block.readUint32();

+      case FMT_URATIONAL:

+      case FMT_SRATIONAL: {

+        int num = block.readInt32();

+        int den = block.readInt32();

+        if (den == 0) {

+          return 0.0;

+        }

+        return num / den;

+      }

+      case FMT_SSHORT:

+        return block.readInt16();

+      case FMT_SLONG:

+        return block.readInt32();

+      // Not sure if this is correct (never seen float used in Exif format)

+      case FMT_SINGLE:

+        return block.readFloat32();

+      case FMT_DOUBLE:

+        return block.readFloat64();

+      default:

+        return 0;

+    }

+  }

+

+  void _readExifDir(InputBuffer block, [int nesting = 0]) {

+    if (nesting > 4) {

+      return; // Maximum Exif directory nesting exceeded (corrupt Exif header)

+    }

+

+    int numDirEntries = block.readUint16();

+

+    const TAG_ORIENTATION = 0x0112;

+    const TAG_INTEROP_OFFSET = 0xA005;

+    const TAG_EXIF_OFFSET = 0x8769;

+    const maxFormats = 12;

+    const bytesPerFormat = const [0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8];

+

+    for (int di = 0; di < numDirEntries; ++di) {

+      int tag = block.readUint16();

+      int format = block.readUint16();

+      int components = block.readUint32();

+

+      if (format - 1 >= maxFormats) {

+        continue;

+      }

+

+      // too many components

+      if (components > 0x10000) {

+        continue;

+      }

+

+      int byteCount = bytesPerFormat[format];

+

+      // If its bigger than 4 bytes, the dir entry contains an offset.

+      if (byteCount > 4) {

+        int offset = block.readUint32();

+        if (offset + byteCount > block.length) {

+          continue; // Bogus pointer offset and / or bytecount value

+        }

+

+        //ValuePtr = OffsetBase+OffsetVal;

+      }

+

+      switch (tag) {

+        case TAG_ORIENTATION: {

+            num orientation = _readExifValue(block, format);

+            exif.orientation = orientation.toInt();

+          }

+          break;

+        case TAG_EXIF_OFFSET:

+        case TAG_INTEROP_OFFSET:

+          break;

+        default:

+          // skip unknown tags

+          break;

+      }

+    }

+  }

+

+  void _readExifData(InputBuffer block) {

+    if (exif.rawData == null) {

+      exif.rawData = List<Uint8List>();

+    }

+

+    Uint8List rawData = Uint8List.fromList(block.toUint8List());

+    exif.rawData.add(rawData);

+

+    const EXIF_TAG = 0x45786966; // Exif\0\0

+    if (block.readUint32() != EXIF_TAG) {

+      return;

+    }

+    if (block.readUint16() != 0) {

+      return;

+    }

+

+    bool saveEndian = block.bigEndian;

+

+    // Exif Directory

+    String alignment = block.readString(2);

+    if (alignment == 'II') { // Exif is in Intel order

+      block.bigEndian = false;

+    } else if (alignment == 'MM') { // Exif section in Motorola order

+      block.bigEndian = true;

+    } else {

+      return;

+    }

+

+    block.skip(2);

+

+    int offset = block.readUint32();

+    if (offset < 8 || offset > 16){

+      if (offset > block.length - 16) {

+        // invalid offset for first Exif IFD value ;

+        block.bigEndian = saveEndian;

+        return;

+      }

+    }

+

+    if (offset > 8) {

+      block.skip(offset - 8);

+    }

+

+    _readExifDir(block);

+

+    block.bigEndian = saveEndian;

+  }

+

+  void _readAppData(int marker, InputBuffer block) {

+    InputBuffer appData = block;

+

+    if (marker == Jpeg.M_APP0) {

+      // 'JFIF\0'

+      if (appData[0] == 0x4A && appData[1] == 0x46 &&

+          appData[2] == 0x49 && appData[3] == 0x46 && appData[4] == 0) {

+        jfif = JpegJfif();

+        jfif.majorVersion = appData[5];

+        jfif.minorVersion = appData[6];

+        jfif.densityUnits = appData[7];

+        jfif.xDensity = shiftL(appData[8], 8) | appData[9];

+        jfif.yDensity = shiftL(appData[10], 8) | appData[11];

+        jfif.thumbWidth = appData[12];

+        jfif.thumbHeight = appData[13];

+        int thumbSize = 3 * jfif.thumbWidth * jfif.thumbHeight;

+        jfif.thumbData = appData.subset(14 + thumbSize, offset: 14);

+      }

+    } else if (marker == Jpeg.M_APP1) {

+      // 'EXIF\0'

+      _readExifData(appData);

+    } else if (marker == Jpeg.M_APP14) {

+      // 'Adobe\0'

+      if (appData[0] == 0x41 && appData[1] == 0x64 &&

+          appData[2] == 0x6F && appData[3] == 0x62 &&

+          appData[4] == 0x65 && appData[5] == 0) {

+        adobe = JpegAdobe();

+        adobe.version = appData[6];

+        adobe.flags0 = shiftL(appData[7], 8) | appData[8];

+        adobe.flags1 = shiftL(appData[9], 8) | appData[10];

+        adobe.transformCode = appData[11];

+      }

+    } else {

+      //print("!!!! UNHANDLED APP TAG 0x${marker.toRadixString(16)}");

+    }

+  }

+

+  void _readDQT(InputBuffer block) {

+    while (!block.isEOS) {

+      int n = block.readByte();

+      int prec = shiftR(n, 4);

+      n &= 0x0F;

+

+      if (n >= Jpeg.NUM_QUANT_TBLS) {

+        throw new ImageException('Invalid number of quantization tables');

+      }

+

+      if (quantizationTables[n] == null) {

+        quantizationTables[n] = Int16List(64);

+      }

+

+      Int16List tableData = quantizationTables[n];

+      for (int i = 0; i < Jpeg.DCTSIZE2; i++) {

+        int tmp;

+        if (prec != 0) {

+          tmp = block.readUint16();

+        } else {

+          tmp = block.readByte();

+        }

+

+        tableData[Jpeg.dctZigZag[i]] = tmp;

+      }

+    }

+

+    if (!block.isEOS) {

+      throw new ImageException('Bad length for DQT block');

+    }

+  }

+

+  void _readFrame(int marker, InputBuffer block) {

+    if (frame != null) {

+      throw new ImageException('Duplicate JPG frame data found.');

+    }

+

+    frame = JpegFrame();

+    frame.extended = (marker == Jpeg.M_SOF1);

+    frame.progressive = (marker == Jpeg.M_SOF2);

+    frame.precision = block.readByte();

+    frame.scanLines = block.readUint16();

+    frame.samplesPerLine = block.readUint16();

+

+    int numComponents = block.readByte();

+

+    for (int i = 0; i < numComponents; i++) {

+      int componentId = block.readByte();

+      int x = block.readByte();

+      int h = shiftR(x, 4) & 15;

+      int v = x & 15;

+      int qId = block.readByte();

+      frame.componentsOrder.add(componentId);

+      frame.components[componentId] =

+          new JpegComponent(h, v, quantizationTables, qId);

+    }

+

+    frame.prepare();

+    frames.add(frame);

+  }

+

+  void _readDHT(InputBuffer block) {

+    while (!block.isEOS) {

+      int index = block.readByte();

+

+      Uint8List bits = Uint8List(16);

+      int count = 0;

+      for (int j = 0; j < 16; j++) {

+        bits[j] = block.readByte();

+        count += bits[j];

+      }

+

+      Uint8List huffmanValues = Uint8List(count);

+      for (int j = 0; j < count; j++) {

+        huffmanValues[j] = block.readByte();

+      }

+

+      List ht;

+      if (index & 0x10 != 0) { // AC table definition

+        index -= 0x10;

+        ht = huffmanTablesAC;

+      } else { // DC table definition

+        ht = huffmanTablesDC;

+      }

+

+      if (ht.length <= index) {

+        ht.length = index + 1;

+      }

+

+      ht[index] = _buildHuffmanTable(bits, huffmanValues);

+    }

+  }

+

+  void _readDRI(InputBuffer block) {

+    resetInterval = block.readUint16();

+  }

+

+  void _readSOS(InputBuffer block) {

+    int n = block.readByte();

+    if (n < 1 || n > Jpeg.MAX_COMPS_IN_SCAN) {

+      throw new ImageException('Invalid SOS block');

+    }

+

+    List components = List(n);

+    for (int i = 0; i < n; i++) {

+      int id = block.readByte();

+      int c = block.readByte();

+

+      if (!frame.components.containsKey(id)) {

+        throw new ImageException('Invalid Component in SOS block');

+      }

+

+      JpegComponent component = frame.components[id];

+      components[i] = component;

+

+      int dc_tbl_no = shiftR(c, 4) & 15;

+      int ac_tbl_no = c & 15;

+

+      if (dc_tbl_no < huffmanTablesDC.length) {

+        component.huffmanTableDC = huffmanTablesDC[dc_tbl_no];

+      }

+      if (ac_tbl_no < huffmanTablesAC.length) {

+        component.huffmanTableAC = huffmanTablesAC[ac_tbl_no];

+      }

+    }

+

+    int spectralStart = block.readByte();

+    int spectralEnd = block.readByte();

+    int successiveApproximation = block.readByte();

+

+    int Ah = shiftR(successiveApproximation, 4) & 15;

+    int Al = successiveApproximation & 15;

+

+    new JpegScan(input, frame, components, resetInterval,

+                  spectralStart, spectralEnd, Ah, Al).decode();

+  }

+

+  List _buildHuffmanTable(Uint8List codeLengths, Uint8List values) {

+    int k = 0;

+    List code = [];

+    int length = 16;

+

+    while (length > 0 && (codeLengths[length - 1] == 0)) {

+      length--;

+    }

+

+    code.add(new _JpegHuffman());

+

+    _JpegHuffman p = code[0];

+    _JpegHuffman q;

+

+    for (int i = 0; i < length; i++) {

+      for (int j = 0; j < codeLengths[i]; j++) {

+        p = code.removeLast();

+        if (p.children.length <= p.index) {

+          p.children.length = p.index + 1;

+        }

+        p.children[p.index] = values[k];

+        while (p.index > 0) {

+          p = code.removeLast();

+        }

+        p.index++;

+        code.add(p);

+        while (code.length <= i) {

+          q = _JpegHuffman();

+          code.add(q);

+          if (p.children.length <= p.index) {

+            p.children.length = p.index + 1;

+          }

+          p.children[p.index] = q.children;

+          p = q;

+        }

+        k++;

+      }

+

+      if ((i + 1) < length) {

+        // p here points to last code

+        q = _JpegHuffman();

+        code.add(q);

+        if (p.children.length <= p.index) {

+          p.children.length = p.index + 1;

+        }

+        p.children[p.index] = q.children;

+        p = q;

+      }

+    }

+

+    return code[0].children;

+  }

+

+  List<Uint8List> _buildComponentData(JpegFrame frame,

+                                      JpegComponent component) {

+    final int blocksPerLine = component.blocksPerLine;

+    final int blocksPerColumn = component.blocksPerColumn;

+    int samplesPerLine = shiftL(blocksPerLine, 3);

+    Int32List R = Int32List(64);

+    Uint8List r = Uint8List(64);

+    List<Uint8List> lines = List(blocksPerColumn * 8);

+

+    int l = 0;

+    for (int blockRow = 0; blockRow < blocksPerColumn; blockRow++) {

+      int scanLine = shiftL(blockRow, 3);

+      for (int i = 0; i < 8; i++) {

+        lines[l++] = Uint8List(samplesPerLine);

+      }

+

+      for (int blockCol = 0; blockCol < blocksPerLine; blockCol++) {

+        _quantizeAndInverse(component.quantizationTable,

+                            component.blocks[blockRow][blockCol],

+                            r, R);

+

+        int offset = 0;

+        int sample = shiftL(blockCol, 3);

+        for (int j = 0; j < 8; j++) {

+          Uint8List line = lines[scanLine + j];

+          for (int i = 0; i < 8; i++) {

+            line[sample + i] = r[offset++];

+          }

+        }

+      }

+    }

+

+    return lines;

+  }

+

+  static int toFix(double val) {

+    const int FIXED_POINT = 20;

+    const int ONE = 1 << FIXED_POINT;

+    return (val * ONE).toInt() & 0xffffffff;

+  }

+

+  static int _clamp8(int i) => i < 0 ? 0 : i > 255 ? 255 : i;

+

+  static Uint8List dctClip;

+

+  /**

+   * Quantize the coefficients and apply IDCT.

+   *

+   * A port of poppler's IDCT method which in turn is taken from:

+   * Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,

+   * "Practical Fast 1-D DCT Algorithms with 11 Multiplications",

+   * IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, 988-991.

+   */

+  void _quantizeAndInverse(Int16List quantizationTable,

+                           Int32List coefBlock,

+                           Uint8List dataOut,

+                           Int32List dataIn) {

+    Int32List p = dataIn;

+

+    const int dctClipOffset = 256;

+    const int dctClipLength = 768;

+    if (dctClip == null) {

+      dctClip = Uint8List(dctClipLength);

+      int i;

+      for (i = -256; i < 0; ++i) {

+        dctClip[dctClipOffset + i] = 0;

+      }

+      for (i = 0; i < 256; ++i) {

+        dctClip[dctClipOffset + i] = i;

+      }

+      for (i = 256; i < 512; ++i) {

+        dctClip[dctClipOffset + i] = 255;

+      }

+    }

+

+    // IDCT constants (20.12 fixed point format)

+    const int COS_1 = 4017;  // cos(pi/16)*4096

+    const int SIN_1 = 799;   // sin(pi/16)*4096

+    const int COS_3 = 3406;  // cos(3*pi/16)*4096

+    const int SIN_3 = 2276;  // sin(3*pi/16)*4096

+    const int COS_6 = 1567;  // cos(6*pi/16)*4096

+    const int SIN_6 = 3784;  // sin(6*pi/16)*4096

+    const int SQRT_2 = 5793;  // sqrt(2)*4096

+    const int SQRT_1D2 = 2896; // sqrt(2) / 2

+

+    // de-quantize

+    for (int i = 0; i < 64; i++) {

+      p[i] = (coefBlock[i] * quantizationTable[i]);

+    }

+

+    // inverse DCT on rows

+    int row = 0;

+    for (int i = 0; i < 8; ++i, row += 8) {

+      // check for all-zero AC coefficients

+      if (p[1 + row] == 0 &&

+      p[2 + row] == 0 &&

+      p[3 + row] == 0 &&

+      p[4 + row] == 0 &&

+      p[5 + row] == 0 &&

+      p[6 + row] == 0 &&

+      p[7 + row] == 0) {

+        int t = shiftR((SQRT_2 * p[0 + row] + 512), 10);

+        p[row + 0] = t;

+        p[row + 1] = t;

+        p[row + 2] = t;

+        p[row + 3] = t;

+        p[row + 4] = t;

+        p[row + 5] = t;

+        p[row + 6] = t;

+        p[row + 7] = t;

+        continue;

+      }

+

+      // stage 4

+      int v0 = shiftR((SQRT_2 * p[0 + row] + 128), 8);

+      int v1 = shiftR((SQRT_2 * p[4 + row] + 128), 8);

+      int v2 = p[2 + row];

+      int v3 = p[6 + row];

+      int v4 = shiftR((SQRT_1D2 * (p[1 + row] - p[7 + row]) + 128), 8);

+      int v7 = shiftR((SQRT_1D2 * (p[1 + row] + p[7 + row]) + 128), 8);

+      int v5 = shiftL(p[3 + row], 4);

+      int v6 = shiftL(p[5 + row], 4);

+

+      // stage 3

+      int t = shiftR((v0 - v1 + 1), 1);

+      v0 = shiftR((v0 + v1 + 1), 1);

+      v1 = t;

+      t = shiftR((v2 * SIN_6 + v3 * COS_6 + 128), 8);

+      v2 = shiftR((v2 * COS_6 - v3 * SIN_6 + 128), 8);

+      v3 = t;

+      t = shiftR((v4 - v6 + 1), 1);

+      v4 = shiftR((v4 + v6 + 1), 1);

+      v6 = t;

+      t = shiftR((v7 + v5 + 1), 1);

+      v5 = shiftR((v7 - v5 + 1), 1);

+      v7 = t;

+

+      // stage 2

+      t = shiftR((v0 - v3 + 1), 1);

+      v0 = shiftR((v0 + v3 + 1), 1);

+      v3 = t;

+      t = shiftR((v1 - v2 + 1), 1);

+      v1 = shiftR((v1 + v2 + 1), 1);

+      v2 = t;

+      t = shiftR((v4 * SIN_3 + v7 * COS_3 + 2048), 12);

+      v4 = shiftR((v4 * COS_3 - v7 * SIN_3 + 2048), 12);

+      v7 = t;

+      t = shiftR((v5 * SIN_1 + v6 * COS_1 + 2048), 12);

+      v5 = shiftR((v5 * COS_1 - v6 * SIN_1 + 2048), 12);

+      v6 = t;

+

+      // stage 1

+      p[0 + row] = (v0 + v7);

+      p[7 + row] = (v0 - v7);

+      p[1 + row] = (v1 + v6);

+      p[6 + row] = (v1 - v6);

+      p[2 + row] = (v2 + v5);

+      p[5 + row] = (v2 - v5);

+      p[3 + row] = (v3 + v4);

+      p[4 + row] = (v3 - v4);

+    }

+

+    // inverse DCT on columns

+    for (int i = 0; i < 8; ++i) {

+      int col = i;

+

+      // check for all-zero AC coefficients

+      if (p[1 * 8 + col] == 0 &&

+      p[2 * 8 + col] == 0 &&

+      p[3 * 8 + col] == 0 &&

+      p[4 * 8 + col] == 0 &&

+      p[5 * 8 + col] == 0 &&

+      p[6 * 8 + col] == 0 &&

+      p[7 * 8 + col] == 0) {

+        int t = shiftR((SQRT_2 * dataIn[i] + 8192), 14);

+        p[0 * 8 + col] = t;

+        p[1 * 8 + col] = t;

+        p[2 * 8 + col] = t;

+        p[3 * 8 + col] = t;

+        p[4 * 8 + col] = t;

+        p[5 * 8 + col] = t;

+        p[6 * 8 + col] = t;

+        p[7 * 8 + col] = t;

+        continue;

+      }

+

+      // stage 4

+      int v0 = shiftR((SQRT_2 * p[0 * 8 + col] + 2048), 12);

+      int v1 = shiftR((SQRT_2 * p[4 * 8 + col] + 2048), 12);

+      int v2 = p[2 * 8 + col];

+      int v3 = p[6 * 8 + col];

+      int v4 = shiftR((SQRT_1D2 * (p[1 * 8 + col] - p[7 * 8 + col]) + 2048), 12);

+      int v7 = shiftR((SQRT_1D2 * (p[1 * 8 + col] + p[7 * 8 + col]) + 2048), 12);

+      int v5 = p[3 * 8 + col];

+      int v6 = p[5 * 8 + col];

+

+      // stage 3

+      int t = shiftR((v0 - v1 + 1), 1);

+      v0 = shiftR((v0 + v1 + 1), 1);

+      v1 = t;

+      t = shiftR((v2 * SIN_6 + v3 * COS_6 + 2048), 12);

+      v2 = shiftR((v2 * COS_6 - v3 * SIN_6 + 2048), 12);

+      v3 = t;

+      t = shiftR((v4 - v6 + 1), 1);

+      v4 = shiftR((v4 + v6 + 1), 1);

+      v6 = t;

+      t = shiftR((v7 + v5 + 1), 1);

+      v5 = shiftR((v7 - v5 + 1), 1);

+      v7 = t;

+

+      // stage 2

+      t = shiftR((v0 - v3 + 1), 1);

+      v0 = shiftR((v0 + v3 + 1), 1);

+      v3 = t;

+      t = shiftR((v1 - v2 + 1), 1);

+      v1 = shiftR((v1 + v2 + 1), 1);

+      v2 = t;

+      t = shiftR((v4 * SIN_3 + v7 * COS_3 + 2048), 12);

+      v4 = shiftR((v4 * COS_3 - v7 * SIN_3 + 2048), 12);

+      v7 = t;

+      t = shiftR((v5 * SIN_1 + v6 * COS_1 + 2048), 12);

+      v5 = shiftR((v5 * COS_1 - v6 * SIN_1 + 2048), 12);

+      v6 = t;

+

+      // stage 1

+      p[0 * 8 + col] = (v0 + v7);

+      p[7 * 8 + col] = (v0 - v7);

+      p[1 * 8 + col] = (v1 + v6);

+      p[6 * 8 + col] = (v1 - v6);

+      p[2 * 8 + col] = (v2 + v5);

+      p[5 * 8 + col] = (v2 - v5);

+      p[3 * 8 + col] = (v3 + v4);

+      p[4 * 8 + col] = (v3 - v4);

+    }

+

+    // convert to 8-bit integers

+    for (int i = 0; i < 64; ++i) {

+      dataOut[i] = dctClip[(dctClipOffset + 128 + shiftR((p[i] + 8), 4))];

+    }

+  }

+

+  static const CRR = const [

+    -179, -178, -177, -175, -174, -172, -171, -170, -168, -167, -165, -164, -163,

+    -161, -160, -158, -157, -156, -154, -153, -151, -150, -149, -147, -146, -144, -143,

+    -142, -140, -139, -137, -136, -135, -133, -132, -130, -129, -128, -126, -125,

+    -123, -122, -121, -119, -118, -116, -115, -114, -112, -111, -109, -108, -107,

+    -105, -104, -102, -101, -100, -98, -97, -95, -94, -93, -91, -90, -88, -87, -86,

+    -84, -83, -81, -80, -79, -77, -76, -74, -73, -72, -70, -69, -67, -66, -64, -63,

+    -62, -60, -59, -57, -56, -55, -53, -52, -50, -49, -48, -46, -45, -43, -42, -41,

+    -39, -38, -36, -35, -34, -32, -31, -29, -28, -27, -25, -24, -22, -21, -20, -18,

+    -17, -15, -14, -13, -11, -10, -8, -7, -6, -4, -3, -1, 0, 1, 3, 4, 6, 7, 8, 10,

+    11, 13, 14, 15, 17, 18, 20, 21, 22, 24, 25, 27, 28, 29, 31, 32, 34, 35, 36, 38,

+    39, 41, 42, 43, 45, 46, 48, 49, 50, 52, 53, 55, 56, 57, 59, 60, 62, 63, 64, 66,

+    67, 69, 70, 72, 73, 74, 76, 77, 79, 80, 81, 83, 84, 86, 87, 88, 90, 91, 93, 94,

+    95, 97, 98, 100, 101, 102, 104, 105, 107, 108, 109, 111, 112, 114, 115, 116, 118,

+    119, 121, 122, 123, 125, 126, 128, 129, 130, 132, 133, 135, 136, 137, 139, 140,

+    142, 143, 144, 146, 147, 149, 150, 151, 153, 154, 156, 157, 158, 160, 161, 163,

+    164, 165, 167, 168, 170, 171, 172, 174, 175, 177, 178

+  ];

+

+  static const CRG = const [

+    5990656, 5943854, 5897052, 5850250, 5803448, 5756646, 5709844, 5663042, 5616240,

+    5569438, 5522636, 5475834, 5429032, 5382230, 5335428, 5288626, 5241824, 5195022,

+    5148220, 5101418, 5054616, 5007814, 4961012, 4914210, 4867408, 4820606, 4773804,

+    4727002, 4680200, 4633398, 4586596, 4539794, 4492992, 4446190, 4399388, 4352586,

+    4305784, 4258982, 4212180, 4165378, 4118576, 4071774, 4024972, 3978170, 3931368,

+    3884566, 3837764, 3790962, 3744160, 3697358, 3650556, 3603754, 3556952, 3510150,

+    3463348, 3416546, 3369744, 3322942, 3276140, 3229338, 3182536, 3135734, 3088932,

+    3042130, 2995328, 2948526, 2901724, 2854922, 2808120, 2761318, 2714516, 2667714,

+    2620912, 2574110, 2527308, 2480506, 2433704, 2386902, 2340100, 2293298, 2246496,

+    2199694, 2152892, 2106090, 2059288, 2012486, 1965684, 1918882, 1872080, 1825278,

+    1778476, 1731674, 1684872, 1638070, 1591268, 1544466, 1497664, 1450862, 1404060,

+    1357258, 1310456, 1263654, 1216852, 1170050, 1123248, 1076446, 1029644, 982842,

+    936040, 889238, 842436, 795634, 748832, 702030, 655228, 608426, 561624, 514822,

+    468020, 421218, 374416, 327614, 280812, 234010, 187208, 140406, 93604, 46802, 0,

+    -46802, -93604, -140406, -187208, -234010, -280812, -327614, -374416, -421218,

+    -468020, -514822, -561624, -608426, -655228, -702030, -748832, -795634, -842436,

+    -889238, -936040, -982842, -1029644, -1076446, -1123248, -1170050, -1216852,

+    -1263654, -1310456, -1357258, -1404060, -1450862, -1497664, -1544466, -1591268,

+    -1638070, -1684872, -1731674, -1778476, -1825278, -1872080, -1918882, -1965684,

+    -2012486, -2059288, -2106090, -2152892, -2199694, -2246496, -2293298, -2340100,

+    -2386902, -2433704, -2480506, -2527308, -2574110, -2620912, -2667714, -2714516,

+    -2761318, -2808120, -2854922, -2901724, -2948526, -2995328, -3042130, -3088932,

+    -3135734, -3182536, -3229338, -3276140, -3322942, -3369744, -3416546, -3463348,

+    -3510150, -3556952, -3603754, -3650556, -3697358, -3744160, -3790962, -3837764,

+    -3884566, -3931368, -3978170, -4024972, -4071774, -4118576, -4165378, -4212180,

+    -4258982, -4305784, -4352586, -4399388, -4446190, -4492992, -4539794, -4586596,

+    -4633398, -4680200, -4727002, -4773804, -4820606, -4867408, -4914210, -4961012,

+    -5007814, -5054616, -5101418, -5148220, -5195022, -5241824, -5288626, -5335428,

+    -5382230, -5429032, -5475834, -5522636, -5569438, -5616240, -5663042, -5709844,

+    -5756646, -5803448, -5850250, -5897052, -5943854

+  ];

+

+  static const CBG = const [

+    2919680, 2897126, 2874572, 2852018, 2829464, 2806910, 2784356, 2761802, 2739248, 2716694,

+    2694140, 2671586, 2649032, 2626478, 2603924, 2581370, 2558816, 2536262, 2513708,

+    2491154, 2468600, 2446046, 2423492, 2400938, 2378384, 2355830, 2333276, 2310722,

+    2288168, 2265614, 2243060, 2220506, 2197952, 2175398, 2152844, 2130290, 2107736,

+    2085182, 2062628, 2040074, 2017520, 1994966, 1972412, 1949858, 1927304, 1904750,

+    1882196, 1859642, 1837088, 1814534, 1791980, 1769426, 1746872, 1724318, 1701764,

+    1679210, 1656656, 1634102, 1611548, 1588994, 1566440, 1543886, 1521332, 1498778,

+    1476224, 1453670, 1431116, 1408562, 1386008, 1363454, 1340900, 1318346, 1295792,

+    1273238, 1250684, 1228130, 1205576, 1183022, 1160468, 1137914, 1115360,

+    1092806, 1070252, 1047698, 1025144, 1002590, 980036, 957482, 934928, 912374,

+    889820, 867266, 844712, 822158, 799604, 777050, 754496, 731942, 709388, 686834,

+    664280, 641726, 619172, 596618, 574064, 551510, 528956, 506402, 483848, 461294,

+    438740, 416186, 393632, 371078, 348524, 325970, 303416, 280862, 258308, 235754,

+    213200, 190646, 168092, 145538, 122984, 100430, 77876, 55322, 32768, 10214, -12340,

+    -34894, -57448, -80002, -102556, -125110, -147664, -170218, -192772, -215326,

+    -237880, -260434, -282988, -305542, -328096, -350650, -373204, -395758, -418312,

+    -440866, -463420, -485974, -508528, -531082, -553636, -576190, -598744, -621298,

+    -643852, -666406, -688960, -711514, -734068, -756622, -779176, -801730, -824284,

+    -846838, -869392, -891946, -914500, -937054, -959608, -982162, -1004716, -1027270,

+    -1049824, -1072378, -1094932, -1117486, -1140040, -1162594, -1185148, -1207702,

+    -1230256, -1252810, -1275364, -1297918, -1320472, -1343026, -1365580, -1388134,

+    -1410688, -1433242, -1455796, -1478350, -1500904, -1523458, -1546012, -1568566,

+    -1591120, -1613674, -1636228, -1658782, -1681336, -1703890, -1726444, -1748998,

+    -1771552, -1794106, -1816660, -1839214, -1861768, -1884322, -1906876, -1929430,

+    -1951984, -1974538, -1997092, -2019646, -2042200, -2064754, -2087308, -2109862,

+    -2132416, -2154970, -2177524, -2200078, -2222632, -2245186, -2267740, -2290294,

+    -2312848, -2335402, -2357956, -2380510, -2403064, -2425618, -2448172, -2470726,

+    -2493280, -2515834, -2538388, -2560942, -2583496, -2606050, -2628604, -2651158,

+    -2673712, -2696266, -2718820, -2741374, -2763928, -2786482, -2809036, -2831590

+  ];

+

+  static const CBB = const [

+    -227, -225, -223, -222, -220, -218, -216, -214, -213, -211, -209, -207, -206,

+    -204, -202, -200, -198, -197, -195, -193, -191, -190, -188,

+    -186, -184, -183, -181, -179, -177, -175, -174, -172, -170, -168, -167, -165,

+    -163, -161, -159, -158, -156, -154, -152, -151, -149, -147, -145, -144, -142,

+    -140, -138, -136, -135, -133, -131, -129, -128, -126, -124, -122, -120, -119, -117,

+    -115, -113, -112, -110, -108, -106, -105, -103, -101, -99, -97, -96, -94, -92,

+    -90, -89, -87, -85, -83, -82, -80, -78, -76, -74, -73, -71, -69, -67, -66, -64,

+    -62, -60, -58, -57, -55, -53, -51, -50, -48, -46, -44, -43, -41, -39, -37, -35,

+    -34, -32, -30, -28, -27, -25, -23, -21, -19, -18, -16, -14, -12, -11, -9, -7,

+    -5, -4, -2, 0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, 27, 28, 30, 32,

+    34, 35, 37, 39, 41, 43, 44, 46, 48, 50, 51, 53, 55, 57, 58, 60, 62, 64, 66, 67,

+    69, 71, 73, 74, 76, 78, 80, 82, 83, 85, 87, 89, 90, 92, 94, 96, 97, 99, 101, 103,

+    105, 106, 108, 110, 112, 113, 115, 117, 119, 120, 122, 124, 126, 128, 129, 131,

+    133, 135, 136, 138, 140, 142, 144, 145, 147, 149, 151, 152, 154, 156, 158, 159,

+    161, 163, 165, 167, 168, 170, 172, 174, 175, 177, 179, 181, 183, 184, 186, 188,

+    190, 191, 193, 195, 197, 198, 200, 202, 204, 206, 207, 209, 211, 213, 214, 216,

+    218, 220, 222, 223, 225

+  ];

+}

+

+class _JpegHuffman {

+  List children = [];

+  int index = 0;

+}

+

+class _ComponentData {

+  int hSamples;

+  int maxHSamples;

+  int vSamples;

+  int maxVSamples;

+  List<Uint8List> lines;

+  int hScaleShift;

+  int vScaleShift;

+  _ComponentData(this.hSamples, this.maxHSamples, this.vSamples,

+                 this.maxVSamples, this.lines)

+    : hScaleShift = (hSamples == 1 && maxHSamples == 2) ? 1 : 0

+    , vScaleShift = (vSamples == 1 && maxVSamples == 2) ? 1 : 0;

+}

diff --git a/image/lib/src/formats/jpeg/jpeg_frame.dart b/image/lib/src/formats/jpeg/jpeg_frame.dart
old mode 100644
new mode 100755
index bac3e4d..776f5db
--- a/image/lib/src/formats/jpeg/jpeg_frame.dart
+++ b/image/lib/src/formats/jpeg/jpeg_frame.dart
@@ -1,55 +1,51 @@
-import 'dart:typed_data';
-
-import 'jpeg_component.dart';
-
-class JpegFrame {
-  bool extended;
-  bool progressive;
-  int precision;
-  int scanLines;
-  int samplesPerLine;
-  int maxH = 0;
-  int maxV = 0;
-  int mcusPerLine;
-  int mcusPerColumn;
-  final Map<int, JpegComponent> components = {};
-  final List<int> componentsOrder = new List<int>();
-
-  void prepare() {
-    for (int componentId in components.keys) {
-      JpegComponent component = components[componentId];
-      if (maxH < component.h) {
-        maxH = component.h;
-      }
-      if (maxV < component.v) {
-        maxV = component.v;
-      }
-    }
-
-    mcusPerLine = (samplesPerLine / 8 / maxH).ceil();
-    mcusPerColumn = (scanLines / 8 / maxV).ceil();
-
-    for (int componentId in components.keys) {
-      JpegComponent component = components[componentId];
-      int blocksPerLine = ((samplesPerLine / 8).ceil() *
-                           component.h / maxH).ceil();
-      int blocksPerColumn = ((scanLines / 8).ceil() *
-                             component.v / maxV).ceil();
-      int blocksPerLineForMcu = mcusPerLine * component.h;
-      int blocksPerColumnForMcu = mcusPerColumn * component.v;
-
-      List blocks = new List(blocksPerColumnForMcu);
-      for (int i = 0; i < blocksPerColumnForMcu; i++) {
-        List row = new List(blocksPerLineForMcu);
-        for (int j = 0; j < blocksPerLineForMcu; j++) {
-          row[j] = new Int32List(64);
-        }
-        blocks[i] = row;
-      }
-
-      component.blocksPerLine = blocksPerLine;
-      component.blocksPerColumn = blocksPerColumn;
-      component.blocks = blocks;
-    }
-  }
-}
+import 'dart:math';

+import 'dart:typed_data';

+import 'jpeg_component.dart';

+

+class JpegFrame {

+  bool extended;

+  bool progressive;

+  int precision;

+  int scanLines;

+  int samplesPerLine;

+  int maxHSamples = 0;

+  int maxVSamples = 0;

+  int mcusPerLine;

+  int mcusPerColumn;

+  final Map<int, JpegComponent> components = {};

+  final List<int> componentsOrder = List<int>();

+

+  void prepare() {

+    for (int componentId in components.keys) {

+      JpegComponent component = components[componentId];

+      maxHSamples = max(maxHSamples, component.hSamples);

+      maxVSamples = max(maxVSamples, component.vSamples);

+    }

+

+    mcusPerLine = (samplesPerLine / 8 / maxHSamples).ceil();

+    mcusPerColumn = (scanLines / 8 / maxVSamples).ceil();

+

+    for (int componentId in components.keys) {

+      JpegComponent component = components[componentId];

+      int blocksPerLine = ((samplesPerLine / 8).ceil() *

+                           component.hSamples / maxHSamples).ceil();

+      int blocksPerColumn = ((scanLines / 8).ceil() *

+                             component.vSamples / maxVSamples).ceil();

+      int blocksPerLineForMcu = mcusPerLine * component.hSamples;

+      int blocksPerColumnForMcu = mcusPerColumn * component.vSamples;

+

+      List blocks = List(blocksPerColumnForMcu);

+      for (int i = 0; i < blocksPerColumnForMcu; i++) {

+        List row = List(blocksPerLineForMcu);

+        for (int j = 0; j < blocksPerLineForMcu; j++) {

+          row[j] = Int32List(64);

+        }

+        blocks[i] = row;

+      }

+

+      component.blocksPerLine = blocksPerLine;

+      component.blocksPerColumn = blocksPerColumn;

+      component.blocks = blocks;

+    }

+  }

+}

diff --git a/image/lib/src/formats/jpeg/jpeg_info.dart b/image/lib/src/formats/jpeg/jpeg_info.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/jpeg/jpeg_jfif.dart b/image/lib/src/formats/jpeg/jpeg_jfif.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/jpeg/jpeg_scan.dart b/image/lib/src/formats/jpeg/jpeg_scan.dart
old mode 100644
new mode 100755
index cef2595..50b2ccf
--- a/image/lib/src/formats/jpeg/jpeg_scan.dart
+++ b/image/lib/src/formats/jpeg/jpeg_scan.dart
@@ -1,323 +1,323 @@
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-import 'jpeg.dart';
-import 'jpeg_component.dart';
-import 'jpeg_frame.dart';
-
-
-class JpegScan {
-  InputBuffer input;
-  JpegFrame frame;
-  int precision;
-  int samplesPerLine;
-  int scanLines;
-  int mcusPerLine;
-  bool progressive;
-  int maxH;
-  int maxV;
-  List components;
-  int resetInterval;
-  int spectralStart;
-  int spectralEnd;
-  int successivePrev;
-  int successive;
-
-  int bitsData = 0;
-  int bitsCount = 0;
-  int eobrun = 0;
-  int successiveACState = 0;
-  int successiveACNextValue;
-
-  JpegScan(this.input, this.frame, this.components,
-           this.resetInterval, this.spectralStart, this.spectralEnd,
-           this.successivePrev, this.successive) {
-    precision = frame.precision;
-    samplesPerLine = frame.samplesPerLine;
-    scanLines = frame.scanLines;
-    mcusPerLine = frame.mcusPerLine;
-    progressive = frame.progressive;
-    maxH = frame.maxH;
-    maxV = frame.maxV;
-  }
-
-  void decode() {
-    int componentsLength = components.length;
-    JpegComponent component;
-    var decodeFn;
-
-    if (progressive) {
-      if (spectralStart == 0) {
-        decodeFn = successivePrev == 0 ? _decodeDCFirst : _decodeDCSuccessive;
-      } else {
-        decodeFn = successivePrev == 0 ? _decodeACFirst : _decodeACSuccessive;
-      }
-    } else {
-      decodeFn = _decodeBaseline;
-    }
-
-    int mcu = 0;
-
-    int mcuExpected;
-    if (componentsLength == 1) {
-      mcuExpected = (components[0].blocksPerLine * components[0].blocksPerColumn);
-    } else {
-      mcuExpected = (mcusPerLine * frame.mcusPerColumn);
-    }
-
-    if (resetInterval == null || resetInterval == 0) {
-      resetInterval = mcuExpected;
-    }
-
-    int h, v;
-    while (mcu < mcuExpected) {
-      // reset interval stuff
-      for (int i = 0; i < componentsLength; i++) {
-        components[i].pred = 0;
-      }
-      eobrun = 0;
-
-      if (componentsLength == 1) {
-        component = components[0];
-        for (int n = 0; n < resetInterval; n++) {
-          _decodeBlock(component, decodeFn, mcu);
-          mcu++;
-        }
-      } else {
-        for (int n = 0; n < resetInterval; n++) {
-          for (int i = 0; i < componentsLength; i++) {
-            component = components[i];
-            h = component.h;
-            v = component.v;
-            for (int j = 0; j < v; j++) {
-              for (int k = 0; k < h; k++) {
-                _decodeMcu(component, decodeFn, mcu, j, k);
-              }
-            }
-          }
-          mcu++;
-        }
-      }
-
-      // find marker
-      bitsCount = 0;
-      int m1 = input[0];
-      int m2 = input[1];
-      if (m1 == 0xff) {
-        if (m2 >= Jpeg.M_RST0 && m2 <= Jpeg.M_RST7) {
-          input.offset += 2;
-        } else {
-          break;
-        }
-      }
-    }
-  }
-
-  int _readBit() {
-    if (bitsCount > 0) {
-      bitsCount--;
-      return (bitsData >> bitsCount) & 1;
-    }
-
-    if (input.isEOS) {
-      return null;
-    }
-
-    bitsData = input.readByte();
-    if (bitsData == 0xff) {
-      int nextByte = input.readByte();
-      if (nextByte != 0) {
-        throw new ImageException('unexpected marker: ' +
-              ((bitsData << 8) | nextByte).toRadixString(16));
-      }
-    }
-
-    bitsCount = 7;
-    return (bitsData >> 7) & 1;
-  }
-
-  int _decodeHuffman(tree) {
-    var node = tree;
-    int bit;
-    while ((bit = _readBit()) != null) {
-      node = node[bit];
-      if (node is num) {
-        return node.toInt();
-      }
-    }
-
-    return null;
-  }
-
-  int _receive(int length) {
-    int  n = 0;
-    while (length > 0) {
-      int bit = _readBit();
-      if (bit == null) {
-        return null;
-      }
-      n = ((n << 1) | bit);
-      length--;
-    }
-    return n;
-  }
-
-  int _receiveAndExtend(int length) {
-    if (length == 1) {
-      return _readBit() == 1 ? 1 : -1;
-    }
-    int n = _receive(length);
-    if (n >= (1 << (length - 1))) {
-      return n;
-    }
-    return n + (-1 << length) + 1;
-  }
-
-  void _decodeBaseline(JpegComponent component, List zz) {
-    int t = _decodeHuffman(component.huffmanTableDC);
-    int diff = t == 0 ? 0 : _receiveAndExtend(t);
-    component.pred += diff;
-    zz[0] = component.pred;
-
-    int k = 1;
-    while (k < 64) {
-      var rs = _decodeHuffman(component.huffmanTableAC);
-      int s = rs & 15;
-      int r = rs >> 4;
-      if (s == 0) {
-        if (r < 15) {
-          break;
-        }
-        k += 16;
-        continue;
-      }
-
-      k += r;
-
-      s = _receiveAndExtend(s);
-
-      int z = Jpeg.dctZigZag[k];
-      zz[z] = s;
-      k++;
-    }
-  }
-
-  void _decodeDCFirst(JpegComponent component, List zz) {
-    int t = _decodeHuffman(component.huffmanTableDC);
-    int diff = (t == 0) ? 0 : (_receiveAndExtend(t) << successive);
-    component.pred += diff;
-    zz[0] = component.pred;
-  }
-
-  void _decodeDCSuccessive(JpegComponent component, List zz) {
-    zz[0] = (zz[0] | (_readBit() << successive));
-  }
-
-  void _decodeACFirst(JpegComponent component, List zz) {
-    if (eobrun > 0) {
-      eobrun--;
-      return;
-    }
-    int k = spectralStart;
-    int e = spectralEnd;
-    while (k <= e) {
-      int rs = _decodeHuffman(component.huffmanTableAC);
-      int s = rs & 15;
-      int r = rs >> 4;
-      if (s == 0) {
-        if (r < 15) {
-          eobrun = (_receive(r) + (1 << r) - 1);
-          break;
-        }
-        k += 16;
-        continue;
-      }
-      k += r;
-      int z = Jpeg.dctZigZag[k];
-      zz[z] = (_receiveAndExtend(s) * (1 << successive));
-      k++;
-    }
-  }
-
-  void _decodeACSuccessive(JpegComponent component, zz) {
-    int k = spectralStart;
-    int e = spectralEnd;
-    int s = 0;
-    int r = 0;
-    while (k <= e) {
-      int z = Jpeg.dctZigZag[k];
-      switch (successiveACState) {
-        case 0: // initial state
-          int rs = _decodeHuffman(component.huffmanTableAC);
-          if (rs == null) continue;
-          s = rs & 15;
-          r = rs >> 4;
-          if (s == 0) {
-            if (r < 15) {
-              eobrun = (_receive(r) + (1 << r));
-              successiveACState = 4;
-            } else {
-              r = 16;
-              successiveACState = 1;
-            }
-          } else {
-            if (s != 1) {
-              throw new ImageException('invalid ACn encoding');
-            }
-            successiveACNextValue = _receiveAndExtend(s);
-            successiveACState = r != 0 ? 2 : 3;
-          }
-          continue;
-        case 1: // skipping r zero items
-        case 2:
-          if (zz[z] != 0) {
-            zz[z] += (_readBit() << successive);
-          } else {
-            r--;
-            if (r == 0) {
-              successiveACState = successiveACState == 2 ? 3 : 0;
-            }
-          }
-          break;
-        case 3: // set value for a zero item
-          if (zz[z] != 0) {
-            zz[z] += (_readBit() << successive);
-          } else {
-            zz[z] = (successiveACNextValue << successive);
-            successiveACState = 0;
-          }
-          break;
-        case 4: // eob
-          if (zz[z] != 0) {
-            zz[z] += (_readBit() << successive);
-          }
-          break;
-      }
-      k++;
-    }
-    if (successiveACState == 4) {
-      eobrun--;
-      if (eobrun == 0) {
-        successiveACState = 0;
-      }
-    }
-  }
-
-  void _decodeMcu(JpegComponent component, decodeFn,
-                  int mcu, int row, int col) {
-    int mcuRow = (mcu ~/ mcusPerLine);
-    int mcuCol = mcu % mcusPerLine;
-    int blockRow = mcuRow * component.v + row;
-    int blockCol = mcuCol * component.h + col;
-    if (blockRow >= component.blocks.length ||
-        blockCol >= component.blocks[blockRow].length) {
-      return;
-    }
-    decodeFn(component, component.blocks[blockRow][blockCol]);
-  }
-
-  void _decodeBlock(JpegComponent component, decodeFn, int mcu) {
-    int blockRow = mcu ~/ component.blocksPerLine;
-    int blockCol = mcu % component.blocksPerLine;
-    decodeFn(component, component.blocks[blockRow][blockCol]);
-  }
-}
+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+import 'jpeg.dart';

+import 'jpeg_component.dart';

+import 'jpeg_frame.dart';

+

+

+class JpegScan {

+  InputBuffer input;

+  JpegFrame frame;

+  int precision;

+  int samplesPerLine;

+  int scanLines;

+  int mcusPerLine;

+  bool progressive;

+  int maxH;

+  int maxV;

+  List components;

+  int resetInterval;

+  int spectralStart;

+  int spectralEnd;

+  int successivePrev;

+  int successive;

+

+  int bitsData = 0;

+  int bitsCount = 0;

+  int eobrun = 0;

+  int successiveACState = 0;

+  int successiveACNextValue;

+

+  JpegScan(this.input, this.frame, this.components,

+           this.resetInterval, this.spectralStart, this.spectralEnd,

+           this.successivePrev, this.successive) {

+    precision = frame.precision;

+    samplesPerLine = frame.samplesPerLine;

+    scanLines = frame.scanLines;

+    mcusPerLine = frame.mcusPerLine;

+    progressive = frame.progressive;

+    maxH = frame.maxHSamples;

+    maxV = frame.maxVSamples;

+  }

+

+  void decode() {

+    int componentsLength = components.length;

+    JpegComponent component;

+    var decodeFn;

+

+    if (progressive) {

+      if (spectralStart == 0) {

+        decodeFn = successivePrev == 0 ? _decodeDCFirst : _decodeDCSuccessive;

+      } else {

+        decodeFn = successivePrev == 0 ? _decodeACFirst : _decodeACSuccessive;

+      }

+    } else {

+      decodeFn = _decodeBaseline;

+    }

+

+    int mcu = 0;

+

+    int mcuExpected;

+    if (componentsLength == 1) {

+      mcuExpected = (components[0].blocksPerLine * components[0].blocksPerColumn);

+    } else {

+      mcuExpected = (mcusPerLine * frame.mcusPerColumn);

+    }

+

+    if (resetInterval == null || resetInterval == 0) {

+      resetInterval = mcuExpected;

+    }

+

+    int h, v;

+    while (mcu < mcuExpected) {

+      // reset interval stuff

+      for (int i = 0; i < componentsLength; i++) {

+        components[i].pred = 0;

+      }

+      eobrun = 0;

+

+      if (componentsLength == 1) {

+        component = components[0];

+        for (int n = 0; n < resetInterval; n++) {

+          _decodeBlock(component, decodeFn, mcu);

+          mcu++;

+        }

+      } else {

+        for (int n = 0; n < resetInterval; n++) {

+          for (int i = 0; i < componentsLength; i++) {

+            component = components[i];

+            h = component.hSamples;

+            v = component.vSamples;

+            for (int j = 0; j < v; j++) {

+              for (int k = 0; k < h; k++) {

+                _decodeMcu(component, decodeFn, mcu, j, k);

+              }

+            }

+          }

+          mcu++;

+        }

+      }

+

+      // find marker

+      bitsCount = 0;

+      int m1 = input[0];

+      int m2 = input[1];

+      if (m1 == 0xff) {

+        if (m2 >= Jpeg.M_RST0 && m2 <= Jpeg.M_RST7) {

+          input.offset += 2;

+        } else {

+          break;

+        }

+      }

+    }

+  }

+

+  int _readBit() {

+    if (bitsCount > 0) {

+      bitsCount--;

+      return (bitsData >> bitsCount) & 1;

+    }

+

+    if (input.isEOS) {

+      return null;

+    }

+

+    bitsData = input.readByte();

+    if (bitsData == 0xff) {

+      int nextByte = input.readByte();

+      if (nextByte != 0) {

+        throw new ImageException('unexpected marker: ' +

+              ((bitsData << 8) | nextByte).toRadixString(16));

+      }

+    }

+

+    bitsCount = 7;

+    return (bitsData >> 7) & 1;

+  }

+

+  int _decodeHuffman(tree) {

+    var node = tree;

+    int bit;

+    while ((bit = _readBit()) != null) {

+      node = node[bit];

+      if (node is num) {

+        return node.toInt();

+      }

+    }

+

+    return null;

+  }

+

+  int _receive(int length) {

+    int  n = 0;

+    while (length > 0) {

+      int bit = _readBit();

+      if (bit == null) {

+        return null;

+      }

+      n = ((n << 1) | bit);

+      length--;

+    }

+    return n;

+  }

+

+  int _receiveAndExtend(int length) {

+    if (length == 1) {

+      return _readBit() == 1 ? 1 : -1;

+    }

+    int n = _receive(length);

+    if (n >= (1 << (length - 1))) {

+      return n;

+    }

+    return n + (-1 << length) + 1;

+  }

+

+  void _decodeBaseline(JpegComponent component, List zz) {

+    int t = _decodeHuffman(component.huffmanTableDC);

+    int diff = t == 0 ? 0 : _receiveAndExtend(t);

+    component.pred += diff;

+    zz[0] = component.pred;

+

+    int k = 1;

+    while (k < 64) {

+      var rs = _decodeHuffman(component.huffmanTableAC);

+      int s = rs & 15;

+      int r = rs >> 4;

+      if (s == 0) {

+        if (r < 15) {

+          break;

+        }

+        k += 16;

+        continue;

+      }

+

+      k += r;

+

+      s = _receiveAndExtend(s);

+

+      int z = Jpeg.dctZigZag[k];

+      zz[z] = s;

+      k++;

+    }

+  }

+

+  void _decodeDCFirst(JpegComponent component, List zz) {

+    int t = _decodeHuffman(component.huffmanTableDC);

+    int diff = (t == 0) ? 0 : (_receiveAndExtend(t) << successive);

+    component.pred += diff;

+    zz[0] = component.pred;

+  }

+

+  void _decodeDCSuccessive(JpegComponent component, List zz) {

+    zz[0] = (zz[0] | (_readBit() << successive));

+  }

+

+  void _decodeACFirst(JpegComponent component, List zz) {

+    if (eobrun > 0) {

+      eobrun--;

+      return;

+    }

+    int k = spectralStart;

+    int e = spectralEnd;

+    while (k <= e) {

+      int rs = _decodeHuffman(component.huffmanTableAC);

+      int s = rs & 15;

+      int r = rs >> 4;

+      if (s == 0) {

+        if (r < 15) {

+          eobrun = (_receive(r) + (1 << r) - 1);

+          break;

+        }

+        k += 16;

+        continue;

+      }

+      k += r;

+      int z = Jpeg.dctZigZag[k];

+      zz[z] = (_receiveAndExtend(s) * (1 << successive));

+      k++;

+    }

+  }

+

+  void _decodeACSuccessive(JpegComponent component, zz) {

+    int k = spectralStart;

+    int e = spectralEnd;

+    int s = 0;

+    int r = 0;

+    while (k <= e) {

+      int z = Jpeg.dctZigZag[k];

+      switch (successiveACState) {

+        case 0: // initial state

+          int rs = _decodeHuffman(component.huffmanTableAC);

+          if (rs == null) continue;

+          s = rs & 15;

+          r = rs >> 4;

+          if (s == 0) {

+            if (r < 15) {

+              eobrun = (_receive(r) + (1 << r));

+              successiveACState = 4;

+            } else {

+              r = 16;

+              successiveACState = 1;

+            }

+          } else {

+            if (s != 1) {

+              throw new ImageException('invalid ACn encoding');

+            }

+            successiveACNextValue = _receiveAndExtend(s);

+            successiveACState = r != 0 ? 2 : 3;

+          }

+          continue;

+        case 1: // skipping r zero items

+        case 2:

+          if (zz[z] != 0) {

+            zz[z] += (_readBit() << successive);

+          } else {

+            r--;

+            if (r == 0) {

+              successiveACState = successiveACState == 2 ? 3 : 0;

+            }

+          }

+          break;

+        case 3: // set value for a zero item

+          if (zz[z] != 0) {

+            zz[z] += (_readBit() << successive);

+          } else {

+            zz[z] = (successiveACNextValue << successive);

+            successiveACState = 0;

+          }

+          break;

+        case 4: // eob

+          if (zz[z] != 0) {

+            zz[z] += (_readBit() << successive);

+          }

+          break;

+      }

+      k++;

+    }

+    if (successiveACState == 4) {

+      eobrun--;

+      if (eobrun == 0) {

+        successiveACState = 0;

+      }

+    }

+  }

+

+  void _decodeMcu(JpegComponent component, decodeFn,

+                  int mcu, int row, int col) {

+    int mcuRow = (mcu ~/ mcusPerLine);

+    int mcuCol = mcu % mcusPerLine;

+    int blockRow = mcuRow * component.vSamples + row;

+    int blockCol = mcuCol * component.hSamples + col;

+    if (blockRow >= component.blocks.length ||

+        blockCol >= component.blocks[blockRow].length) {

+      return;

+    }

+    decodeFn(component, component.blocks[blockRow][blockCol]);

+  }

+

+  void _decodeBlock(JpegComponent component, decodeFn, int mcu) {

+    int blockRow = mcu ~/ component.blocksPerLine;

+    int blockCol = mcu % component.blocksPerLine;

+    decodeFn(component, component.blocks[blockRow][blockCol]);

+  }

+}

diff --git a/image/lib/src/formats/jpeg_decoder.dart b/image/lib/src/formats/jpeg_decoder.dart
old mode 100644
new mode 100755
index aae1637..284a4b4
--- a/image/lib/src/formats/jpeg_decoder.dart
+++ b/image/lib/src/formats/jpeg_decoder.dart
@@ -1,134 +1,134 @@
-import 'dart:typed_data';
-
-import '../animation.dart';
-import '../color.dart';
-import '../exif_data.dart';
-import '../image.dart';
-import '../image_exception.dart';
-import '../util/input_buffer.dart';
-import 'decode_info.dart';
-import 'decoder.dart';
-import 'jpeg/jpeg_data.dart';
-import 'jpeg/jpeg_info.dart';
-
-/**
- * Decode a jpeg encoded image.
- */
-class JpegDecoder extends Decoder {
-  JpegInfo info;
-  InputBuffer input;
-
-  /**
-   * Is the given file a valid JPEG image?
-   */
-  bool isValidFile(List<int> data) {
-    return new JpegData().validate(data);
-  }
-
-  DecodeInfo startDecode(List<int> data) {
-    input = new InputBuffer(data, bigEndian: true);
-    info = new JpegData().readInfo(data);
-    return info;
-  }
-
-  int numFrames() => info == null ? 0 : info.numFrames;
-
-  Image decodeFrame(int frame) {
-    if (input == null) {
-      return null;
-    }
-    JpegData jpeg = new JpegData();
-    jpeg.read(input.buffer);
-
-    if (jpeg.frames.length != 1) {
-      throw new ImageException('only single frame JPEGs supported');
-    }
-
-    Image image = new Image(jpeg.width, jpeg.height, Image.RGB);
-
-    _copyToImage(jpeg, image);
-
-    return image;
-  }
-
-  Image decodeImage(List<int> data, {int frame: 0}) {
-    JpegData jpeg = new JpegData();
-    jpeg.read(data);
-
-    if (jpeg.frames.length != 1) {
-      throw new ImageException('only single frame JPEGs supported');
-    }
-
-    Image image = new Image(jpeg.width, jpeg.height, Image.RGB);
-
-    _copyToImage(jpeg, image);
-
-    return image;
-  }
-
-  Animation decodeAnimation(List<int> data) {
-    Image image = decodeImage(data);
-    if (image == null) {
-      return null;
-    }
-
-    Animation anim = new Animation();
-    anim.width = image.width;
-    anim.height = image.height;
-    anim.addFrame(image);
-
-    return anim;
-  }
-
-  void _copyToImage(JpegData jpeg, Image imageData) {
-    imageData.exif = new ExifData.from(jpeg.exif);
-
-    final width = imageData.width;
-    final height = imageData.height;
-    final data = jpeg.getData(width, height);
-    final components = jpeg.components;
-
-    int i = 0;
-    int j = 0;
-    switch (components.length) {
-      case 1: // Luminance
-        for (int y = 0; y < height; y++) {
-          for (int x = 0; x < width; x++) {
-            int Y = data[i++];
-            imageData[j++] = getColor(Y, Y, Y, 255);
-          }
-        }
-        break;
-      case 3: // RGB
-        for (int y = 0; y < height; y++) {
-          for (int x = 0; x < width; x++) {
-            int R = data[i++];
-            int G = data[i++];
-            int B = data[i++];
-
-            int c = getColor(R, G, B, 255);
-            imageData[j++] = c;
-          }
-        }
-        break;
-      case 4: // CMYK
-        for (int y = 0; y < height; y++) {
-          for (int x = 0; x < width; x++) {
-            int C = data[i++];
-            int M = data[i++];
-            int Y = data[i++];
-            int K = data[i++];
-
-            int R = (C * (K)) >> 8;
-            int G = (M * (K)) >> 8;
-            int B = (Y * (K)) >> 8;
-
-            imageData[j++] = getColor(R, G, B, 255);
-          }
-        }
-        break;
-      default:
-        throw 'Unsupported color mode';
-    }
-  }
-}
+import 'dart:typed_data';

+

+import '../animation.dart';

+import '../color.dart';

+import '../exif_data.dart';

+import '../image.dart';

+import '../image_exception.dart';

+import '../util/input_buffer.dart';

+import 'decode_info.dart';

+import 'decoder.dart';

+import 'jpeg/jpeg_data.dart';

+import 'jpeg/jpeg_info.dart';

+

+/**

+ * Decode a jpeg encoded image.

+ */

+class JpegDecoder extends Decoder {

+  JpegInfo info;

+  InputBuffer input;

+

+  /**

+   * Is the given file a valid JPEG image?

+   */

+  bool isValidFile(List<int> data) {

+    return new JpegData().validate(data);

+  }

+

+  DecodeInfo startDecode(List<int> data) {

+    input = InputBuffer(data, bigEndian: true);

+    info = JpegData().readInfo(data);

+    return info;

+  }

+

+  int numFrames() => info == null ? 0 : info.numFrames;

+

+  Image decodeFrame(int frame) {

+    if (input == null) {

+      return null;

+    }

+    JpegData jpeg = JpegData();

+    jpeg.read(input.buffer);

+

+    if (jpeg.frames.length != 1) {

+      throw new ImageException('only single frame JPEGs supported');

+    }

+

+    Image image = Image(jpeg.width, jpeg.height, Image.RGB);

+

+    _copyToImage(jpeg, image);

+

+    return image;

+  }

+

+  Image decodeImage(List<int> data, {int frame: 0}) {

+    JpegData jpeg = JpegData();

+    jpeg.read(data);

+

+    if (jpeg.frames.length != 1) {

+      throw new ImageException('only single frame JPEGs supported');

+    }

+

+    Image image = Image(jpeg.width, jpeg.height, Image.RGB);

+

+    _copyToImage(jpeg, image);

+

+    return image;

+  }

+

+  Animation decodeAnimation(List<int> data) {

+    Image image = decodeImage(data);

+    if (image == null) {

+      return null;

+    }

+

+    Animation anim = Animation();

+    anim.width = image.width;

+    anim.height = image.height;

+    anim.addFrame(image);

+

+    return anim;

+  }

+

+  void _copyToImage(JpegData jpeg, Image imageData) {

+    imageData.exif = ExifData.from(jpeg.exif);

+

+    final width = imageData.width;

+    final height = imageData.height;

+    final data = jpeg.getData(width, height);

+    final components = jpeg.components;

+

+    int i = 0;

+    int j = 0;

+    switch (components.length) {

+      case 1: // Luminance

+        for (int y = 0; y < height; y++) {

+          for (int x = 0; x < width; x++) {

+            int Y = data[i++];

+            imageData[j++] = getColor(Y, Y, Y, 255);

+          }

+        }

+        break;

+      case 3: // RGB

+        for (int y = 0; y < height; y++) {

+          for (int x = 0; x < width; x++) {

+            int R = data[i++];

+            int G = data[i++];

+            int B = data[i++];

+

+            int c = getColor(R, G, B, 255);

+            imageData[j++] = c;

+          }

+        }

+        break;

+      case 4: // CMYK

+        for (int y = 0; y < height; y++) {

+          for (int x = 0; x < width; x++) {

+            int C = data[i++];

+            int M = data[i++];

+            int Y = data[i++];

+            int K = data[i++];

+

+            int R = (C * (K)) >> 8;

+            int G = (M * (K)) >> 8;

+            int B = (Y * (K)) >> 8;

+

+            imageData[j++] = getColor(R, G, B, 255);

+          }

+        }

+        break;

+      default:

+        throw 'Unsupported color mode';

+    }

+  }

+}

diff --git a/image/lib/src/formats/jpeg_encoder.dart b/image/lib/src/formats/jpeg_encoder.dart
old mode 100644
new mode 100755
index 8e738d7..943867d
--- a/image/lib/src/formats/jpeg_encoder.dart
+++ b/image/lib/src/formats/jpeg_encoder.dart
@@ -39,7 +39,7 @@
   }

 

   List<int> encodeImage(Image image) {

-    OutputBuffer fp = new OutputBuffer(bigEndian: true);

+    OutputBuffer fp = OutputBuffer(bigEndian: true);

 

     // Add JPEG headers

     _writeMarker(fp, Jpeg.M_SOI);

@@ -83,9 +83,9 @@
             p -= ((x + col) - quadWidth + 4);

           }

 

-          int r = imageData[p++];

-          int g = imageData[p++];

           int b = imageData[p++];

+          int g = imageData[p++];

+          int r = imageData[p++];

 

           // calculate YUV values

           YDU[pos] = ((RGB_YUV_TABLE[r] +

@@ -187,7 +187,7 @@
   List _computeHuffmanTbl(List nrcodes, List std_table) {

     int codevalue = 0;

     int pos_in_table = 0;

-    List HT = new List();

+    List HT = List();

     for (int k = 1; k <= 16; k++) {

       for (int j = 1; j <= nrcodes[k]; j++) {

         int index = std_table[pos_in_table];

@@ -575,24 +575,24 @@
     _bytepos = 7;

   }

 

-  final YTable = new Uint8List(64);

-  final UVTable = new Uint8List(64);

-  final fdtbl_Y = new Float32List(64);

-  final fdtbl_UV = new Float32List(64);

+  final YTable = Uint8List(64);

+  final UVTable = Uint8List(64);

+  final fdtbl_Y = Float32List(64);

+  final fdtbl_UV = Float32List(64);

   List YDC_HT;

   List UVDC_HT;

   List YAC_HT;

   List UVAC_HT;

 

-  final bitcode = new List(65535);

-  final category = new List(65535);

-  final outputfDCTQuant = new List<int>(64);

-  final DU = new List(64);

+  final bitcode = List(65535);

+  final category = List(65535);

+  final outputfDCTQuant = List<int>(64);

+  final DU = List(64);

 

-  final Float32List YDU = new Float32List(64);

-  final Float32List UDU = new Float32List(64);

-  final Float32List VDU = new Float32List(64);

-  final Int32List RGB_YUV_TABLE = new Int32List(2048);

+  final Float32List YDU = Float32List(64);

+  final Float32List UDU = Float32List(64);

+  final Float32List VDU = Float32List(64);

+  final Int32List RGB_YUV_TABLE = Int32List(2048);

   int currentQuality;

 

   static const List<int> ZIGZAG = const [

diff --git a/image/lib/src/formats/png/png_frame.dart b/image/lib/src/formats/png/png_frame.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/png/png_info.dart b/image/lib/src/formats/png/png_info.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/png_decoder.dart b/image/lib/src/formats/png_decoder.dart
old mode 100644
new mode 100755
index ed67081..e52f06f
--- a/image/lib/src/formats/png_decoder.dart
+++ b/image/lib/src/formats/png_decoder.dart
@@ -24,7 +24,7 @@
    * Is the given file a valid PNG image?

    */

   bool isValidFile(List<int> data) {

-    InputBuffer input = new InputBuffer(data, bigEndian: true);

+    InputBuffer input = InputBuffer(data, bigEndian: true);

     InputBuffer pngHeader = input.readBytes(8);

     const PNG_HEADER = const [137, 80, 78, 71, 13, 10, 26, 10];

     for (int i = 0; i < 8; ++i) {

@@ -43,7 +43,7 @@
    * process the frames until they are requested with decodeFrame.

    */

   DecodeInfo startDecode(List<int> data) {

-    _input = new InputBuffer(data, bigEndian: true);

+    _input = InputBuffer(data, bigEndian: true);

 

     InputBuffer pngHeader = _input.readBytes(8);

     const PNG_HEADER = const [137, 80, 78, 71, 13, 10, 26, 10];

@@ -59,9 +59,9 @@
       String chunkType = _input.readString(4);

       switch (chunkType) {

         case 'IHDR':

-          InputBuffer hdr = new InputBuffer.from(_input.readBytes(chunkSize));

+          InputBuffer hdr = InputBuffer.from(_input.readBytes(chunkSize));

           List<int> hdrBytes = hdr.toUint8List();

-          _info = new InternalPngInfo();

+          _info = InternalPngInfo();

           _info.width = hdr.readUint32();

           _info.height = hdr.readUint32();

           _info.bits = hdr.readByte();

@@ -158,7 +158,7 @@
           _input.skip(4); // CRC

           break;

         case 'fcTL': // Frame control chunk

-          PngFrame frame = new InternalPngFrame();

+          PngFrame frame = InternalPngFrame();

           _info.frames.add(frame);

           frame.sequenceNumber = _input.readUint32();

           frame.width = _input.readUint32();

@@ -287,17 +287,17 @@
       format = Image.RGB;

     }

 

-    Image image = new Image(width, height, format);

+    Image image = Image(width, height, format);

 

-    List<int> uncompressed = new ZLibDecoder().decodeBytes(imageData);

+    List<int> uncompressed = ZLibDecoder().decodeBytes(imageData);

 

     // input is the decompressed data.

-    InputBuffer input = new InputBuffer(uncompressed, bigEndian: true);

+    InputBuffer input = InputBuffer(uncompressed, bigEndian: true);

     _resetBits();

 

     // Set up a LUT to transform colors for gamma correction.

     if (_info.colorLut == null) {

-      _info.colorLut = new List<int>(256);

+      _info.colorLut = List<int>(256);

       for (int i = 0; i < 256; ++i) {

         int c = i;

         /*if (info.gamma != null) {

@@ -337,7 +337,7 @@
     _info.width = origW;

     _info.height = origH;

 

-    image.iccProfile = new ICCProfileData(_info.iCCPName,

+    image.iccProfile = ICCProfileData(_info.iCCPName,

                                           ICCPCompression.deflate,

                                           _info.iCCPData);

 

@@ -356,7 +356,7 @@
       return null;

     }

 

-    Animation anim = new Animation();

+    Animation anim = Animation();

     anim.width = _info.width;

     anim.height = _info.height;

 

@@ -367,13 +367,13 @@
     }

 

     int dispose = PngFrame.APNG_DISPOSE_OP_BACKGROUND;

-    Image lastImage = new Image(_info.width, _info.height);

+    Image lastImage = Image(_info.width, _info.height);

     for (int i = 0; i < _info.numFrames; ++i) {

       //_frame = i;

       if (lastImage == null) {

-        lastImage = new Image(_info.width, _info.height);

+        lastImage = Image(_info.width, _info.height);

       } else {

-        lastImage = new Image.from(lastImage);

+        lastImage = Image.from(lastImage);

       }

 

       PngFrame frame = _info.frames[i];

@@ -415,7 +415,7 @@
     final int bpp = (pixelDepth + 7) >> 3;

     final int rowBytes = (pixelDepth * passWidth + 7) >> 3;

 

-    final List<int> line = new List<int>.filled(rowBytes, 0);

+    final List<int> line = List<int>.filled(rowBytes, 0);

     final List<List<int>> inData = [line, line];

 

     final List<int> pixel = [0, 0, 0, 0];

@@ -437,7 +437,7 @@
       // reset the bit stream counter.

       _resetBits();

 

-      InputBuffer rowInput = new InputBuffer(row, bigEndian: true);

+      InputBuffer rowInput = InputBuffer(row, bigEndian: true);

 

       final int blockHeight = xStep;

       final int blockWidth = xStep - xOffset;

@@ -476,7 +476,7 @@
     final int rowBytes = (((w * pixelDepth + 7)) >> 3);

     final int bpp = (pixelDepth + 7) >> 3;

 

-    final List<int> line = new List<int>.filled(rowBytes, 0);

+    final List<int> line = List<int>.filled(rowBytes, 0);

     final List<List<int>> inData = [line, line];

 

     final List<int> pixel = [0, 0, 0, 0];

@@ -496,7 +496,7 @@
       // reset the bit stream counter.

       _resetBits();

 

-      InputBuffer rowInput = new InputBuffer(inData[ri], bigEndian: true);

+      InputBuffer rowInput = InputBuffer(inData[ri], bigEndian: true);

 

       for (int x = 0; x < w; ++x) {

         _readPixel(rowInput, pixel);

diff --git a/image/lib/src/formats/png_encoder.dart b/image/lib/src/formats/png_encoder.dart
old mode 100644
new mode 100755
index 7c7c6b6..26df9da
--- a/image/lib/src/formats/png_encoder.dart
+++ b/image/lib/src/formats/png_encoder.dart
@@ -24,7 +24,7 @@
     blendMethod = image.blendMethod;

 

     if (output == null) {

-      output = new OutputBuffer(bigEndian: true);

+      output = OutputBuffer(bigEndian: true);

 

       format = image.format;

       _width = image.width;

@@ -40,12 +40,12 @@
     }

 

     // Include room for the filter bytes (1 byte per row).

-    List<int> filteredImage = new Uint8List((image.width * image.height *

+    List<int> filteredImage = Uint8List((image.width * image.height *

         image.format) + image.height);

 

     _filter(image, filteredImage);

 

-    List<int> compressed = new ZLibEncoder().encode(filteredImage,

+    List<int> compressed = ZLibEncoder().encode(filteredImage,

                                                         level: level);

 

     if (isAnimated) {

@@ -57,7 +57,7 @@
       _writeChunk(output, 'IDAT', compressed);

     } else {

       // fdAT chunk

-      OutputBuffer fdat = new OutputBuffer(bigEndian: true);

+      OutputBuffer fdat = OutputBuffer(bigEndian: true);

       fdat.writeUint32(sequenceNumber);

       fdat.writeBytes(compressed);

       _writeChunk(output, 'fdAT', fdat.getBytes());

@@ -115,7 +115,7 @@
     output.writeBytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);

 

     // IHDR chunk

-    OutputBuffer chunk = new OutputBuffer(bigEndian: true);

+    OutputBuffer chunk = OutputBuffer(bigEndian: true);

     chunk.writeUint32(width);

     chunk.writeUint32(height);

     chunk.writeByte(8);

@@ -127,14 +127,14 @@
   }

 

   void _writeAnimationControlChunk() {

-    OutputBuffer chunk = new OutputBuffer(bigEndian: true);

+    OutputBuffer chunk = OutputBuffer(bigEndian: true);

     chunk.writeUint32(_frames); // number of frames

     chunk.writeUint32(repeat); // loop count

     _writeChunk(output, 'acTL', chunk.getBytes());

   }

 

   void _writeFrameControlChunk() {

-    OutputBuffer chunk = new OutputBuffer(bigEndian: true);

+    OutputBuffer chunk = OutputBuffer(bigEndian: true);

     chunk.writeUint32(sequenceNumber);

     chunk.writeUint32(_width);

     chunk.writeUint32(_height);

@@ -152,7 +152,7 @@
       return;

     }

 

-    OutputBuffer chunk = new OutputBuffer(bigEndian: true);

+    OutputBuffer chunk = OutputBuffer(bigEndian: true);

 

     // name

     chunk.writeBytes(iccp.name.codeUnits);

@@ -389,5 +389,5 @@
   static const int FILTER_AGRESSIVE = 5;

 

   // Table of CRCs of all 8-bit messages.

-  //final List<int> _crcTable = new List<int>(256);

+  //final List<int> _crcTable = List<int>(256);

 }

diff --git a/image/lib/src/formats/psd/effect/psd_bevel_effect.dart b/image/lib/src/formats/psd/effect/psd_bevel_effect.dart
old mode 100644
new mode 100755
index 0d09e74..91ce269
--- a/image/lib/src/formats/psd/effect/psd_bevel_effect.dart
+++ b/image/lib/src/formats/psd/effect/psd_bevel_effect.dart
@@ -1,18 +1,18 @@
-import 'psd_effect.dart';
-
-class PsdBevelEffect extends PsdEffect {
-  int angle;
-  int strength;
-  int blur;
-  String highlightBlendMode;
-  String shadowBlendMode;
-  List<int> highlightColor;
-  List<int> shadowColor;
-  int bevelStyle;
-  int highlightOpacity;
-  int shadowOpacity;
-  bool globalAngle;
-  int upOrDown;
-  List<int> realHighlightColor;
-  List<int> realShadowColor;
-}
+import 'psd_effect.dart';

+

+class PsdBevelEffect extends PsdEffect {

+  int angle;

+  int strength;

+  int blur;

+  String highlightBlendMode;

+  String shadowBlendMode;

+  List<int> highlightColor;

+  List<int> shadowColor;

+  int bevelStyle;

+  int highlightOpacity;

+  int shadowOpacity;

+  bool globalAngle;

+  int upOrDown;

+  List<int> realHighlightColor;

+  List<int> realShadowColor;

+}

diff --git a/image/lib/src/formats/psd/effect/psd_drop_shadow_effect.dart b/image/lib/src/formats/psd/effect/psd_drop_shadow_effect.dart
old mode 100644
new mode 100755
index 5fcf275..112d8d2
--- a/image/lib/src/formats/psd/effect/psd_drop_shadow_effect.dart
+++ b/image/lib/src/formats/psd/effect/psd_drop_shadow_effect.dart
@@ -1,13 +1,13 @@
-import 'psd_effect.dart';
-
-class PsdDropShadowEffect extends PsdEffect {
-  int blur;
-  int intensity;
-  int angle;
-  int distance;
-  List<int> color;
-  String blendMode;
-  bool globalAngle;
-  int opacity;
-  List<int> nativeColor;
-}
+import 'psd_effect.dart';

+

+class PsdDropShadowEffect extends PsdEffect {

+  int blur;

+  int intensity;

+  int angle;

+  int distance;

+  List<int> color;

+  String blendMode;

+  bool globalAngle;

+  int opacity;

+  List<int> nativeColor;

+}

diff --git a/image/lib/src/formats/psd/effect/psd_effect.dart b/image/lib/src/formats/psd/effect/psd_effect.dart
old mode 100644
new mode 100755
index 508a569..6b65fec
--- a/image/lib/src/formats/psd/effect/psd_effect.dart
+++ b/image/lib/src/formats/psd/effect/psd_effect.dart
@@ -1,4 +1,4 @@
-class PsdEffect {
-  int version;
-  bool enabled;
-}
+class PsdEffect {

+  int version;

+  bool enabled;

+}

diff --git a/image/lib/src/formats/psd/effect/psd_inner_glow_effect.dart b/image/lib/src/formats/psd/effect/psd_inner_glow_effect.dart
old mode 100644
new mode 100755
index 2658164..1dfc21e
--- a/image/lib/src/formats/psd/effect/psd_inner_glow_effect.dart
+++ b/image/lib/src/formats/psd/effect/psd_inner_glow_effect.dart
@@ -1,11 +1,11 @@
-import 'psd_effect.dart';
-
-class PsdInnerGlowEffect extends PsdEffect {
-  int blur;
-  int intensity;
-  List<int> color;
-  String blendMode;
-  int opacity;
-  bool invert;
-  List<int> nativeColor;
-}
+import 'psd_effect.dart';

+

+class PsdInnerGlowEffect extends PsdEffect {

+  int blur;

+  int intensity;

+  List<int> color;

+  String blendMode;

+  int opacity;

+  bool invert;

+  List<int> nativeColor;

+}

diff --git a/image/lib/src/formats/psd/effect/psd_inner_shadow_effect.dart b/image/lib/src/formats/psd/effect/psd_inner_shadow_effect.dart
old mode 100644
new mode 100755
index f8b7c67..6ac10aa
--- a/image/lib/src/formats/psd/effect/psd_inner_shadow_effect.dart
+++ b/image/lib/src/formats/psd/effect/psd_inner_shadow_effect.dart
@@ -1,13 +1,13 @@
-import 'psd_effect.dart';
-
-class PsdInnerShadowEffect extends PsdEffect {
-  int blur;
-  int intensity;
-  int angle;
-  int distance;
-  List<int> color;
-  String blendMode;
-  bool globalAngle;
-  int opacity;
-  List<int> nativeColor;
-}
+import 'psd_effect.dart';

+

+class PsdInnerShadowEffect extends PsdEffect {

+  int blur;

+  int intensity;

+  int angle;

+  int distance;

+  List<int> color;

+  String blendMode;

+  bool globalAngle;

+  int opacity;

+  List<int> nativeColor;

+}

diff --git a/image/lib/src/formats/psd/effect/psd_outer_glow_effect.dart b/image/lib/src/formats/psd/effect/psd_outer_glow_effect.dart
old mode 100644
new mode 100755
index 551e3b1..db86a3c
--- a/image/lib/src/formats/psd/effect/psd_outer_glow_effect.dart
+++ b/image/lib/src/formats/psd/effect/psd_outer_glow_effect.dart
@@ -1,10 +1,10 @@
-import 'psd_effect.dart';
-
-class PsdOuterGlowEffect extends PsdEffect {
-  int blur;
-  int intensity;
-  List<int> color;
-  String blendMode;
-  int opacity;
-  List<int> nativeColor;
-}
+import 'psd_effect.dart';

+

+class PsdOuterGlowEffect extends PsdEffect {

+  int blur;

+  int intensity;

+  List<int> color;

+  String blendMode;

+  int opacity;

+  List<int> nativeColor;

+}

diff --git a/image/lib/src/formats/psd/effect/psd_solid_fill_effect.dart b/image/lib/src/formats/psd/effect/psd_solid_fill_effect.dart
old mode 100644
new mode 100755
index bec7fe2..5b8ce6e
--- a/image/lib/src/formats/psd/effect/psd_solid_fill_effect.dart
+++ b/image/lib/src/formats/psd/effect/psd_solid_fill_effect.dart
@@ -1,8 +1,8 @@
-import 'psd_effect.dart';
-
-class PsdSolidFillEffect extends PsdEffect {
-  String blendMode;
-  List<int> color;
-  int opacity;
-  List<int> nativeColor;
-}
+import 'psd_effect.dart';

+

+class PsdSolidFillEffect extends PsdEffect {

+  String blendMode;

+  List<int> color;

+  int opacity;

+  List<int> nativeColor;

+}

diff --git a/image/lib/src/formats/psd/layer_data/psd_layer_additional_data.dart b/image/lib/src/formats/psd/layer_data/psd_layer_additional_data.dart
old mode 100644
new mode 100755
index cd33751..21f9732
--- a/image/lib/src/formats/psd/layer_data/psd_layer_additional_data.dart
+++ b/image/lib/src/formats/psd/layer_data/psd_layer_additional_data.dart
@@ -1,10 +1,10 @@
-import '../../../util/input_buffer.dart';
-import '../psd_layer_data.dart';
-
-class PsdLayerAdditionalData extends PsdLayerData {
-  InputBuffer data;
-
-  PsdLayerAdditionalData(String tag, InputBuffer data) :
-    this.data = data,
-    super.type(tag);
-}
+import '../../../util/input_buffer.dart';

+import '../psd_layer_data.dart';

+

+class PsdLayerAdditionalData extends PsdLayerData {

+  InputBuffer data;

+

+  PsdLayerAdditionalData(String tag, InputBuffer data) :

+    this.data = data,

+    super.type(tag);

+}

diff --git a/image/lib/src/formats/psd/layer_data/psd_layer_section_divider.dart b/image/lib/src/formats/psd/layer_data/psd_layer_section_divider.dart
old mode 100644
new mode 100755
index 40f50fe..71ae146
--- a/image/lib/src/formats/psd/layer_data/psd_layer_section_divider.dart
+++ b/image/lib/src/formats/psd/layer_data/psd_layer_section_divider.dart
@@ -1,38 +1,38 @@
-import '../../../image_exception.dart';
-import '../../../util/input_buffer.dart';
-import '../psd_layer_data.dart';
-
-class PsdLayerSectionDivider extends PsdLayerData {
-  static const String TAG = 'lsct';
-
-  static const int NORMAL = 0;
-  static const int OPEN_FOLDER = 1;
-  static const int CLOSED_FOLDER = 2;
-  static const int SECTION_DIVIDER = 3;
-
-  static const int SUBTYPE_NORMAL = 0;
-  static const int SUBTYPE_SCENE_GROUP = 1;
-
-  int type;
-  String key;
-  int subType = SUBTYPE_NORMAL;
-
-  PsdLayerSectionDivider(String tag, InputBuffer data) :
-    super.type(tag) {
-    int len = data.length;
-
-    type = data.readUint32();
-
-    if (len >= 12) {
-      String sig = data.readString(4);
-      if (sig != '8BIM') {
-        throw new ImageException('Invalid key in layer additional data');
-      }
-      key = data.readString(4);
-    }
-
-    if (len >= 16) {
-      subType = data.readUint32();
-    }
-  }
-}
+import '../../../image_exception.dart';

+import '../../../util/input_buffer.dart';

+import '../psd_layer_data.dart';

+

+class PsdLayerSectionDivider extends PsdLayerData {

+  static const String TAG = 'lsct';

+

+  static const int NORMAL = 0;

+  static const int OPEN_FOLDER = 1;

+  static const int CLOSED_FOLDER = 2;

+  static const int SECTION_DIVIDER = 3;

+

+  static const int SUBTYPE_NORMAL = 0;

+  static const int SUBTYPE_SCENE_GROUP = 1;

+

+  int type;

+  String key;

+  int subType = SUBTYPE_NORMAL;

+

+  PsdLayerSectionDivider(String tag, InputBuffer data) :

+    super.type(tag) {

+    int len = data.length;

+

+    type = data.readUint32();

+

+    if (len >= 12) {

+      String sig = data.readString(4);

+      if (sig != '8BIM') {

+        throw new ImageException('Invalid key in layer additional data');

+      }

+      key = data.readString(4);

+    }

+

+    if (len >= 16) {

+      subType = data.readUint32();

+    }

+  }

+}

diff --git a/image/lib/src/formats/psd/psd_blending_ranges.dart b/image/lib/src/formats/psd/psd_blending_ranges.dart
old mode 100644
new mode 100755
index 320bd29..bb5e850
--- a/image/lib/src/formats/psd/psd_blending_ranges.dart
+++ b/image/lib/src/formats/psd/psd_blending_ranges.dart
@@ -1,39 +1,39 @@
-import 'dart:typed_data';
-
-import '../../util/input_buffer.dart';
-
-class PsdBlendingRanges {
-  int grayBlackSrc;
-  int grayWhiteSrc;
-  int grayBlackDst;
-  int grayWhiteDst;
-  Uint16List blackSrc;
-  Uint16List whiteSrc;
-  Uint16List blackDst;
-  Uint16List whiteDst;
-
-  PsdBlendingRanges(InputBuffer input) {
-    grayBlackSrc = input.readUint16();
-    grayWhiteSrc = input.readUint16();
-
-    grayBlackDst = input.readUint16();
-    grayWhiteDst = input.readUint16();
-
-    int len = input.length;
-    int numChannels = len ~/ 8;
-
-    if (numChannels > 0) {
-      blackSrc = new Uint16List(numChannels);
-      whiteSrc = new Uint16List(numChannels);
-      blackDst = new Uint16List(numChannels);
-      whiteDst = new Uint16List(numChannels);
-
-      for (int i = 0; i < numChannels; ++i) {
-        blackSrc[i] = input.readUint16();
-        whiteSrc[i] = input.readUint16();
-        blackDst[i] = input.readUint16();
-        whiteDst[i] = input.readUint16();
-      }
-    }
-  }
+import 'dart:typed_data';

+

+import '../../util/input_buffer.dart';

+

+class PsdBlendingRanges {

+  int grayBlackSrc;

+  int grayWhiteSrc;

+  int grayBlackDst;

+  int grayWhiteDst;

+  Uint16List blackSrc;

+  Uint16List whiteSrc;

+  Uint16List blackDst;

+  Uint16List whiteDst;

+

+  PsdBlendingRanges(InputBuffer input) {

+    grayBlackSrc = input.readUint16();

+    grayWhiteSrc = input.readUint16();

+

+    grayBlackDst = input.readUint16();

+    grayWhiteDst = input.readUint16();

+

+    int len = input.length;

+    int numChannels = len ~/ 8;

+

+    if (numChannels > 0) {

+      blackSrc = Uint16List(numChannels);

+      whiteSrc = Uint16List(numChannels);

+      blackDst = Uint16List(numChannels);

+      whiteDst = Uint16List(numChannels);

+

+      for (int i = 0; i < numChannels; ++i) {

+        blackSrc[i] = input.readUint16();

+        whiteSrc[i] = input.readUint16();

+        blackDst[i] = input.readUint16();

+        whiteDst[i] = input.readUint16();

+      }

+    }

+  }

 }
\ No newline at end of file
diff --git a/image/lib/src/formats/psd/psd_channel.dart b/image/lib/src/formats/psd/psd_channel.dart
old mode 100644
new mode 100755
index 2568bd0..7a95ce6
--- a/image/lib/src/formats/psd/psd_channel.dart
+++ b/image/lib/src/formats/psd/psd_channel.dart
@@ -1,119 +1,119 @@
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-
-class PsdChannel {
-  static const int RED = 0;
-  static const int GREEN = 1;
-  static const int BLUE = 2;
-  static const int BLACK = 3;
-  static const int ALPHA = -1;
-  static const int MASK = -2;
-  static const int REAL_MASK = -3;
-
-  static const int COMPRESS_NONE = 0;
-  static const int COMPRESS_RLE = 1;
-  static const int COMPRESS_ZIP = 2;
-  static const int COMPRESS_ZIP_PREDICTOR = 3;
-
-  int id;
-  int dataLength;
-  Uint8List data;
-
-  PsdChannel(this.id, this.dataLength);
-
-  PsdChannel.read(InputBuffer input, this.id, int width, int height,
-                  int bitDepth, int compression, Uint16List lineLengths,
-                  int planeNumber) {
-    readPlane(input, width, height, bitDepth, compression, lineLengths,
-              planeNumber);
-  }
-
-  void readPlane(InputBuffer input, int width, int height, int bitDepth,
-                 [int compression, Uint16List lineLengths, int planeNum = 0]) {
-    if (compression == null) {
-      compression = input.readUint16();
-    }
-
-    switch (compression) {
-      case COMPRESS_NONE:
-        _readPlaneUncompressed(input, width, height, bitDepth);
-        break;
-      case COMPRESS_RLE:
-        if (lineLengths == null) {
-          lineLengths = _readLineLengths(input, height);
-        }
-        _readPlaneRleCompressed(input, width, height, bitDepth, lineLengths,
-                                planeNum);
-        break;
-      default:
-        throw new ImageException('Unsupported compression: $compression');
-    }
-  }
-
-  Uint16List _readLineLengths(InputBuffer input, int height) {
-    Uint16List lineLengths = new Uint16List(height);
-    for (int i = 0; i < height; ++i) {
-      lineLengths[i] = input.readUint16();
-    }
-    return lineLengths;
-  }
-
-  void _readPlaneUncompressed(InputBuffer input, int width, int height,
-                              int bitDepth) {
-    int len = width * height;
-    if (bitDepth == 16) {
-      len *= 2;
-    }
-    if (len > input.length) {
-      data = new Uint8List(len);
-      data.fillRange(0, len, 255);
-      return;
-    }
-
-    InputBuffer imgData = input.readBytes(len);
-    data = imgData.toUint8List();
-  }
-
-  void _readPlaneRleCompressed(InputBuffer input, int width, int height,
-                               int bitDepth, Uint16List lineLengths,
-                               int planeNum) {
-    int len = width * height;
-    if (bitDepth == 16) {
-      len *= 2;
-    }
-    data = new Uint8List(len);
-    int pos = 0;
-    int lineIndex = planeNum * height;
-    if (lineIndex >= lineLengths.length) {
-      data.fillRange(0, data.length, 255);
-      return;
-    }
-
-    for (int i = 0; i < height; ++i) {
-      int len = lineLengths[lineIndex++];
-      InputBuffer s = input.readBytes(len);
-      _decodeRLE(s, data, pos);
-      pos += width;
-    }
-  }
-
-  void _decodeRLE(InputBuffer src, Uint8List dst, int dstIndex) {
-    while (!src.isEOS) {
-      int n = src.readInt8();
-      if (n < 0) {
-        n = 1 - n;
-        int b = src.readByte();
-        for (int i = 0; i < n; ++i) {
-          dst[dstIndex++] = b;
-        }
-      } else {
-        n++;
-        for (int i = 0; i < n; ++i) {
-          dst[dstIndex++] = src.readByte();
-        }
-      }
-    }
-  }
-}
+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+

+class PsdChannel {

+  static const int RED = 0;

+  static const int GREEN = 1;

+  static const int BLUE = 2;

+  static const int BLACK = 3;

+  static const int ALPHA = -1;

+  static const int MASK = -2;

+  static const int REAL_MASK = -3;

+

+  static const int COMPRESS_NONE = 0;

+  static const int COMPRESS_RLE = 1;

+  static const int COMPRESS_ZIP = 2;

+  static const int COMPRESS_ZIP_PREDICTOR = 3;

+

+  int id;

+  int dataLength;

+  Uint8List data;

+

+  PsdChannel(this.id, this.dataLength);

+

+  PsdChannel.read(InputBuffer input, this.id, int width, int height,

+                  int bitDepth, int compression, Uint16List lineLengths,

+                  int planeNumber) {

+    readPlane(input, width, height, bitDepth, compression, lineLengths,

+              planeNumber);

+  }

+

+  void readPlane(InputBuffer input, int width, int height, int bitDepth,

+                 [int compression, Uint16List lineLengths, int planeNum = 0]) {

+    if (compression == null) {

+      compression = input.readUint16();

+    }

+

+    switch (compression) {

+      case COMPRESS_NONE:

+        _readPlaneUncompressed(input, width, height, bitDepth);

+        break;

+      case COMPRESS_RLE:

+        if (lineLengths == null) {

+          lineLengths = _readLineLengths(input, height);

+        }

+        _readPlaneRleCompressed(input, width, height, bitDepth, lineLengths,

+                                planeNum);

+        break;

+      default:

+        throw new ImageException('Unsupported compression: $compression');

+    }

+  }

+

+  Uint16List _readLineLengths(InputBuffer input, int height) {

+    Uint16List lineLengths = Uint16List(height);

+    for (int i = 0; i < height; ++i) {

+      lineLengths[i] = input.readUint16();

+    }

+    return lineLengths;

+  }

+

+  void _readPlaneUncompressed(InputBuffer input, int width, int height,

+                              int bitDepth) {

+    int len = width * height;

+    if (bitDepth == 16) {

+      len *= 2;

+    }

+    if (len > input.length) {

+      data = Uint8List(len);

+      data.fillRange(0, len, 255);

+      return;

+    }

+

+    InputBuffer imgData = input.readBytes(len);

+    data = imgData.toUint8List();

+  }

+

+  void _readPlaneRleCompressed(InputBuffer input, int width, int height,

+                               int bitDepth, Uint16List lineLengths,

+                               int planeNum) {

+    int len = width * height;

+    if (bitDepth == 16) {

+      len *= 2;

+    }

+    data = Uint8List(len);

+    int pos = 0;

+    int lineIndex = planeNum * height;

+    if (lineIndex >= lineLengths.length) {

+      data.fillRange(0, data.length, 255);

+      return;

+    }

+

+    for (int i = 0; i < height; ++i) {

+      int len = lineLengths[lineIndex++];

+      InputBuffer s = input.readBytes(len);

+      _decodeRLE(s, data, pos);

+      pos += width;

+    }

+  }

+

+  void _decodeRLE(InputBuffer src, Uint8List dst, int dstIndex) {

+    while (!src.isEOS) {

+      int n = src.readInt8();

+      if (n < 0) {

+        n = 1 - n;

+        int b = src.readByte();

+        for (int i = 0; i < n; ++i) {

+          dst[dstIndex++] = b;

+        }

+      } else {

+        n++;

+        for (int i = 0; i < n; ++i) {

+          dst[dstIndex++] = src.readByte();

+        }

+      }

+    }

+  }

+}

diff --git a/image/lib/src/formats/psd/psd_image.dart b/image/lib/src/formats/psd/psd_image.dart
old mode 100644
new mode 100755
index 0641644..b2a3ce7
--- a/image/lib/src/formats/psd/psd_image.dart
+++ b/image/lib/src/formats/psd/psd_image.dart
@@ -1,617 +1,617 @@
-import 'dart:math' as Math;
-import 'dart:typed_data';
-
-import '../decode_info.dart';
-import '../../color.dart';
-import '../../image.dart';
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-import 'psd_channel.dart';
-import 'psd_image_resource.dart';
-import 'psd_layer.dart';
-
-class PsdImage extends DecodeInfo {
-  static const int SIGNATURE = 0x38425053; // '8BPS'
-
-  static const int COLORMODE_BITMAP = 0;
-  static const int COLORMODE_GRAYSCALE = 1;
-  static const int COLORMODE_INDEXED = 2;
-  static const int COLORMODE_RGB = 3;
-  static const int COLORMODE_CMYK = 4;
-  static const int COLORMODE_MULTICHANNEL = 7;
-  static const int COLORMODE_DUOTONE = 8;
-  static const int COLORMODE_LAB = 9;
-
-  int signature;
-  int version;
-  int channels;
-  int depth;
-  int colorMode;
-  List<PsdLayer> layers;
-  List<PsdChannel> mergeImageChannels;
-  Image mergedImage;
-  Map<int, PsdImageResource> imageResources = {};
-  bool hasAlpha = false;
-
-  PsdImage(List<int> bytes) {
-    _input = new InputBuffer(bytes, bigEndian: true);
-
-    _readHeader();
-    if (!isValid) {
-      return;
-    }
-
-    int len = _input.readUint32();
-    /*_colorData =*/ _input.readBytes(len);
-
-    len = _input.readUint32();
-    _imageResourceData = _input.readBytes(len);
-
-    len = _input.readUint32();
-    _layerAndMaskData = _input.readBytes(len);
-
-    _imageData = _input.readBytes(_input.length);
-  }
-
-  bool get isValid => signature == SIGNATURE;
-
-  /// The number of frames that can be decoded.
-  int get numFrames => 1;
-
-  /**
-   * Decode the raw psd structure without rendering the output image.
-   * Use [renderImage] to render the output image.
-   */
-  bool decode() {
-    if (!isValid || _input == null) {
-      return false;
-    }
-
-    // Color Mode Data Block:
-    // Indexed and duotone images have palette data in colorData...
-    _readColorModeData();
-
-    // Image Resource Block:
-    // Image resources are used to store non-pixel data associated with images,
-    // such as pen tool paths.
-    _readImageResources();
-
-    _readLayerAndMaskData();
-
-    _readMergeImageData();
-
-    _input = null;
-    //_colorData = null;
-    _imageResourceData = null;
-    _layerAndMaskData = null;
-    _imageData = null;
-
-    return true;
-  }
-
-  Image decodeImage() {
-    if (!decode()) {
-      return null;
-    }
-
-    return renderImage();
-  }
-
-  Image renderImage() {
-    if (mergedImage != null) {
-      return mergedImage;
-    }
-
-    mergedImage = new Image(width, height);
-    mergedImage.fill(0);
-
-    Uint8List pixels = mergedImage.getBytes();
-
-    for (int li = 0; li < layers.length; ++li) {
-      PsdLayer layer = layers[li];
-      if (!layer.isVisible()) {
-        continue;
-      }
-
-      double opacity = layer.opacity / 255.0;
-      int blendMode = layer.blendMode;
-
-      //int ns = depth == 16 ? 2 : 1;
-      Uint8List srcP = layer.layerImage.getBytes();
-
-      for (int y = 0, sy = layer.top, si = 0; y < layer.height; ++y, ++sy) {
-        int di = (layer.top + y) * width * 4 + layer.left * 4;
-        for (int x = 0, sx = layer.left; x < layer.width; ++x, ++sx) {
-          int br = srcP[si++];
-          int bg = srcP[si++];
-          int bb = srcP[si++];
-          int ba = srcP[si++];
-
-          if (sx >= 0 && sx < width && sy >= 0 && sy < height) {
-            int ar = pixels[di];
-            int ag = pixels[di + 1];
-            int ab = pixels[di + 2];
-            int aa = pixels[di + 3];
-
-            _blend(ar, ag, ab, aa, br, bg, bb, ba, blendMode, opacity,
-                   pixels, di);
-          }
-
-          di += 4;
-        }
-      }
-    }
-
-    return mergedImage;
-  }
-
-  void _blend(int ar, int ag, int ab, int aa,
-              int br, int bg, int bb, int ba,
-              int blendMode, double opacity,
-              Uint8List pixels, int di) {
-    int r = br;
-    int g = bg;
-    int b = bb;
-    int a = ba;
-    double da = (ba / 255.0) * opacity;
-
-    switch (blendMode) {
-      case PsdLayer.BLEND_PASSTHROUGH:
-        r = ar;
-        g = ag;
-        b = ab;
-        a = aa;
-        break;
-      case PsdLayer.BLEND_NORMAL:
-        break;
-      case PsdLayer.BLEND_DISSOLVE:
-        break;
-      case PsdLayer.BLEND_DARKEN:
-        r = _blendDarken(ar, br);
-        g = _blendDarken(ag, bg);
-        b = _blendDarken(ab, bb);
-        break;
-      case PsdLayer.BLEND_MULTIPLY:
-        r = _blendMultiply(ar, br);
-        g = _blendMultiply(ag, bg);
-        b = _blendMultiply(ab, bb);
-        break;
-      case PsdLayer.BLEND_COLOR_BURN:
-        r = _blendColorBurn(ar, br);
-        g = _blendColorBurn(ag, bg);
-        b = _blendColorBurn(ab, bb);
-        break;
-      case PsdLayer.BLEND_LINEAR_BURN:
-        r = _blendLinearBurn(ar, br);
-        g = _blendLinearBurn(ag, bg);
-        b = _blendLinearBurn(ab, bb);
-        break;
-      case PsdLayer.BLEND_DARKEN_COLOR:
-        break;
-      case PsdLayer.BLEND_LIGHTEN:
-        r = _blendLighten(ar, br);
-        g = _blendLighten(ag, bg);
-        b = _blendLighten(ab, bb);
-        break;
-      case PsdLayer.BLEND_SCREEN:
-        r = _blendScreen(ar, br);
-        g = _blendScreen(ag, bg);
-        b = _blendScreen(ab, bb);
-        break;
-      case PsdLayer.BLEND_COLOR_DODGE:
-        r = _blendColorDodge(ar, br);
-        g = _blendColorDodge(ag, bg);
-        b = _blendColorDodge(ab, bb);
-        break;
-      case PsdLayer.BLEND_LINEAR_DODGE:
-        r = _blendLinearDodge(ar, br);
-        g = _blendLinearDodge(ag, bg);
-        b = _blendLinearDodge(ab, bb);
-        break;
-      case PsdLayer.BLEND_LIGHTER_COLOR:
-        break;
-      case PsdLayer.BLEND_OVERLAY:
-        r = _blendOverlay(ar, br, aa, ba);
-        g = _blendOverlay(ag, bg, aa, ba);
-        b = _blendOverlay(ab, bb, aa, ba);
-        break;
-      case PsdLayer.BLEND_SOFT_LIGHT:
-        r = _blendSoftLight(ar, br);
-        g = _blendSoftLight(ag, bg);
-        b = _blendSoftLight(ab, bb);
-        break;
-      case PsdLayer.BLEND_HARD_LIGHT:
-        r = _blendHardLight(ar, br);
-        g = _blendHardLight(ag, bg);
-        b = _blendHardLight(ab, bb);
-        break;
-      case PsdLayer.BLEND_VIVID_LIGHT:
-        r = _blendVividLight(ar, br);
-        g = _blendVividLight(ag, bg);
-        b = _blendVividLight(ab, bb);
-        break;
-      case PsdLayer.BLEND_LINEAR_LIGHT:
-        r = _blendLinearLight(ar, br);
-        g = _blendLinearLight(ag, bg);
-        b = _blendLinearLight(ab, bb);
-        break;
-      case PsdLayer.BLEND_PIN_LIGHT:
-        r = _blendPinLight(ar, br);
-        g = _blendPinLight(ag, bg);
-        b = _blendPinLight(ab, bb);
-        break;
-      case PsdLayer.BLEND_HARD_MIX:
-        r = _blendHardMix(ar, br);
-        g = _blendHardMix(ag, bg);
-        b = _blendHardMix(ab, bb);
-        break;
-      case PsdLayer.BLEND_DIFFERENCE:
-        r = _blendDifference(ar, br);
-        g = _blendDifference(ag, bg);
-        b = _blendDifference(ab, bb);
-        break;
-      case PsdLayer.BLEND_EXCLUSION:
-        r = _blendExclusion(ar, br);
-        g = _blendExclusion(ag, bg);
-        b = _blendExclusion(ab, bb);
-        break;
-      case PsdLayer.BLEND_SUBTRACT:
-        break;
-      case PsdLayer.BLEND_DIVIDE:
-        break;
-      case PsdLayer.BLEND_HUE:
-        break;
-      case PsdLayer.BLEND_SATURATION:
-        break;
-      case PsdLayer.BLEND_COLOR:
-        break;
-      case PsdLayer.BLEND_LUMINOSITY:
-        break;
-    }
-
-    r = ((ar * (1.0 - da)) + (r * da)).toInt();
-    g = ((ag * (1.0 - da)) + (g * da)).toInt();
-    b = ((ab * (1.0 - da)) + (b * da)).toInt();
-    a = ((aa * (1.0 - da)) + (a * da)).toInt();
-
-    pixels[di++] = r;
-    pixels[di++] = g;
-    pixels[di++] = b;
-    pixels[di++] = a;
-  }
-
-  static int _blendLighten(int a, int b) {
-    return Math.max(a, b);
-  }
-
-  static int _blendDarken(int a, int b) {
-    return Math.min(a,  b);
-  }
-
-  static int _blendMultiply(int a, int b) {
-    return (a * b) >> 8;
-  }
-
-  static int _blendOverlay(int a, int b, int aAlpha, int bAlpha) {
-    double x = a / 255.0;
-    double y = b / 255.0;
-    double aa = aAlpha / 255.0;
-    double ba = bAlpha / 255.0;
-
-    double z;
-    if (2.0 * x < aa) {
-      z = 2.0 * y * x + y * (1.0 - aa) + x * (1.0 - ba);
-    } else {
-      z = ba * aa - 2.0 * (aa - x) * (ba - y) +
-          y * (1.0 - aa) + x * (1.0 - ba);
-    }
-
-    return (z * 255.0).toInt().clamp(0, 255);
-  }
-
-  static int _blendColorBurn(int a, int b) {
-    if (b == 0) {
-      return 0; // We don't want to divide by zero
-    }
-    int c = (255.0 * (1.0 - (1.0 - (a / 255.0)) / (b / 255.0))).toInt();
-    return c.clamp(0, 255);
-  }
-
-  static int _blendLinearBurn(int a, int b) {
-    return (a + b - 255).clamp(0, 255);
-  }
-
-  static int _blendScreen(int a, int b) {
-    return (255 - ((255 - b) * (255 - a))).clamp(0, 255);
-  }
-
-  static int _blendColorDodge(int a, int b) {
-    if (b == 255) {
-      return 255;
-    }
-    return (((a / 255) / (1.0 - (b / 255.0))) * 255.0).toInt().clamp(0, 255);
-  }
-
-  static int _blendLinearDodge(int a, int b) {
-    return (b + a > 255) ? 0xff : a + b;
-  }
-
-  static int _blendSoftLight(int a, int b) {
-    double aa = a / 255.0;
-    double bb = b / 255.0;
-    return (255.0 * ((1.0 - bb) * bb * aa +
-                     bb * (1.0 - (1.0 - bb) * (1.0 - aa)))).round();
-  }
-
-  static int _blendHardLight(int bottom, int top) {
-    double a = top / 255.0;
-    double b = bottom / 255.0;
-    if (b < 0.5) {
-      return (255.0 * 2.0 * a * b).round();
-    } else {
-      return (255.0 * (1.0 - 2.0 * (1.0 - a) * (1.0 - b))).round();
-    }
-  }
-
-  static int _blendVividLight(int bottom, int top) {
-    if ( top < 128) {
-      return _blendColorBurn(bottom, 2 * top);
-    } else {
-      return _blendColorDodge(bottom, 2 * (top - 128));
-    }
-  }
-
-  static int _blendLinearLight(int bottom, int top) {
-    if (top < 128) {
-      return _blendLinearBurn(bottom, 2 * top);
-    } else {
-      return _blendLinearDodge(bottom, 2 * (top - 128));
-    }
-  }
-
-  static int _blendPinLight(int bottom, int top) {
-    return (top < 128) ?
-           _blendDarken(bottom, 2 * top) :
-           _blendLighten(bottom, 2 * (top - 128));
-  }
-
-  static int _blendHardMix(int bottom, int top) {
-    return (top < 255 - bottom) ? 0 : 255;
-  }
-
-  static int _blendDifference(int bottom, int top) {
-    return (top - bottom).abs();
-  }
-
-  static int _blendExclusion(int bottom, int top) {
-    return (top + bottom - 2 * top * bottom / 255.0).round();
-  }
-
-  void _readHeader() {
-    signature = _input.readUint32();
-    version = _input.readUint16();
-
-    // version should be 1 (2 for PSB files).
-    if (version != 1) {
-      signature = 0;
-      return;
-    }
-
-    // padding should be all 0's
-    InputBuffer padding = _input.readBytes(6);
-    for (int i = 0; i < 6; ++i) {
-      if (padding[i] != 0) {
-        signature = 0;
-        return;
-      }
-    }
-
-    channels = _input.readUint16();
-    height = _input.readUint32();
-    width = _input.readUint32();
-    depth = _input.readUint16();
-    colorMode = _input.readUint16();
-  }
-
-  void _readColorModeData() {
-    // TODO support indexed and duotone images.
-  }
-
-  void _readImageResources() {
-    _imageResourceData.rewind();
-    while (!_imageResourceData.isEOS) {
-      int blockSignature = _imageResourceData.readUint32();
-      int blockId = _imageResourceData.readUint16();
-
-      int len = _imageResourceData.readByte();
-      String blockName = _imageResourceData.readString(len);
-      // name string is padded to an even size
-      if (len & 1 == 0) {
-        _imageResourceData.skip(1);
-      }
-
-      len = _imageResourceData.readUint32();
-      InputBuffer blockData = _imageResourceData.readBytes(len);
-      // blocks are padded to an even length.
-      if (len & 1 == 1) {
-        _imageResourceData.skip(1);
-      }
-
-      if (blockSignature == RESOURCE_BLOCK_SIGNATURE) {
-        imageResources[blockId] = new PsdImageResource(blockId, blockName,
-                                                       blockData);
-      }
-    }
-  }
-
-  void _readLayerAndMaskData() {
-    _layerAndMaskData.rewind();
-    int len = _layerAndMaskData.readUint32();
-    if ((len & 1) != 0) {
-      len++;
-    }
-
-    InputBuffer layerData = _layerAndMaskData.readBytes(len);
-
-    layers = [];
-    if (len > 0) {
-      int count = layerData.readInt16();
-      // If it is a negative number, its absolute value is the number of
-      // layers and the first alpha channel contains the transparency data for
-      // the merged result.
-      if (count < 0) {
-        hasAlpha = true;
-        count = -count;
-      }
-
-      for (int i = 0; i < count; ++i) {
-        PsdLayer layer = new PsdLayer(layerData);
-        layers.add(layer);
-      }
-    }
-
-    for (int i = 0; i < layers.length; ++i) {
-      layers[i].readImageData(layerData, this);
-    }
-
-    // Global layer mask info
-    len = _layerAndMaskData.readUint32();
-    InputBuffer maskData = _layerAndMaskData.readBytes(len);
-    if (len > 0) {
-      /*int colorSpace =*/ maskData.readUint16();
-      /*int rc =*/ maskData.readUint16();
-      /*int gc =*/ maskData.readUint16();
-      /*int bc =*/ maskData.readUint16();
-      /*int ac =*/ maskData.readUint16();
-      /*int opacity =*/ maskData.readUint16(); // 0-100
-      /*int kind =*/ maskData.readByte();
-    }
-  }
-
-  void _readMergeImageData() {
-    _imageData.rewind();
-    int compression = _imageData.readUint16();
-
-    Uint16List lineLengths;
-    if (compression == PsdChannel.COMPRESS_RLE) {
-      int numLines = height * this.channels;
-      lineLengths = new Uint16List(numLines);
-      for (int i = 0; i < numLines; ++i) {
-        lineLengths[i] = _imageData.readUint16();
-      }
-    }
-
-    mergeImageChannels = [];
-    for (int i = 0; i < channels; ++i) {
-      mergeImageChannels.add(new PsdChannel.read(_imageData, i == 3 ? -1 : i,
-                                         width, height, depth, compression,
-                                         lineLengths, i));
-    }
-
-    mergedImage = createImageFromChannels(colorMode, depth,
-                                         width, height,
-                                         mergeImageChannels);
-  }
-
-  static int _ch(List<int> data, int si, int ns) {
-    return ns == 1 ? data[si] :
-           ((data[si] << 8) | data[si + 1]) >> 8;
-  }
-
-  static Image createImageFromChannels(int colorMode, int bitDepth, int width,
-                                       int height,
-                                       List<PsdChannel> channelList) {
-    Image output = new Image(width, height);
-    Uint8List pixels = output.getBytes();
-
-    Map<int, PsdChannel> channels = {};
-    for (PsdChannel ch in channelList) {
-      channels[ch.id] = ch;
-    }
-
-    int numChannels = channelList.length;
-    int ns = (bitDepth == 8) ? 1 : (bitDepth == 16) ? 2 : -1;
-    if (ns == -1) {
-      throw new ImageException('PSD: unsupported bit depth: $bitDepth');
-    }
-
-    final channel0 = channels[0];
-    final channel1 = channels[1];
-    final channel2 = channels[2];
-    final channel_1 = channels[-1];
-
-    for (int y = 0, di = 0, si = 0; y < height; ++y) {
-      for (int x = 0; x < width; ++x, si += ns) {
-        switch (colorMode) {
-          case COLORMODE_RGB:
-            int xi = di;
-            pixels[di++] = _ch(channel0.data, si, ns);
-            pixels[di++] = _ch(channel1.data, si, ns);
-            pixels[di++] = _ch(channel2.data, si, ns);
-            pixels[di++] = numChannels >= 4 ?
-                           _ch(channel_1.data, si, ns) : 255;
-
-            var r = pixels[xi];
-            var g = pixels[xi + 1];
-            var b = pixels[xi + 2];
-            var a = pixels[xi + 3];
-            if (a != 0) {
-              // Photoshop/Gimp blend the image against white (argh!),
-              // which is not what we want for compositing. Invert the blend
-              // operation to try and undo the damage.
-              pixels[xi] = (((r + a) - 255) * 255) ~/ a;
-              pixels[xi + 1] = (((g + a) - 255) * 255) ~/ a;
-              pixels[xi + 2] = (((b + a) - 255) * 255) ~/ a;
-            }
-            break;
-          case COLORMODE_LAB:
-            int L = _ch(channel0.data, si, ns) * 100 >> 8;
-            int a = _ch(channel1.data, si, ns) - 128;
-            int b = _ch(channel2.data, si, ns) - 128;
-            int alpha = numChannels >= 4 ?
-                        _ch(channel_1.data, si, ns) : 255;
-            List<int> rgb = labToRGB(L, a, b);
-            pixels[di++] = rgb[0];
-            pixels[di++] = rgb[1];
-            pixels[di++] = rgb[2];
-            pixels[di++] = alpha;
-            break;
-          case COLORMODE_GRAYSCALE:
-            int gray = _ch(channel0.data, si, ns);
-            int alpha = numChannels >= 2 ?
-                       _ch(channel_1.data, si, ns) : 255;
-            pixels[di++] = gray;
-            pixels[di++] = gray;
-            pixels[di++] = gray;
-            pixels[di++] = alpha;
-            break;
-          case COLORMODE_CMYK:
-            int c = _ch(channel0.data, si, ns);
-            int m = _ch(channel1.data, si, ns);
-            int y = _ch(channel2.data, si, ns);
-            int k = _ch(channels[numChannels == 4 ? -1 : 3].data, si, ns);
-            int alpha = numChannels >= 5 ?
-                        _ch(channel_1.data, si, ns) : 255;
-            List<int> rgb = cmykToRGB(255 - c, 255 - m, 255 - y, 255 - k);
-            pixels[di++] = rgb[0];
-            pixels[di++] = rgb[1];
-            pixels[di++] = rgb[2];
-            pixels[di++] = alpha;
-            break;
-          default:
-            throw new ImageException('Unhandled color mode: $colorMode');
-        }
-      }
-    }
-
-    return output;
-  }
-
-  static const int RESOURCE_BLOCK_SIGNATURE = 0x3842494d; // '8BIM'
-
-  InputBuffer _input;
-  //InputBuffer _colorData;
-  InputBuffer _imageResourceData;
-  InputBuffer _layerAndMaskData;
-  InputBuffer _imageData;
-}
+import 'dart:math' as Math;

+import 'dart:typed_data';

+

+import '../decode_info.dart';

+import '../../color.dart';

+import '../../image.dart';

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+import 'psd_channel.dart';

+import 'psd_image_resource.dart';

+import 'psd_layer.dart';

+

+class PsdImage extends DecodeInfo {

+  static const int SIGNATURE = 0x38425053; // '8BPS'

+

+  static const int COLORMODE_BITMAP = 0;

+  static const int COLORMODE_GRAYSCALE = 1;

+  static const int COLORMODE_INDEXED = 2;

+  static const int COLORMODE_RGB = 3;

+  static const int COLORMODE_CMYK = 4;

+  static const int COLORMODE_MULTICHANNEL = 7;

+  static const int COLORMODE_DUOTONE = 8;

+  static const int COLORMODE_LAB = 9;

+

+  int signature;

+  int version;

+  int channels;

+  int depth;

+  int colorMode;

+  List<PsdLayer> layers;

+  List<PsdChannel> mergeImageChannels;

+  Image mergedImage;

+  Map<int, PsdImageResource> imageResources = {};

+  bool hasAlpha = false;

+

+  PsdImage(List<int> bytes) {

+    _input = InputBuffer(bytes, bigEndian: true);

+

+    _readHeader();

+    if (!isValid) {

+      return;

+    }

+

+    int len = _input.readUint32();

+    /*_colorData =*/ _input.readBytes(len);

+

+    len = _input.readUint32();

+    _imageResourceData = _input.readBytes(len);

+

+    len = _input.readUint32();

+    _layerAndMaskData = _input.readBytes(len);

+

+    _imageData = _input.readBytes(_input.length);

+  }

+

+  bool get isValid => signature == SIGNATURE;

+

+  /// The number of frames that can be decoded.

+  int get numFrames => 1;

+

+  /**

+   * Decode the raw psd structure without rendering the output image.

+   * Use [renderImage] to render the output image.

+   */

+  bool decode() {

+    if (!isValid || _input == null) {

+      return false;

+    }

+

+    // Color Mode Data Block:

+    // Indexed and duotone images have palette data in colorData...

+    _readColorModeData();

+

+    // Image Resource Block:

+    // Image resources are used to store non-pixel data associated with images,

+    // such as pen tool paths.

+    _readImageResources();

+

+    _readLayerAndMaskData();

+

+    _readMergeImageData();

+

+    _input = null;

+    //_colorData = null;

+    _imageResourceData = null;

+    _layerAndMaskData = null;

+    _imageData = null;

+

+    return true;

+  }

+

+  Image decodeImage() {

+    if (!decode()) {

+      return null;

+    }

+

+    return renderImage();

+  }

+

+  Image renderImage() {

+    if (mergedImage != null) {

+      return mergedImage;

+    }

+

+    mergedImage = Image(width, height);

+    mergedImage.fill(0);

+

+    Uint8List pixels = mergedImage.getBytes();

+

+    for (int li = 0; li < layers.length; ++li) {

+      PsdLayer layer = layers[li];

+      if (!layer.isVisible()) {

+        continue;

+      }

+

+      double opacity = layer.opacity / 255.0;

+      int blendMode = layer.blendMode;

+

+      //int ns = depth == 16 ? 2 : 1;

+      Uint8List srcP = layer.layerImage.getBytes();

+

+      for (int y = 0, sy = layer.top, si = 0; y < layer.height; ++y, ++sy) {

+        int di = (layer.top + y) * width * 4 + layer.left * 4;

+        for (int x = 0, sx = layer.left; x < layer.width; ++x, ++sx) {

+          int br = srcP[si++];

+          int bg = srcP[si++];

+          int bb = srcP[si++];

+          int ba = srcP[si++];

+

+          if (sx >= 0 && sx < width && sy >= 0 && sy < height) {

+            int ar = pixels[di];

+            int ag = pixels[di + 1];

+            int ab = pixels[di + 2];

+            int aa = pixels[di + 3];

+

+            _blend(ar, ag, ab, aa, br, bg, bb, ba, blendMode, opacity,

+                   pixels, di);

+          }

+

+          di += 4;

+        }

+      }

+    }

+

+    return mergedImage;

+  }

+

+  void _blend(int ar, int ag, int ab, int aa,

+              int br, int bg, int bb, int ba,

+              int blendMode, double opacity,

+              Uint8List pixels, int di) {

+    int r = br;

+    int g = bg;

+    int b = bb;

+    int a = ba;

+    double da = (ba / 255.0) * opacity;

+

+    switch (blendMode) {

+      case PsdLayer.BLEND_PASSTHROUGH:

+        r = ar;

+        g = ag;

+        b = ab;

+        a = aa;

+        break;

+      case PsdLayer.BLEND_NORMAL:

+        break;

+      case PsdLayer.BLEND_DISSOLVE:

+        break;

+      case PsdLayer.BLEND_DARKEN:

+        r = _blendDarken(ar, br);

+        g = _blendDarken(ag, bg);

+        b = _blendDarken(ab, bb);

+        break;

+      case PsdLayer.BLEND_MULTIPLY:

+        r = _blendMultiply(ar, br);

+        g = _blendMultiply(ag, bg);

+        b = _blendMultiply(ab, bb);

+        break;

+      case PsdLayer.BLEND_COLOR_BURN:

+        r = _blendColorBurn(ar, br);

+        g = _blendColorBurn(ag, bg);

+        b = _blendColorBurn(ab, bb);

+        break;

+      case PsdLayer.BLEND_LINEAR_BURN:

+        r = _blendLinearBurn(ar, br);

+        g = _blendLinearBurn(ag, bg);

+        b = _blendLinearBurn(ab, bb);

+        break;

+      case PsdLayer.BLEND_DARKEN_COLOR:

+        break;

+      case PsdLayer.BLEND_LIGHTEN:

+        r = _blendLighten(ar, br);

+        g = _blendLighten(ag, bg);

+        b = _blendLighten(ab, bb);

+        break;

+      case PsdLayer.BLEND_SCREEN:

+        r = _blendScreen(ar, br);

+        g = _blendScreen(ag, bg);

+        b = _blendScreen(ab, bb);

+        break;

+      case PsdLayer.BLEND_COLOR_DODGE:

+        r = _blendColorDodge(ar, br);

+        g = _blendColorDodge(ag, bg);

+        b = _blendColorDodge(ab, bb);

+        break;

+      case PsdLayer.BLEND_LINEAR_DODGE:

+        r = _blendLinearDodge(ar, br);

+        g = _blendLinearDodge(ag, bg);

+        b = _blendLinearDodge(ab, bb);

+        break;

+      case PsdLayer.BLEND_LIGHTER_COLOR:

+        break;

+      case PsdLayer.BLEND_OVERLAY:

+        r = _blendOverlay(ar, br, aa, ba);

+        g = _blendOverlay(ag, bg, aa, ba);

+        b = _blendOverlay(ab, bb, aa, ba);

+        break;

+      case PsdLayer.BLEND_SOFT_LIGHT:

+        r = _blendSoftLight(ar, br);

+        g = _blendSoftLight(ag, bg);

+        b = _blendSoftLight(ab, bb);

+        break;

+      case PsdLayer.BLEND_HARD_LIGHT:

+        r = _blendHardLight(ar, br);

+        g = _blendHardLight(ag, bg);

+        b = _blendHardLight(ab, bb);

+        break;

+      case PsdLayer.BLEND_VIVID_LIGHT:

+        r = _blendVividLight(ar, br);

+        g = _blendVividLight(ag, bg);

+        b = _blendVividLight(ab, bb);

+        break;

+      case PsdLayer.BLEND_LINEAR_LIGHT:

+        r = _blendLinearLight(ar, br);

+        g = _blendLinearLight(ag, bg);

+        b = _blendLinearLight(ab, bb);

+        break;

+      case PsdLayer.BLEND_PIN_LIGHT:

+        r = _blendPinLight(ar, br);

+        g = _blendPinLight(ag, bg);

+        b = _blendPinLight(ab, bb);

+        break;

+      case PsdLayer.BLEND_HARD_MIX:

+        r = _blendHardMix(ar, br);

+        g = _blendHardMix(ag, bg);

+        b = _blendHardMix(ab, bb);

+        break;

+      case PsdLayer.BLEND_DIFFERENCE:

+        r = _blendDifference(ar, br);

+        g = _blendDifference(ag, bg);

+        b = _blendDifference(ab, bb);

+        break;

+      case PsdLayer.BLEND_EXCLUSION:

+        r = _blendExclusion(ar, br);

+        g = _blendExclusion(ag, bg);

+        b = _blendExclusion(ab, bb);

+        break;

+      case PsdLayer.BLEND_SUBTRACT:

+        break;

+      case PsdLayer.BLEND_DIVIDE:

+        break;

+      case PsdLayer.BLEND_HUE:

+        break;

+      case PsdLayer.BLEND_SATURATION:

+        break;

+      case PsdLayer.BLEND_COLOR:

+        break;

+      case PsdLayer.BLEND_LUMINOSITY:

+        break;

+    }

+

+    r = ((ar * (1.0 - da)) + (r * da)).toInt();

+    g = ((ag * (1.0 - da)) + (g * da)).toInt();

+    b = ((ab * (1.0 - da)) + (b * da)).toInt();

+    a = ((aa * (1.0 - da)) + (a * da)).toInt();

+

+    pixels[di++] = r;

+    pixels[di++] = g;

+    pixels[di++] = b;

+    pixels[di++] = a;

+  }

+

+  static int _blendLighten(int a, int b) {

+    return Math.max(a, b);

+  }

+

+  static int _blendDarken(int a, int b) {

+    return Math.min(a,  b);

+  }

+

+  static int _blendMultiply(int a, int b) {

+    return (a * b) >> 8;

+  }

+

+  static int _blendOverlay(int a, int b, int aAlpha, int bAlpha) {

+    double x = a / 255.0;

+    double y = b / 255.0;

+    double aa = aAlpha / 255.0;

+    double ba = bAlpha / 255.0;

+

+    double z;

+    if (2.0 * x < aa) {

+      z = 2.0 * y * x + y * (1.0 - aa) + x * (1.0 - ba);

+    } else {

+      z = ba * aa - 2.0 * (aa - x) * (ba - y) +

+          y * (1.0 - aa) + x * (1.0 - ba);

+    }

+

+    return (z * 255.0).toInt().clamp(0, 255);

+  }

+

+  static int _blendColorBurn(int a, int b) {

+    if (b == 0) {

+      return 0; // We don't want to divide by zero

+    }

+    int c = (255.0 * (1.0 - (1.0 - (a / 255.0)) / (b / 255.0))).toInt();

+    return c.clamp(0, 255);

+  }

+

+  static int _blendLinearBurn(int a, int b) {

+    return (a + b - 255).clamp(0, 255);

+  }

+

+  static int _blendScreen(int a, int b) {

+    return (255 - ((255 - b) * (255 - a))).clamp(0, 255);

+  }

+

+  static int _blendColorDodge(int a, int b) {

+    if (b == 255) {

+      return 255;

+    }

+    return (((a / 255) / (1.0 - (b / 255.0))) * 255.0).toInt().clamp(0, 255);

+  }

+

+  static int _blendLinearDodge(int a, int b) {

+    return (b + a > 255) ? 0xff : a + b;

+  }

+

+  static int _blendSoftLight(int a, int b) {

+    double aa = a / 255.0;

+    double bb = b / 255.0;

+    return (255.0 * ((1.0 - bb) * bb * aa +

+                     bb * (1.0 - (1.0 - bb) * (1.0 - aa)))).round();

+  }

+

+  static int _blendHardLight(int bottom, int top) {

+    double a = top / 255.0;

+    double b = bottom / 255.0;

+    if (b < 0.5) {

+      return (255.0 * 2.0 * a * b).round();

+    } else {

+      return (255.0 * (1.0 - 2.0 * (1.0 - a) * (1.0 - b))).round();

+    }

+  }

+

+  static int _blendVividLight(int bottom, int top) {

+    if ( top < 128) {

+      return _blendColorBurn(bottom, 2 * top);

+    } else {

+      return _blendColorDodge(bottom, 2 * (top - 128));

+    }

+  }

+

+  static int _blendLinearLight(int bottom, int top) {

+    if (top < 128) {

+      return _blendLinearBurn(bottom, 2 * top);

+    } else {

+      return _blendLinearDodge(bottom, 2 * (top - 128));

+    }

+  }

+

+  static int _blendPinLight(int bottom, int top) {

+    return (top < 128) ?

+           _blendDarken(bottom, 2 * top) :

+           _blendLighten(bottom, 2 * (top - 128));

+  }

+

+  static int _blendHardMix(int bottom, int top) {

+    return (top < 255 - bottom) ? 0 : 255;

+  }

+

+  static int _blendDifference(int bottom, int top) {

+    return (top - bottom).abs();

+  }

+

+  static int _blendExclusion(int bottom, int top) {

+    return (top + bottom - 2 * top * bottom / 255.0).round();

+  }

+

+  void _readHeader() {

+    signature = _input.readUint32();

+    version = _input.readUint16();

+

+    // version should be 1 (2 for PSB files).

+    if (version != 1) {

+      signature = 0;

+      return;

+    }

+

+    // padding should be all 0's

+    InputBuffer padding = _input.readBytes(6);

+    for (int i = 0; i < 6; ++i) {

+      if (padding[i] != 0) {

+        signature = 0;

+        return;

+      }

+    }

+

+    channels = _input.readUint16();

+    height = _input.readUint32();

+    width = _input.readUint32();

+    depth = _input.readUint16();

+    colorMode = _input.readUint16();

+  }

+

+  void _readColorModeData() {

+    // TODO support indexed and duotone images.

+  }

+

+  void _readImageResources() {

+    _imageResourceData.rewind();

+    while (!_imageResourceData.isEOS) {

+      int blockSignature = _imageResourceData.readUint32();

+      int blockId = _imageResourceData.readUint16();

+

+      int len = _imageResourceData.readByte();

+      String blockName = _imageResourceData.readString(len);

+      // name string is padded to an even size

+      if (len & 1 == 0) {

+        _imageResourceData.skip(1);

+      }

+

+      len = _imageResourceData.readUint32();

+      InputBuffer blockData = _imageResourceData.readBytes(len);

+      // blocks are padded to an even length.

+      if (len & 1 == 1) {

+        _imageResourceData.skip(1);

+      }

+

+      if (blockSignature == RESOURCE_BLOCK_SIGNATURE) {

+        imageResources[blockId] = PsdImageResource(blockId, blockName,

+                                                       blockData);

+      }

+    }

+  }

+

+  void _readLayerAndMaskData() {

+    _layerAndMaskData.rewind();

+    int len = _layerAndMaskData.readUint32();

+    if ((len & 1) != 0) {

+      len++;

+    }

+

+    InputBuffer layerData = _layerAndMaskData.readBytes(len);

+

+    layers = [];

+    if (len > 0) {

+      int count = layerData.readInt16();

+      // If it is a negative number, its absolute value is the number of

+      // layers and the first alpha channel contains the transparency data for

+      // the merged result.

+      if (count < 0) {

+        hasAlpha = true;

+        count = -count;

+      }

+

+      for (int i = 0; i < count; ++i) {

+        PsdLayer layer = PsdLayer(layerData);

+        layers.add(layer);

+      }

+    }

+

+    for (int i = 0; i < layers.length; ++i) {

+      layers[i].readImageData(layerData, this);

+    }

+

+    // Global layer mask info

+    len = _layerAndMaskData.readUint32();

+    InputBuffer maskData = _layerAndMaskData.readBytes(len);

+    if (len > 0) {

+      /*int colorSpace =*/ maskData.readUint16();

+      /*int rc =*/ maskData.readUint16();

+      /*int gc =*/ maskData.readUint16();

+      /*int bc =*/ maskData.readUint16();

+      /*int ac =*/ maskData.readUint16();

+      /*int opacity =*/ maskData.readUint16(); // 0-100

+      /*int kind =*/ maskData.readByte();

+    }

+  }

+

+  void _readMergeImageData() {

+    _imageData.rewind();

+    int compression = _imageData.readUint16();

+

+    Uint16List lineLengths;

+    if (compression == PsdChannel.COMPRESS_RLE) {

+      int numLines = height * this.channels;

+      lineLengths = Uint16List(numLines);

+      for (int i = 0; i < numLines; ++i) {

+        lineLengths[i] = _imageData.readUint16();

+      }

+    }

+

+    mergeImageChannels = [];

+    for (int i = 0; i < channels; ++i) {

+      mergeImageChannels.add(new PsdChannel.read(_imageData, i == 3 ? -1 : i,

+                                         width, height, depth, compression,

+                                         lineLengths, i));

+    }

+

+    mergedImage = createImageFromChannels(colorMode, depth,

+                                         width, height,

+                                         mergeImageChannels);

+  }

+

+  static int _ch(List<int> data, int si, int ns) {

+    return ns == 1 ? data[si] :

+           ((data[si] << 8) | data[si + 1]) >> 8;

+  }

+

+  static Image createImageFromChannels(int colorMode, int bitDepth, int width,

+                                       int height,

+                                       List<PsdChannel> channelList) {

+    Image output = Image(width, height);

+    Uint8List pixels = output.getBytes();

+

+    Map<int, PsdChannel> channels = {};

+    for (PsdChannel ch in channelList) {

+      channels[ch.id] = ch;

+    }

+

+    int numChannels = channelList.length;

+    int ns = (bitDepth == 8) ? 1 : (bitDepth == 16) ? 2 : -1;

+    if (ns == -1) {

+      throw new ImageException('PSD: unsupported bit depth: $bitDepth');

+    }

+

+    final channel0 = channels[0];

+    final channel1 = channels[1];

+    final channel2 = channels[2];

+    final channel_1 = channels[-1];

+

+    for (int y = 0, di = 0, si = 0; y < height; ++y) {

+      for (int x = 0; x < width; ++x, si += ns) {

+        switch (colorMode) {

+          case COLORMODE_RGB:

+            int xi = di;

+            pixels[di++] = _ch(channel2.data, si, ns);

+            pixels[di++] = _ch(channel1.data, si, ns);

+            pixels[di++] = _ch(channel0.data, si, ns);

+            pixels[di++] = numChannels >= 4 ?

+                           _ch(channel_1.data, si, ns) : 255;

+

+            var b = pixels[xi];

+            var g = pixels[xi + 1];

+            var r = pixels[xi + 2];

+            var a = pixels[xi + 3];

+            if (a != 0) {

+              // Photoshop/Gimp blend the image against white (argh!),

+              // which is not what we want for compositing. Invert the blend

+              // operation to try and undo the damage.

+              pixels[xi] = (((b + a) - 255) * 255) ~/ a;

+              pixels[xi + 1] = (((g + a) - 255) * 255) ~/ a;

+              pixels[xi + 2] = (((r + a) - 255) * 255) ~/ a;

+            }

+            break;

+          case COLORMODE_LAB:

+            int L = _ch(channel0.data, si, ns) * 100 >> 8;

+            int a = _ch(channel1.data, si, ns) - 128;

+            int b = _ch(channel2.data, si, ns) - 128;

+            int alpha = numChannels >= 4 ?

+                        _ch(channel_1.data, si, ns) : 255;

+            List<int> rgb = labToRGB(L, a, b);

+            pixels[di++] = rgb[2];

+            pixels[di++] = rgb[1];

+            pixels[di++] = rgb[0];

+            pixels[di++] = alpha;

+            break;

+          case COLORMODE_GRAYSCALE:

+            int gray = _ch(channel0.data, si, ns);

+            int alpha = numChannels >= 2 ?

+                       _ch(channel_1.data, si, ns) : 255;

+            pixels[di++] = gray;

+            pixels[di++] = gray;

+            pixels[di++] = gray;

+            pixels[di++] = alpha;

+            break;

+          case COLORMODE_CMYK:

+            int c = _ch(channel0.data, si, ns);

+            int m = _ch(channel1.data, si, ns);

+            int y = _ch(channel2.data, si, ns);

+            int k = _ch(channels[numChannels == 4 ? -1 : 3].data, si, ns);

+            int alpha = numChannels >= 5 ?

+                        _ch(channel_1.data, si, ns) : 255;

+            List<int> rgb = cmykToRGB(255 - c, 255 - m, 255 - y, 255 - k);

+            pixels[di++] = rgb[2];

+            pixels[di++] = rgb[1];

+            pixels[di++] = rgb[0];

+            pixels[di++] = alpha;

+            break;

+          default:

+            throw new ImageException('Unhandled color mode: $colorMode');

+        }

+      }

+    }

+

+    return output;

+  }

+

+  static const int RESOURCE_BLOCK_SIGNATURE = 0x3842494d; // '8BIM'

+

+  InputBuffer _input;

+  //InputBuffer _colorData;

+  InputBuffer _imageResourceData;

+  InputBuffer _layerAndMaskData;

+  InputBuffer _imageData;

+}

diff --git a/image/lib/src/formats/psd/psd_image_resource.dart b/image/lib/src/formats/psd/psd_image_resource.dart
old mode 100644
new mode 100755
index 3ab3fa8..e6e6e69
--- a/image/lib/src/formats/psd/psd_image_resource.dart
+++ b/image/lib/src/formats/psd/psd_image_resource.dart
@@ -1,9 +1,9 @@
-import '../../util/input_buffer.dart';
-
-class PsdImageResource {
-  int id;
-  String name;
-  InputBuffer data;
-
-  PsdImageResource(this.id, this.name, this.data);
-}
+import '../../util/input_buffer.dart';

+

+class PsdImageResource {

+  int id;

+  String name;

+  InputBuffer data;

+

+  PsdImageResource(this.id, this.name, this.data);

+}

diff --git a/image/lib/src/formats/psd/psd_layer.dart b/image/lib/src/formats/psd/psd_layer.dart
old mode 100644
new mode 100755
index a46d69b..9e25c12
--- a/image/lib/src/formats/psd/psd_layer.dart
+++ b/image/lib/src/formats/psd/psd_layer.dart
@@ -1,333 +1,333 @@
-import '../../image.dart';
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-import 'psd_blending_ranges.dart';
-import 'psd_channel.dart';
-import 'psd_image.dart';
-import 'psd_layer_data.dart';
-import 'psd_mask.dart';
-import 'effect/psd_bevel_effect.dart';
-import 'effect/psd_drop_shadow_effect.dart';
-import 'effect/psd_effect.dart';
-import 'effect/psd_inner_glow_effect.dart';
-import 'effect/psd_inner_shadow_effect.dart';
-import 'effect/psd_outer_glow_effect.dart';
-import 'effect/psd_solid_fill_effect.dart';
-import 'layer_data/psd_layer_additional_data.dart';
-import 'layer_data/psd_layer_section_divider.dart';
-
-class PsdLayer {
-  int top;
-  int left;
-  int bottom;
-  int right;
-  int width;
-  int height;
-  int blendMode;
-  int opacity;
-  int clipping;
-  int flags;
-  int compression;
-  String name;
-  List<PsdChannel> channels;
-  PsdMask mask;
-  PsdBlendingRanges blendingRanges;
-  Map<String, PsdLayerData> additionalData = {};
-  List<PsdLayer> children = [];
-  PsdLayer parent;
-  Image layerImage;
-  List<PsdEffect> effects = [];
-
-  static const int SIGNATURE = 0x3842494d; // '8BIM'
-
-  static const int BLEND_PASSTHROUGH = 0x70617373; // 'pass'
-  static const int BLEND_NORMAL = 0x6e6f726d; // 'norm'
-  static const int BLEND_DISSOLVE = 0x64697373; // 'diss'
-  static const int BLEND_DARKEN = 0x6461726b; // 'dark'
-  static const int BLEND_MULTIPLY = 0x6d756c20; // 'mul '
-  static const int BLEND_COLOR_BURN = 0x69646976; // 'idiv'
-  static const int BLEND_LINEAR_BURN = 0x6c62726e; // 'lbrn'
-  static const int BLEND_DARKEN_COLOR = 0x646b436c; // 'dkCl'
-  static const int BLEND_LIGHTEN = 0x6c697465; // 'lite'
-  static const int BLEND_SCREEN = 0x7363726e; // 'scrn'
-  static const int BLEND_COLOR_DODGE = 0x64697620; // 'div '
-  static const int BLEND_LINEAR_DODGE = 0x6c646467; // 'lddg'
-  static const int BLEND_LIGHTER_COLOR = 0x6c67436c; // 'lgCl'
-  static const int BLEND_OVERLAY = 0x6f766572; // 'over'
-  static const int BLEND_SOFT_LIGHT = 0x734c6974; // 'sLit'
-  static const int BLEND_HARD_LIGHT = 0x684c6974; // 'hLit'
-  static const int BLEND_VIVID_LIGHT = 0x764c6974; // 'vLit'
-  static const int BLEND_LINEAR_LIGHT = 0x6c4c6974; // lLit'
-  static const int BLEND_PIN_LIGHT = 0x704c6974; // 'pLit'
-  static const int BLEND_HARD_MIX = 0x684d6978; // 'hMix'
-  static const int BLEND_DIFFERENCE = 0x64696666; // 'diff'
-  static const int BLEND_EXCLUSION = 0x736d7564; // 'smud'
-  static const int BLEND_SUBTRACT = 0x66737562; // 'fsub'
-  static const int BLEND_DIVIDE = 0x66646976; // 'fdiv'
-  static const int BLEND_HUE = 0x68756520; // 'hue '
-  static const int BLEND_SATURATION = 0x73617420; // 'sat '
-  static const int BLEND_COLOR = 0x636f6c72; // 'colr'
-  static const int BLEND_LUMINOSITY = 0x6c756d20; // 'lum '
-
-  static const int FLAG_TRANSPARENCY_PROTECTED = 1;
-  static const int FLAG_HIDDEN = 2;
-  static const int FLAG_OBSOLETE = 4;
-  static const int FLAG_PHOTOSHOP_5 = 8;
-  static const int FLAG_PIXEL_DATA_IRRELEVANT_TO_APPEARANCE = 16;
-
-
-  PsdLayer([InputBuffer input]) {
-    if (input == null) {
-      return;
-    }
-
-    top = input.readInt32();
-    left = input.readInt32();
-    bottom = input.readInt32();
-    right = input.readInt32();
-    width = right - left;
-    height = bottom - top;
-
-    channels = [];
-    int numChannels = input.readUint16();
-    for (int i = 0; i < numChannels; ++i) {
-      int id = input.readInt16();
-      int len = input.readUint32();
-      channels.add(new PsdChannel(id, len));
-    }
-
-    int sig = input.readUint32();
-    if (sig != SIGNATURE) {
-      throw new ImageException('Invalid PSD layer signature: '
-                               '${sig.toRadixString(16)}');
-    }
-
-    blendMode = input.readUint32();
-    opacity = input.readByte();
-    clipping = input.readByte();
-    flags = input.readByte();
-
-    int filler = input.readByte(); // should be 0
-    if (filler != 0) {
-      throw new ImageException('Invalid PSD layer data');
-    }
-
-    int len = input.readUint32();
-    InputBuffer extra = input.readBytes(len);
-
-    if (len > 0) {
-      // Mask Data
-      len = extra.readUint32();
-      assert(len == 0 || len == 20 || len == 36);
-      if (len > 0) {
-        InputBuffer maskData = extra.readBytes(len);
-        mask = new PsdMask(maskData);
-      }
-
-      // Layer Blending Ranges
-      len = extra.readUint32();
-      if (len > 0) {
-        InputBuffer data = extra.readBytes(len);
-        blendingRanges = new PsdBlendingRanges(data);
-      }
-
-      // Layer name
-      len = extra.readByte();
-      name = extra.readString(len);
-      // Layer name is padded to a multiple of 4 bytes.
-      int padding = (4 - (len % 4)) - 1;
-      if (padding > 0) {
-        extra.skip(padding);
-      }
-
-      // Additional layer sections
-      while (!extra.isEOS) {
-        int sig = extra.readUint32();
-        if (sig != SIGNATURE) {
-          throw new ImageException('PSD invalid signature for layer additional '
-                                   'data: ${sig.toRadixString(16)}');
-        }
-
-        String tag = extra.readString(4);
-
-        len = extra.readUint32();
-        InputBuffer data = extra.readBytes(len);
-        // pad to an even byte count.
-        if (len & 1 == 1) {
-          extra.skip(1);
-        }
-
-        additionalData[tag] = new PsdLayerData(tag, data);
-
-        // Layer effects data
-        if (tag == 'lrFX') {
-          var fxData = (additionalData['lrFX'] as PsdLayerAdditionalData);
-          var data = new InputBuffer.from(fxData.data);
-          /*int version =*/ data.readUint16();
-          int numFx = data.readUint16();
-
-          for (int j = 0; j < numFx; ++j) {
-            /*var tag =*/ data.readString(4); // 8BIM
-            var fxTag = data.readString(4);
-            int size = data.readUint32();
-
-            if (fxTag == 'dsdw') {
-              var fx = new PsdDropShadowEffect();
-              effects.add(fx);
-              fx.version = data.readUint32();
-              fx.blur = data.readUint32();
-              fx.intensity = data.readUint32();
-              fx.angle = data.readUint32();
-              fx.distance = data.readUint32();
-              fx.color = [data.readUint16(), data.readUint16(),
-                          data.readUint16(), data.readUint16(),
-                          data.readUint16()];
-              fx.blendMode = data.readString(8);
-              fx.enabled = data.readByte() != 0;
-              fx.globalAngle = data.readByte() != 0;
-              fx.opacity = data.readByte();
-              fx.nativeColor = [data.readUint16(), data.readUint16(),
-                                data.readUint16(), data.readUint16(),
-                                data.readUint16()];
-            } else if (fxTag == 'isdw') {
-              var fx = new PsdInnerShadowEffect();
-              effects.add(fx);
-              fx.version = data.readUint32();
-              fx.blur = data.readUint32();
-              fx.intensity = data.readUint32();
-              fx.angle = data.readUint32();
-              fx.distance = data.readUint32();
-              fx.color = [data.readUint16(), data.readUint16(),
-                          data.readUint16(), data.readUint16(),
-                          data.readUint16()];
-              fx.blendMode = data.readString(8);
-              fx.enabled = data.readByte() != 0;
-              fx.globalAngle = data.readByte() != 0;
-              fx.opacity = data.readByte();
-              fx.nativeColor = [data.readUint16(), data.readUint16(),
-                                data.readUint16(), data.readUint16(),
-                                data.readUint16()];
-            } else if (fxTag == 'oglw') {
-              var fx = new PsdOuterGlowEffect();
-              effects.add(fx);
-              fx.version = data.readUint32();
-              fx.blur = data.readUint32();
-              fx.intensity = data.readUint32();
-              fx.color = [data.readUint16(), data.readUint16(),
-                          data.readUint16(), data.readUint16(),
-                          data.readUint16()];
-              fx.blendMode = data.readString(8);
-              fx.enabled = data.readByte() != 0;
-              fx.opacity = data.readByte();
-              if (fx.version == 2) {
-                fx.nativeColor = [data.readUint16(), data.readUint16(),
-                                  data.readUint16(), data.readUint16(),
-                                  data.readUint16()];
-              }
-            } else if (fxTag == 'iglw') {
-              var fx = new PsdInnerGlowEffect();
-              effects.add(fx);
-              fx.version = data.readUint32();
-              fx.blur = data.readUint32();
-              fx.intensity = data.readUint32();
-              fx.color = [data.readUint16(), data.readUint16(),
-                          data.readUint16(), data.readUint16(),
-                          data.readUint16()];
-              fx.blendMode = data.readString(8);
-              fx.enabled = data.readByte() != 0;
-              fx.opacity = data.readByte();
-              if (fx.version == 2) {
-                fx.invert = data.readByte() != 0;
-                fx.nativeColor = [data.readUint16(), data.readUint16(),
-                                  data.readUint16(), data.readUint16(),
-                                  data.readUint16()];
-              }
-            } else if (fxTag == 'bevl') {
-              var fx = new PsdBevelEffect();
-              effects.add(fx);
-              fx.version = data.readUint32();
-              fx.angle = data.readUint32();
-              fx.strength = data.readUint32();
-              fx.blur = data.readUint32();
-              fx.highlightBlendMode = data.readString(8);
-              fx.shadowBlendMode = data.readString(8);
-              fx.highlightColor = [data.readUint16(), data.readUint16(),
-                                   data.readUint16(), data.readUint16(),
-                                   data.readUint16()];
-              fx.shadowColor = [data.readUint16(), data.readUint16(),
-                                data.readUint16(), data.readUint16(),
-                                data.readUint16()];
-              fx.bevelStyle = data.readByte();
-              fx.highlightOpacity = data.readByte();
-              fx.shadowOpacity = data.readByte();
-              fx.enabled = data.readByte() != 0;
-              fx.globalAngle = data.readByte() != 0;
-              fx.upOrDown = data.readByte();
-              if (fx.version == 2) {
-                fx.realHighlightColor = [data.readUint16(), data.readUint16(),
-                                         data.readUint16(), data.readUint16(),
-                                         data.readUint16()];
-                fx.realShadowColor = [data.readUint16(), data.readUint16(),
-                                      data.readUint16(), data.readUint16(),
-                                      data.readUint16()];
-              }
-            } else if (fxTag == 'sofi') {
-              var fx = new PsdSolidFillEffect();
-              effects.add(fx);
-              fx.version = data.readUint32();
-              fx.blendMode = data.readString(4);
-              fx.color = [data.readUint16(), data.readUint16(),
-                          data.readUint16(), data.readUint16(),
-                          data.readUint16()];
-              fx.opacity = data.readByte();
-              fx.enabled = data.readByte() != 0;
-              fx.nativeColor = [data.readUint16(), data.readUint16(),
-                                data.readUint16(), data.readUint16(),
-                                data.readUint16()];
-            } else {
-              data.skip(size);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  /**
-   * Is this layer visible?
-   */
-  bool isVisible() => flags & FLAG_HIDDEN == 0;
-
-  /**
-   * Is this layer a folder?
-   */
-  int type() {
-    if (additionalData.containsKey(PsdLayerSectionDivider.TAG)) {
-      PsdLayerSectionDivider section = additionalData[PsdLayerSectionDivider.TAG];
-      return section.type;
-    }
-    return PsdLayerSectionDivider.NORMAL;
-  }
-
-  /**
-   * Get the channel for the given [id].
-   * Returns null if the layer does not have the given channel.
-   */
-  PsdChannel getChannel(int id) {
-    for (int i = 0; i < channels.length; ++i) {
-      if (channels[i].id == id) {
-        return channels[i];
-      }
-    }
-    return null;
-  }
-
-  void readImageData(InputBuffer input, PsdImage psd) {
-    for (int i = 0; i < channels.length; ++i) {
-      channels[i].readPlane(input, width, height, psd.depth);
-    }
-
-    layerImage = PsdImage.createImageFromChannels(psd.colorMode, psd.depth,
-                                                  width, height, channels);
-  }
-}
+import '../../image.dart';

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+import 'psd_blending_ranges.dart';

+import 'psd_channel.dart';

+import 'psd_image.dart';

+import 'psd_layer_data.dart';

+import 'psd_mask.dart';

+import 'effect/psd_bevel_effect.dart';

+import 'effect/psd_drop_shadow_effect.dart';

+import 'effect/psd_effect.dart';

+import 'effect/psd_inner_glow_effect.dart';

+import 'effect/psd_inner_shadow_effect.dart';

+import 'effect/psd_outer_glow_effect.dart';

+import 'effect/psd_solid_fill_effect.dart';

+import 'layer_data/psd_layer_additional_data.dart';

+import 'layer_data/psd_layer_section_divider.dart';

+

+class PsdLayer {

+  int top;

+  int left;

+  int bottom;

+  int right;

+  int width;

+  int height;

+  int blendMode;

+  int opacity;

+  int clipping;

+  int flags;

+  int compression;

+  String name;

+  List<PsdChannel> channels;

+  PsdMask mask;

+  PsdBlendingRanges blendingRanges;

+  Map<String, PsdLayerData> additionalData = {};

+  List<PsdLayer> children = [];

+  PsdLayer parent;

+  Image layerImage;

+  List<PsdEffect> effects = [];

+

+  static const int SIGNATURE = 0x3842494d; // '8BIM'

+

+  static const int BLEND_PASSTHROUGH = 0x70617373; // 'pass'

+  static const int BLEND_NORMAL = 0x6e6f726d; // 'norm'

+  static const int BLEND_DISSOLVE = 0x64697373; // 'diss'

+  static const int BLEND_DARKEN = 0x6461726b; // 'dark'

+  static const int BLEND_MULTIPLY = 0x6d756c20; // 'mul '

+  static const int BLEND_COLOR_BURN = 0x69646976; // 'idiv'

+  static const int BLEND_LINEAR_BURN = 0x6c62726e; // 'lbrn'

+  static const int BLEND_DARKEN_COLOR = 0x646b436c; // 'dkCl'

+  static const int BLEND_LIGHTEN = 0x6c697465; // 'lite'

+  static const int BLEND_SCREEN = 0x7363726e; // 'scrn'

+  static const int BLEND_COLOR_DODGE = 0x64697620; // 'div '

+  static const int BLEND_LINEAR_DODGE = 0x6c646467; // 'lddg'

+  static const int BLEND_LIGHTER_COLOR = 0x6c67436c; // 'lgCl'

+  static const int BLEND_OVERLAY = 0x6f766572; // 'over'

+  static const int BLEND_SOFT_LIGHT = 0x734c6974; // 'sLit'

+  static const int BLEND_HARD_LIGHT = 0x684c6974; // 'hLit'

+  static const int BLEND_VIVID_LIGHT = 0x764c6974; // 'vLit'

+  static const int BLEND_LINEAR_LIGHT = 0x6c4c6974; // lLit'

+  static const int BLEND_PIN_LIGHT = 0x704c6974; // 'pLit'

+  static const int BLEND_HARD_MIX = 0x684d6978; // 'hMix'

+  static const int BLEND_DIFFERENCE = 0x64696666; // 'diff'

+  static const int BLEND_EXCLUSION = 0x736d7564; // 'smud'

+  static const int BLEND_SUBTRACT = 0x66737562; // 'fsub'

+  static const int BLEND_DIVIDE = 0x66646976; // 'fdiv'

+  static const int BLEND_HUE = 0x68756520; // 'hue '

+  static const int BLEND_SATURATION = 0x73617420; // 'sat '

+  static const int BLEND_COLOR = 0x636f6c72; // 'colr'

+  static const int BLEND_LUMINOSITY = 0x6c756d20; // 'lum '

+

+  static const int FLAG_TRANSPARENCY_PROTECTED = 1;

+  static const int FLAG_HIDDEN = 2;

+  static const int FLAG_OBSOLETE = 4;

+  static const int FLAG_PHOTOSHOP_5 = 8;

+  static const int FLAG_PIXEL_DATA_IRRELEVANT_TO_APPEARANCE = 16;

+

+

+  PsdLayer([InputBuffer input]) {

+    if (input == null) {

+      return;

+    }

+

+    top = input.readInt32();

+    left = input.readInt32();

+    bottom = input.readInt32();

+    right = input.readInt32();

+    width = right - left;

+    height = bottom - top;

+

+    channels = [];

+    int numChannels = input.readUint16();

+    for (int i = 0; i < numChannels; ++i) {

+      int id = input.readInt16();

+      int len = input.readUint32();

+      channels.add(new PsdChannel(id, len));

+    }

+

+    int sig = input.readUint32();

+    if (sig != SIGNATURE) {

+      throw new ImageException('Invalid PSD layer signature: '

+                               '${sig.toRadixString(16)}');

+    }

+

+    blendMode = input.readUint32();

+    opacity = input.readByte();

+    clipping = input.readByte();

+    flags = input.readByte();

+

+    int filler = input.readByte(); // should be 0

+    if (filler != 0) {

+      throw new ImageException('Invalid PSD layer data');

+    }

+

+    int len = input.readUint32();

+    InputBuffer extra = input.readBytes(len);

+

+    if (len > 0) {

+      // Mask Data

+      len = extra.readUint32();

+      assert(len == 0 || len == 20 || len == 36);

+      if (len > 0) {

+        InputBuffer maskData = extra.readBytes(len);

+        mask = PsdMask(maskData);

+      }

+

+      // Layer Blending Ranges

+      len = extra.readUint32();

+      if (len > 0) {

+        InputBuffer data = extra.readBytes(len);

+        blendingRanges = PsdBlendingRanges(data);

+      }

+

+      // Layer name

+      len = extra.readByte();

+      name = extra.readString(len);

+      // Layer name is padded to a multiple of 4 bytes.

+      int padding = (4 - (len % 4)) - 1;

+      if (padding > 0) {

+        extra.skip(padding);

+      }

+

+      // Additional layer sections

+      while (!extra.isEOS) {

+        int sig = extra.readUint32();

+        if (sig != SIGNATURE) {

+          throw new ImageException('PSD invalid signature for layer additional '

+                                   'data: ${sig.toRadixString(16)}');

+        }

+

+        String tag = extra.readString(4);

+

+        len = extra.readUint32();

+        InputBuffer data = extra.readBytes(len);

+        // pad to an even byte count.

+        if (len & 1 == 1) {

+          extra.skip(1);

+        }

+

+        additionalData[tag] = PsdLayerData(tag, data);

+

+        // Layer effects data

+        if (tag == 'lrFX') {

+          var fxData = (additionalData['lrFX'] as PsdLayerAdditionalData);

+          var data = InputBuffer.from(fxData.data);

+          /*int version =*/ data.readUint16();

+          int numFx = data.readUint16();

+

+          for (int j = 0; j < numFx; ++j) {

+            /*var tag =*/ data.readString(4); // 8BIM

+            var fxTag = data.readString(4);

+            int size = data.readUint32();

+

+            if (fxTag == 'dsdw') {

+              var fx = PsdDropShadowEffect();

+              effects.add(fx);

+              fx.version = data.readUint32();

+              fx.blur = data.readUint32();

+              fx.intensity = data.readUint32();

+              fx.angle = data.readUint32();

+              fx.distance = data.readUint32();

+              fx.color = [data.readUint16(), data.readUint16(),

+                          data.readUint16(), data.readUint16(),

+                          data.readUint16()];

+              fx.blendMode = data.readString(8);

+              fx.enabled = data.readByte() != 0;

+              fx.globalAngle = data.readByte() != 0;

+              fx.opacity = data.readByte();

+              fx.nativeColor = [data.readUint16(), data.readUint16(),

+                                data.readUint16(), data.readUint16(),

+                                data.readUint16()];

+            } else if (fxTag == 'isdw') {

+              var fx = PsdInnerShadowEffect();

+              effects.add(fx);

+              fx.version = data.readUint32();

+              fx.blur = data.readUint32();

+              fx.intensity = data.readUint32();

+              fx.angle = data.readUint32();

+              fx.distance = data.readUint32();

+              fx.color = [data.readUint16(), data.readUint16(),

+                          data.readUint16(), data.readUint16(),

+                          data.readUint16()];

+              fx.blendMode = data.readString(8);

+              fx.enabled = data.readByte() != 0;

+              fx.globalAngle = data.readByte() != 0;

+              fx.opacity = data.readByte();

+              fx.nativeColor = [data.readUint16(), data.readUint16(),

+                                data.readUint16(), data.readUint16(),

+                                data.readUint16()];

+            } else if (fxTag == 'oglw') {

+              var fx = PsdOuterGlowEffect();

+              effects.add(fx);

+              fx.version = data.readUint32();

+              fx.blur = data.readUint32();

+              fx.intensity = data.readUint32();

+              fx.color = [data.readUint16(), data.readUint16(),

+                          data.readUint16(), data.readUint16(),

+                          data.readUint16()];

+              fx.blendMode = data.readString(8);

+              fx.enabled = data.readByte() != 0;

+              fx.opacity = data.readByte();

+              if (fx.version == 2) {

+                fx.nativeColor = [data.readUint16(), data.readUint16(),

+                                  data.readUint16(), data.readUint16(),

+                                  data.readUint16()];

+              }

+            } else if (fxTag == 'iglw') {

+              var fx = PsdInnerGlowEffect();

+              effects.add(fx);

+              fx.version = data.readUint32();

+              fx.blur = data.readUint32();

+              fx.intensity = data.readUint32();

+              fx.color = [data.readUint16(), data.readUint16(),

+                          data.readUint16(), data.readUint16(),

+                          data.readUint16()];

+              fx.blendMode = data.readString(8);

+              fx.enabled = data.readByte() != 0;

+              fx.opacity = data.readByte();

+              if (fx.version == 2) {

+                fx.invert = data.readByte() != 0;

+                fx.nativeColor = [data.readUint16(), data.readUint16(),

+                                  data.readUint16(), data.readUint16(),

+                                  data.readUint16()];

+              }

+            } else if (fxTag == 'bevl') {

+              var fx = PsdBevelEffect();

+              effects.add(fx);

+              fx.version = data.readUint32();

+              fx.angle = data.readUint32();

+              fx.strength = data.readUint32();

+              fx.blur = data.readUint32();

+              fx.highlightBlendMode = data.readString(8);

+              fx.shadowBlendMode = data.readString(8);

+              fx.highlightColor = [data.readUint16(), data.readUint16(),

+                                   data.readUint16(), data.readUint16(),

+                                   data.readUint16()];

+              fx.shadowColor = [data.readUint16(), data.readUint16(),

+                                data.readUint16(), data.readUint16(),

+                                data.readUint16()];

+              fx.bevelStyle = data.readByte();

+              fx.highlightOpacity = data.readByte();

+              fx.shadowOpacity = data.readByte();

+              fx.enabled = data.readByte() != 0;

+              fx.globalAngle = data.readByte() != 0;

+              fx.upOrDown = data.readByte();

+              if (fx.version == 2) {

+                fx.realHighlightColor = [data.readUint16(), data.readUint16(),

+                                         data.readUint16(), data.readUint16(),

+                                         data.readUint16()];

+                fx.realShadowColor = [data.readUint16(), data.readUint16(),

+                                      data.readUint16(), data.readUint16(),

+                                      data.readUint16()];

+              }

+            } else if (fxTag == 'sofi') {

+              var fx = PsdSolidFillEffect();

+              effects.add(fx);

+              fx.version = data.readUint32();

+              fx.blendMode = data.readString(4);

+              fx.color = [data.readUint16(), data.readUint16(),

+                          data.readUint16(), data.readUint16(),

+                          data.readUint16()];

+              fx.opacity = data.readByte();

+              fx.enabled = data.readByte() != 0;

+              fx.nativeColor = [data.readUint16(), data.readUint16(),

+                                data.readUint16(), data.readUint16(),

+                                data.readUint16()];

+            } else {

+              data.skip(size);

+            }

+          }

+        }

+      }

+    }

+  }

+

+  /**

+   * Is this layer visible?

+   */

+  bool isVisible() => flags & FLAG_HIDDEN == 0;

+

+  /**

+   * Is this layer a folder?

+   */

+  int type() {

+    if (additionalData.containsKey(PsdLayerSectionDivider.TAG)) {

+      PsdLayerSectionDivider section = additionalData[PsdLayerSectionDivider.TAG];

+      return section.type;

+    }

+    return PsdLayerSectionDivider.NORMAL;

+  }

+

+  /**

+   * Get the channel for the given [id].

+   * Returns null if the layer does not have the given channel.

+   */

+  PsdChannel getChannel(int id) {

+    for (int i = 0; i < channels.length; ++i) {

+      if (channels[i].id == id) {

+        return channels[i];

+      }

+    }

+    return null;

+  }

+

+  void readImageData(InputBuffer input, PsdImage psd) {

+    for (int i = 0; i < channels.length; ++i) {

+      channels[i].readPlane(input, width, height, psd.depth);

+    }

+

+    layerImage = PsdImage.createImageFromChannels(psd.colorMode, psd.depth,

+                                                  width, height, channels);

+  }

+}

diff --git a/image/lib/src/formats/psd/psd_layer_data.dart b/image/lib/src/formats/psd/psd_layer_data.dart
old mode 100644
new mode 100755
index 7a9830d..09e2a38
--- a/image/lib/src/formats/psd/psd_layer_data.dart
+++ b/image/lib/src/formats/psd/psd_layer_data.dart
@@ -1,18 +1,18 @@
-import '../../util/input_buffer.dart';
-import 'layer_data/psd_layer_additional_data.dart';
-import 'layer_data/psd_layer_section_divider.dart';
-
-class PsdLayerData {
-  String tag;
-
-  factory PsdLayerData(String tag, InputBuffer data) {
-    switch (tag) {
-      case PsdLayerSectionDivider.TAG:
-        return new PsdLayerSectionDivider(tag, data);
-      default:
-        return new PsdLayerAdditionalData(tag, data);
-    }
-  }
-
-  PsdLayerData.type(this.tag);
-}
+import '../../util/input_buffer.dart';

+import 'layer_data/psd_layer_additional_data.dart';

+import 'layer_data/psd_layer_section_divider.dart';

+

+class PsdLayerData {

+  String tag;

+

+  factory PsdLayerData(String tag, InputBuffer data) {

+    switch (tag) {

+      case PsdLayerSectionDivider.TAG:

+        return new PsdLayerSectionDivider(tag, data);

+      default:

+        return new PsdLayerAdditionalData(tag, data);

+    }

+  }

+

+  PsdLayerData.type(this.tag);

+}

diff --git a/image/lib/src/formats/psd/psd_mask.dart b/image/lib/src/formats/psd/psd_mask.dart
old mode 100644
new mode 100755
index d63e34b..90233d5
--- a/image/lib/src/formats/psd/psd_mask.dart
+++ b/image/lib/src/formats/psd/psd_mask.dart
@@ -1,40 +1,40 @@
-import '../../util/input_buffer.dart';
-
-class PsdMask {
-  int top;
-  int left;
-  int right;
-  int bottom;
-  int defaultColor;
-  int flags;
-  int params = 0;
-
-  PsdMask(InputBuffer input) {
-    int len = input.length;
-
-    top = input.readUint32();
-    left = input.readUint32();
-    right = input.readUint32();
-    bottom = input.readUint32();
-    defaultColor = input.readByte();
-    flags = input.readByte();
-
-    if (len == 20) {
-      input.skip(2);
-    } else {
-      flags = input.readByte();
-
-      defaultColor = input.readByte();
-      top = input.readUint32();
-      left = input.readUint32();
-      right = input.readUint32();
-      bottom = input.readUint32();
-    }
-  }
-
-  bool get relative => flags & 1 != 0;
-
-  bool get disabled => flags & 2 != 0;
-
-  bool get invert => flags & 4 != 0;
-}
+import '../../util/input_buffer.dart';

+

+class PsdMask {

+  int top;

+  int left;

+  int right;

+  int bottom;

+  int defaultColor;

+  int flags;

+  int params = 0;

+

+  PsdMask(InputBuffer input) {

+    int len = input.length;

+

+    top = input.readUint32();

+    left = input.readUint32();

+    right = input.readUint32();

+    bottom = input.readUint32();

+    defaultColor = input.readByte();

+    flags = input.readByte();

+

+    if (len == 20) {

+      input.skip(2);

+    } else {

+      flags = input.readByte();

+

+      defaultColor = input.readByte();

+      top = input.readUint32();

+      left = input.readUint32();

+      right = input.readUint32();

+      bottom = input.readUint32();

+    }

+  }

+

+  bool get relative => flags & 1 != 0;

+

+  bool get disabled => flags & 2 != 0;

+

+  bool get invert => flags & 4 != 0;

+}

diff --git a/image/lib/src/formats/psd_decoder.dart b/image/lib/src/formats/psd_decoder.dart
old mode 100644
new mode 100755
index 44d328c..1d9ef46
--- a/image/lib/src/formats/psd_decoder.dart
+++ b/image/lib/src/formats/psd_decoder.dart
@@ -1,95 +1,95 @@
-import '../animation.dart';
-import '../image.dart';
-import 'decoder.dart';
-import 'decode_info.dart';
-import 'psd/psd_image.dart';
-
-/**
- * Decode a Photoshop PSD image.
- */
-class PsdDecoder extends Decoder {
-  PsdImage info;
-
-  /**
-   * A light-weight function to test if the given file is able to be decoded
-   * by this Decoder.
-   */
-  bool isValidFile(List<int> bytes) {
-    return new PsdImage(bytes).isValid;
-  }
-
-  /**
-   * Decode a raw PSD image without rendering it to a flat image.
-   */
-  PsdImage decodePsd(List<int> bytes) {
-    PsdImage psd = new PsdImage(bytes);
-    if (!psd.decode()) {
-      return null;
-    }
-    return psd;
-  }
-
-  /**
-   * Decode the file and extract a single image from it.  If the file is
-   * animated, the specified [frame] will be decoded.  If there was a problem
-   * decoding the file, null is returned.
-   */
-  Image decodeImage(List<int> bytes, {int frame: 0}) {
-    startDecode(bytes);
-    return decodeFrame(frame);
-  }
-
-  /**
-   * Decode all of the frames from an animation.  If the file is not an
-   * animation, a single frame animation is returned.  If there was a problem
-   * decoding the file, null is returned.
-   */
-  Animation decodeAnimation(List<int> bytes) {
-    if (startDecode(bytes) == null) {
-      return null;
-    }
-
-    Animation anim = new Animation();
-    anim.width = info.width;
-    anim.height = info.height;
-    anim.frameType = Animation.PAGE;
-    for (int i = 0, len = numFrames(); i < len; ++i) {
-      Image image = decodeFrame(i);
-      if (i == null) {
-        continue;
-      }
-      anim.addFrame(image);
-    }
-
-    return anim;
-  }
-
-  /**
-   * Start decoding the data as an animation sequence, but don't actually
-   * process the frames until they are requested with decodeFrame.
-   */
-  DecodeInfo startDecode(List<int> bytes) {
-    info = new PsdImage(bytes);
-    return info;
-  }
-
-  /**
-   * How many frames are available to be decoded.  [startDecode] should have
-   * been called first. Non animated image files will have a single frame.
-   */
-  int numFrames() => info != null ? info.numFrames : 0;
-
-  /**
-   * Decode a single frame from the data stat was set with [startDecode].
-   * If [frame] is out of the range of available frames, null is returned.
-   * Non animated image files will only have [frame] 0.  An [AnimationFrame]
-   * is returned, which provides the image, and top-left coordinates of the
-   * image, as animated frames may only occupy a subset of the canvas.
-   */
-  Image decodeFrame(int frame) {
-    if (info == null) {
-      return null;
-    }
-    return info.decodeImage();
-  }
-}
+import '../animation.dart';

+import '../image.dart';

+import 'decoder.dart';

+import 'decode_info.dart';

+import 'psd/psd_image.dart';

+

+/**

+ * Decode a Photoshop PSD image.

+ */

+class PsdDecoder extends Decoder {

+  PsdImage info;

+

+  /**

+   * A light-weight function to test if the given file is able to be decoded

+   * by this Decoder.

+   */

+  bool isValidFile(List<int> bytes) {

+    return new PsdImage(bytes).isValid;

+  }

+

+  /**

+   * Decode a raw PSD image without rendering it to a flat image.

+   */

+  PsdImage decodePsd(List<int> bytes) {

+    PsdImage psd = PsdImage(bytes);

+    if (!psd.decode()) {

+      return null;

+    }

+    return psd;

+  }

+

+  /**

+   * Decode the file and extract a single image from it.  If the file is

+   * animated, the specified [frame] will be decoded.  If there was a problem

+   * decoding the file, null is returned.

+   */

+  Image decodeImage(List<int> bytes, {int frame: 0}) {

+    startDecode(bytes);

+    return decodeFrame(frame);

+  }

+

+  /**

+   * Decode all of the frames from an animation.  If the file is not an

+   * animation, a single frame animation is returned.  If there was a problem

+   * decoding the file, null is returned.

+   */

+  Animation decodeAnimation(List<int> bytes) {

+    if (startDecode(bytes) == null) {

+      return null;

+    }

+

+    Animation anim = Animation();

+    anim.width = info.width;

+    anim.height = info.height;

+    anim.frameType = Animation.PAGE;

+    for (int i = 0, len = numFrames(); i < len; ++i) {

+      Image image = decodeFrame(i);

+      if (i == null) {

+        continue;

+      }

+      anim.addFrame(image);

+    }

+

+    return anim;

+  }

+

+  /**

+   * Start decoding the data as an animation sequence, but don't actually

+   * process the frames until they are requested with decodeFrame.

+   */

+  DecodeInfo startDecode(List<int> bytes) {

+    info = PsdImage(bytes);

+    return info;

+  }

+

+  /**

+   * How many frames are available to be decoded.  [startDecode] should have

+   * been called first. Non animated image files will have a single frame.

+   */

+  int numFrames() => info != null ? info.numFrames : 0;

+

+  /**

+   * Decode a single frame from the data stat was set with [startDecode].

+   * If [frame] is out of the range of available frames, null is returned.

+   * Non animated image files will only have [frame] 0.  An [AnimationFrame]

+   * is returned, which provides the image, and top-left coordinates of the

+   * image, as animated frames may only occupy a subset of the canvas.

+   */

+  Image decodeFrame(int frame) {

+    if (info == null) {

+      return null;

+    }

+    return info.decodeImage();

+  }

+}

diff --git a/image/lib/src/formats/pvrtc/pvrtc_bit_utility.dart b/image/lib/src/formats/pvrtc/pvrtc_bit_utility.dart
old mode 100644
new mode 100755
index 00d4ef9..86cb522
--- a/image/lib/src/formats/pvrtc/pvrtc_bit_utility.dart
+++ b/image/lib/src/formats/pvrtc/pvrtc_bit_utility.dart
@@ -1,187 +1,187 @@
-class BitUtility {
-  static bool isPowerOf2(int x) => (x & (x - 1)) == 0;
-
-  static int rotateRight(int value, int shift) =>
-      (value >> shift) | (value << (32 - shift));
-
-  static const List<int> BITSCALE_5_TO_8 = const [
-   0, 8, 16, 24, 32, 41, 49, 57, 65, 74,
-   82, 90, 98, 106, 115, 123, 131, 139, 148, 156,
-   164, 172, 180, 189, 197, 205, 213, 222, 230, 238,
-   246, 255];
-
-  static const List<int> BITSCALE_4_TO_8 = const [
-   0, 17, 34, 51, 68, 85, 102, 119, 136, 153,
-   170, 187, 204, 221, 238, 255];
-
-  static const List<int> BITSCALE_3_TO_8 = const [
-   0, 36, 72, 109, 145, 182, 218, 255];
-
-  static const List<int> BITSCALE_8_TO_5_FLOOR = const [
-   0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-   1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
-   2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
-   3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
-   6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
-   7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
-   8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
-   9, 9, 9, 10, 10, 10, 10, 10, 10, 10,
-   10, 11, 11, 11, 11, 11, 11, 11, 11, 12,
-   12, 12, 12, 12, 12, 12, 12, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 14, 14, 14, 14,
-   14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
-   15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 18,
-   18, 18, 18, 18, 18, 18, 18, 19, 19, 19,
-   19, 19, 19, 19, 19, 20, 20, 20, 20, 20,
-   20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
-   21, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
-   24, 24, 24, 24, 24, 24, 25, 25, 25, 25,
-   25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
-   26, 26, 26, 27, 27, 27, 27, 27, 27, 27,
-   27, 28, 28, 28, 28, 28, 28, 28, 28, 29,
-   29, 29, 29, 29, 29, 29, 29, 30, 30, 30,
-   30, 30, 30, 30, 30, 31];
-
-  static const List<int> BITSCALE_8_TO_4_FLOOR = const [
-   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-   0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
-   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-   7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
-   8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-   8, 8, 8, 9, 9, 9, 9, 9, 9, 9,
-   9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-   10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-   10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
-   11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
-   12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-   12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 14, 14,
-   14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-   14, 14, 14, 14, 14, 15];
-
-  static const List<int> BITSCALE_8_TO_3_FLOOR = const [
-   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-   0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 7];
-
-  static const List<int> BITSCALE_8_TO_5_CEIL = const [
-   0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
-   2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
-   3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
-   4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
-   7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
-   8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
-   9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
-   10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
-   11, 12, 12, 12, 12, 12, 12, 12, 12, 13,
-   13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
-   14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
-   15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
-   16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
-   18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
-   19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
-   20, 20, 20, 20, 20, 21, 21, 21, 21, 21,
-   21, 21, 21, 22, 22, 22, 22, 22, 22, 22,
-   22, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-   24, 24, 24, 24, 24, 24, 24, 24, 25, 25,
-   25, 25, 25, 25, 25, 25, 26, 26, 26, 26,
-   26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
-   27, 27, 27, 28, 28, 28, 28, 28, 28, 28,
-   28, 29, 29, 29, 29, 29, 29, 29, 29, 30,
-   30, 30, 30, 30, 30, 30, 30, 31, 31, 31,
-   31, 31, 31, 31, 31, 31];
-
-  static const List<int> BITSCALE_8_TO_4_CEIL = const [
-   0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
-   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-   8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-   8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
-   9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-   9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
-   10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-   10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 11, 11, 11, 11, 12, 12,
-   12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-   12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 14, 14, 14, 14, 14, 14, 14, 14,
-   14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
-   15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-   15, 15, 15, 15, 15, 15];
-
-  static const List<int> BITSCALE_8_TO_3_CEIL = const [
-   0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-   1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-   2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-   4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-   5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-   6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
-   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-   7, 7, 7, 7, 7, 7];
-}
+class BitUtility {

+  static bool isPowerOf2(int x) => (x & (x - 1)) == 0;

+

+  static int rotateRight(int value, int shift) =>

+      (value >> shift) | (value << (32 - shift));

+

+  static const List<int> BITSCALE_5_TO_8 = const [

+   0, 8, 16, 24, 32, 41, 49, 57, 65, 74,

+   82, 90, 98, 106, 115, 123, 131, 139, 148, 156,

+   164, 172, 180, 189, 197, 205, 213, 222, 230, 238,

+   246, 255];

+

+  static const List<int> BITSCALE_4_TO_8 = const [

+   0, 17, 34, 51, 68, 85, 102, 119, 136, 153,

+   170, 187, 204, 221, 238, 255];

+

+  static const List<int> BITSCALE_3_TO_8 = const [

+   0, 36, 72, 109, 145, 182, 218, 255];

+

+  static const List<int> BITSCALE_8_TO_5_FLOOR = const [

+   0, 0, 0, 0, 0, 0, 0, 0, 0, 1,

+   1, 1, 1, 1, 1, 1, 1, 2, 2, 2,

+   2, 2, 2, 2, 2, 3, 3, 3, 3, 3,

+   3, 3, 3, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 5, 5, 5, 5, 5, 5, 5, 5,

+   6, 6, 6, 6, 6, 6, 6, 6, 7, 7,

+   7, 7, 7, 7, 7, 7, 8, 8, 8, 8,

+   8, 8, 8, 8, 8, 9, 9, 9, 9, 9,

+   9, 9, 9, 10, 10, 10, 10, 10, 10, 10,

+   10, 11, 11, 11, 11, 11, 11, 11, 11, 12,

+   12, 12, 12, 12, 12, 12, 12, 13, 13, 13,

+   13, 13, 13, 13, 13, 13, 14, 14, 14, 14,

+   14, 14, 14, 14, 15, 15, 15, 15, 15, 15,

+   15, 15, 16, 16, 16, 16, 16, 16, 16, 16,

+   17, 17, 17, 17, 17, 17, 17, 17, 17, 18,

+   18, 18, 18, 18, 18, 18, 18, 19, 19, 19,

+   19, 19, 19, 19, 19, 20, 20, 20, 20, 20,

+   20, 20, 20, 21, 21, 21, 21, 21, 21, 21,

+   21, 22, 22, 22, 22, 22, 22, 22, 22, 22,

+   23, 23, 23, 23, 23, 23, 23, 23, 24, 24,

+   24, 24, 24, 24, 24, 24, 25, 25, 25, 25,

+   25, 25, 25, 25, 26, 26, 26, 26, 26, 26,

+   26, 26, 26, 27, 27, 27, 27, 27, 27, 27,

+   27, 28, 28, 28, 28, 28, 28, 28, 28, 29,

+   29, 29, 29, 29, 29, 29, 29, 30, 30, 30,

+   30, 30, 30, 30, 30, 31];

+

+  static const List<int> BITSCALE_8_TO_4_FLOOR = const [

+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+   0, 0, 0, 0, 0, 0, 0, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 1, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   2, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 3, 3, 4, 4,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 5, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 6, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 7,

+   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,

+   7, 7, 7, 7, 7, 7, 8, 8, 8, 8,

+   8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

+   8, 8, 8, 9, 9, 9, 9, 9, 9, 9,

+   9, 9, 9, 9, 9, 9, 9, 9, 9, 9,

+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10,

+   10, 10, 10, 10, 10, 10, 10, 11, 11, 11,

+   11, 11, 11, 11, 11, 11, 11, 11, 11, 11,

+   11, 11, 11, 11, 12, 12, 12, 12, 12, 12,

+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12,

+   12, 13, 13, 13, 13, 13, 13, 13, 13, 13,

+   13, 13, 13, 13, 13, 13, 13, 13, 14, 14,

+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14,

+   14, 14, 14, 14, 14, 15];

+

+  static const List<int> BITSCALE_8_TO_3_FLOOR = const [

+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+   0, 0, 0, 0, 0, 0, 0, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 2, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 7];

+

+  static const List<int> BITSCALE_8_TO_5_CEIL = const [

+   0, 1, 1, 1, 1, 1, 1, 1, 1, 2,

+   2, 2, 2, 2, 2, 2, 2, 3, 3, 3,

+   3, 3, 3, 3, 3, 4, 4, 4, 4, 4,

+   4, 4, 4, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 6, 6, 6, 6, 6, 6, 6, 6,

+   7, 7, 7, 7, 7, 7, 7, 7, 8, 8,

+   8, 8, 8, 8, 8, 8, 9, 9, 9, 9,

+   9, 9, 9, 9, 9, 10, 10, 10, 10, 10,

+   10, 10, 10, 11, 11, 11, 11, 11, 11, 11,

+   11, 12, 12, 12, 12, 12, 12, 12, 12, 13,

+   13, 13, 13, 13, 13, 13, 13, 14, 14, 14,

+   14, 14, 14, 14, 14, 14, 15, 15, 15, 15,

+   15, 15, 15, 15, 16, 16, 16, 16, 16, 16,

+   16, 16, 17, 17, 17, 17, 17, 17, 17, 17,

+   18, 18, 18, 18, 18, 18, 18, 18, 18, 19,

+   19, 19, 19, 19, 19, 19, 19, 20, 20, 20,

+   20, 20, 20, 20, 20, 21, 21, 21, 21, 21,

+   21, 21, 21, 22, 22, 22, 22, 22, 22, 22,

+   22, 23, 23, 23, 23, 23, 23, 23, 23, 23,

+   24, 24, 24, 24, 24, 24, 24, 24, 25, 25,

+   25, 25, 25, 25, 25, 25, 26, 26, 26, 26,

+   26, 26, 26, 26, 27, 27, 27, 27, 27, 27,

+   27, 27, 27, 28, 28, 28, 28, 28, 28, 28,

+   28, 29, 29, 29, 29, 29, 29, 29, 29, 30,

+   30, 30, 30, 30, 30, 30, 30, 31, 31, 31,

+   31, 31, 31, 31, 31, 31];

+

+  static const List<int> BITSCALE_8_TO_4_CEIL = const [

+   0, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 1, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 2, 2, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 7, 7, 7, 7, 7, 7, 7,

+   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,

+   8, 8, 8, 8, 8, 8, 8, 8, 8, 8,

+   8, 8, 8, 8, 8, 8, 8, 9, 9, 9,

+   9, 9, 9, 9, 9, 9, 9, 9, 9, 9,

+   9, 9, 9, 9, 10, 10, 10, 10, 10, 10,

+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10,

+   10, 11, 11, 11, 11, 11, 11, 11, 11, 11,

+   11, 11, 11, 11, 11, 11, 11, 11, 12, 12,

+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12,

+   12, 12, 12, 12, 12, 13, 13, 13, 13, 13,

+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,

+   13, 13, 14, 14, 14, 14, 14, 14, 14, 14,

+   14, 14, 14, 14, 14, 14, 14, 14, 14, 15,

+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15,

+   15, 15, 15, 15, 15, 15];

+

+  static const List<int> BITSCALE_8_TO_3_CEIL = const [

+   0, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+   1, 1, 1, 1, 1, 1, 1, 2, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+   2, 2, 2, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

+   4, 4, 4, 4, 4, 4, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

+   5, 5, 5, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 6,

+   6, 6, 6, 6, 6, 6, 6, 6, 6, 7,

+   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,

+   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,

+   7, 7, 7, 7, 7, 7, 7, 7, 7, 7,

+   7, 7, 7, 7, 7, 7];

+}

diff --git a/image/lib/src/formats/pvrtc/pvrtc_color.dart b/image/lib/src/formats/pvrtc/pvrtc_color.dart
old mode 100644
new mode 100755
index bfb771b..3060cba
--- a/image/lib/src/formats/pvrtc/pvrtc_color.dart
+++ b/image/lib/src/formats/pvrtc/pvrtc_color.dart
@@ -1,107 +1,107 @@
-class PvrtcColorRgb {
-  int r;
-  int g;
-  int b;
-
-  PvrtcColorRgb([this.r = 0, this.g = 0, this.b = 0]);
-
-  PvrtcColorRgb.from(PvrtcColorRgb other)
-      : r = other.r
-      , g = other.g
-      , b = other.b;
-
-  PvrtcColorRgb copy() => new PvrtcColorRgb.from(this);
-
-  PvrtcColorRgb operator *(int x) =>
-    new PvrtcColorRgb(r * x, g * x, b * x);
-
-  PvrtcColorRgb operator +(PvrtcColorRgb x) =>
-      new PvrtcColorRgb(r + x.r, g + x.g, b + x.b);
-
-  PvrtcColorRgb operator -(PvrtcColorRgb x) =>
-      new PvrtcColorRgb(r - x.r, g - x.g, b - x.b);
-
-  int dotProd(PvrtcColorRgb x) => r * x.r + g * x.g + b * x.b;
-
-  void setMin(PvrtcColorRgb c) {
-    if (c.r < r) {
-      r = c.r;
-    }
-    if (c.g < g) {
-      g = c.g;
-    }
-    if (c.b < b) {
-      b = c.b;
-    }
-  }
-
-  void setMax(PvrtcColorRgb c) {
-    if (c.r > r) {
-      r = c.r;
-    }
-    if (c.g > g) {
-      g = c.g;
-    }
-    if (c.b > b) {
-      b = c.b;
-    }
-  }
-}
-
-class PvrtcColorRgba {
-  int r;
-  int g;
-  int b;
-  int a;
-
-  PvrtcColorRgba([this.r = 0, this.g = 0, this.b = 0, this.a = 0]);
-
-  PvrtcColorRgba.from(PvrtcColorRgba other)
-      : r = other.r
-      , g = other.g
-      , b = other.b
-      , a = other.a;
-
-  PvrtcColorRgba copy() => new PvrtcColorRgba.from(this);
-
-  PvrtcColorRgba operator *(int x) =>
-    new PvrtcColorRgba(r * x, g * x, b * x, a * x);
-
-  PvrtcColorRgba operator +(PvrtcColorRgba x) =>
-      new PvrtcColorRgba(r + x.r, g + x.g, b + x.b, a + x.a);
-
-  PvrtcColorRgba operator -(PvrtcColorRgba x) =>
-      new PvrtcColorRgba(r - x.r, g - x.g, b - x.b, a - x.a);
-
-  int dotProd(PvrtcColorRgba x) => r * x.r + g * x.g + b * x.b + a * x.a;
-
-  void setMin(PvrtcColorRgba c) {
-    if (c.r < r) {
-      r = c.r;
-    }
-    if (c.g < g) {
-      g = c.g;
-    }
-    if (c.b < b) {
-      b = c.b;
-    }
-    if (c.a < a) {
-      a = c.a;
-    }
-  }
-
-  void setMax(PvrtcColorRgba c) {
-    if (c.r > r) {
-      r = c.r;
-    }
-    if (c.g > g) {
-      g = c.g;
-    }
-    if (c.b > b) {
-      b = c.b;
-    }
-    if (c.a > a) {
-      a = c.a;
-    }
-  }
-}
+class PvrtcColorRgb {

+  int r;

+  int g;

+  int b;

+

+  PvrtcColorRgb([this.r = 0, this.g = 0, this.b = 0]);

+

+  PvrtcColorRgb.from(PvrtcColorRgb other)

+      : r = other.r

+      , g = other.g

+      , b = other.b;

+

+  PvrtcColorRgb copy() => new PvrtcColorRgb.from(this);

+

+  PvrtcColorRgb operator *(int x) =>

+    new PvrtcColorRgb(r * x, g * x, b * x);

+

+  PvrtcColorRgb operator +(PvrtcColorRgb x) =>

+      new PvrtcColorRgb(r + x.r, g + x.g, b + x.b);

+

+  PvrtcColorRgb operator -(PvrtcColorRgb x) =>

+      new PvrtcColorRgb(r - x.r, g - x.g, b - x.b);

+

+  int dotProd(PvrtcColorRgb x) => r * x.r + g * x.g + b * x.b;

+

+  void setMin(PvrtcColorRgb c) {

+    if (c.r < r) {

+      r = c.r;

+    }

+    if (c.g < g) {

+      g = c.g;

+    }

+    if (c.b < b) {

+      b = c.b;

+    }

+  }

+

+  void setMax(PvrtcColorRgb c) {

+    if (c.r > r) {

+      r = c.r;

+    }

+    if (c.g > g) {

+      g = c.g;

+    }

+    if (c.b > b) {

+      b = c.b;

+    }

+  }

+}

+

+class PvrtcColorRgba {

+  int r;

+  int g;

+  int b;

+  int a;

+

+  PvrtcColorRgba([this.r = 0, this.g = 0, this.b = 0, this.a = 0]);

+

+  PvrtcColorRgba.from(PvrtcColorRgba other)

+      : r = other.r

+      , g = other.g

+      , b = other.b

+      , a = other.a;

+

+  PvrtcColorRgba copy() => new PvrtcColorRgba.from(this);

+

+  PvrtcColorRgba operator *(int x) =>

+    new PvrtcColorRgba(r * x, g * x, b * x, a * x);

+

+  PvrtcColorRgba operator +(PvrtcColorRgba x) =>

+      new PvrtcColorRgba(r + x.r, g + x.g, b + x.b, a + x.a);

+

+  PvrtcColorRgba operator -(PvrtcColorRgba x) =>

+      new PvrtcColorRgba(r - x.r, g - x.g, b - x.b, a - x.a);

+

+  int dotProd(PvrtcColorRgba x) => r * x.r + g * x.g + b * x.b + a * x.a;

+

+  void setMin(PvrtcColorRgba c) {

+    if (c.r < r) {

+      r = c.r;

+    }

+    if (c.g < g) {

+      g = c.g;

+    }

+    if (c.b < b) {

+      b = c.b;

+    }

+    if (c.a < a) {

+      a = c.a;

+    }

+  }

+

+  void setMax(PvrtcColorRgba c) {

+    if (c.r > r) {

+      r = c.r;

+    }

+    if (c.g > g) {

+      g = c.g;

+    }

+    if (c.b > b) {

+      b = c.b;

+    }

+    if (c.a > a) {

+      a = c.a;

+    }

+  }

+}

diff --git a/image/lib/src/formats/pvrtc/pvrtc_color_bounding_box.dart b/image/lib/src/formats/pvrtc/pvrtc_color_bounding_box.dart
old mode 100644
new mode 100755
index 3af0fad..036a55c
--- a/image/lib/src/formats/pvrtc/pvrtc_color_bounding_box.dart
+++ b/image/lib/src/formats/pvrtc/pvrtc_color_bounding_box.dart
@@ -1,13 +1,13 @@
-class PvrtcColorBoundingBox {
-  var min;
-  var max;
-
-  PvrtcColorBoundingBox(min, max)
-      : this.min = min.copy()
-      , this.max = max.copy();
-
-  void add(c) {
-    min.setMin(c);
-    max.setMax(c);
-  }
-}
+class PvrtcColorBoundingBox {

+  var min;

+  var max;

+

+  PvrtcColorBoundingBox(min, max)

+      : this.min = min.copy()

+      , this.max = max.copy();

+

+  void add(c) {

+    min.setMin(c);

+    max.setMax(c);

+  }

+}

diff --git a/image/lib/src/formats/pvrtc/pvrtc_decoder.dart b/image/lib/src/formats/pvrtc/pvrtc_decoder.dart
old mode 100644
new mode 100755
index 968b7b7..1355e0d
--- a/image/lib/src/formats/pvrtc/pvrtc_decoder.dart
+++ b/image/lib/src/formats/pvrtc/pvrtc_decoder.dart
@@ -1,595 +1,595 @@
-import 'dart:typed_data';
-
-import '../../color.dart';
-import '../../image.dart';
-import '../../util/input_buffer.dart';
-import 'pvrtc_color.dart';
-import 'pvrtc_packet.dart';
-
-/**
- * Ported from Jeffrey Lim's PVRTC encoder/decoder,
- * https://bitbucket.org/jthlim/pvrtccompressor
- */
-class PvrtcDecoder {
-  Image decodePvr(List<int> data) {
-    // Use a heuristic to detect potential apple PVRTC formats
-    if (_countBits(data.length) == 1) {
-      // very likely to be apple PVRTC
-      var image = decodeApplePVRTC(data);
-      if (image != null) {
-         return image;
-      }
-    }
-
-    var input = new InputBuffer(data, bigEndian: false);
-    var magic = input.readUint32();
-    if (magic == 0x03525650) {
-      return decodePVR3(data);
-    }
-
-    return decodePVR2(data);
-  }
-
-  Image decodeApplePVRTC(List<int> data) {
-    // additional heuristic
-    const int HEADER_SIZE = 52;
-    if (data.length > HEADER_SIZE) {
-      InputBuffer input = new InputBuffer(data, bigEndian: false);
-      // Header
-      int size = input.readUint32();
-      if (size == HEADER_SIZE) {
-        return null;
-      }
-      /*int height =*/ input.readUint32();
-      /*int width =*/ input.readUint32();
-      /*int mipcount =*/ input.readUint32();
-      /*int flags =*/ input.readUint32();
-      /*int texdatasize =*/ input.readUint32();
-      /*int bpp =*/ input.readUint32();
-      /*int rmask =*/ input.readUint32();
-      /*int gmask =*/ input.readUint32();
-      /*int bmask =*/ input.readUint32();
-      int magic = input.readUint32();
-      if (magic == 0x21525650) {
-        // this looks more like a PowerVR file.
-        return null;
-      }
-    }
-
-    //const int PVRTC2 = 1;
-    //const int PVRTC4 = 2;
-
-    int mode = 1;
-    int res = 8;
-    int size = data.length;
-    //int format = 0;
-
-    // this is a tough one, could be 2bpp 8x8, 4bpp 8x8
-    if (size == 32) {
-      // assume 4bpp, 8x8
-      mode = 0;
-      res = 8;
-    } else {
-      // Detect if it's 2bpp or 4bpp
-      int shift = 0;
-      int test2bpp = 0x40; // 16x16
-      int test4bpp = 0x80; // 16x16
-
-      while (shift < 10) {
-        int s2 = shift << 1;
-
-        if ((test2bpp << s2) & size != 0) {
-          res = 16 << shift;
-          mode = 1;
-          //format = PVRTC2;
-          break;
-        }
-
-        if ((test4bpp << s2) & size != 0) {
-          res = 16 << shift;
-          mode = 0;
-          //format = PVRTC4;
-          break;
-        }
-
-        ++shift;
-      }
-
-      if (shift == 10) {
-        // no mode could be found.
-        return null;
-      }
-    }
-
-    // there is no reliable way to know if it's a 2bpp or 4bpp file. Assuming
-    int width = res;
-    int height = res;
-    int bpp = (mode + 1) * 2;
-    //int numMips = 0;
-
-    if (bpp == 4) {
-      // 2bpp is currently unsupported
-      return null;
-    }
-
-    return decodeRgba4bpp(width, height, data as TypedData);
-  }
-
-  Image decodePVR2(List<int> data) {
-    int length = data.length;
-
-    const int HEADER_SIZE = 52;
-    const int PVRTEX_CUBEMAP = (1 << 12);
-    const int PVR_PIXELTYPE_MASK  = 0xff;
-    const int PVR_TYPE_RGBA4444   = 0x10;
-    const int PVR_TYPE_RGBA5551   = 0x11;
-    const int PVR_TYPE_RGBA8888   = 0x12;
-    const int PVR_TYPE_RGB565     = 0x13;
-    const int PVR_TYPE_RGB555     = 0x14;
-    const int PVR_TYPE_RGB888     = 0x15;
-    const int PVR_TYPE_I8         = 0x16;
-    const int PVR_TYPE_AI8        = 0x17;
-    const int PVR_TYPE_PVRTC2     = 0x18;
-    const int PVR_TYPE_PVRTC4     = 0x19;
-
-    if (length < HEADER_SIZE) {
-      return null;
-    }
-
-    InputBuffer input = new InputBuffer(data, bigEndian: false);
-    // Header
-    int size = input.readUint32();
-    int height = input.readUint32();
-    int width = input.readUint32();
-    /*int mipcount =*/ input.readUint32();
-    int flags = input.readUint32();
-    /*int texdatasize =*/ input.readUint32();
-    int bpp = input.readUint32();
-    /*int rmask =*/ input.readUint32();
-    /*int gmask =*/ input.readUint32();
-    /*int bmask =*/ input.readUint32();
-    int amask = input.readUint32();
-    int magic = input.readUint32();
-    int numtex = input.readUint32();
-
-    if (size != HEADER_SIZE || magic != 0x21525650) {
-      return null;
-    }
-
-    if (numtex < 1) {
-      numtex = (flags & PVRTEX_CUBEMAP) != 0 ? 6 : 1;
-    }
-
-    if (numtex != 1) {
-      // only 1 surface supported currently
-      return null;
-    }
-
-    if (width * height * bpp / 8 > length - HEADER_SIZE) {
-      return null;
-    }
-
-    int ptype = flags & PVR_PIXELTYPE_MASK;
-
-    switch (ptype) {
-      case PVR_TYPE_RGBA4444:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for (int x = 0; x < width; ++x) {
-            int v1 = input.readByte();
-            int v2 = input.readByte();
-            int a = (v1 & 0x0f) << 4;
-            int b = (v1 & 0xf0);
-            int g = (v2 & 0x0f) << 4;
-            int r = (v2 & 0xf0);
-
-            out[oi++] = r;
-            out[oi++] = g;
-            out[oi++] = b;
-            out[oi++] = a;
-          }
-        }
-        return image;
-      case PVR_TYPE_RGBA5551:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for (int x = 0; x < width; ++x) {
-            int v = input.readUint16();
-
-            int r = (v & 0xf800) >> 8;
-            int g = (v & 0x07c0) >> 3;
-            int b = (v & 0x003e) << 2;
-            int a = (v & 0x0001) != 0 ? 255 : 0;
-
-            out[oi++] = r;
-            out[oi++] = g;
-            out[oi++] = b;
-            out[oi++] = a;
-          }
-        }
-        return image;
-      case PVR_TYPE_RGBA8888:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for (int x = 0; x < width; ++x) {
-            out[oi++] = input.readByte();
-            out[oi++] = input.readByte();
-            out[oi++] = input.readByte();
-            out[oi++] = input.readByte();
-          }
-        }
-        return image;
-      case PVR_TYPE_RGB565:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for (int x = 0; x < width; ++x) {
-            int v = input.readUint16();
-            int b = (v & 0x001f) << 3;
-            int g = (v & 0x07e0) >> 3;
-            int r = (v & 0xf800) >> 8;
-            int a = 255;
-            out[oi++] = r;
-            out[oi++] = g;
-            out[oi++] = b;
-            out[oi++] = a;
-          }
-        }
-        return image;
-      case PVR_TYPE_RGB555:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for (int x = 0; x < width; ++x) {
-            int v = input.readUint16();
-            int r = (v & 0x001f) << 3;
-            int g = (v & 0x03e0) >> 2;
-            int b = (v & 0x7c00) >> 7;
-            int a = 255;
-            out[oi++] = r;
-            out[oi++] = g;
-            out[oi++] = b;
-            out[oi++] = a;
-          }
-        }
-        return image;
-      case PVR_TYPE_RGB888:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for (int x = 0; x < width; ++x) {
-            out[oi++] = input.readByte();
-            out[oi++] = input.readByte();
-            out[oi++] = input.readByte();
-            out[oi++] = 255;
-          }
-        }
-        return image;
-      case PVR_TYPE_I8:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for(int x = 0; x < width; ++x) {
-            int i = input.readByte();
-            out[oi++] = i;
-            out[oi++] = i;
-            out[oi++] = i;
-            out[oi++] = 255;
-          }
-        }
-        return image;
-      case PVR_TYPE_AI8:
-        Image image = new Image(width, height);
-        Uint8List out = image.getBytes();
-        int oi = 0;
-        for (int y = 0; y < height; ++y) {
-          for(int x = 0; x < width; ++x) {
-            int i = input.readByte();
-            int a = input.readByte();
-            out[oi++] = i;
-            out[oi++] = i;
-            out[oi++] = i;
-            out[oi++] = a;
-          }
-        }
-        return image;
-      case PVR_TYPE_PVRTC2:
-        // Currently unsupported
-        return null;
-      case PVR_TYPE_PVRTC4:
-        return amask == 0 ? decodeRgb4bpp(width, height, input.toUint8List()) :
-               decodeRgba4bpp(width, height, input.toUint8List());
-    }
-
-    // Unknown format
-    return null;
-  }
-
-  Image decodePVR3(List<int> data) {
-    //const int PVR3_PVRTC_2BPP_RGB = 0;
-    //const int PVR3_PVRTC_2BPP_RGBA = 1;
-    const int PVR3_PVRTC_4BPP_RGB = 2;
-    const int PVR3_PVRTC_4BPP_RGBA = 3;
-    /*const int PVR3_PVRTC2_2BPP = 4;
-    const int PVR3_PVRTC2_4BPP = 5;
-    const int PVR3_ETC1 = 6;
-    const int PVR3_DXT1 = 7;
-    const int PVR3_DXT2 = 8;
-    const int PVR3_DXT3 = 9;
-    const int PVR3_DXT4 = 10;
-    const int PVR3_DXT5 = 11;
-    const int PVR3_BC1 = 7;
-    const int PVR3_BC2 = 9;
-    const int PVR3_BC3 = 11;
-    const int PVR3_BC4 = 12;
-    const int PVR3_BC5 = 13;
-    const int PVR3_BC6 = 14;
-    const int PVR3_BC7 = 15;
-    const int PVR3_UYVY = 16;
-    const int PVR3_YUY2 = 17;
-    const int PVR3_BW_1BPP = 18;
-    const int PVR3_R9G9B9E5 = 19;
-    const int PVR3_RGBG8888 = 20;
-    const int PVR3_GRGB8888 = 21;
-    const int PVR3_ETC2_RGB = 22;
-    const int PVR3_ETC2_RGBA = 23;
-    const int PVR3_ETC2_RGB_A1 = 24;
-    const int PVR3_EAC_R11_U = 25;
-    const int PVR3_EAC_R11_S = 26;
-    const int PVR3_EAC_RG11_U = 27;
-    const int PVR3_EAC_RG11_S = 28;*/
-
-    InputBuffer input = new InputBuffer(data);
-
-    // Header
-    int version = input.readUint32();
-    if (version != 0x03525650) {
-      return null;
-    }
-
-    /*int flags =*/ input.readUint32();
-    var format = input.readUint32();
-    var order = [input.readByte(), input.readByte(),
-                 input.readByte(), input.readByte()];
-    /*int colorspace =*/ input.readUint32();
-    /*int channeltype =*/ input.readUint32();
-    int height = input.readUint32();
-    int width = input.readUint32();
-    /*int depth =*/ input.readUint32();
-    /*int num_surfaces =*/ input.readUint32();
-    /*int num_faces =*/ input.readUint32();
-    /*int mipcount =*/ input.readUint32();
-    int metadata_size = input.readUint32();
-
-    input.skip(metadata_size);
-
-    if (order[0] == 0) {
-      switch (format) {
-        case PVR3_PVRTC_4BPP_RGB:
-          return decodeRgb4bpp(width, height, input.toUint8List());
-        case PVR3_PVRTC_4BPP_RGBA:
-          return decodeRgba4bpp(width, height, input.toUint8List());
-        /*case PVR3_PVRTC_2BPP_RGB:
-          return null;
-        case PVR3_PVRTC_2BPP_RGBA:
-          return null;
-        case PVR3_PVRTC2_2BPP:
-          return null;
-        case PVR3_PVRTC2_4BPP:
-          return null;
-        case PVR3_ETC1:
-          return null;
-        case PVR3_DXT1:
-          return null;
-        case PVR3_DXT2:
-          return null;
-        case PVR3_DXT3:
-          return null;
-        case PVR3_DXT4:
-          return null;
-        case PVR3_DXT5:
-          return null;
-        case PVR3_BC1:
-          return null;
-        case PVR3_BC2:
-          return null;
-        case PVR3_BC3:
-          return null;
-        case PVR3_BC4:
-          return null;
-        case PVR3_BC5:
-          return null;
-        case PVR3_BC6:
-          return null;
-        case PVR3_BC7:
-          return null;
-        case PVR3_UYVY:
-          return null;
-        case PVR3_YUY2:
-          return null;
-        case PVR3_BW_1BPP:
-          return null;
-        case PVR3_R9G9B9E5:
-          return null;
-        case PVR3_RGBG8888:
-          return null;
-        case PVR3_GRGB8888:
-          return null;
-        case PVR3_ETC2_RGB:
-          return null;
-        case PVR3_ETC2_RGBA:
-          return null;
-        case PVR3_ETC2_RGB_A1:
-          return null;
-        case PVR3_EAC_R11_U:
-          return null;
-        case PVR3_EAC_R11_S:
-          return null;
-        case PVR3_EAC_RG11_U:
-          return null;
-        case PVR3_EAC_RG11_S:
-          return null;*/
-      }
-    }
-
-    return null;
-  }
-
-  int _countBits(int x) {
-    x = (x - ((x >> 1) & 0x55555555)) & 0xffffffff;
-    x = ((x & 0x33333333) + ((x >> 2) & 0x33333333)) & 0xffffffff;
-    x = (x + (x >> 4)) & 0xffffffff;
-    x &= 0xf0f0f0f;
-    x = ((x * 0x01010101) & 0xffffffff) >> 24;
-    return x;
-  }
-
-  Image decodeRgb4bpp(int width, int height, TypedData data) {
-    var result = new Image(width, height, Image.RGB);
-
-    final int blocks = width ~/ 4;
-    final int blockMask = blocks - 1;
-
-    final packet = new PvrtcPacket(data);
-    final p0 = new PvrtcPacket(data);
-    final p1 = new PvrtcPacket(data);
-    final p2 = new PvrtcPacket(data);
-    final p3 = new PvrtcPacket(data);
-    final c = new PvrtcColorRgb();
-    const factors = PvrtcPacket.BILINEAR_FACTORS;
-    const weights = PvrtcPacket.WEIGHTS;
-
-    for (int y = 0; y < blocks; ++y) {
-      for (int x = 0; x < blocks; ++x) {
-        packet.setBlock(x, y);
-
-        int mod = packet.modulationData;
-        int weightIndex = 4 * packet.usePunchthroughAlpha;
-        int factorIndex = 0;
-
-        for (int py = 0; py < 4; ++py) {
-          int yOffset = (py < 2) ? -1 : 0;
-          int y0 = (y + yOffset) & blockMask;
-          int y1 = (y0 + 1) & blockMask;
-          int pyi = (py + y * 4) * width;
-
-          for (int px = 0; px < 4; ++px) {
-            int xOffset = (px < 2) ? -1 : 0;
-            int x0 = (x + xOffset) & blockMask;
-            int x1 = (x0 + 1) & blockMask;
-
-            p0.setBlock(x0, y0);
-            p1.setBlock(x1, y0);
-            p2.setBlock(x0, y1);
-            p3.setBlock(x1, y1);
-
-            var ca = p0.getColorRgbA() * factors[factorIndex][0] +
-                     p1.getColorRgbA() * factors[factorIndex][1] +
-                     p2.getColorRgbA() * factors[factorIndex][2] +
-                     p3.getColorRgbA() * factors[factorIndex][3];
-
-            var cb = p0.getColorRgbB() * factors[factorIndex][0] +
-                     p1.getColorRgbB() * factors[factorIndex][1] +
-                     p2.getColorRgbB() * factors[factorIndex][2] +
-                     p3.getColorRgbB() * factors[factorIndex][3];
-
-            var w = weights[weightIndex + mod & 3];
-
-            c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;
-            c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;
-            c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;
-
-            int pi = (pyi + (px + x * 4));
-
-            result[pi] = getColor(c.r, c.g, c.b, 255);
-
-            mod >>= 2;
-            factorIndex++;
-          }
-        }
-      }
-    }
-
-    return result;
-  }
-
-  Image decodeRgba4bpp(int width, int height, TypedData data) {
-    var result = new Image(width, height, Image.RGBA);
-
-    final int blocks = width ~/ 4;
-    final int blockMask = blocks - 1;
-
-    final packet = new PvrtcPacket(data);
-    final p0 = new PvrtcPacket(data);
-    final p1 = new PvrtcPacket(data);
-    final p2 = new PvrtcPacket(data);
-    final p3 = new PvrtcPacket(data);
-    final c = new PvrtcColorRgba();
-    const factors = PvrtcPacket.BILINEAR_FACTORS;
-    const weights = PvrtcPacket.WEIGHTS;
-
-    for (int y = 0; y < blocks; ++y) {
-      for (int x = 0; x < blocks; ++x) {
-        packet.setBlock(x, y);
-
-        int mod = packet.modulationData;
-        int weightIndex = 4 * packet.usePunchthroughAlpha;
-        int factorIndex = 0;
-
-        for (int py = 0; py < 4; ++py) {
-          int yOffset = (py < 2) ? -1 : 0;
-          int y0 = (y + yOffset) & blockMask;
-          int y1 = (y0 + 1) & blockMask;
-          int pyi = (py + y * 4) * width;
-
-          for (int px = 0; px < 4; ++px) {
-            int xOffset = (px < 2) ? -1 : 0;
-            int x0 = (x + xOffset) & blockMask;
-            int x1 = (x0 + 1) & blockMask;
-
-            p0.setBlock(x0, y0);
-            p1.setBlock(x1, y0);
-            p2.setBlock(x0, y1);
-            p3.setBlock(x1, y1);
-
-            var ca = p0.getColorRgbaA() * factors[factorIndex][0] +
-                     p1.getColorRgbaA() * factors[factorIndex][1] +
-                     p2.getColorRgbaA() * factors[factorIndex][2] +
-                     p3.getColorRgbaA() * factors[factorIndex][3];
-
-            var cb = p0.getColorRgbaB() * factors[factorIndex][0] +
-                     p1.getColorRgbaB() * factors[factorIndex][1] +
-                     p2.getColorRgbaB() * factors[factorIndex][2] +
-                     p3.getColorRgbaB() * factors[factorIndex][3];
-
-            var w = weights[weightIndex + mod & 3];
-
-            c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;
-            c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;
-            c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;
-            c.a = (ca.a * w[2] + cb.a * w[3]) >> 7;
-
-            int pi = (pyi + (px + x * 4));
-
-            result[pi] = getColor(c.r, c.g, c.b, c.a);
-
-            mod >>= 2;
-            factorIndex++;
-          }
-        }
-      }
-    }
-
-    return result;
-  }
-}
+import 'dart:typed_data';

+

+import '../../color.dart';

+import '../../image.dart';

+import '../../util/input_buffer.dart';

+import 'pvrtc_color.dart';

+import 'pvrtc_packet.dart';

+

+/**

+ * Ported from Jeffrey Lim's PVRTC encoder/decoder,

+ * https://bitbucket.org/jthlim/pvrtccompressor

+ */

+class PvrtcDecoder {

+  Image decodePvr(List<int> data) {

+    // Use a heuristic to detect potential apple PVRTC formats

+    if (_countBits(data.length) == 1) {

+      // very likely to be apple PVRTC

+      var image = decodeApplePVRTC(data);

+      if (image != null) {

+         return image;

+      }

+    }

+

+    var input = InputBuffer(data, bigEndian: false);

+    var magic = input.readUint32();

+    if (magic == 0x03525650) {

+      return decodePVR3(data);

+    }

+

+    return decodePVR2(data);

+  }

+

+  Image decodeApplePVRTC(List<int> data) {

+    // additional heuristic

+    const int HEADER_SIZE = 52;

+    if (data.length > HEADER_SIZE) {

+      InputBuffer input = InputBuffer(data, bigEndian: false);

+      // Header

+      int size = input.readUint32();

+      if (size == HEADER_SIZE) {

+        return null;

+      }

+      /*int height =*/ input.readUint32();

+      /*int width =*/ input.readUint32();

+      /*int mipcount =*/ input.readUint32();

+      /*int flags =*/ input.readUint32();

+      /*int texdatasize =*/ input.readUint32();

+      /*int bpp =*/ input.readUint32();

+      /*int rmask =*/ input.readUint32();

+      /*int gmask =*/ input.readUint32();

+      /*int bmask =*/ input.readUint32();

+      int magic = input.readUint32();

+      if (magic == 0x21525650) {

+        // this looks more like a PowerVR file.

+        return null;

+      }

+    }

+

+    //const int PVRTC2 = 1;

+    //const int PVRTC4 = 2;

+

+    int mode = 1;

+    int res = 8;

+    int size = data.length;

+    //int format = 0;

+

+    // this is a tough one, could be 2bpp 8x8, 4bpp 8x8

+    if (size == 32) {

+      // assume 4bpp, 8x8

+      mode = 0;

+      res = 8;

+    } else {

+      // Detect if it's 2bpp or 4bpp

+      int shift = 0;

+      int test2bpp = 0x40; // 16x16

+      int test4bpp = 0x80; // 16x16

+

+      while (shift < 10) {

+        int s2 = shift << 1;

+

+        if ((test2bpp << s2) & size != 0) {

+          res = 16 << shift;

+          mode = 1;

+          //format = PVRTC2;

+          break;

+        }

+

+        if ((test4bpp << s2) & size != 0) {

+          res = 16 << shift;

+          mode = 0;

+          //format = PVRTC4;

+          break;

+        }

+

+        ++shift;

+      }

+

+      if (shift == 10) {

+        // no mode could be found.

+        return null;

+      }

+    }

+

+    // there is no reliable way to know if it's a 2bpp or 4bpp file. Assuming

+    int width = res;

+    int height = res;

+    int bpp = (mode + 1) * 2;

+    //int numMips = 0;

+

+    if (bpp == 4) {

+      // 2bpp is currently unsupported

+      return null;

+    }

+

+    return decodeRgba4bpp(width, height, data as TypedData);

+  }

+

+  Image decodePVR2(List<int> data) {

+    int length = data.length;

+

+    const int HEADER_SIZE = 52;

+    const int PVRTEX_CUBEMAP = (1 << 12);

+    const int PVR_PIXELTYPE_MASK  = 0xff;

+    const int PVR_TYPE_RGBA4444   = 0x10;

+    const int PVR_TYPE_RGBA5551   = 0x11;

+    const int PVR_TYPE_RGBA8888   = 0x12;

+    const int PVR_TYPE_RGB565     = 0x13;

+    const int PVR_TYPE_RGB555     = 0x14;

+    const int PVR_TYPE_RGB888     = 0x15;

+    const int PVR_TYPE_I8         = 0x16;

+    const int PVR_TYPE_AI8        = 0x17;

+    const int PVR_TYPE_PVRTC2     = 0x18;

+    const int PVR_TYPE_PVRTC4     = 0x19;

+

+    if (length < HEADER_SIZE) {

+      return null;

+    }

+

+    InputBuffer input = InputBuffer(data, bigEndian: false);

+    // Header

+    int size = input.readUint32();

+    int height = input.readUint32();

+    int width = input.readUint32();

+    /*int mipcount =*/ input.readUint32();

+    int flags = input.readUint32();

+    /*int texdatasize =*/ input.readUint32();

+    int bpp = input.readUint32();

+    /*int rmask =*/ input.readUint32();

+    /*int gmask =*/ input.readUint32();

+    /*int bmask =*/ input.readUint32();

+    int amask = input.readUint32();

+    int magic = input.readUint32();

+    int numtex = input.readUint32();

+

+    if (size != HEADER_SIZE || magic != 0x21525650) {

+      return null;

+    }

+

+    if (numtex < 1) {

+      numtex = (flags & PVRTEX_CUBEMAP) != 0 ? 6 : 1;

+    }

+

+    if (numtex != 1) {

+      // only 1 surface supported currently

+      return null;

+    }

+

+    if (width * height * bpp / 8 > length - HEADER_SIZE) {

+      return null;

+    }

+

+    int ptype = flags & PVR_PIXELTYPE_MASK;

+

+    switch (ptype) {

+      case PVR_TYPE_RGBA4444:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for (int x = 0; x < width; ++x) {

+            int v1 = input.readByte();

+            int v2 = input.readByte();

+            int a = (v1 & 0x0f) << 4;

+            int b = (v1 & 0xf0);

+            int g = (v2 & 0x0f) << 4;

+            int r = (v2 & 0xf0);

+

+            out[oi++] = r;

+            out[oi++] = g;

+            out[oi++] = b;

+            out[oi++] = a;

+          }

+        }

+        return image;

+      case PVR_TYPE_RGBA5551:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for (int x = 0; x < width; ++x) {

+            int v = input.readUint16();

+

+            int r = (v & 0xf800) >> 8;

+            int g = (v & 0x07c0) >> 3;

+            int b = (v & 0x003e) << 2;

+            int a = (v & 0x0001) != 0 ? 255 : 0;

+

+            out[oi++] = r;

+            out[oi++] = g;

+            out[oi++] = b;

+            out[oi++] = a;

+          }

+        }

+        return image;

+      case PVR_TYPE_RGBA8888:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for (int x = 0; x < width; ++x) {

+            out[oi++] = input.readByte();

+            out[oi++] = input.readByte();

+            out[oi++] = input.readByte();

+            out[oi++] = input.readByte();

+          }

+        }

+        return image;

+      case PVR_TYPE_RGB565:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for (int x = 0; x < width; ++x) {

+            int v = input.readUint16();

+            int b = (v & 0x001f) << 3;

+            int g = (v & 0x07e0) >> 3;

+            int r = (v & 0xf800) >> 8;

+            int a = 255;

+            out[oi++] = r;

+            out[oi++] = g;

+            out[oi++] = b;

+            out[oi++] = a;

+          }

+        }

+        return image;

+      case PVR_TYPE_RGB555:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for (int x = 0; x < width; ++x) {

+            int v = input.readUint16();

+            int r = (v & 0x001f) << 3;

+            int g = (v & 0x03e0) >> 2;

+            int b = (v & 0x7c00) >> 7;

+            int a = 255;

+            out[oi++] = r;

+            out[oi++] = g;

+            out[oi++] = b;

+            out[oi++] = a;

+          }

+        }

+        return image;

+      case PVR_TYPE_RGB888:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for (int x = 0; x < width; ++x) {

+            out[oi++] = input.readByte();

+            out[oi++] = input.readByte();

+            out[oi++] = input.readByte();

+            out[oi++] = 255;

+          }

+        }

+        return image;

+      case PVR_TYPE_I8:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for(int x = 0; x < width; ++x) {

+            int i = input.readByte();

+            out[oi++] = i;

+            out[oi++] = i;

+            out[oi++] = i;

+            out[oi++] = 255;

+          }

+        }

+        return image;

+      case PVR_TYPE_AI8:

+        Image image = Image(width, height);

+        Uint8List out = image.getBytes();

+        int oi = 0;

+        for (int y = 0; y < height; ++y) {

+          for(int x = 0; x < width; ++x) {

+            int i = input.readByte();

+            int a = input.readByte();

+            out[oi++] = i;

+            out[oi++] = i;

+            out[oi++] = i;

+            out[oi++] = a;

+          }

+        }

+        return image;

+      case PVR_TYPE_PVRTC2:

+        // Currently unsupported

+        return null;

+      case PVR_TYPE_PVRTC4:

+        return amask == 0 ? decodeRgb4bpp(width, height, input.toUint8List()) :

+               decodeRgba4bpp(width, height, input.toUint8List());

+    }

+

+    // Unknown format

+    return null;

+  }

+

+  Image decodePVR3(List<int> data) {

+    //const int PVR3_PVRTC_2BPP_RGB = 0;

+    //const int PVR3_PVRTC_2BPP_RGBA = 1;

+    const int PVR3_PVRTC_4BPP_RGB = 2;

+    const int PVR3_PVRTC_4BPP_RGBA = 3;

+    /*const int PVR3_PVRTC2_2BPP = 4;

+    const int PVR3_PVRTC2_4BPP = 5;

+    const int PVR3_ETC1 = 6;

+    const int PVR3_DXT1 = 7;

+    const int PVR3_DXT2 = 8;

+    const int PVR3_DXT3 = 9;

+    const int PVR3_DXT4 = 10;

+    const int PVR3_DXT5 = 11;

+    const int PVR3_BC1 = 7;

+    const int PVR3_BC2 = 9;

+    const int PVR3_BC3 = 11;

+    const int PVR3_BC4 = 12;

+    const int PVR3_BC5 = 13;

+    const int PVR3_BC6 = 14;

+    const int PVR3_BC7 = 15;

+    const int PVR3_UYVY = 16;

+    const int PVR3_YUY2 = 17;

+    const int PVR3_BW_1BPP = 18;

+    const int PVR3_R9G9B9E5 = 19;

+    const int PVR3_RGBG8888 = 20;

+    const int PVR3_GRGB8888 = 21;

+    const int PVR3_ETC2_RGB = 22;

+    const int PVR3_ETC2_RGBA = 23;

+    const int PVR3_ETC2_RGB_A1 = 24;

+    const int PVR3_EAC_R11_U = 25;

+    const int PVR3_EAC_R11_S = 26;

+    const int PVR3_EAC_RG11_U = 27;

+    const int PVR3_EAC_RG11_S = 28;*/

+

+    InputBuffer input = InputBuffer(data);

+

+    // Header

+    int version = input.readUint32();

+    if (version != 0x03525650) {

+      return null;

+    }

+

+    /*int flags =*/ input.readUint32();

+    var format = input.readUint32();

+    var order = [input.readByte(), input.readByte(),

+                 input.readByte(), input.readByte()];

+    /*int colorspace =*/ input.readUint32();

+    /*int channeltype =*/ input.readUint32();

+    int height = input.readUint32();

+    int width = input.readUint32();

+    /*int depth =*/ input.readUint32();

+    /*int num_surfaces =*/ input.readUint32();

+    /*int num_faces =*/ input.readUint32();

+    /*int mipcount =*/ input.readUint32();

+    int metadata_size = input.readUint32();

+

+    input.skip(metadata_size);

+

+    if (order[0] == 0) {

+      switch (format) {

+        case PVR3_PVRTC_4BPP_RGB:

+          return decodeRgb4bpp(width, height, input.toUint8List());

+        case PVR3_PVRTC_4BPP_RGBA:

+          return decodeRgba4bpp(width, height, input.toUint8List());

+        /*case PVR3_PVRTC_2BPP_RGB:

+          return null;

+        case PVR3_PVRTC_2BPP_RGBA:

+          return null;

+        case PVR3_PVRTC2_2BPP:

+          return null;

+        case PVR3_PVRTC2_4BPP:

+          return null;

+        case PVR3_ETC1:

+          return null;

+        case PVR3_DXT1:

+          return null;

+        case PVR3_DXT2:

+          return null;

+        case PVR3_DXT3:

+          return null;

+        case PVR3_DXT4:

+          return null;

+        case PVR3_DXT5:

+          return null;

+        case PVR3_BC1:

+          return null;

+        case PVR3_BC2:

+          return null;

+        case PVR3_BC3:

+          return null;

+        case PVR3_BC4:

+          return null;

+        case PVR3_BC5:

+          return null;

+        case PVR3_BC6:

+          return null;

+        case PVR3_BC7:

+          return null;

+        case PVR3_UYVY:

+          return null;

+        case PVR3_YUY2:

+          return null;

+        case PVR3_BW_1BPP:

+          return null;

+        case PVR3_R9G9B9E5:

+          return null;

+        case PVR3_RGBG8888:

+          return null;

+        case PVR3_GRGB8888:

+          return null;

+        case PVR3_ETC2_RGB:

+          return null;

+        case PVR3_ETC2_RGBA:

+          return null;

+        case PVR3_ETC2_RGB_A1:

+          return null;

+        case PVR3_EAC_R11_U:

+          return null;

+        case PVR3_EAC_R11_S:

+          return null;

+        case PVR3_EAC_RG11_U:

+          return null;

+        case PVR3_EAC_RG11_S:

+          return null;*/

+      }

+    }

+

+    return null;

+  }

+

+  int _countBits(int x) {

+    x = (x - ((x >> 1) & 0x55555555)) & 0xffffffff;

+    x = ((x & 0x33333333) + ((x >> 2) & 0x33333333)) & 0xffffffff;

+    x = (x + (x >> 4)) & 0xffffffff;

+    x &= 0xf0f0f0f;

+    x = ((x * 0x01010101) & 0xffffffff) >> 24;

+    return x;

+  }

+

+  Image decodeRgb4bpp(int width, int height, TypedData data) {

+    var result = Image(width, height, Image.RGB);

+

+    final int blocks = width ~/ 4;

+    final int blockMask = blocks - 1;

+

+    final packet = PvrtcPacket(data);

+    final p0 = PvrtcPacket(data);

+    final p1 = PvrtcPacket(data);

+    final p2 = PvrtcPacket(data);

+    final p3 = PvrtcPacket(data);

+    final c = PvrtcColorRgb();

+    const factors = PvrtcPacket.BILINEAR_FACTORS;

+    const weights = PvrtcPacket.WEIGHTS;

+

+    for (int y = 0; y < blocks; ++y) {

+      for (int x = 0; x < blocks; ++x) {

+        packet.setBlock(x, y);

+

+        int mod = packet.modulationData;

+        int weightIndex = 4 * packet.usePunchthroughAlpha;

+        int factorIndex = 0;

+

+        for (int py = 0; py < 4; ++py) {

+          int yOffset = (py < 2) ? -1 : 0;

+          int y0 = (y + yOffset) & blockMask;

+          int y1 = (y0 + 1) & blockMask;

+          int pyi = (py + y * 4) * width;

+

+          for (int px = 0; px < 4; ++px) {

+            int xOffset = (px < 2) ? -1 : 0;

+            int x0 = (x + xOffset) & blockMask;

+            int x1 = (x0 + 1) & blockMask;

+

+            p0.setBlock(x0, y0);

+            p1.setBlock(x1, y0);

+            p2.setBlock(x0, y1);

+            p3.setBlock(x1, y1);

+

+            var ca = p0.getColorRgbA() * factors[factorIndex][0] +

+                     p1.getColorRgbA() * factors[factorIndex][1] +

+                     p2.getColorRgbA() * factors[factorIndex][2] +

+                     p3.getColorRgbA() * factors[factorIndex][3];

+

+            var cb = p0.getColorRgbB() * factors[factorIndex][0] +

+                     p1.getColorRgbB() * factors[factorIndex][1] +

+                     p2.getColorRgbB() * factors[factorIndex][2] +

+                     p3.getColorRgbB() * factors[factorIndex][3];

+

+            var w = weights[weightIndex + mod & 3];

+

+            c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;

+            c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;

+            c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;

+

+            int pi = (pyi + (px + x * 4));

+

+            result[pi] = getColor(c.r, c.g, c.b, 255);

+

+            mod >>= 2;

+            factorIndex++;

+          }

+        }

+      }

+    }

+

+    return result;

+  }

+

+  Image decodeRgba4bpp(int width, int height, TypedData data) {

+    var result = Image(width, height, Image.RGBA);

+

+    final int blocks = width ~/ 4;

+    final int blockMask = blocks - 1;

+

+    final packet = PvrtcPacket(data);

+    final p0 = PvrtcPacket(data);

+    final p1 = PvrtcPacket(data);

+    final p2 = PvrtcPacket(data);

+    final p3 = PvrtcPacket(data);

+    final c = PvrtcColorRgba();

+    const factors = PvrtcPacket.BILINEAR_FACTORS;

+    const weights = PvrtcPacket.WEIGHTS;

+

+    for (int y = 0; y < blocks; ++y) {

+      for (int x = 0; x < blocks; ++x) {

+        packet.setBlock(x, y);

+

+        int mod = packet.modulationData;

+        int weightIndex = 4 * packet.usePunchthroughAlpha;

+        int factorIndex = 0;

+

+        for (int py = 0; py < 4; ++py) {

+          int yOffset = (py < 2) ? -1 : 0;

+          int y0 = (y + yOffset) & blockMask;

+          int y1 = (y0 + 1) & blockMask;

+          int pyi = (py + y * 4) * width;

+

+          for (int px = 0; px < 4; ++px) {

+            int xOffset = (px < 2) ? -1 : 0;

+            int x0 = (x + xOffset) & blockMask;

+            int x1 = (x0 + 1) & blockMask;

+

+            p0.setBlock(x0, y0);

+            p1.setBlock(x1, y0);

+            p2.setBlock(x0, y1);

+            p3.setBlock(x1, y1);

+

+            var ca = p0.getColorRgbaA() * factors[factorIndex][0] +

+                     p1.getColorRgbaA() * factors[factorIndex][1] +

+                     p2.getColorRgbaA() * factors[factorIndex][2] +

+                     p3.getColorRgbaA() * factors[factorIndex][3];

+

+            var cb = p0.getColorRgbaB() * factors[factorIndex][0] +

+                     p1.getColorRgbaB() * factors[factorIndex][1] +

+                     p2.getColorRgbaB() * factors[factorIndex][2] +

+                     p3.getColorRgbaB() * factors[factorIndex][3];

+

+            var w = weights[weightIndex + mod & 3];

+

+            c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;

+            c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;

+            c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;

+            c.a = (ca.a * w[2] + cb.a * w[3]) >> 7;

+

+            int pi = (pyi + (px + x * 4));

+

+            result[pi] = getColor(c.r, c.g, c.b, c.a);

+

+            mod >>= 2;

+            factorIndex++;

+          }

+        }

+      }

+    }

+

+    return result;

+  }

+}

diff --git a/image/lib/src/formats/pvrtc/pvrtc_encoder.dart b/image/lib/src/formats/pvrtc/pvrtc_encoder.dart
old mode 100644
new mode 100755
index fd91dc7..ca1241d
--- a/image/lib/src/formats/pvrtc/pvrtc_encoder.dart
+++ b/image/lib/src/formats/pvrtc/pvrtc_encoder.dart
@@ -1,368 +1,368 @@
-import 'dart:typed_data';
-
-import '../../color.dart';
-import '../../image.dart';
-import '../../image_exception.dart';
-import '../../util/output_buffer.dart';
-import 'pvrtc_bit_utility.dart';
-import 'pvrtc_color.dart';
-import 'pvrtc_color_bounding_box.dart';
-import 'pvrtc_packet.dart';
-
-/**
- * Ported from Jeffrey Lim's PVRTC encoder/decoder,
- * https://bitbucket.org/jthlim/pvrtccompressor
- */
-class PvrtcEncoder {
-  // PVR Format
-  static const int PVR_AUTO = -1;
-  static const int PVR_RGB_2BPP = 0;
-  static const int PVR_RGBA_2BPP = 1;
-  static const int PVR_RGB_4BPP = 2;
-  static const int PVR_RGBA_4BPP = 3;
-
-  Uint8List encodePvr(Image bitmap, {int format: PVR_AUTO}) {
-    OutputBuffer output = new OutputBuffer();
-
-    var pvrtc;
-    if (format == PVR_AUTO) {
-       if (bitmap.format == Image.RGB) {
-        pvrtc = encodeRgb4Bpp(bitmap);
-        format = PVR_RGB_4BPP;
-      } else {
-        pvrtc = encodeRgba4Bpp(bitmap);
-        format = PVR_RGBA_4BPP;
-      }
-    } else if (format == PVR_RGB_2BPP) {
-      //pvrtc = encodeRgb2Bpp(bitmap);
-      pvrtc = encodeRgb4Bpp(bitmap);
-    } else if (format == PVR_RGBA_2BPP) {
-      //pvrtc = encodeRgba2Bpp(bitmap);
-      pvrtc = encodeRgba4Bpp(bitmap);
-    } else if (format == PVR_RGB_4BPP) {
-      pvrtc = encodeRgb4Bpp(bitmap);
-    } else if (format == PVR_RGBA_4BPP) {
-      pvrtc = encodeRgba4Bpp(bitmap);
-    }
-
-    int version = 55727696;
-    int flags = 0;
-    int pixelFormat = format;
-    int channelOrder = 0;
-    int colorSpace = 0;
-    int channelType = 0;
-    int height = bitmap.height;
-    int width = bitmap.width;
-    int depth = 1;
-    int numSurfaces = 1;
-    int numFaces = 1;
-    int mipmapCount = 1;
-    int metaDataSize = 0;
-
-    output.writeUint32(version);
-    output.writeUint32(flags);
-    output.writeUint32(pixelFormat);
-    output.writeUint32(channelOrder);
-    output.writeUint32(colorSpace);
-    output.writeUint32(channelType);
-    output.writeUint32(height);
-    output.writeUint32(width);
-    output.writeUint32(depth);
-    output.writeUint32(numSurfaces);
-    output.writeUint32(numFaces);
-    output.writeUint32(mipmapCount);
-    output.writeUint32(metaDataSize);
-
-    output.writeBytes(pvrtc);
-
-    return output.getBytes();
-  }
-
-  Uint8List encodeRgb4Bpp(Image bitmap) {
-    if (bitmap.width != bitmap.height) {
-      throw new ImageException('PVRTC requires a square image.');
-    }
-
-    if (!BitUtility.isPowerOf2(bitmap.width)) {
-      throw new ImageException('PVRTC requires a power-of-two sized image.');
-    }
-
-    final int size = bitmap.width;
-    final int blocks = size ~/ 4;
-    final int blockMask = blocks - 1;
-
-    var bitmapData = bitmap.getBytes();
-
-    // Allocate enough data for encoding the image.
-    var outputData = new Uint8List((bitmap.width * bitmap.height) ~/ 2);
-    var packet = new PvrtcPacket(outputData);
-    var p0 = new PvrtcPacket(outputData);
-    var p1 = new PvrtcPacket(outputData);
-    var p2 = new PvrtcPacket(outputData);
-    var p3 = new PvrtcPacket(outputData);
-
-    for (int y = 0; y < blocks; ++y) {
-      for (int x = 0; x < blocks; ++x) {
-        packet.setBlock(x, y);
-        packet.usePunchthroughAlpha = 0;
-        var cbb = _calculateBoundingBoxRgb(bitmap, x, y);
-        packet.setColorRgbA(cbb.min);
-        packet.setColorRgbB(cbb.max);
-      }
-    }
-
-    const factors = PvrtcPacket.BILINEAR_FACTORS;
-
-    for (int y = 0; y < blocks; ++y) {
-      for (int x = 0; x < blocks; ++x) {
-        int factorIndex = 0;
-        final pixelIndex = (y * 4 * size + x * 4) * 4;
-
-        int modulationData = 0;
-
-        for (int py = 0; py < 4; ++py) {
-          final int yOffset = (py < 2) ? -1 : 0;
-          final int y0 = (y + yOffset) & blockMask;
-          final int y1 = (y0 + 1) & blockMask;
-
-          for(int px = 0; px < 4; ++px) {
-            final int xOffset = (px < 2) ? -1 : 0;
-            final int x0 = (x + xOffset) & blockMask;
-            final int x1 = (x0 + 1) & blockMask;
-
-            p0.setBlock(x0, y0);
-            p1.setBlock(x1, y0);
-            p2.setBlock(x0, y1);
-            p3.setBlock(x1, y1);
-
-            var ca = p0.getColorRgbA() * factors[factorIndex][0] +
-                     p1.getColorRgbA() * factors[factorIndex][1] +
-                     p2.getColorRgbA() * factors[factorIndex][2] +
-                     p3.getColorRgbA() * factors[factorIndex][3];
-
-            var cb = p0.getColorRgbB() * factors[factorIndex][0] +
-                     p1.getColorRgbB() * factors[factorIndex][1] +
-                     p2.getColorRgbB() * factors[factorIndex][2] +
-                     p3.getColorRgbB() * factors[factorIndex][3];
-
-            int pi = pixelIndex + ((py * size + px) * 4);
-            int r = bitmapData[pi];
-            int g = bitmapData[pi + 1];
-            int b = bitmapData[pi + 2];
-
-            var d = cb - ca;
-            var p = new PvrtcColorRgb(r * 16, g * 16, b * 16);
-            var v = p - ca;
-
-            // PVRTC uses weightings of 0, 3/8, 5/8 and 1
-            // The boundaries for these are 3/16, 1/2 (=8/16), 13/16
-            int projection = v.dotProd(d) * 16;
-            int lengthSquared = d.dotProd(d);
-            if (projection > 3 * lengthSquared) {
-              modulationData++;
-            }
-            if (projection > 8 * lengthSquared) {
-              modulationData++;
-            }
-            if (projection > 13 * lengthSquared) {
-              modulationData++;
-            }
-
-            modulationData = BitUtility.rotateRight(modulationData, 2);
-
-            factorIndex++;
-          }
-        }
-
-        packet.setBlock(x, y);
-        packet.modulationData = modulationData;
-      }
-    }
-
-    return outputData;
-  }
-
-
-  Uint8List encodeRgba4Bpp(Image bitmap) {
-    if (bitmap.width != bitmap.height) {
-      throw new ImageException('PVRTC requires a square image.');
-    }
-
-    if (!BitUtility.isPowerOf2(bitmap.width)) {
-      throw new ImageException('PVRTC requires a power-of-two sized image.');
-    }
-
-    final int size = bitmap.width;
-    final int blocks = size ~/ 4;
-    final int blockMask = blocks - 1;
-
-    var bitmapData = bitmap.getBytes();
-
-    // Allocate enough data for encoding the image.
-    var outputData = new Uint8List((bitmap.width * bitmap.height) ~/ 2);
-    var packet = new PvrtcPacket(outputData);
-    var p0 = new PvrtcPacket(outputData);
-    var p1 = new PvrtcPacket(outputData);
-    var p2 = new PvrtcPacket(outputData);
-    var p3 = new PvrtcPacket(outputData);
-
-    for (int y = 0; y < blocks; ++y) {
-      for (int x = 0; x < blocks; ++x) {
-        packet.setBlock(x, y);
-        packet.usePunchthroughAlpha = 0;
-        var cbb = _calculateBoundingBoxRgba(bitmap, x, y);
-        packet.setColorRgbaA(cbb.min);
-        packet.setColorRgbaB(cbb.max);
-      }
-    }
-
-    const factors = PvrtcPacket.BILINEAR_FACTORS;
-
-    for (int y = 0; y < blocks; ++y) {
-      for (int x = 0; x < blocks; ++x) {
-        int factorIndex = 0;
-        final pixelIndex = (y * 4 * size + x * 4) * 4;
-
-        int modulationData = 0;
-
-        for (int py = 0; py < 4; ++py) {
-          final int yOffset = (py < 2) ? -1 : 0;
-          final int y0 = (y + yOffset) & blockMask;
-          final int y1 = (y0 + 1) & blockMask;
-
-          for(int px = 0; px < 4; ++px) {
-            final int xOffset = (px < 2) ? -1 : 0;
-            final int x0 = (x + xOffset) & blockMask;
-            final int x1 = (x0 + 1) & blockMask;
-
-            p0.setBlock(x0, y0);
-            p1.setBlock(x1, y0);
-            p2.setBlock(x0, y1);
-            p3.setBlock(x1, y1);
-
-            var ca = p0.getColorRgbaA() * factors[factorIndex][0] +
-                     p1.getColorRgbaA() * factors[factorIndex][1] +
-                     p2.getColorRgbaA() * factors[factorIndex][2] +
-                     p3.getColorRgbaA() * factors[factorIndex][3];
-
-            var cb = p0.getColorRgbaB() * factors[factorIndex][0] +
-                     p1.getColorRgbaB() * factors[factorIndex][1] +
-                     p2.getColorRgbaB() * factors[factorIndex][2] +
-                     p3.getColorRgbaB() * factors[factorIndex][3];
-
-            int pi = pixelIndex + ((py * size + px) * 4);
-            int r = bitmapData[pi];
-            int g = bitmapData[pi + 1];
-            int b = bitmapData[pi + 2];
-            int a = bitmapData[pi + 3];
-
-            var d = cb - ca;
-            var p = new PvrtcColorRgba(r * 16, g * 16, b * 16, a * 16);
-            var v = p - ca;
-
-            // PVRTC uses weightings of 0, 3/8, 5/8 and 1
-            // The boundaries for these are 3/16, 1/2 (=8/16), 13/16
-            int projection = v.dotProd(d) * 16;
-            int lengthSquared = d.dotProd(d);
-
-            if (projection > 3 * lengthSquared) {
-              modulationData++;
-            }
-            if (projection > 8 * lengthSquared) {
-              modulationData++;
-            }
-            if (projection > 13 * lengthSquared) {
-              modulationData++;
-            }
-
-            modulationData = BitUtility.rotateRight(modulationData, 2);
-
-            factorIndex++;
-          }
-        }
-
-        packet.setBlock(x, y);
-        packet.modulationData = modulationData;
-      }
-    }
-
-    return outputData;
-  }
-
-  static PvrtcColorBoundingBox _calculateBoundingBoxRgb(Image bitmap,
-                                                        int blockX,
-                                                        int blockY) {
-    int size = bitmap.width;
-    int pi = (blockY * 4 * size + blockX * 4);
-
-    _pixel(i) {
-      int c = bitmap[pi + i];
-      return new PvrtcColorRgb(getRed(c), getGreen(c), getBlue(c));
-    }
-
-    var cbb = new PvrtcColorBoundingBox(_pixel(0), _pixel(0));
-    cbb.add(_pixel(1));
-    cbb.add(_pixel(2));
-    cbb.add(_pixel(3));
-
-    cbb.add(_pixel(size));
-    cbb.add(_pixel(size + 1));
-    cbb.add(_pixel(size + 2));
-    cbb.add(_pixel(size + 3));
-
-    cbb.add(_pixel(2 * size));
-    cbb.add(_pixel(2 * size + 1));
-    cbb.add(_pixel(2 * size + 2));
-    cbb.add(_pixel(2 * size + 3));
-
-    cbb.add(_pixel(3 * size));
-    cbb.add(_pixel(3 * size + 1));
-    cbb.add(_pixel(3 * size + 2));
-    cbb.add(_pixel(3 * size + 3));
-
-    return cbb;
-  }
-
-  static PvrtcColorBoundingBox _calculateBoundingBoxRgba(Image bitmap,
-                                                         int blockX,
-                                                         int blockY) {
-    int size = bitmap.width;
-    int pi = (blockY * 4 * size + blockX * 4);
-
-    _pixel(i) {
-      int c = bitmap[pi + i];
-      return new PvrtcColorRgba(getRed(c), getGreen(c), getBlue(c), getAlpha(c));
-    }
-
-    var cbb = new PvrtcColorBoundingBox(_pixel(0), _pixel(0));
-    cbb.add(_pixel(1));
-    cbb.add(_pixel(2));
-    cbb.add(_pixel(3));
-
-    cbb.add(_pixel(size));
-    cbb.add(_pixel(size + 1));
-    cbb.add(_pixel(size + 2));
-    cbb.add(_pixel(size + 3));
-
-    cbb.add(_pixel(2 * size));
-    cbb.add(_pixel(2 * size + 1));
-    cbb.add(_pixel(2 * size + 2));
-    cbb.add(_pixel(2 * size + 3));
-
-    cbb.add(_pixel(3 * size));
-    cbb.add(_pixel(3 * size + 1));
-    cbb.add(_pixel(3 * size + 2));
-    cbb.add(_pixel(3 * size + 3));
-
-    return cbb;
-  }
-
-  /*static void _getPacket(packet, packetData, index) {
-    index *= 2;
-    packet.modulationData = packetData[index];
-    packet.colorData = packetData[index + 1];
-  }*/
-
-  static const MODULATION_LUT =
-      const [ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 ];
-}
+import 'dart:typed_data';

+

+import '../../color.dart';

+import '../../image.dart';

+import '../../image_exception.dart';

+import '../../util/output_buffer.dart';

+import 'pvrtc_bit_utility.dart';

+import 'pvrtc_color.dart';

+import 'pvrtc_color_bounding_box.dart';

+import 'pvrtc_packet.dart';

+

+/**

+ * Ported from Jeffrey Lim's PVRTC encoder/decoder,

+ * https://bitbucket.org/jthlim/pvrtccompressor

+ */

+class PvrtcEncoder {

+  // PVR Format

+  static const int PVR_AUTO = -1;

+  static const int PVR_RGB_2BPP = 0;

+  static const int PVR_RGBA_2BPP = 1;

+  static const int PVR_RGB_4BPP = 2;

+  static const int PVR_RGBA_4BPP = 3;

+

+  Uint8List encodePvr(Image bitmap, {int format: PVR_AUTO}) {

+    OutputBuffer output = OutputBuffer();

+

+    var pvrtc;

+    if (format == PVR_AUTO) {

+       if (bitmap.format == Image.RGB) {

+        pvrtc = encodeRgb4Bpp(bitmap);

+        format = PVR_RGB_4BPP;

+      } else {

+        pvrtc = encodeRgba4Bpp(bitmap);

+        format = PVR_RGBA_4BPP;

+      }

+    } else if (format == PVR_RGB_2BPP) {

+      //pvrtc = encodeRgb2Bpp(bitmap);

+      pvrtc = encodeRgb4Bpp(bitmap);

+    } else if (format == PVR_RGBA_2BPP) {

+      //pvrtc = encodeRgba2Bpp(bitmap);

+      pvrtc = encodeRgba4Bpp(bitmap);

+    } else if (format == PVR_RGB_4BPP) {

+      pvrtc = encodeRgb4Bpp(bitmap);

+    } else if (format == PVR_RGBA_4BPP) {

+      pvrtc = encodeRgba4Bpp(bitmap);

+    }

+

+    int version = 55727696;

+    int flags = 0;

+    int pixelFormat = format;

+    int channelOrder = 0;

+    int colorSpace = 0;

+    int channelType = 0;

+    int height = bitmap.height;

+    int width = bitmap.width;

+    int depth = 1;

+    int numSurfaces = 1;

+    int numFaces = 1;

+    int mipmapCount = 1;

+    int metaDataSize = 0;

+

+    output.writeUint32(version);

+    output.writeUint32(flags);

+    output.writeUint32(pixelFormat);

+    output.writeUint32(channelOrder);

+    output.writeUint32(colorSpace);

+    output.writeUint32(channelType);

+    output.writeUint32(height);

+    output.writeUint32(width);

+    output.writeUint32(depth);

+    output.writeUint32(numSurfaces);

+    output.writeUint32(numFaces);

+    output.writeUint32(mipmapCount);

+    output.writeUint32(metaDataSize);

+

+    output.writeBytes(pvrtc);

+

+    return output.getBytes();

+  }

+

+  Uint8List encodeRgb4Bpp(Image bitmap) {

+    if (bitmap.width != bitmap.height) {

+      throw new ImageException('PVRTC requires a square image.');

+    }

+

+    if (!BitUtility.isPowerOf2(bitmap.width)) {

+      throw new ImageException('PVRTC requires a power-of-two sized image.');

+    }

+

+    final int size = bitmap.width;

+    final int blocks = size ~/ 4;

+    final int blockMask = blocks - 1;

+

+    var bitmapData = bitmap.getBytes();

+

+    // Allocate enough data for encoding the image.

+    var outputData = Uint8List((bitmap.width * bitmap.height) ~/ 2);

+    var packet = PvrtcPacket(outputData);

+    var p0 = PvrtcPacket(outputData);

+    var p1 = PvrtcPacket(outputData);

+    var p2 = PvrtcPacket(outputData);

+    var p3 = PvrtcPacket(outputData);

+

+    for (int y = 0; y < blocks; ++y) {

+      for (int x = 0; x < blocks; ++x) {

+        packet.setBlock(x, y);

+        packet.usePunchthroughAlpha = 0;

+        var cbb = _calculateBoundingBoxRgb(bitmap, x, y);

+        packet.setColorRgbA(cbb.min);

+        packet.setColorRgbB(cbb.max);

+      }

+    }

+

+    const factors = PvrtcPacket.BILINEAR_FACTORS;

+

+    for (int y = 0; y < blocks; ++y) {

+      for (int x = 0; x < blocks; ++x) {

+        int factorIndex = 0;

+        final pixelIndex = (y * 4 * size + x * 4) * 4;

+

+        int modulationData = 0;

+

+        for (int py = 0; py < 4; ++py) {

+          final int yOffset = (py < 2) ? -1 : 0;

+          final int y0 = (y + yOffset) & blockMask;

+          final int y1 = (y0 + 1) & blockMask;

+

+          for(int px = 0; px < 4; ++px) {

+            final int xOffset = (px < 2) ? -1 : 0;

+            final int x0 = (x + xOffset) & blockMask;

+            final int x1 = (x0 + 1) & blockMask;

+

+            p0.setBlock(x0, y0);

+            p1.setBlock(x1, y0);

+            p2.setBlock(x0, y1);

+            p3.setBlock(x1, y1);

+

+            var ca = p0.getColorRgbA() * factors[factorIndex][0] +

+                     p1.getColorRgbA() * factors[factorIndex][1] +

+                     p2.getColorRgbA() * factors[factorIndex][2] +

+                     p3.getColorRgbA() * factors[factorIndex][3];

+

+            var cb = p0.getColorRgbB() * factors[factorIndex][0] +

+                     p1.getColorRgbB() * factors[factorIndex][1] +

+                     p2.getColorRgbB() * factors[factorIndex][2] +

+                     p3.getColorRgbB() * factors[factorIndex][3];

+

+            int pi = pixelIndex + ((py * size + px) * 4);

+            int r = bitmapData[pi];

+            int g = bitmapData[pi + 1];

+            int b = bitmapData[pi + 2];

+

+            var d = cb - ca;

+            var p = PvrtcColorRgb(r * 16, g * 16, b * 16);

+            var v = p - ca;

+

+            // PVRTC uses weightings of 0, 3/8, 5/8 and 1

+            // The boundaries for these are 3/16, 1/2 (=8/16), 13/16

+            int projection = v.dotProd(d) * 16;

+            int lengthSquared = d.dotProd(d);

+            if (projection > 3 * lengthSquared) {

+              modulationData++;

+            }

+            if (projection > 8 * lengthSquared) {

+              modulationData++;

+            }

+            if (projection > 13 * lengthSquared) {

+              modulationData++;

+            }

+

+            modulationData = BitUtility.rotateRight(modulationData, 2);

+

+            factorIndex++;

+          }

+        }

+

+        packet.setBlock(x, y);

+        packet.modulationData = modulationData;

+      }

+    }

+

+    return outputData;

+  }

+

+

+  Uint8List encodeRgba4Bpp(Image bitmap) {

+    if (bitmap.width != bitmap.height) {

+      throw new ImageException('PVRTC requires a square image.');

+    }

+

+    if (!BitUtility.isPowerOf2(bitmap.width)) {

+      throw new ImageException('PVRTC requires a power-of-two sized image.');

+    }

+

+    final int size = bitmap.width;

+    final int blocks = size ~/ 4;

+    final int blockMask = blocks - 1;

+

+    var bitmapData = bitmap.getBytes();

+

+    // Allocate enough data for encoding the image.

+    var outputData = Uint8List((bitmap.width * bitmap.height) ~/ 2);

+    var packet = PvrtcPacket(outputData);

+    var p0 = PvrtcPacket(outputData);

+    var p1 = PvrtcPacket(outputData);

+    var p2 = PvrtcPacket(outputData);

+    var p3 = PvrtcPacket(outputData);

+

+    for (int y = 0; y < blocks; ++y) {

+      for (int x = 0; x < blocks; ++x) {

+        packet.setBlock(x, y);

+        packet.usePunchthroughAlpha = 0;

+        var cbb = _calculateBoundingBoxRgba(bitmap, x, y);

+        packet.setColorRgbaA(cbb.min);

+        packet.setColorRgbaB(cbb.max);

+      }

+    }

+

+    const factors = PvrtcPacket.BILINEAR_FACTORS;

+

+    for (int y = 0; y < blocks; ++y) {

+      for (int x = 0; x < blocks; ++x) {

+        int factorIndex = 0;

+        final pixelIndex = (y * 4 * size + x * 4) * 4;

+

+        int modulationData = 0;

+

+        for (int py = 0; py < 4; ++py) {

+          final int yOffset = (py < 2) ? -1 : 0;

+          final int y0 = (y + yOffset) & blockMask;

+          final int y1 = (y0 + 1) & blockMask;

+

+          for(int px = 0; px < 4; ++px) {

+            final int xOffset = (px < 2) ? -1 : 0;

+            final int x0 = (x + xOffset) & blockMask;

+            final int x1 = (x0 + 1) & blockMask;

+

+            p0.setBlock(x0, y0);

+            p1.setBlock(x1, y0);

+            p2.setBlock(x0, y1);

+            p3.setBlock(x1, y1);

+

+            var ca = p0.getColorRgbaA() * factors[factorIndex][0] +

+                     p1.getColorRgbaA() * factors[factorIndex][1] +

+                     p2.getColorRgbaA() * factors[factorIndex][2] +

+                     p3.getColorRgbaA() * factors[factorIndex][3];

+

+            var cb = p0.getColorRgbaB() * factors[factorIndex][0] +

+                     p1.getColorRgbaB() * factors[factorIndex][1] +

+                     p2.getColorRgbaB() * factors[factorIndex][2] +

+                     p3.getColorRgbaB() * factors[factorIndex][3];

+

+            int pi = pixelIndex + ((py * size + px) * 4);

+            int r = bitmapData[pi];

+            int g = bitmapData[pi + 1];

+            int b = bitmapData[pi + 2];

+            int a = bitmapData[pi + 3];

+

+            var d = cb - ca;

+            var p = PvrtcColorRgba(r * 16, g * 16, b * 16, a * 16);

+            var v = p - ca;

+

+            // PVRTC uses weightings of 0, 3/8, 5/8 and 1

+            // The boundaries for these are 3/16, 1/2 (=8/16), 13/16

+            int projection = v.dotProd(d) * 16;

+            int lengthSquared = d.dotProd(d);

+

+            if (projection > 3 * lengthSquared) {

+              modulationData++;

+            }

+            if (projection > 8 * lengthSquared) {

+              modulationData++;

+            }

+            if (projection > 13 * lengthSquared) {

+              modulationData++;

+            }

+

+            modulationData = BitUtility.rotateRight(modulationData, 2);

+

+            factorIndex++;

+          }

+        }

+

+        packet.setBlock(x, y);

+        packet.modulationData = modulationData;

+      }

+    }

+

+    return outputData;

+  }

+

+  static PvrtcColorBoundingBox _calculateBoundingBoxRgb(Image bitmap,

+                                                        int blockX,

+                                                        int blockY) {

+    int size = bitmap.width;

+    int pi = (blockY * 4 * size + blockX * 4);

+

+    _pixel(i) {

+      int c = bitmap[pi + i];

+      return new PvrtcColorRgb(getRed(c), getGreen(c), getBlue(c));

+    }

+

+    var cbb = PvrtcColorBoundingBox(_pixel(0), _pixel(0));

+    cbb.add(_pixel(1));

+    cbb.add(_pixel(2));

+    cbb.add(_pixel(3));

+

+    cbb.add(_pixel(size));

+    cbb.add(_pixel(size + 1));

+    cbb.add(_pixel(size + 2));

+    cbb.add(_pixel(size + 3));

+

+    cbb.add(_pixel(2 * size));

+    cbb.add(_pixel(2 * size + 1));

+    cbb.add(_pixel(2 * size + 2));

+    cbb.add(_pixel(2 * size + 3));

+

+    cbb.add(_pixel(3 * size));

+    cbb.add(_pixel(3 * size + 1));

+    cbb.add(_pixel(3 * size + 2));

+    cbb.add(_pixel(3 * size + 3));

+

+    return cbb;

+  }

+

+  static PvrtcColorBoundingBox _calculateBoundingBoxRgba(Image bitmap,

+                                                         int blockX,

+                                                         int blockY) {

+    int size = bitmap.width;

+    int pi = (blockY * 4 * size + blockX * 4);

+

+    _pixel(i) {

+      int c = bitmap[pi + i];

+      return new PvrtcColorRgba(getRed(c), getGreen(c), getBlue(c), getAlpha(c));

+    }

+

+    var cbb = PvrtcColorBoundingBox(_pixel(0), _pixel(0));

+    cbb.add(_pixel(1));

+    cbb.add(_pixel(2));

+    cbb.add(_pixel(3));

+

+    cbb.add(_pixel(size));

+    cbb.add(_pixel(size + 1));

+    cbb.add(_pixel(size + 2));

+    cbb.add(_pixel(size + 3));

+

+    cbb.add(_pixel(2 * size));

+    cbb.add(_pixel(2 * size + 1));

+    cbb.add(_pixel(2 * size + 2));

+    cbb.add(_pixel(2 * size + 3));

+

+    cbb.add(_pixel(3 * size));

+    cbb.add(_pixel(3 * size + 1));

+    cbb.add(_pixel(3 * size + 2));

+    cbb.add(_pixel(3 * size + 3));

+

+    return cbb;

+  }

+

+  /*static void _getPacket(packet, packetData, index) {

+    index *= 2;

+    packet.modulationData = packetData[index];

+    packet.colorData = packetData[index + 1];

+  }*/

+

+  static const MODULATION_LUT =

+      const [ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 ];

+}

diff --git a/image/lib/src/formats/pvrtc/pvrtc_packet.dart b/image/lib/src/formats/pvrtc/pvrtc_packet.dart
old mode 100644
new mode 100755
index cabe1e6..71fc51d
--- a/image/lib/src/formats/pvrtc/pvrtc_packet.dart
+++ b/image/lib/src/formats/pvrtc/pvrtc_packet.dart
@@ -1,299 +1,299 @@
-import 'dart:typed_data';
-
-import 'pvrtc_bit_utility.dart';
-import 'pvrtc_color.dart';
-
-/**
- * Ported from Jeffrey Lim's PVRTC encoder/decoder,
- * https://bitbucket.org/jthlim/pvrtccompressor
- */
-class PvrtcPacket {
-  Uint32List rawData;
-  int index;
-
-  PvrtcPacket(TypedData data)
-      : rawData = new Uint32List.view(data.buffer);
-
-  void setBlock(int x, int y) => setIndex(_getMortonNumber(x, y));
-
-  void setIndex(int i) {
-    // A PvrtcPacket uses 2 uint32 values, so get the physical index
-    // from the logical index by multiplying by 2.
-    index = i << 1;
-    // Pull in the values from the raw data.
-    _update();
-  }
-
-  int get modulationData => rawData[index];
-
-  set modulationData(int x) => rawData[index] = x;
-
-  int get colorData => rawData[index + 1];
-
-  set colorData(int x) => rawData[index + 1] = x;
-
-  int get usePunchthroughAlpha => _usePunchthroughAlpha;
-
-  set usePunchthroughAlpha(int x) {
-    _usePunchthroughAlpha = x;
-    colorData = _getColorData();
-  }
-
-  int get colorA => _colorA;
-
-  set colorA(int x) {
-    _colorA = x;
-    colorData = _getColorData();
-  }
-
-  int get colorAIsOpaque => _colorAIsOpaque;
-
-  set colorAIsOpaque(int x) {
-    _colorAIsOpaque = x;
-    colorData = _getColorData();
-  }
-
-  int get colorB => _colorB;
-
-  set colorB(int x) {
-    _colorB = x;
-    colorData = _getColorData();
-  }
-
-  int get colorBIsOpaque => _colorBIsOpaque;
-
-  set colorBIsOpaque(int x) {
-    _colorBIsOpaque = x;
-    colorData = _getColorData();
-  }
-
-  void setColorRgbA(PvrtcColorRgb c) {
-    int r = BitUtility.BITSCALE_8_TO_5_FLOOR[c.r];
-    int g = BitUtility.BITSCALE_8_TO_5_FLOOR[c.g];
-    int b = BitUtility.BITSCALE_8_TO_4_FLOOR[c.b];
-    colorA = r << 9 | g << 4 | b;
-    colorAIsOpaque = 1;
-  }
-
-  void setColorRgbaA(PvrtcColorRgba c) {
-    int a = BitUtility.BITSCALE_8_TO_3_FLOOR[c.a];
-    if (a == 7) {
-      int r = BitUtility.BITSCALE_8_TO_5_FLOOR[c.r];
-      int g = BitUtility.BITSCALE_8_TO_5_FLOOR[c.g];
-      int b = BitUtility.BITSCALE_8_TO_4_FLOOR[c.b];
-      colorA = r << 9 | g << 4 | b;
-      colorAIsOpaque = 1;
-    } else {
-      int r = BitUtility.BITSCALE_8_TO_4_FLOOR[c.r];
-      int g = BitUtility.BITSCALE_8_TO_4_FLOOR[c.g];
-      int b = BitUtility.BITSCALE_8_TO_3_FLOOR[c.b];
-      colorA = a << 11 | r << 7 | g << 3 | b;
-      colorAIsOpaque = 0;
-    }
-  }
-
-  void setColorRgbB(PvrtcColorRgb c) {
-    int r = BitUtility.BITSCALE_8_TO_5_CEIL[c.r];
-    int g = BitUtility.BITSCALE_8_TO_5_CEIL[c.g];
-    int b = BitUtility.BITSCALE_8_TO_5_CEIL[c.b];
-    colorB = r << 10 | g << 5 | b;
-    colorBIsOpaque = 1;
-  }
-
-  void setColorRgbaB(PvrtcColorRgba c) {
-    int a = BitUtility.BITSCALE_8_TO_3_CEIL[c.a];
-    if (a == 7) {
-      int r = BitUtility.BITSCALE_8_TO_5_CEIL[c.r];
-      int g = BitUtility.BITSCALE_8_TO_5_CEIL[c.g];
-      int b = BitUtility.BITSCALE_8_TO_5_CEIL[c.b];
-      colorB = r << 10 | g << 5 | b;
-      colorBIsOpaque = 1;
-    } else {
-      int r = BitUtility.BITSCALE_8_TO_4_CEIL[c.r];
-      int g = BitUtility.BITSCALE_8_TO_4_CEIL[c.g];
-      int b = BitUtility.BITSCALE_8_TO_4_CEIL[c.b];
-      colorB = a << 12 | r << 8 | g << 4 | b;
-      colorBIsOpaque = 0;
-    }
-  }
-
-  PvrtcColorRgb getColorRgbA() {
-    if (colorAIsOpaque != 0) {
-      var r = colorA >> 9;
-      var g = colorA >> 4 & 0x1f;
-      var b = colorA & 0xf;
-      return new PvrtcColorRgb(BitUtility.BITSCALE_5_TO_8[r],
-          BitUtility.BITSCALE_5_TO_8[g],
-          BitUtility.BITSCALE_4_TO_8[b]);
-    } else {
-      var r = (colorA >> 7) & 0xf;
-      var g = (colorA >> 3) & 0xf;
-      var b = colorA & 7;
-      return new PvrtcColorRgb(BitUtility.BITSCALE_4_TO_8[r],
-          BitUtility.BITSCALE_4_TO_8[g],
-          BitUtility.BITSCALE_3_TO_8[b]);
-    }
-  }
-
-  PvrtcColorRgba getColorRgbaA() {
-    if (colorAIsOpaque != 0) {
-      var r = colorA >> 9;
-      var g = colorA >> 4 & 0x1f;
-      var b = colorA & 0xf;
-      return new PvrtcColorRgba(BitUtility.BITSCALE_5_TO_8[r],
-          BitUtility.BITSCALE_5_TO_8[g],
-          BitUtility.BITSCALE_4_TO_8[b],
-          255);
-    } else {
-      var a = colorA >> 11 & 7;
-      var r = (colorA >> 7) & 0xf;
-      var g = (colorA >> 3) & 0xf;
-      var b = colorA & 7;
-      return new PvrtcColorRgba(BitUtility.BITSCALE_4_TO_8[r],
-          BitUtility.BITSCALE_4_TO_8[g],
-          BitUtility.BITSCALE_3_TO_8[b],
-          BitUtility.BITSCALE_3_TO_8[a]);
-    }
-  }
-
-  PvrtcColorRgb getColorRgbB() {
-    if (colorBIsOpaque != 0) {
-      var r = colorB >> 10;
-      var g = colorB >> 5 & 0x1f;
-      var b = colorB & 0x1f;
-      return new PvrtcColorRgb(BitUtility.BITSCALE_5_TO_8[r],
-          BitUtility.BITSCALE_5_TO_8[g],
-          BitUtility.BITSCALE_5_TO_8[b]);
-    } else {
-      var r = colorB >> 8 & 0xf;
-      var g = colorB >> 4 & 0xf;
-      var b = colorB & 0xf;
-      return new PvrtcColorRgb(BitUtility.BITSCALE_4_TO_8[r],
-          BitUtility.BITSCALE_4_TO_8[g],
-          BitUtility.BITSCALE_4_TO_8[b]);
-    }
-  }
-
-  PvrtcColorRgba getColorRgbaB() {
-    if (colorBIsOpaque != 0) {
-      var r = colorB >> 10;
-      var g = colorB >> 5 & 0x1f;
-      var b = colorB & 0x1f;
-      return new PvrtcColorRgba(BitUtility.BITSCALE_5_TO_8[r],
-          BitUtility.BITSCALE_5_TO_8[g],
-          BitUtility.BITSCALE_5_TO_8[b],
-          255);
-    } else {
-      var a = colorB >> 12 & 7;
-      var r = colorB >> 8 & 0xf;
-      var g = colorB >> 4 & 0xf;
-      var b = colorB & 0xf;
-      return new PvrtcColorRgba(BitUtility.BITSCALE_4_TO_8[r],
-          BitUtility.BITSCALE_4_TO_8[g],
-          BitUtility.BITSCALE_4_TO_8[b],
-          BitUtility.BITSCALE_3_TO_8[a]);
-    }
-  }
-
-  int _usePunchthroughAlpha = 0;
-  int _colorA = 0;
-  int _colorAIsOpaque = 0;
-  int _colorB = 0;
-  int _colorBIsOpaque = 0;
-
-  int _getColorData() =>
-      ((usePunchthroughAlpha & 1)) |
-      ((colorA & BITS_14) << 1) |
-      ((colorAIsOpaque & 1) << 15) |
-      ((colorB & BITS_15) << 16) |
-      ((colorBIsOpaque & 1) << 31);
-
-  void _update() {
-    int x = colorData;
-    usePunchthroughAlpha = x & 1;
-    colorA = (x >> 1) & BITS_14;
-    colorAIsOpaque = (x >> 15) & 1;
-    colorB = (x >> 16) & BITS_15;
-    colorBIsOpaque = (x >> 31) & 1;
-  }
-
-  static int _getMortonNumber(int x, int y) {
-    return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 |
-           MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF];
-  }
-
-  static const BITS_14 = (1 << 14) - 1;
-  static const BITS_15 = (1 << 15) - 1;
-
-  static const BILINEAR_FACTORS = const [
-    const [ 4, 4, 4, 4 ],
-    const [ 2, 6, 2, 6 ],
-    const [ 8, 0, 8, 0 ],
-    const [ 6, 2, 6, 2 ],
-
-    const [ 2, 2, 6, 6 ],
-    const [ 1, 3, 3, 9 ],
-    const [ 4, 0, 12, 0 ],
-    const [ 3, 1, 9, 3 ],
-
-    const [ 8, 8, 0, 0 ],
-    const [ 4, 12, 0, 0 ],
-    const [ 16, 0, 0, 0 ],
-    const [ 12, 4, 0, 0 ],
-
-    const [ 6, 6, 2, 2 ],
-    const [ 3, 9, 1, 3 ],
-    const [ 12, 0, 4, 0 ],
-    const [ 9, 3, 3, 1 ],
-  ];
-
-  // Weights are { colorA, colorB, alphaA, alphaB }
-  static const WEIGHTS = const [
-    // Weights for Mode=0
-    const [ 8, 0, 8, 0 ],
-    const [ 5, 3, 5, 3 ],
-    const [ 3, 5, 3, 5 ],
-    const [ 0, 8, 0, 8 ],
-
-    // Weights for Mode=1
-    const [ 8, 0, 8, 0 ],
-    const [ 4, 4, 4, 4 ],
-    const [ 4, 4, 0, 0 ],
-    const [ 0, 8, 0, 8 ],
-  ];
-
-  static const MORTON_TABLE = const [
-        0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
-        0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
-        0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
-        0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
-        0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
-        0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
-        0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
-        0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
-        0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
-        0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
-        0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
-        0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
-        0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
-        0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
-        0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
-        0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
-        0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
-        0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
-        0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
-        0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
-        0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
-        0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
-        0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
-        0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
-        0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
-        0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
-        0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
-        0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
-        0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
-        0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
-        0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
-        0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
-    ];
-}
+import 'dart:typed_data';

+

+import 'pvrtc_bit_utility.dart';

+import 'pvrtc_color.dart';

+

+/**

+ * Ported from Jeffrey Lim's PVRTC encoder/decoder,

+ * https://bitbucket.org/jthlim/pvrtccompressor

+ */

+class PvrtcPacket {

+  Uint32List rawData;

+  int index;

+

+  PvrtcPacket(TypedData data)

+      : rawData = Uint32List.view(data.buffer);

+

+  void setBlock(int x, int y) => setIndex(_getMortonNumber(x, y));

+

+  void setIndex(int i) {

+    // A PvrtcPacket uses 2 uint32 values, so get the physical index

+    // from the logical index by multiplying by 2.

+    index = i << 1;

+    // Pull in the values from the raw data.

+    _update();

+  }

+

+  int get modulationData => rawData[index];

+

+  set modulationData(int x) => rawData[index] = x;

+

+  int get colorData => rawData[index + 1];

+

+  set colorData(int x) => rawData[index + 1] = x;

+

+  int get usePunchthroughAlpha => _usePunchthroughAlpha;

+

+  set usePunchthroughAlpha(int x) {

+    _usePunchthroughAlpha = x;

+    colorData = _getColorData();

+  }

+

+  int get colorA => _colorA;

+

+  set colorA(int x) {

+    _colorA = x;

+    colorData = _getColorData();

+  }

+

+  int get colorAIsOpaque => _colorAIsOpaque;

+

+  set colorAIsOpaque(int x) {

+    _colorAIsOpaque = x;

+    colorData = _getColorData();

+  }

+

+  int get colorB => _colorB;

+

+  set colorB(int x) {

+    _colorB = x;

+    colorData = _getColorData();

+  }

+

+  int get colorBIsOpaque => _colorBIsOpaque;

+

+  set colorBIsOpaque(int x) {

+    _colorBIsOpaque = x;

+    colorData = _getColorData();

+  }

+

+  void setColorRgbA(PvrtcColorRgb c) {

+    int r = BitUtility.BITSCALE_8_TO_5_FLOOR[c.r];

+    int g = BitUtility.BITSCALE_8_TO_5_FLOOR[c.g];

+    int b = BitUtility.BITSCALE_8_TO_4_FLOOR[c.b];

+    colorA = r << 9 | g << 4 | b;

+    colorAIsOpaque = 1;

+  }

+

+  void setColorRgbaA(PvrtcColorRgba c) {

+    int a = BitUtility.BITSCALE_8_TO_3_FLOOR[c.a];

+    if (a == 7) {

+      int r = BitUtility.BITSCALE_8_TO_5_FLOOR[c.r];

+      int g = BitUtility.BITSCALE_8_TO_5_FLOOR[c.g];

+      int b = BitUtility.BITSCALE_8_TO_4_FLOOR[c.b];

+      colorA = r << 9 | g << 4 | b;

+      colorAIsOpaque = 1;

+    } else {

+      int r = BitUtility.BITSCALE_8_TO_4_FLOOR[c.r];

+      int g = BitUtility.BITSCALE_8_TO_4_FLOOR[c.g];

+      int b = BitUtility.BITSCALE_8_TO_3_FLOOR[c.b];

+      colorA = a << 11 | r << 7 | g << 3 | b;

+      colorAIsOpaque = 0;

+    }

+  }

+

+  void setColorRgbB(PvrtcColorRgb c) {

+    int r = BitUtility.BITSCALE_8_TO_5_CEIL[c.r];

+    int g = BitUtility.BITSCALE_8_TO_5_CEIL[c.g];

+    int b = BitUtility.BITSCALE_8_TO_5_CEIL[c.b];

+    colorB = r << 10 | g << 5 | b;

+    colorBIsOpaque = 1;

+  }

+

+  void setColorRgbaB(PvrtcColorRgba c) {

+    int a = BitUtility.BITSCALE_8_TO_3_CEIL[c.a];

+    if (a == 7) {

+      int r = BitUtility.BITSCALE_8_TO_5_CEIL[c.r];

+      int g = BitUtility.BITSCALE_8_TO_5_CEIL[c.g];

+      int b = BitUtility.BITSCALE_8_TO_5_CEIL[c.b];

+      colorB = r << 10 | g << 5 | b;

+      colorBIsOpaque = 1;

+    } else {

+      int r = BitUtility.BITSCALE_8_TO_4_CEIL[c.r];

+      int g = BitUtility.BITSCALE_8_TO_4_CEIL[c.g];

+      int b = BitUtility.BITSCALE_8_TO_4_CEIL[c.b];

+      colorB = a << 12 | r << 8 | g << 4 | b;

+      colorBIsOpaque = 0;

+    }

+  }

+

+  PvrtcColorRgb getColorRgbA() {

+    if (colorAIsOpaque != 0) {

+      var r = colorA >> 9;

+      var g = colorA >> 4 & 0x1f;

+      var b = colorA & 0xf;

+      return new PvrtcColorRgb(BitUtility.BITSCALE_5_TO_8[r],

+          BitUtility.BITSCALE_5_TO_8[g],

+          BitUtility.BITSCALE_4_TO_8[b]);

+    } else {

+      var r = (colorA >> 7) & 0xf;

+      var g = (colorA >> 3) & 0xf;

+      var b = colorA & 7;

+      return new PvrtcColorRgb(BitUtility.BITSCALE_4_TO_8[r],

+          BitUtility.BITSCALE_4_TO_8[g],

+          BitUtility.BITSCALE_3_TO_8[b]);

+    }

+  }

+

+  PvrtcColorRgba getColorRgbaA() {

+    if (colorAIsOpaque != 0) {

+      var r = colorA >> 9;

+      var g = colorA >> 4 & 0x1f;

+      var b = colorA & 0xf;

+      return new PvrtcColorRgba(BitUtility.BITSCALE_5_TO_8[r],

+          BitUtility.BITSCALE_5_TO_8[g],

+          BitUtility.BITSCALE_4_TO_8[b],

+          255);

+    } else {

+      var a = colorA >> 11 & 7;

+      var r = (colorA >> 7) & 0xf;

+      var g = (colorA >> 3) & 0xf;

+      var b = colorA & 7;

+      return new PvrtcColorRgba(BitUtility.BITSCALE_4_TO_8[r],

+          BitUtility.BITSCALE_4_TO_8[g],

+          BitUtility.BITSCALE_3_TO_8[b],

+          BitUtility.BITSCALE_3_TO_8[a]);

+    }

+  }

+

+  PvrtcColorRgb getColorRgbB() {

+    if (colorBIsOpaque != 0) {

+      var r = colorB >> 10;

+      var g = colorB >> 5 & 0x1f;

+      var b = colorB & 0x1f;

+      return new PvrtcColorRgb(BitUtility.BITSCALE_5_TO_8[r],

+          BitUtility.BITSCALE_5_TO_8[g],

+          BitUtility.BITSCALE_5_TO_8[b]);

+    } else {

+      var r = colorB >> 8 & 0xf;

+      var g = colorB >> 4 & 0xf;

+      var b = colorB & 0xf;

+      return new PvrtcColorRgb(BitUtility.BITSCALE_4_TO_8[r],

+          BitUtility.BITSCALE_4_TO_8[g],

+          BitUtility.BITSCALE_4_TO_8[b]);

+    }

+  }

+

+  PvrtcColorRgba getColorRgbaB() {

+    if (colorBIsOpaque != 0) {

+      var r = colorB >> 10;

+      var g = colorB >> 5 & 0x1f;

+      var b = colorB & 0x1f;

+      return new PvrtcColorRgba(BitUtility.BITSCALE_5_TO_8[r],

+          BitUtility.BITSCALE_5_TO_8[g],

+          BitUtility.BITSCALE_5_TO_8[b],

+          255);

+    } else {

+      var a = colorB >> 12 & 7;

+      var r = colorB >> 8 & 0xf;

+      var g = colorB >> 4 & 0xf;

+      var b = colorB & 0xf;

+      return new PvrtcColorRgba(BitUtility.BITSCALE_4_TO_8[r],

+          BitUtility.BITSCALE_4_TO_8[g],

+          BitUtility.BITSCALE_4_TO_8[b],

+          BitUtility.BITSCALE_3_TO_8[a]);

+    }

+  }

+

+  int _usePunchthroughAlpha = 0;

+  int _colorA = 0;

+  int _colorAIsOpaque = 0;

+  int _colorB = 0;

+  int _colorBIsOpaque = 0;

+

+  int _getColorData() =>

+      ((usePunchthroughAlpha & 1)) |

+      ((colorA & BITS_14) << 1) |

+      ((colorAIsOpaque & 1) << 15) |

+      ((colorB & BITS_15) << 16) |

+      ((colorBIsOpaque & 1) << 31);

+

+  void _update() {

+    int x = colorData;

+    usePunchthroughAlpha = x & 1;

+    colorA = (x >> 1) & BITS_14;

+    colorAIsOpaque = (x >> 15) & 1;

+    colorB = (x >> 16) & BITS_15;

+    colorBIsOpaque = (x >> 31) & 1;

+  }

+

+  static int _getMortonNumber(int x, int y) {

+    return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 |

+           MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF];

+  }

+

+  static const BITS_14 = (1 << 14) - 1;

+  static const BITS_15 = (1 << 15) - 1;

+

+  static const BILINEAR_FACTORS = const [

+    const [ 4, 4, 4, 4 ],

+    const [ 2, 6, 2, 6 ],

+    const [ 8, 0, 8, 0 ],

+    const [ 6, 2, 6, 2 ],

+

+    const [ 2, 2, 6, 6 ],

+    const [ 1, 3, 3, 9 ],

+    const [ 4, 0, 12, 0 ],

+    const [ 3, 1, 9, 3 ],

+

+    const [ 8, 8, 0, 0 ],

+    const [ 4, 12, 0, 0 ],

+    const [ 16, 0, 0, 0 ],

+    const [ 12, 4, 0, 0 ],

+

+    const [ 6, 6, 2, 2 ],

+    const [ 3, 9, 1, 3 ],

+    const [ 12, 0, 4, 0 ],

+    const [ 9, 3, 3, 1 ],

+  ];

+

+  // Weights are { colorA, colorB, alphaA, alphaB }

+  static const WEIGHTS = const [

+    // Weights for Mode=0

+    const [ 8, 0, 8, 0 ],

+    const [ 5, 3, 5, 3 ],

+    const [ 3, 5, 3, 5 ],

+    const [ 0, 8, 0, 8 ],

+

+    // Weights for Mode=1

+    const [ 8, 0, 8, 0 ],

+    const [ 4, 4, 4, 4 ],

+    const [ 4, 4, 0, 0 ],

+    const [ 0, 8, 0, 8 ],

+  ];

+

+  static const MORTON_TABLE = const [

+        0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,

+        0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,

+        0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,

+        0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,

+        0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,

+        0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,

+        0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,

+        0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,

+        0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,

+        0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,

+        0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,

+        0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,

+        0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,

+        0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,

+        0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,

+        0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,

+        0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,

+        0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,

+        0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,

+        0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,

+        0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,

+        0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,

+        0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,

+        0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,

+        0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,

+        0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,

+        0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,

+        0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,

+        0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,

+        0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,

+        0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,

+        0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555

+    ];

+}

diff --git a/image/lib/src/formats/tga/tga_info.dart b/image/lib/src/formats/tga/tga_info.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/tga_decoder.dart b/image/lib/src/formats/tga_decoder.dart
old mode 100644
new mode 100755
index 7c73200..1bf9053
--- a/image/lib/src/formats/tga_decoder.dart
+++ b/image/lib/src/formats/tga_decoder.dart
@@ -18,7 +18,7 @@
    * Is the given file a valid TGA image?

    */

   bool isValidFile(List<int> data) {

-    InputBuffer input = new InputBuffer(data,

+    InputBuffer input = InputBuffer(data,

         bigEndian: true);

 

     InputBuffer header = input.readBytes(18);

@@ -33,8 +33,8 @@
   }

 

   DecodeInfo startDecode(List<int> data) {

-    info = new TgaInfo();

-    input = new InputBuffer(data, bigEndian: true);

+    info = TgaInfo();

+    input = InputBuffer(data, bigEndian: true);

 

     InputBuffer header = input.readBytes(18);

     if (header[2] != 2) {

@@ -60,7 +60,7 @@
     }

 

     input.offset = info.imageOffset;

-    Image image = new Image(info.width, info.height, Image.RGB);

+    Image image = Image(info.width, info.height, Image.RGB);

     for (int y = image.height - 1; y >= 0; --y) {

       for (int x = 0; x < image.width; ++x) {

         int b = input.readByte();

@@ -88,7 +88,7 @@
       return null;

     }

 

-    Animation anim = new Animation();

+    Animation anim = Animation();

     anim.width = image.width;

     anim.height = image.height;

     anim.addFrame(image);

diff --git a/image/lib/src/formats/tga_encoder.dart b/image/lib/src/formats/tga_encoder.dart
old mode 100644
new mode 100755
index 2287c67..7143fbd
--- a/image/lib/src/formats/tga_encoder.dart
+++ b/image/lib/src/formats/tga_encoder.dart
@@ -8,9 +8,9 @@
  */

 class TgaEncoder extends Encoder {

   List<int> encodeImage(Image image) {

-    OutputBuffer out = new OutputBuffer(bigEndian: true);

+    OutputBuffer out = OutputBuffer(bigEndian: true);

 

-    List<int> header = new List<int>(18);

+    List<int> header = List<int>(18);

     header.fillRange(0, 18, 0);

     header[2] = 2;

     header[12] = image.width & 0xff;

diff --git a/image/lib/src/formats/tiff/tiff_bit_reader.dart b/image/lib/src/formats/tiff/tiff_bit_reader.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/tiff/tiff_entry.dart b/image/lib/src/formats/tiff/tiff_entry.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/tiff/tiff_fax_decoder.dart b/image/lib/src/formats/tiff/tiff_fax_decoder.dart
old mode 100644
new mode 100755
index 9e8421c..097be05
--- a/image/lib/src/formats/tiff/tiff_fax_decoder.dart
+++ b/image/lib/src/formats/tiff/tiff_fax_decoder.dart
@@ -25,8 +25,8 @@
   int oneD;

 

   TiffFaxDecoder(this.fillOrder, this.width, this.height) {

-    prevChangingElems = new List<int>(width);

-    currChangingElems = new List<int>(width);

+    prevChangingElems = List<int>(width);

+    currChangingElems = List<int>(width);

   }

 

   /**

@@ -197,7 +197,7 @@
     int scanlineStride = (width + 7) ~/ 8;

 

     int a0, a1, b1, b2;

-    List<int> b = new List<int>(2);

+    List<int> b = List<int>(2);

     int entry, code, bits;

     bool isWhite;

     int currIndex = 0;

@@ -347,7 +347,7 @@
     List<int> temp;

 

     // Return values from getNextChangingElement

-    List<int> b = new List<int>(2);

+    List<int> b = List<int>(2);

 

     uncompressedMode = ((tiffT6Options & 0x02) >> 1);

 

diff --git a/image/lib/src/formats/tiff/tiff_image.dart b/image/lib/src/formats/tiff/tiff_image.dart
old mode 100644
new mode 100755
index 8c539de..5c3a8e3
--- a/image/lib/src/formats/tiff/tiff_image.dart
+++ b/image/lib/src/formats/tiff/tiff_image.dart
@@ -50,14 +50,14 @@
   HdrImage hdrImage;

 

   TiffImage(InputBuffer p) {

-    InputBuffer p3 = new InputBuffer.from(p);

+    InputBuffer p3 = InputBuffer.from(p);

 

     int numDirEntries = p.readUint16();

     for (int i = 0; i < numDirEntries; ++i) {

       int tag = p.readUint16();

       int type = p.readUint16();

       int numValues = p.readUint32();

-      TiffEntry entry = new TiffEntry(tag, type, numValues);

+      TiffEntry entry = TiffEntry(tag, type, numValues);

 

       // The value for the tag is either stored in another location,

       // or within the tag itself (if the size fits in 4 bytes).

@@ -223,7 +223,7 @@
                       compression != null;

 

   Image decode(InputBuffer p) {

-    image = new Image(width, height);

+    image = Image(width, height);

     for (int tileY = 0, ti = 0; tileY < tilesY; ++tileY) {

       for (int tileX = 0; tileX < tilesX; ++tileX, ++ti) {

         _decodeTile(p, tileX, tileY);

@@ -233,7 +233,7 @@
   }

 

   HdrImage decodeHdr(InputBuffer p) {

-    hdrImage = new HdrImage.create(width, height, 4, HdrImage.HALF);

+    hdrImage = HdrImage.create(width, height, 4, HdrImage.HALF);

       for (int tileY = 0, ti = 0; tileY < tilesY; ++tileY) {

         for (int tileX = 0; tileX < tilesX; ++tileX, ++ti) {

           _decodeTile(p, tileX, tileY);

@@ -270,8 +270,8 @@
         bdata = p;

 

       } else if (compression == COMPRESSION_LZW) {

-        bdata = new InputBuffer(new Uint8List(bytesInThisTile));

-        LzwDecoder decoder = new LzwDecoder();

+        bdata = InputBuffer(new Uint8List(bytesInThisTile));

+        LzwDecoder decoder = LzwDecoder();

         try {

           decoder.decode(new InputBuffer.from(p, offset: 0, length: byteCount),

                          bdata.buffer);

@@ -290,27 +290,27 @@
           }

         }

       } else if (compression == COMPRESSION_PACKBITS) {

-        bdata = new InputBuffer(new Uint8List(bytesInThisTile));

+        bdata = InputBuffer(new Uint8List(bytesInThisTile));

         _decodePackbits(p, bytesInThisTile, bdata.buffer);

 

       } else if (compression == COMPRESSION_DEFLATE) {

         List<int> data = p.toList(0, byteCount);

-        List<int> outData = new Inflate(data).getBytes();

-        bdata = new InputBuffer(outData);

+        List<int> outData = Inflate(data).getBytes();

+        bdata = InputBuffer(outData);

 

       } else if (compression == COMPRESSION_ZIP) {

         List<int> data = p.toList(0, byteCount);

-        List<int> outData = new ZLibDecoder().decodeBytes(data);

-        bdata = new InputBuffer(outData);

+        List<int> outData = ZLibDecoder().decodeBytes(data);

+        bdata = InputBuffer(outData);

       } else if (compression == COMPRESSION_OLD_JPEG) {

         if (image == null) {

-          image = new Image(width, height);

+          image = Image(width, height);

         }

         List<int> data = p.toList(0, byteCount);

-        Image tile = new JpegDecoder().decodeImage(data);

+        Image tile = JpegDecoder().decodeImage(data);

         _jpegToImage(tile, image, outX, outY, tileWidth, tileHeight);

         if (hdrImage != null) {

-          hdrImage = new HdrImage.fromImage(image);

+          hdrImage = HdrImage.fromImage(image);

         }

         return;

       } else {

@@ -540,12 +540,12 @@
       } else {

         bytesInThisTile = (tileWidth ~/ 8 + 1) * tileHeight;

       }

-      bdata = new InputBuffer(new Uint8List(tileWidth * tileHeight));

+      bdata = InputBuffer(new Uint8List(tileWidth * tileHeight));

       _decodePackbits(p, bytesInThisTile, bdata.buffer);

     } else if (compression == COMPRESSION_LZW) {

-      bdata = new InputBuffer(new Uint8List(tileWidth * tileHeight));

+      bdata = InputBuffer(new Uint8List(tileWidth * tileHeight));

 

-      LzwDecoder decoder = new LzwDecoder();

+      LzwDecoder decoder = LzwDecoder();

       decoder.decode(new InputBuffer.from(p, length: byteCount), bdata.buffer);

 

       // Horizontal Differencing Predictor

@@ -560,21 +560,21 @@
         }

       }

     } else if (compression == COMPRESSION_CCITT_RLE) {

-      bdata = new InputBuffer(new Uint8List(tileWidth * tileHeight));

+      bdata = InputBuffer(new Uint8List(tileWidth * tileHeight));

       try {

         new TiffFaxDecoder(fillOrder, tileWidth, tileHeight).

             decode1D(bdata, p, 0, tileHeight);

       } catch (_) {

       }

     } else if (compression == COMPRESSION_CCITT_FAX3) {

-      bdata = new InputBuffer(new Uint8List(tileWidth * tileHeight));

+      bdata = InputBuffer(new Uint8List(tileWidth * tileHeight));

       try {

         new TiffFaxDecoder(fillOrder, tileWidth, tileHeight).

             decode2D(bdata, p, 0, tileHeight, t4Options);

       } catch (_) {

       }

     } else if (compression == COMPRESSION_CCITT_FAX4) {

-      bdata = new InputBuffer(new Uint8List(tileWidth * tileHeight));

+      bdata = InputBuffer(new Uint8List(tileWidth * tileHeight));

       try {

         new TiffFaxDecoder(fillOrder, tileWidth, tileHeight).

             decodeT6(bdata, p, 0, tileHeight, t6Options);

@@ -582,12 +582,12 @@
       }

     } else if (compression == COMPRESSION_ZIP) {

       List<int> data = p.toList(0, byteCount);

-      List<int> outData = new ZLibDecoder().decodeBytes(data);

-      bdata = new InputBuffer(outData);

+      List<int> outData = ZLibDecoder().decodeBytes(data);

+      bdata = InputBuffer(outData);

     } else if (compression == COMPRESSION_DEFLATE) {

       List<int> data = p.toList(0, byteCount);

-      List<int> outData = new Inflate(data).getBytes();

-      bdata = new InputBuffer(outData);

+      List<int> outData = Inflate(data).getBytes();

+      bdata = InputBuffer(outData);

     } else if (compression == COMPRESSION_NONE) {

       bdata = p;

     } else {

@@ -598,7 +598,7 @@
       return;

     }

 

-    TiffBitReader br = new TiffBitReader(bdata);

+    TiffBitReader br = TiffBitReader(bdata);

     final int white = isWhiteZero ? 0xff000000 : 0xffffffff;

     final int black = isWhiteZero ? 0xffffffff : 0xff000000;

 

diff --git a/image/lib/src/formats/tiff/tiff_info.dart b/image/lib/src/formats/tiff/tiff_info.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/formats/tiff/tiff_lzw_decoder.dart b/image/lib/src/formats/tiff/tiff_lzw_decoder.dart
old mode 100644
new mode 100755
index d11d8a1..aaf0a6e
--- a/image/lib/src/formats/tiff/tiff_lzw_decoder.dart
+++ b/image/lib/src/formats/tiff/tiff_lzw_decoder.dart
@@ -114,8 +114,8 @@
    * Initialize the string table.

    */

   void _initializeStringTable() {

-    _table = new Uint8List(LZ_MAX_CODE + 1);

-    _prefix = new Uint32List(LZ_MAX_CODE + 1);

+    _table = Uint8List(LZ_MAX_CODE + 1);

+    _prefix = Uint32List(LZ_MAX_CODE + 1);

     _prefix.fillRange(0, _prefix.length, NO_SUCH_CODE);

 

     for (int i = 0; i < 256; i++) {

@@ -138,7 +138,7 @@
   List<int> _out;

   int _outPointer;

 

-  Uint8List _buffer = new Uint8List(4096);

+  Uint8List _buffer = Uint8List(4096);

   Uint8List _table;

   Uint32List _prefix;

   int _tableIndex;

diff --git a/image/lib/src/formats/tiff_decoder.dart b/image/lib/src/formats/tiff_decoder.dart
old mode 100644
new mode 100755
index 817bcfc..12ef08f
--- a/image/lib/src/formats/tiff_decoder.dart
+++ b/image/lib/src/formats/tiff_decoder.dart
@@ -23,7 +23,7 @@
    * If the file is not a valid Gif image, null is returned.

    */

   TiffInfo startDecode(List<int> bytes) {

-    _input = new InputBuffer(new Uint8List.fromList(bytes));

+    _input = InputBuffer(new Uint8List.fromList(bytes));

     info = _readHeader(_input);

     return info;

   }

@@ -55,7 +55,7 @@
    * decoding the file, null is returned.

    */

   Image decodeImage(List<int> data, {int frame: 0}) {

-    InputBuffer ptr = new InputBuffer(new Uint8List.fromList(data));

+    InputBuffer ptr = InputBuffer(new Uint8List.fromList(data));

 

     TiffInfo info = _readHeader(ptr);

     if (info == null) {

@@ -66,7 +66,7 @@
   }

 

   HdrImage decodeHdrImage(List<int> data, {int frame: 0}) {

-    InputBuffer ptr = new InputBuffer(new Uint8List.fromList(data));

+    InputBuffer ptr = InputBuffer(new Uint8List.fromList(data));

 

     TiffInfo info = _readHeader(ptr);

     if (info == null) {

@@ -86,7 +86,7 @@
       return null;

     }

 

-    Animation anim = new Animation();

+    Animation anim = Animation();

     anim.width = info.width;

     anim.height = info.height;

     anim.frameType = Animation.PAGE;

@@ -105,7 +105,7 @@
    * Read the TIFF header and IFD blocks.

    */

   TiffInfo _readHeader(InputBuffer p) {

-    TiffInfo info = new TiffInfo();

+    TiffInfo info = TiffInfo();

     int byteOrder = p.readUint16();

     if (byteOrder != TIFF_LITTLE_ENDIAN &&

         byteOrder != TIFF_BIG_ENDIAN) {

@@ -128,13 +128,13 @@
     int offset = p.readUint32();

     info.ifdOffset = offset;

 

-    InputBuffer p2 = new InputBuffer.from(p);

+    InputBuffer p2 = InputBuffer.from(p);

     p2.offset = offset;

 

     while (offset != 0) {

       TiffImage img;

       try {

-        img = new TiffImage(p2);

+        img = TiffImage(p2);

         if (!img.isValid) {

           break;

         }

diff --git a/image/lib/src/formats/webp/vp8.dart b/image/lib/src/formats/webp/vp8.dart
old mode 100644
new mode 100755
index 04682aa..9d27dfd
--- a/image/lib/src/formats/webp/vp8.dart
+++ b/image/lib/src/formats/webp/vp8.dart
@@ -1,1974 +1,1974 @@
-import 'dart:typed_data';
-
-import '../../image.dart';
-import '../../util/input_buffer.dart';
-import 'vp8_bit_reader.dart';
-import 'vp8_filter.dart';
-import 'vp8_types.dart';
-import 'webp_alpha.dart';
-import 'webp_info.dart';
-
-/**
- * WebP lossy format.
- */
-class VP8 {
-  InputBuffer input;
-  InternalWebPInfo _webp;
-
-  VP8(InputBuffer input, this._webp) :
-    this.input = input;
-
-  WebPInfo get webp => _webp;
-
-  bool decodeHeader() {
-    int bits = input.readUint24();
-
-    final bool keyFrame = (bits & 1) == 0;
-    if (!keyFrame) {
-      return false;
-    }
-
-    if (((bits >> 1) & 7) > 3) {
-      return false; // unknown profile
-    }
-
-    if (((bits >> 4) & 1) == 0) {
-      return false; // first frame is invisible!
-    }
-
-    _frameHeader.keyFrame = (bits & 1) == 0;
-    _frameHeader.profile = (bits >> 1) & 7;
-    _frameHeader.show = (bits >> 4) & 1;
-    _frameHeader.partitionLength = (bits >> 5);
-
-    int signature = input.readUint24();
-    if (signature != VP8_SIGNATURE) {
-      return false;
-    }
-
-    webp.width = input.readUint16();
-    webp.height = input.readUint16();
-
-    return true;
-  }
-
-  Image decode() {
-    if (!_getHeaders()) {
-      return null;
-    }
-
-    output = new Image(webp.width, webp.height);
-
-    // Will allocate memory and prepare everything.
-    if (!_initFrame()) {
-      return null;
-    }
-
-    // Main decoding loop
-    if (!_parseFrame()) {
-      return null;
-    }
-
-    return output;
-  }
-
-  bool _getHeaders() {
-    if (!decodeHeader()) {
-      return false;
-    }
-
-    _proba = new VP8Proba();
-    for (int i = 0; i < NUM_MB_SEGMENTS; ++i) {
-      _dqm[i] = new VP8QuantMatrix();
-    }
-
-    _picHeader.width = webp.width;
-    _picHeader.height = webp.height;
-    _picHeader.xscale = (webp.width >> 8) >> 6;
-    _picHeader.yscale = (webp.height >> 8) >> 6;
-
-    _cropTop = 0;
-    _cropLeft = 0;
-    _cropRight = webp.width;
-    _cropBottom = webp.height;
-
-    _mbWidth = (webp.width + 15) >> 4;
-    _mbHeight = (webp.height + 15) >> 4;
-
-    _segment = 0;
-
-    br = new VP8BitReader(input.subset(_frameHeader.partitionLength));
-    input.skip(_frameHeader.partitionLength);
-
-    _picHeader.colorspace = br.get();
-    _picHeader.clampType = br.get();
-
-    if (!_parseSegmentHeader(_segmentHeader, _proba)) {
-      return false;
-    }
-
-    // Filter specs
-    if (!_parseFilterHeader()) {
-      return false;
-    }
-
-    if (!_parsePartitions(input)) {
-      return false;
-    }
-
-    // quantizer change
-    _parseQuant();
-
-    // Frame buffer marking
-    br.get();   // ignore the value of update_proba_
-
-    _parseProba();
-
-    return true;
-  }
-
-  bool _parseSegmentHeader(VP8SegmentHeader hdr, VP8Proba proba) {
-    hdr.useSegment = br.get() != 0;
-    if (hdr.useSegment) {
-      hdr.updateMap = br.get() != 0;
-      if (br.get() != 0) {   // update data
-        hdr.absoluteDelta = br.get() != 0;
-        for (int s = 0; s < NUM_MB_SEGMENTS; ++s) {
-          hdr.quantizer[s] = br.get() != 0 ? br.getSignedValue(7) : 0;
-        }
-        for (int s = 0; s < NUM_MB_SEGMENTS; ++s) {
-          hdr.filterStrength[s] = br.get() != 0 ? br.getSignedValue(6) : 0;
-        }
-      }
-      if (hdr.updateMap) {
-        for (int s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
-          proba.segments[s] = br.get() != 0 ? br.getValue(8) : 255;
-        }
-      }
-    } else {
-      hdr.updateMap = false;
-    }
-
-    return true;
-  }
-
-  bool _parseFilterHeader() {
-    VP8FilterHeader hdr = _filterHeader;
-    hdr.simple = br.get() != 0;
-    hdr.level = br.getValue(6);
-    hdr.sharpness = br.getValue(3);
-    hdr.useLfDelta = br.get() != 0;
-    if (hdr.useLfDelta) {
-      if (br.get() != 0) {   // update lf-delta?
-        for (int i = 0; i < NUM_REF_LF_DELTAS; ++i) {
-          if (br.get() != 0) {
-            hdr.refLfDelta[i] = br.getSignedValue(6);
-          }
-        }
-
-        for (int i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
-          if (br.get() != 0) {
-            hdr.modeLfDelta[i] = br.getSignedValue(6);
-          }
-        }
-      }
-    }
-
-    _filterType = (hdr.level == 0) ? 0 : hdr.simple ? 1 : 2;
-
-    return true;
-  }
-
-  /**
-   * This function returns VP8_STATUS_SUSPENDED if we don't have all the
-   * necessary data in 'buf'.
-   * This case is not necessarily an error (for incremental decoding).
-   * Still, no bitreader is ever initialized to make it possible to read
-   * unavailable memory.
-   * If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA
-   * is returned, and this is an unrecoverable error.
-   * If the partitions were positioned ok, VP8_STATUS_OK is returned.
-   */
-  bool _parsePartitions(InputBuffer input) {
-    int sz = 0;
-    int bufEnd = input.length;
-
-    _numPartitions = 1 << br.getValue(2);
-    int lastPart = _numPartitions - 1;
-    int partStart = lastPart * 3;
-    if (bufEnd < partStart) {
-      // we can't even read the sizes with sz[]! That's a failure.
-      return false;
-    }
-
-    for (int p = 0; p < lastPart; ++p) {
-      InputBuffer szb = input.peekBytes(3, sz);
-      final int psize = szb[0] | (szb[1] << 8) | (szb[2] << 16);
-      int partEnd = partStart + psize;
-      if (partEnd > bufEnd) {
-        partEnd = bufEnd;
-      }
-
-      InputBuffer pin = input.subset(partEnd - partStart, position: partStart);
-      _partitions[p] = new VP8BitReader(pin);
-      partStart = partEnd;
-      sz += 3;
-    }
-
-    InputBuffer pin = input.subset(bufEnd - partStart,
-                                   position: input.position + partStart);
-    _partitions[lastPart] = new VP8BitReader(pin);
-
-    // Init is ok, but there's not enough data
-    return (partStart < bufEnd) ? true : false;
-  }
-
-  void _parseQuant() {
-    final int base_q0 = br.getValue(7);
-    final int dqy1_dc = br.get() != 0 ? br.getSignedValue(4) : 0;
-    final int dqy2_dc = br.get() != 0 ? br.getSignedValue(4) : 0;
-    final int dqy2_ac = br.get() != 0 ? br.getSignedValue(4) : 0;
-    final int dquv_dc = br.get() != 0 ? br.getSignedValue(4) : 0;
-    final int dquv_ac = br.get() != 0 ? br.getSignedValue(4) : 0;
-
-    VP8SegmentHeader hdr = _segmentHeader;
-
-    for (int i = 0; i < NUM_MB_SEGMENTS; ++i) {
-      int q;
-      if (hdr.useSegment) {
-        q = hdr.quantizer[i];
-        if (!hdr.absoluteDelta) {
-          q += base_q0;
-        }
-      } else {
-        if (i > 0) {
-          _dqm[i] = _dqm[0];
-          continue;
-        } else {
-          q = base_q0;
-        }
-      }
-
-      VP8QuantMatrix m = _dqm[i];
-      m.y1Mat[0] = DC_TABLE[_clip(q + dqy1_dc, 127)];
-      m.y1Mat[1] = AC_TABLE[_clip(q + 0,       127)];
-
-      m.y2Mat[0] = DC_TABLE[_clip(q + dqy2_dc, 127)] * 2;
-      // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16.
-      // The smallest precision for that is '(x*6349) >> 12' but 16 is a good
-      // word size.
-      m.y2Mat[1] = (AC_TABLE[_clip(q + dqy2_ac, 127)] * 101581) >> 16;
-      if (m.y2Mat[1] < 8) {
-        m.y2Mat[1] = 8;
-      }
-
-      m.uvMat[0] = DC_TABLE[_clip(q + dquv_dc, 117)];
-      m.uvMat[1] = AC_TABLE[_clip(q + dquv_ac, 127)];
-
-      m.uvQuant = q + dquv_ac;   // for dithering strength evaluation
-    }
-  }
-
-  void _parseProba() {
-    VP8Proba proba = _proba;
-    for (int t = 0; t < NUM_TYPES; ++t) {
-      for (int b = 0; b < NUM_BANDS; ++b) {
-        for (int c = 0; c < NUM_CTX; ++c) {
-          for (int p = 0; p < NUM_PROBAS; ++p) {
-            final int v = br.getBit(COEFFS_UPDATE_PROBA[t][b][c][p]) != 0 ?
-                br.getValue(8) : COEFFS_PROBA_0[t][b][c][p];
-                proba.bands[t][b].probas[c][p] = v;
-          }
-        }
-      }
-    }
-
-    _useSkipProba = br.get() != 0;
-    if (_useSkipProba) {
-      _skipP = br.getValue(8);
-    }
-  }
-
-  /**
-   * Precompute the filtering strength for each segment and each i4x4/i16x16
-   * mode.
-   */
-  void _precomputeFilterStrengths() {
-    if (_filterType > 0) {
-      VP8FilterHeader hdr = _filterHeader;
-      for (int s = 0; s < NUM_MB_SEGMENTS; ++s) {
-        // First, compute the initial level
-        int baseLevel;
-        if (_segmentHeader.useSegment) {
-          baseLevel = _segmentHeader.filterStrength[s];
-          if (!_segmentHeader.absoluteDelta) {
-            baseLevel += hdr.level;
-          }
-        } else {
-          baseLevel = hdr.level;
-        }
-
-        for (int i4x4 = 0; i4x4 <= 1; ++i4x4) {
-          VP8FInfo info = _fStrengths[s][i4x4];
-          int level = baseLevel;
-          if (hdr.useLfDelta) {
-            level += hdr.refLfDelta[0];
-            if (i4x4 != 0) {
-              level += hdr.modeLfDelta[0];
-            }
-          }
-
-          level = (level < 0) ? 0 : (level > 63) ? 63 : level;
-          if (level > 0) {
-            int ilevel = level;
-            if (hdr.sharpness > 0) {
-              if (hdr.sharpness > 4) {
-                ilevel >>= 2;
-              } else {
-                ilevel >>= 1;
-              }
-
-              if (ilevel > 9 - hdr.sharpness) {
-                ilevel = 9 - hdr.sharpness;
-              }
-            }
-
-            if (ilevel < 1) {
-              ilevel = 1;
-            }
-
-            info.fInnerLevel = ilevel;
-            info.fLimit = 2 * level + ilevel;
-            info.hevThresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
-          } else {
-            info.fLimit = 0;  // no filtering
-          }
-
-          info.fInner = i4x4 != 0;
-        }
-      }
-    }
-  }
-
-  bool _initFrame() {
-    if (_webp.alphaData != null) {
-      _alphaData = _webp.alphaData;
-    }
-
-    _fStrengths = new List<List<VP8FInfo>>(NUM_MB_SEGMENTS);
-    for (int i = 0; i < NUM_MB_SEGMENTS; ++i) {
-      _fStrengths[i] = [new VP8FInfo(), new VP8FInfo()];
-    }
-
-    _yuvT = new List<VP8TopSamples>(_mbWidth);
-    for (int i = 0; i < _mbWidth; ++i) {
-      _yuvT[i] = new VP8TopSamples();
-    }
-
-    _yuvBlock = new Uint8List(YUV_SIZE);
-
-    _intraT = new Uint8List(4 * _mbWidth);
-
-    _cacheYStride = 16 * _mbWidth;
-    _cacheUVStride = 8 * _mbWidth;
-
-    final int extra_rows = FILTER_EXTRA_ROWS[_filterType];
-    final int extra_y = extra_rows * _cacheYStride;
-    final int extra_uv = (extra_rows ~/ 2) * _cacheUVStride;
-
-    _cacheY = new InputBuffer(new Uint8List(16 * _cacheYStride + extra_y),
-                         offset: extra_y);
-
-    _cacheU = new InputBuffer(new Uint8List(8 * _cacheUVStride + extra_uv),
-                         offset: extra_uv);
-
-    _cacheV = new InputBuffer(new Uint8List(8 * _cacheUVStride + extra_uv),
-                         offset: extra_uv);
-
-    _tmpY = new InputBuffer(new Uint8List(webp.width));
-
-    final int uvWidth = (webp.width + 1) >> 1;
-    _tmpU = new InputBuffer(new Uint8List(uvWidth));
-    _tmpV = new InputBuffer(new Uint8List(uvWidth));
-
-    // Define the area where we can skip in-loop filtering, in case of cropping.
-    //
-    // 'Simple' filter reads two luma samples outside of the macroblock
-    // and filters one. It doesn't filter the chroma samples. Hence, we can
-    // avoid doing the in-loop filtering before crop_top/crop_left position.
-    // For the 'Complex' filter, 3 samples are read and up to 3 are filtered.
-    // Means: there's a dependency chain that goes all the way up to the
-    // top-left corner of the picture (MB #0). We must filter all the previous
-    // macroblocks.
-    {
-      final int extraPixels = FILTER_EXTRA_ROWS[_filterType];
-      if (_filterType == 2) {
-        // For complex filter, we need to preserve the dependency chain.
-        _tlMbX = 0;
-        _tlMbY = 0;
-      } else {
-        // For simple filter, we can filter only the cropped region.
-        // We include 'extra_pixels' on the other side of the boundary, since
-        // vertical or horizontal filtering of the previous macroblock can
-        // modify some abutting pixels.
-        _tlMbX = (_cropLeft - extraPixels) ~/ 16;
-        _tlMbY = (_cropTop - extraPixels) ~/ 16;
-        if (_tlMbX < 0) {
-          _tlMbX = 0;
-        }
-        if (_tlMbY < 0) {
-          _tlMbY = 0;
-        }
-      }
-
-      // We need some 'extra' pixels on the right/bottom.
-      _brMbY = (_cropBottom + 15 + extraPixels) ~/ 16;
-      _brMbX = (_cropRight + 15 + extraPixels) ~/ 16;
-      if (_brMbX > _mbWidth) {
-        _brMbX = _mbWidth;
-      }
-      if (_brMbY > _mbHeight) {
-        _brMbY = _mbHeight;
-      }
-    }
-
-    _mbInfo = new List<VP8MB>(_mbWidth + 1);
-    _mbData = new List<VP8MBData>(_mbWidth);
-    _fInfo = new List<VP8FInfo>(_mbWidth);
-
-    for (int i = 0; i < _mbWidth; ++i) {
-      _mbInfo[i] = new VP8MB();
-      _mbData[i] = new VP8MBData();
-    }
-    _mbInfo[_mbWidth] = new VP8MB();
-
-    _precomputeFilterStrengths();
-
-    // Init critical function pointers and look-up tables.
-    _dsp = new VP8Filter();
-    return true;
-  }
-
-  bool _parseFrame() {
-    for (_mbY = 0; _mbY < _brMbY; ++_mbY) {
-      // Parse bitstream for this row.
-      VP8BitReader tokenBr = _partitions[_mbY & (_numPartitions - 1)];
-      for (; _mbX < _mbWidth; ++_mbX) {
-        if (!_decodeMB(tokenBr)) {
-          return false;
-        }
-      }
-
-      // Prepare for next scanline
-      VP8MB left = _mbInfo[0];
-      left.nz = 0;
-      left.nzDc = 0;
-      _intraL.fillRange(0, _intraL.length, B_DC_PRED);
-      _mbX = 0;
-
-      // Reconstruct, filter and emit the row.
-      if (!_processRow()) {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  bool _processRow() {
-    _reconstructRow();
-
-    bool useFilter = (_filterType > 0) && (_mbY >= _tlMbY) && (_mbY <= _brMbY);
-    return _finishRow(useFilter);
-  }
-
-  void _reconstructRow() {
-    int mb_y = _mbY;
-    InputBuffer y_dst = new InputBuffer(_yuvBlock, offset: Y_OFF);
-    InputBuffer u_dst = new InputBuffer(_yuvBlock, offset: U_OFF);
-    InputBuffer v_dst = new InputBuffer(_yuvBlock, offset: V_OFF);
-
-    for (int mb_x = 0; mb_x < _mbWidth; ++mb_x) {
-      VP8MBData block = _mbData[mb_x];
-
-      // Rotate in the left samples from previously decoded block. We move four
-      // pixels at a time for alignment reason, and because of in-loop filter.
-      if (mb_x > 0) {
-        for (int j = -1; j < 16; ++j) {
-          y_dst.memcpy(j * BPS - 4, 4, y_dst, j * BPS + 12);
-        }
-
-        for (int j = -1; j < 8; ++j) {
-          u_dst.memcpy(j * BPS - 4, 4, u_dst, j * BPS + 4);
-          v_dst.memcpy(j * BPS - 4, 4, v_dst, j * BPS + 4);
-        }
-      } else {
-        for (int j = 0; j < 16; ++j) {
-          y_dst[j * BPS - 1] = 129;
-        }
-
-        for (int j = 0; j < 8; ++j) {
-          u_dst[j * BPS - 1] = 129;
-          v_dst[j * BPS - 1] = 129;
-        }
-
-        // Init top-left sample on left column too
-        if (mb_y > 0) {
-          y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129;
-        }
-      }
-
-      // bring top samples into the cache
-      VP8TopSamples top_yuv = _yuvT[mb_x];
-      Int16List coeffs = block.coeffs;
-      int bits = block.nonZeroY;
-
-      if (mb_y > 0) {
-        y_dst.memcpy(-BPS, 16, top_yuv.y);
-        u_dst.memcpy(-BPS, 8, top_yuv.u);
-        v_dst.memcpy(-BPS, 8, top_yuv.v);
-      } else if (mb_x == 0) {
-        // we only need to do this init once at block (0,0).
-        // Afterward, it remains valid for the whole topmost row.
-        y_dst.memset(-BPS - 1, 16 + 4 + 1, 127);
-        u_dst.memset(-BPS - 1, 8 + 1, 127);
-        v_dst.memset(-BPS - 1, 8 + 1, 127);
-      }
-
-      // predict and add residuals
-      if (block.isIntra4x4) {   // 4x4
-        InputBuffer topRight = new InputBuffer.from(y_dst, offset: -BPS + 16);
-        Uint32List topRight32 = topRight.toUint32List();
-
-        if (mb_y > 0) {
-          if (mb_x >= _mbWidth - 1) { // on rightmost border
-            topRight.memset(0, 4, top_yuv.y[15]);
-          } else {
-            topRight.memcpy(0, 4, _yuvT[mb_x + 1].y);
-          }
-        }
-
-        // replicate the top-right pixels below
-        int p = topRight32[0];
-        topRight32[3 * BPS] = p;
-        topRight32[2 * BPS] = p;
-        topRight32[BPS] = p;
-
-        // predict and add residuals for all 4x4 blocks in turn.
-        for (int n = 0; n < 16; ++n, bits = (bits << 2) & 0xffffffff) {
-          InputBuffer dst = new InputBuffer.from(y_dst, offset: kScan[n]);
-
-          VP8Filter.PredLuma4[block.imodes[n]](dst);
-
-          _doTransform(bits, new InputBuffer(coeffs, offset: n * 16), dst);
-        }
-      } else { // 16x16
-        int predFunc = _checkMode(mb_x, mb_y, block.imodes[0]);
-
-        VP8Filter.PredLuma16[predFunc](y_dst);
-        if (bits != 0) {
-          for (int n = 0; n < 16; ++n, bits = (bits << 2) & 0xffffffff) {
-            InputBuffer dst = new InputBuffer.from(y_dst, offset: kScan[n]);
-
-            _doTransform(bits, new InputBuffer(coeffs, offset: n * 16), dst);
-          }
-        }
-      }
-
-      // Chroma
-      int bits_uv = block.nonZeroUV;
-      int pred_func = _checkMode(mb_x, mb_y, block.uvmode);
-      VP8Filter.PredChroma8[pred_func](u_dst);
-      VP8Filter.PredChroma8[pred_func](v_dst);
-
-      InputBuffer c1 = new InputBuffer(coeffs, offset: 16 * 16);
-      _doUVTransform(bits_uv, c1, u_dst);
-
-      InputBuffer c2 = new InputBuffer(coeffs, offset: 20 * 16);
-      _doUVTransform(bits_uv >> 8, c2, v_dst);
-
-      // stash away top samples for next block
-      if (mb_y < _mbHeight - 1) {
-        top_yuv.y.setRange(0, 16, y_dst.toUint8List(), 15 * BPS);
-        top_yuv.u.setRange(0, 8, u_dst.toUint8List(), 7 * BPS);
-        top_yuv.v.setRange(0, 8, v_dst.toUint8List(), 7 * BPS);
-      }
-
-      // Transfer reconstructed samples from yuv_b_ cache to final destination.
-      int y_out = mb_x * 16; // dec->cache_y_ +
-      int u_out = mb_x * 8; // dec->cache_u_ +
-      int v_out = mb_x * 8; // _dec->cache_v_ +
-
-      for (int j = 0; j < 16; ++j) {
-        int start = y_out + j * _cacheYStride;
-        _cacheY.memcpy(start, 16, y_dst, j * BPS);
-      }
-
-      for (int j = 0; j < 8; ++j) {
-        int start = u_out + j * _cacheUVStride;
-        _cacheU.memcpy(start, 8, u_dst, j * BPS);
-
-        start = v_out + j * _cacheUVStride;
-        _cacheV.memcpy(start, 8, v_dst, j * BPS);
-      }
-    }
-  }
-
-  static const List<int> kScan = const [
-    0 +  0 * BPS,  4 +  0 * BPS, 8 +  0 * BPS, 12 +  0 * BPS,
-    0 +  4 * BPS,  4 +  4 * BPS, 8 +  4 * BPS, 12 +  4 * BPS,
-    0 +  8 * BPS,  4 +  8 * BPS, 8 +  8 * BPS, 12 +  8 * BPS,
-    0 + 12 * BPS,  4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS ];
-
-  static int _checkMode(int mb_x, int mb_y, int mode) {
-    if (mode == B_DC_PRED) {
-      if (mb_x == 0) {
-        return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT;
-      } else {
-        return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED;
-      }
-    }
-    return mode;
-  }
-
-  void _doTransform(int bits, InputBuffer src, InputBuffer dst) {
-    switch (bits >> 30) {
-      case 3:
-        _dsp.transform(src, dst, false);
-        break;
-      case 2:
-        _dsp.transformAC3(src, dst);
-        break;
-      case 1:
-        _dsp.transformDC(src, dst);
-        break;
-      default:
-        break;
-    }
-  }
-
-  void _doUVTransform(int bits, InputBuffer src, InputBuffer dst) {
-    if (bits & 0xff != 0) { // any non-zero coeff at all?
-      if (bits & 0xaa != 0) { // any non-zero AC coefficient?
-        // note we don't use the AC3 variant for U/V
-        _dsp.transformUV(src, dst);
-      } else {
-        _dsp.transformDCUV(src, dst);
-      }
-    }
-  }
-
-  // vertical position of a MB
-  int MACROBLOCK_VPOS(int mb_y) => mb_y * 16;
-
-  /**
-   * kFilterExtraRows[] = How many extra lines are needed on the MB boundary
-   * for caching, given a filtering level.
-   * Simple filter:  up to 2 luma samples are read and 1 is written.
-   * Complex filter: up to 4 luma samples are read and 3 are written. Same for
-   *                U/V, so it's 8 samples total (because of the 2x upsampling).
-   */
-  static const List<int> kFilterExtraRows = const [ 0, 2, 8 ];
-
-  void _doFilter(int mbX, int mbY) {
-    final int yBps = _cacheYStride;
-    VP8FInfo fInfo = _fInfo[mbX];
-    InputBuffer yDst = new InputBuffer.from(_cacheY, offset: mbX * 16);
-    final int ilevel = fInfo.fInnerLevel;
-    final int limit = fInfo.fLimit;
-    if (limit == 0) {
-      return;
-    }
-
-    if (_filterType == 1) {   // simple
-      if (mbX > 0) {
-        _dsp.simpleHFilter16(yDst, yBps, limit + 4);
-      }
-      if (fInfo.fInner) {
-        _dsp.simpleHFilter16i(yDst, yBps, limit);
-      }
-      if (mbY > 0) {
-        _dsp.simpleVFilter16(yDst, yBps, limit + 4);
-      }
-      if (fInfo.fInner) {
-        _dsp.simpleVFilter16i(yDst, yBps, limit);
-      }
-    } else {    // complex
-      final int uvBps = _cacheUVStride;
-      InputBuffer uDst = new InputBuffer.from(_cacheU, offset: mbX * 8);
-      InputBuffer vDst = new InputBuffer.from(_cacheV, offset: mbX * 8);
-
-      final int hevThresh = fInfo.hevThresh;
-      if (mbX > 0) {
-        _dsp.hFilter16(yDst, yBps, limit + 4, ilevel, hevThresh);
-        _dsp.hFilter8(uDst, vDst, uvBps, limit + 4, ilevel, hevThresh);
-      }
-      if (fInfo.fInner) {
-        _dsp.hFilter16i(yDst, yBps, limit, ilevel, hevThresh);
-        _dsp.hFilter8i(uDst, vDst, uvBps, limit, ilevel, hevThresh);
-      }
-      if (mbY > 0) {
-        _dsp.vFilter16(yDst, yBps, limit + 4, ilevel, hevThresh);
-        _dsp.vFilter8(uDst, vDst, uvBps, limit + 4, ilevel, hevThresh);
-      }
-      if (fInfo.fInner) {
-        _dsp.vFilter16i(yDst, yBps, limit, ilevel, hevThresh);
-        _dsp.vFilter8i(uDst, vDst, uvBps, limit, ilevel, hevThresh);
-      }
-    }
-  }
-
-  /**
-   * Filter the decoded macroblock row (if needed)
-   */
-  void _filterRow() {
-    for (int mbX = _tlMbX; mbX < _brMbX; ++mbX) {
-      _doFilter(mbX, _mbY);
-    }
-  }
-
-  void _ditherRow() {
-  }
-
-
-  /**
-   * This function is called after a row of macroblocks is finished decoding.
-   * It also takes into account the following restrictions:
-   *
-   * * In case of in-loop filtering, we must hold off sending some of the bottom
-   *    pixels as they are yet unfiltered. They will be when the next macroblock
-   *    row is decoded. Meanwhile, we must preserve them by rotating them in the
-   *    cache area. This doesn't hold for the very bottom row of the uncropped
-   *    picture of course.
-   *  * we must clip the remaining pixels against the cropping area. The VP8Io
-   *    struct must have the following fields set correctly before calling put():
-   */
-  bool _finishRow(bool useFilter) {
-    final int extraYRows = kFilterExtraRows[_filterType];
-    final int ySize = extraYRows * _cacheYStride;
-    final int uvSize = (extraYRows ~/ 2) * _cacheUVStride;
-    InputBuffer yDst = new InputBuffer.from(_cacheY, offset: -ySize);
-    InputBuffer uDst = new InputBuffer.from(_cacheU, offset: -uvSize);
-    InputBuffer vDst = new InputBuffer.from(_cacheV, offset: -uvSize);
-    final int mbY = _mbY;
-    final bool isFirstRow = (mbY == 0);
-    final bool isLastRow = (mbY >= _brMbY - 1);
-    int yStart = MACROBLOCK_VPOS(mbY);
-    int yEnd = MACROBLOCK_VPOS(mbY + 1);
-
-    if (useFilter) {
-      _filterRow();
-    }
-
-    if (_dither) {
-      _ditherRow();
-    }
-
-    if (!isFirstRow) {
-      yStart -= extraYRows;
-      _y = new InputBuffer.from(yDst);
-      _u = new InputBuffer.from(uDst);
-      _v = new InputBuffer.from(vDst);
-    } else {
-      _y = new InputBuffer.from(_cacheY);
-      _u = new InputBuffer.from(_cacheU);
-      _v = new InputBuffer.from(_cacheV);
-    }
-
-    if (!isLastRow) {
-      yEnd -= extraYRows;
-    }
-
-    if (yEnd > _cropBottom) {
-      yEnd = _cropBottom;    // make sure we don't overflow on last row.
-    }
-
-    _a = null;
-    if (_alphaData != null && yStart < yEnd) {
-      _a = _decompressAlphaRows(yStart, yEnd - yStart);
-      if (_a == null) {
-        return false;
-      }
-    }
-
-    if (yStart < _cropTop) {
-      final int deltaY = _cropTop - yStart;
-      yStart = _cropTop;
-
-      _y.offset += _cacheYStride * deltaY;
-      _u.offset += _cacheUVStride * (deltaY >> 1);
-      _v.offset += _cacheUVStride * (deltaY >> 1);
-
-      if (_a != null) {
-        _a.offset += webp.width * deltaY;
-      }
-    }
-
-    if (yStart < yEnd) {
-      _y.offset += _cropLeft;
-      _u.offset += _cropLeft >> 1;
-      _v.offset += _cropLeft >> 1;
-      if (_a != null) {
-        _a.offset += _cropLeft;
-      }
-
-      _put(yStart - _cropTop, _cropRight - _cropLeft, yEnd - yStart);
-    }
-
-    // rotate top samples if needed
-    if (!isLastRow) {
-      _cacheY.memcpy(-ySize, ySize, yDst, 16 * _cacheYStride);
-      _cacheU.memcpy(-uvSize, uvSize, uDst, 8 * _cacheUVStride);
-      _cacheV.memcpy(-uvSize, uvSize, vDst, 8 * _cacheUVStride);
-    }
-
-    return true;
-  }
-
-  bool _put(int mbY, int mbW, int mbH) {
-    if (mbW <= 0 || mbH <= 0) {
-      return false;
-    }
-
-    /*int numLinesOut =*/ _emitFancyRGB(mbY, mbW, mbH);
-    _emitAlphaRGB(mbY, mbW, mbH);
-
-    //_lastY += numLinesOut;
-
-    return true;
-  }
-
-  int _clip8(int v) {
-    int d = ((v & XOR_YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255;
-    return d;
-  }
-
-  int _yuvToR(int y, int v) {
-    return _clip8(kYScale * y + kVToR * v + kRCst);
-  }
-
-  int _yuvToG(int y, int u, int v) {
-    return _clip8(kYScale * y - kUToG * u - kVToG * v + kGCst);
-  }
-
-  int _yuvToB(int y, int u) {
-    return _clip8(kYScale * y + kUToB * u + kBCst);
-  }
-
-  void _yuvToRgb(int y, int u, int v, InputBuffer rgb) {
-    rgb[0] = _yuvToR(y, v);
-    rgb[1] = _yuvToG(y, u, v);
-    rgb[2] = _yuvToB(y, u);
-  }
-
-  void _yuvToRgba(int y, int u, int v, InputBuffer rgba) {
-    _yuvToRgb(y, u, v, rgba);
-    rgba[3] = 0xff;
-  }
-
-  void _upsample(InputBuffer topY, InputBuffer bottomY,
-                 InputBuffer topU, InputBuffer topV,
-                 InputBuffer curU, InputBuffer curV,
-                 InputBuffer topDst, InputBuffer bottomDst,
-                 int len) {
-    int LOAD_UV(int u, int v) => ((u) | ((v) << 16));
-
-    final int lastPixelPair = (len - 1) >> 1;
-    int tl_uv = LOAD_UV(topU[0], topV[0]); // top-left sample
-    int l_uv  = LOAD_UV(curU[0], curV[0]); // left-sample
-
-    final int uv0 = (3 * tl_uv + l_uv + 0x00020002) >> 2;
-    _yuvToRgba(topY[0], uv0 & 0xff, (uv0 >> 16), topDst);
-
-    if (bottomY != null) {
-      final int uv0 = (3 * l_uv + tl_uv + 0x00020002) >> 2;
-      _yuvToRgba(bottomY[0], uv0 & 0xff, (uv0 >> 16), bottomDst);
-    }
-
-    for (int x = 1; x <= lastPixelPair; ++x) {
-      final int t_uv = LOAD_UV(topU[x], topV[x]); // top sample
-      final int uv   = LOAD_UV(curU[x], curV[x]); // sample
-      // precompute invariant values associated with first and second diagonals
-      final int avg = tl_uv + t_uv + l_uv + uv + 0x00080008;
-      final int diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3;
-      final int diag_03 = (avg + 2 * (tl_uv + uv)) >> 3;
-
-      int uv0 = (diag_12 + tl_uv) >> 1;
-      int uv1 = (diag_03 + t_uv) >> 1;
-
-      _yuvToRgba(topY[2 * x - 1], uv0 & 0xff, (uv0 >> 16),
-          new InputBuffer.from(topDst, offset: (2 * x - 1) * 4));
-
-      _yuvToRgba(topY[2 * x - 0], uv1 & 0xff, (uv1 >> 16),
-              new InputBuffer.from(topDst, offset: (2 * x - 0) * 4));
-
-      if (bottomY != null) {
-        uv0 = (diag_03 + l_uv) >> 1;
-        uv1 = (diag_12 + uv) >> 1;
-
-        _yuvToRgba(bottomY[2 * x - 1], uv0 & 0xff, (uv0 >> 16),
-            new InputBuffer.from(bottomDst, offset: (2 * x - 1) * 4));
-
-        _yuvToRgba(bottomY[2 * x], uv1 & 0xff, (uv1 >> 16),
-                new InputBuffer.from(bottomDst, offset: (2 * x + 0) * 4));
-      }
-
-      tl_uv = t_uv;
-      l_uv = uv;
-    }
-
-    if ((len & 1) == 0) {
-      final int uv0 = (3 * tl_uv + l_uv + 0x00020002) >> 2;
-      _yuvToRgba(topY[len - 1], uv0 & 0xff, (uv0 >> 16),
-           new InputBuffer.from(topDst, offset: (len - 1) * 4));
-
-      if (bottomY != null) {
-        final int uv0 = (3 * l_uv + tl_uv + 0x00020002) >> 2;
-        _yuvToRgba(bottomY[len - 1], uv0 & 0xff, (uv0 >> 16),
-             new InputBuffer.from(bottomDst, offset: (len - 1) * 4));
-      }
-    }
-  }
-
-  void _emitAlphaRGB(int mbY, int mbW, int mbH) {
-    if (_a == null) {
-      return;
-    }
-
-    final int stride = webp.width * 4;
-    InputBuffer alpha = new InputBuffer.from(_a);
-    int startY = mbY;
-    int numRows = mbH;
-
-    // Compensate for the 1-line delay of the fancy upscaler.
-    // This is similar to EmitFancyRGB().
-    if (startY == 0) {
-      // We don't process the last row yet. It'll be done during the next call.
-      --numRows;
-    } else {
-      --startY;
-      // Fortunately, *alpha data is persistent, so we can go back
-      // one row and finish alpha blending, now that the fancy upscaler
-      // completed the YUV->RGB interpolation.
-      alpha.offset -= webp.width;
-    }
-
-    InputBuffer dst = new InputBuffer(output.getBytes(), offset: startY * stride + 3);
-
-    if (_cropTop + mbY + mbH == _cropBottom) {
-      // If it's the very last call, we process all the remaining rows!
-      numRows = _cropBottom - _cropTop - startY;
-    }
-
-    for (int y = 0; y < numRows; ++y) {
-      for (int x = 0; x < mbW; ++x) {
-        final int alphaValue = alpha[x];
-        dst[4 * x] = alphaValue & 0xff;
-      }
-
-      alpha.offset += webp.width;
-      dst.offset += stride;
-    }
-  }
-
-
-  int _emitFancyRGB(int mbY, int mbW, int mbH) {
-    int numLinesOut = mbH;   // a priori guess
-    InputBuffer dst = new InputBuffer(output.getBytes(), offset: mbY * webp.width * 4);
-    InputBuffer curY = new InputBuffer.from(_y);
-    InputBuffer curU = new InputBuffer.from(_u);
-    InputBuffer curV = new InputBuffer.from(_v);
-    int y = mbY;
-    final int yEnd = mbY + mbH;
-    final int uvW = (mbW + 1) >> 1;
-    final int stride = webp.width * 4;
-    InputBuffer topU = new InputBuffer.from(_tmpU);
-    InputBuffer topV = new InputBuffer.from(_tmpV);
-
-    if (y == 0) {
-      // First line is special cased. We mirror the u/v samples at boundary.
-      _upsample(curY, null, curU, curV, curU, curV, dst, null, mbW);
-    } else {
-      // We can finish the left-over line from previous call.
-      _upsample(_tmpY, curY, topU, topV, curU, curV,
-                new InputBuffer.from(dst, offset: -stride), dst, mbW);
-      ++numLinesOut;
-    }
-
-    // Loop over each output pairs of row.
-    topU.buffer = curU.buffer;
-    topV.buffer = curV.buffer;
-    for (; y + 2 < yEnd; y += 2) {
-      topU.offset = curU.offset;
-      topV.offset = curV.offset;
-      curU.offset += _cacheUVStride;
-      curV.offset += _cacheUVStride;
-      dst.offset += 2 * stride;
-      curY.offset += 2 * _cacheYStride;
-      _upsample(new InputBuffer.from(curY, offset: -_cacheYStride), curY,
-          topU, topV, curU, curV,
-          new InputBuffer.from(dst, offset: -stride), dst, mbW);
-    }
-
-    // move to last row
-    curY.offset += _cacheYStride;
-    if (_cropTop + yEnd < _cropBottom) {
-      // Save the unfinished samples for next call (as we're not done yet).
-      _tmpY.memcpy(0, mbW, curY);
-      _tmpU.memcpy(0, uvW, curU);
-      _tmpV.memcpy(0, uvW, curV);
-      // The fancy upsampler leaves a row unfinished behind
-      // (except for the very last row)
-      numLinesOut--;
-    } else {
-      // Process the very last row of even-sized picture
-      if ((yEnd & 1) == 0) {
-        _upsample(curY, null, curU, curV, curU, curV,
-            new InputBuffer.from(dst, offset: stride), null, mbW);
-      }
-    }
-
-    return numLinesOut;
-  }
-
-  InputBuffer _decompressAlphaRows(int row, int numRows) {
-    final int width = webp.width;
-    final int height = webp.height;
-
-    if (row < 0 || numRows <= 0 || row + numRows > height) {
-      return null;    // sanity check.
-    }
-
-    if (row == 0) {
-      _alphaPlane = new Uint8List(width * height);
-      _alpha = new WebPAlpha(_alphaData, width, height);
-    }
-
-    if (!_alpha.isAlphaDecoded) {
-      if (!_alpha.decode(row, numRows, _alphaPlane)) {
-        return null;
-      }
-    }
-
-    // Return a pointer to the current decoded row.
-    return new InputBuffer(_alphaPlane, offset: row * width);
-  }
-
-  bool _decodeMB(VP8BitReader tokenBr) {
-    VP8MB left = _mbInfo[0];
-    VP8MB mb = _mbInfo[1 + _mbX];
-    VP8MBData block = _mbData[_mbX];
-    bool skip;
-
-    // Note: we don't save segment map (yet), as we don't expect
-    // to decode more than 1 keyframe.
-    if (_segmentHeader.updateMap) {
-      // Hardcoded tree parsing
-      _segment = br.getBit(_proba.segments[0]) == 0 ?
-            br.getBit(_proba.segments[1]) :
-            2 + br.getBit(_proba.segments[2]);
-    }
-
-    skip = _useSkipProba ? br.getBit(_skipP) != 0 : false;
-
-    _parseIntraMode();
-
-    if (!skip) {
-      skip = _parseResiduals(mb, tokenBr);
-    } else {
-      left.nz = mb.nz = 0;
-      if (!block.isIntra4x4) {
-        left.nzDc = mb.nzDc = 0;
-      }
-      block.nonZeroY = 0;
-      block.nonZeroUV = 0;
-    }
-
-    if (_filterType > 0) {  // store filter info
-      _fInfo[_mbX] = _fStrengths[_segment][block.isIntra4x4 ? 1 : 0];
-      VP8FInfo finfo = _fInfo[_mbX];
-      finfo.fInner = finfo.fInner || !skip;
-    }
-
-    return true;
-  }
-
-  bool _parseResiduals(VP8MB mb, VP8BitReader tokenBr) {
-    var bands = _proba.bands;
-    List<VP8BandProbas> acProba;
-    VP8QuantMatrix q = _dqm[_segment];
-    VP8MBData block = _mbData[_mbX];
-    InputBuffer dst = new InputBuffer(block.coeffs);
-    //int di = 0;
-    VP8MB leftMb = _mbInfo[0];
-    int tnz;
-    int lnz;
-    int nonZeroY = 0;
-    int nonZeroUV = 0;
-    int outTopNz;
-    int outLeftNz;
-    int first;
-
-    dst.memset(0, dst.length, 0);
-
-    if (!block.isIntra4x4) {    // parse DC
-      InputBuffer dc = new InputBuffer(new Int16List(16));
-      final int ctx = mb.nzDc + leftMb.nzDc;
-      final int nz = _getCoeffs(tokenBr, bands[1], ctx, q.y2Mat, 0, dc);
-      mb.nzDc = leftMb.nzDc = (nz > 0) ? 1 : 0;
-      if (nz > 1) {   // more than just the DC -> perform the full transform
-        _transformWHT(dc, dst);
-      } else {        // only DC is non-zero -> inlined simplified transform
-        final int dc0 = (dc[0] + 3) >> 3;
-        for (int i = 0; i < 16 * 16; i += 16) {
-          dst[i] = dc0;
-        }
-      }
-
-      first = 1;
-      acProba = bands[0];
-    } else {
-      first = 0;
-      acProba = bands[3];
-    }
-
-    tnz = mb.nz & 0x0f;
-    lnz = leftMb.nz & 0x0f;
-    for (int y = 0; y < 4; ++y) {
-      int l = lnz & 1;
-      int nzCoeffs = 0;
-      for (int x = 0; x < 4; ++x) {
-        final int ctx = l + (tnz & 1);
-        final int nz = _getCoeffs(tokenBr, acProba, ctx, q.y1Mat, first, dst);
-        l = (nz > first) ? 1 : 0;
-        tnz = (tnz >> 1) | (l << 7);
-        nzCoeffs = _nzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0);
-        dst.offset += 16;
-      }
-
-      tnz >>= 4;
-      lnz = (lnz >> 1) | (l << 7);
-      nonZeroY = (nonZeroY << 8) | nzCoeffs;
-    }
-    outTopNz = tnz;
-    outLeftNz = lnz >> 4;
-
-    for (int ch = 0; ch < 4; ch += 2) {
-      int nzCoeffs = 0;
-      tnz = mb.nz >> (4 + ch);
-      lnz = leftMb.nz >> (4 + ch);
-      for (int y = 0; y < 2; ++y) {
-        int l = lnz & 1;
-        for (int x = 0; x < 2; ++x) {
-          final int ctx = l + (tnz & 1);
-          final int nz = _getCoeffs(tokenBr, bands[2], ctx, q.uvMat, 0, dst);
-          l = (nz > 0) ? 1 : 0;
-          tnz = (tnz >> 1) | (l << 3);
-          nzCoeffs = _nzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0);
-          dst.offset += 16;
-        }
-
-        tnz >>= 2;
-        lnz = (lnz >> 1) | (l << 5);
-      }
-
-      // Note: we don't really need the per-4x4 details for U/V blocks.
-      nonZeroUV |= nzCoeffs << (4 * ch);
-      outTopNz |= (tnz << 4) << ch;
-      outLeftNz |= (lnz & 0xf0) << ch;
-    }
-
-    mb.nz = outTopNz;
-    leftMb.nz = outLeftNz;
-
-    block.nonZeroY = nonZeroY;
-    block.nonZeroUV = nonZeroUV;
-
-    // We look at the mode-code of each block and check if some blocks have less
-    // than three non-zero coeffs (code < 2). This is to avoid dithering flat and
-    // empty blocks.
-    block.dither = (nonZeroUV & 0xaaaa) != 0 ? 0 : q.dither;
-
-    // will be used for further optimization
-    return (nonZeroY | nonZeroUV) == 0;
-  }
-
-  void _transformWHT(InputBuffer src, InputBuffer out) {
-    Int32List tmp = new Int32List(16);
-
-    int oi = 0;
-    for (int i = 0; i < 4; ++i) {
-      final int a0 = src[0 + i] + src[12 + i];
-      final int a1 = src[4 + i] + src[ 8 + i];
-      final int a2 = src[4 + i] - src[ 8 + i];
-      final int a3 = src[0 + i] - src[12 + i];
-      tmp[0  + i] = a0 + a1;
-      tmp[8  + i] = a0 - a1;
-      tmp[4  + i] = a3 + a2;
-      tmp[12 + i] = a3 - a2;
-    }
-
-    for (int i = 0; i < 4; ++i) {
-      final int dc = tmp[0 + i * 4] + 3;    // w/ rounder
-      final int a0 = dc             + tmp[3 + i * 4];
-      final int a1 = tmp[1 + i * 4] + tmp[2 + i * 4];
-      final int a2 = tmp[1 + i * 4] - tmp[2 + i * 4];
-      final int a3 = dc             - tmp[3 + i * 4];
-      out[oi + 0] = (a0 + a1) >> 3;
-      out[oi + 16] = (a3 + a2) >> 3;
-      out[oi + 32] = (a0 - a1) >> 3;
-      out[oi + 48] = (a3 - a2) >> 3;
-
-      oi += 64;
-    }
-  }
-
-  int _nzCodeBits(int nz_coeffs, int nz, int dc_nz) {
-    nz_coeffs <<= 2;
-    nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;
-    return nz_coeffs;
-  }
-
-  static const List<int> kBands = const [
-     0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0];
-
-  static const List<int> kCat3 = const [ 173, 148, 140 ];
-  static const List<int> kCat4 = const [ 176, 155, 140, 135 ];
-  static const List<int> kCat5 = const [ 180, 157, 141, 134, 130 ];
-  static const List<int> kCat6 = const [ 254, 254, 243, 230, 196, 177, 153,
-                                         140, 133, 130, 129 ];
-  static const List<List<int>> kCat3456 = const [ kCat3, kCat4, kCat5, kCat6 ];
-  static const List<int> kZigzag = const [ 0, 1, 4, 8,  5, 2, 3, 6,  9, 12,
-                                           13, 10,  7, 11, 14, 15 ];
-
-  /**
-   * See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
-   */
-  int _getLargeValue(VP8BitReader br, List<int> p) {
-    int v;
-    if (br.getBit(p[3]) == 0) {
-      if (br.getBit(p[4]) == 0) {
-        v = 2;
-      } else {
-        v = 3 + br.getBit(p[5]);
-      }
-    } else {
-      if (br.getBit(p[6]) == 0) {
-        if (br.getBit(p[7]) == 0) {
-          v = 5 + br.getBit(159);
-        } else {
-          v = 7 + 2 * br.getBit(165);
-          v += br.getBit(145);
-        }
-      } else {
-        final int bit1 = br.getBit(p[8]);
-        final int bit0 = br.getBit(p[9 + bit1]);
-        final int cat = 2 * bit1 + bit0;
-        v = 0;
-        List<int> tab = kCat3456[cat];
-        for (int i = 0, len = tab.length; i < len; ++i) {
-          v += v + br.getBit(tab[i]);
-        }
-        v += 3 + (8 << cat);
-      }
-    }
-    return v;
-  }
-
-
-  /**
-   * Returns the position of the last non-zero coeff plus one
-   */
-  int _getCoeffs(VP8BitReader br, List<VP8BandProbas> prob,
-                 int ctx, List<int> dq, int n, InputBuffer out) {
-    // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'.
-    List<int> p = prob[n].probas[ctx];
-    for (; n < 16; ++n) {
-      if (br.getBit(p[0]) == 0) {
-        return n;  // previous coeff was last non-zero coeff
-      }
-
-      while (br.getBit(p[1]) == 0) { // sequence of zero coeffs
-        p = prob[kBands[++n]].probas[0];
-        if (n == 16) {
-          return 16;
-        }
-      }
-
-      { // non zero coeff
-        List<Uint8List> p_ctx = prob[kBands[n + 1]].probas;
-        int v;
-        if (br.getBit(p[2]) == 0) {
-          v = 1;
-          p = p_ctx[1];
-        } else {
-          v = _getLargeValue(br, p);
-          p = p_ctx[2];
-        }
-
-        out[kZigzag[n]] = br.getSigned(v) * dq[n > 0 ? 1 : 0];
-      }
-    }
-    return 16;
-  }
-
-  void _parseIntraMode() {
-    int ti = 4 * _mbX;
-    int li = 0;
-    Uint8List top = _intraT;
-    Uint8List left = _intraL;
-
-    VP8MBData block = _mbData[_mbX];
-
-    // decide for B_PRED first
-    block.isIntra4x4 = br.getBit(145) == 0;
-    if (!block.isIntra4x4) {
-      // Hardcoded 16x16 intra-mode decision tree.
-      final int ymode =
-          br.getBit(156) != 0 ?
-              (br.getBit(128) != 0 ? TM_PRED : H_PRED) :
-              (br.getBit(163) != 0 ? V_PRED : DC_PRED);
-      block.imodes[0] = ymode;
-
-      top.fillRange(ti, ti + 4, ymode);
-      left.fillRange(li, li + 4, ymode);
-    } else {
-      Uint8List modes = block.imodes;
-      int mi = 0;
-      for (int y = 0; y < 4; ++y) {
-        int ymode = left[y];
-        for (int x = 0; x < 4; ++x) {
-          List<int> prob = kBModesProba[top[ti + x]][ymode];
-
-          // Generic tree-parsing
-          int b = br.getBit(prob[0]);
-          int i = kYModesIntra4[b];
-
-          while (i > 0) {
-            i = kYModesIntra4[2 * i + br.getBit(prob[i])];
-          }
-
-          ymode = -i;
-          top[ti + x] = ymode;
-        }
-
-        modes.setRange(mi, mi + 4, top, ti);
-
-        mi += 4;
-        left[y] = ymode;
-      }
-    }
-
-    // Hardcoded UVMode decision tree
-    block.uvmode = br.getBit(142) == 0 ? DC_PRED
-        : br.getBit(114) == 0 ? V_PRED
-            : br.getBit(183) != 0 ? TM_PRED : H_PRED;
-  }
-
-  // Main data source
-  VP8BitReader br;
-
-  Image output;
-
-  VP8Filter _dsp;
-
-  // headers
-  VP8FrameHeader _frameHeader = new VP8FrameHeader();
-  VP8PictureHeader _picHeader = new VP8PictureHeader();
-  VP8FilterHeader _filterHeader = new VP8FilterHeader();
-  VP8SegmentHeader _segmentHeader = new VP8SegmentHeader();
-
-  int _cropLeft;
-  int _cropRight;
-  int _cropTop;
-  int _cropBottom;
-
-  /// Width in macroblock units.
-  int _mbWidth;
-  /// Height in macroblock units.
-  int _mbHeight;
-
-  // Macroblock to process/filter, depending on cropping and filter_type.
-  int _tlMbX; // top-left MB that must be in-loop filtered
-  int _tlMbY;
-  int _brMbX; // last bottom-right MB that must be decoded
-  int _brMbY;
-
-  // number of partitions.
-  int _numPartitions;
-  // per-partition boolean decoders.
-  List<VP8BitReader> _partitions = new List<VP8BitReader>(MAX_NUM_PARTITIONS);
-
-  // Dithering strength, deduced from decoding options
-  bool _dither = false; // whether to use dithering or not
-  //VP8Random _ditheringRand; // random generator for dithering
-
-  // dequantization (one set of DC/AC dequant factor per segment)
-  List<VP8QuantMatrix> _dqm = new List<VP8QuantMatrix>(NUM_MB_SEGMENTS);
-
-  // probabilities
-  VP8Proba _proba;
-  bool _useSkipProba;
-  int _skipP;
-
-  // Boundary data cache and persistent buffers.
-  /// top intra modes values: 4 * _mbWidth
-  Uint8List _intraT;
-  /// left intra modes values
-  Uint8List _intraL = new Uint8List(4);
-
-  /// uint8, segment of the currently parsed block
-  int _segment;
-  /// top y/u/v samples
-  List<VP8TopSamples> _yuvT;
-
-  /// contextual macroblock info (mb_w_ + 1)
-  List<VP8MB> _mbInfo;
-  /// filter strength info
-  List<VP8FInfo> _fInfo;
-  /// main block for Y/U/V (size = YUV_SIZE)
-  Uint8List _yuvBlock;
-
-  /// macroblock row for storing unfiltered samples
-  InputBuffer _cacheY;
-  InputBuffer _cacheU;
-  InputBuffer _cacheV;
-  int _cacheYStride;
-  int _cacheUVStride;
-
-  InputBuffer _tmpY;
-  InputBuffer _tmpU;
-  InputBuffer _tmpV;
-
-  InputBuffer _y;
-  InputBuffer _u;
-  InputBuffer _v;
-  InputBuffer _a;
-
-  /// main memory chunk for the above data. Persistent.
-  //Uint8List _mem;
-
-  // Per macroblock non-persistent infos.
-  /// current position, in macroblock units
-  int _mbX = 0;
-  int _mbY = 0;
-  /// parsed reconstruction data
-  List<VP8MBData> _mbData;
-
-  /// 0=off, 1=simple, 2=complex
-  int _filterType;
-  /// precalculated per-segment/type
-  List<List<VP8FInfo>> _fStrengths;
-
-  // Alpha
-  /// alpha-plane decoder object
-  WebPAlpha _alpha;
-  /// compressed alpha data (if present)
-  InputBuffer _alphaData;
-  /// true if alpha_data_ is decoded in alpha_plane_
-  //int _isAlphaDecoded;
-  /// output. Persistent, contains the whole data.
-  Uint8List _alphaPlane;
-
-  // extensions
-  //int _layerColorspace;
-  /// compressed layer data (if present)
-  //Uint8List _layerData;
-
-  static int _clip(int v, int M) {
-    return v < 0 ? 0 : v > M ? M : v;
-  }
-
-  static const List<int> kYModesIntra4 = const [
-    -B_DC_PRED, 1,
-    -B_TM_PRED, 2,
-    -B_VE_PRED, 3,
-    4, 6,
-    -B_HE_PRED, 5,
-    -B_RD_PRED, -B_VR_PRED,
-    -B_LD_PRED, 7,
-    -B_VL_PRED, 8,
-    -B_HD_PRED, -B_HU_PRED ];
-
-  static const List<List<List<int>>> kBModesProba = const [
-     const [ const [ 231, 120, 48, 89, 115, 113, 120, 152, 112 ],
-       const [ 152, 179, 64, 126, 170, 118, 46, 70, 95 ],
-       const [ 175, 69, 143, 80, 85, 82, 72, 155, 103 ],
-       const [ 56, 58, 10, 171, 218, 189, 17, 13, 152 ],
-       const [ 114, 26, 17, 163, 44, 195, 21, 10, 173 ],
-       const [ 121, 24, 80, 195, 26, 62, 44, 64, 85 ],
-       const [ 144, 71, 10, 38, 171, 213, 144, 34, 26 ],
-       const [ 170, 46, 55, 19, 136, 160, 33, 206, 71 ],
-       const [ 63, 20, 8, 114, 114, 208, 12, 9, 226 ],
-       const [ 81, 40, 11, 96, 182, 84, 29, 16, 36 ] ],
-       const [ const [ 134, 183, 89, 137, 98, 101, 106, 165, 148 ],
-         const [ 72, 187, 100, 130, 157, 111, 32, 75, 80 ],
-         const [ 66, 102, 167, 99, 74, 62, 40, 234, 128 ],
-         const [ 41, 53, 9, 178, 241, 141, 26, 8, 107 ],
-         const [ 74, 43, 26, 146, 73, 166, 49, 23, 157 ],
-         const [ 65, 38, 105, 160, 51, 52, 31, 115, 128 ],
-         const [ 104, 79, 12, 27, 217, 255, 87, 17, 7 ],
-         const [ 87, 68, 71, 44, 114, 51, 15, 186, 23 ],
-         const [ 47, 41, 14, 110, 182, 183, 21, 17, 194 ],
-         const [ 66, 45, 25, 102, 197, 189, 23, 18, 22 ] ],
-         const [ const [ 88, 88, 147, 150, 42, 46, 45, 196, 205 ],
-           const [ 43, 97, 183, 117, 85, 38, 35, 179, 61 ],
-           const [ 39, 53, 200, 87, 26, 21, 43, 232, 171 ],
-           const [ 56, 34, 51, 104, 114, 102, 29, 93, 77 ],
-           const [ 39, 28, 85, 171, 58, 165, 90, 98, 64 ],
-           const [ 34, 22, 116, 206, 23, 34, 43, 166, 73 ],
-           const [ 107, 54, 32, 26, 51, 1, 81, 43, 31 ],
-           const [ 68, 25, 106, 22, 64, 171, 36, 225, 114 ],
-           const [ 34, 19, 21, 102, 132, 188, 16, 76, 124 ],
-           const [ 62, 18, 78, 95, 85, 57, 50, 48, 51 ] ],
-           const [ const [ 193, 101, 35, 159, 215, 111, 89, 46, 111 ],
-             const [ 60, 148, 31, 172, 219, 228, 21, 18, 111 ],
-             const [ 112, 113, 77, 85, 179, 255, 38, 120, 114 ],
-             const [ 40, 42, 1, 196, 245, 209, 10, 25, 109 ],
-             const [ 88, 43, 29, 140, 166, 213, 37, 43, 154 ],
-             const [ 61, 63, 30, 155, 67, 45, 68, 1, 209 ],
-             const [ 100, 80, 8, 43, 154, 1, 51, 26, 71 ],
-             const [ 142, 78, 78, 16, 255, 128, 34, 197, 171 ],
-             const [ 41, 40, 5, 102, 211, 183, 4, 1, 221 ],
-             const [ 51, 50, 17, 168, 209, 192, 23, 25, 82 ] ],
-             const [ const [ 138, 31, 36, 171, 27, 166, 38, 44, 229 ],
-               const [ 67, 87, 58, 169, 82, 115, 26, 59, 179 ],
-               const [ 63, 59, 90, 180, 59, 166, 93, 73, 154 ],
-               const [ 40, 40, 21, 116, 143, 209, 34, 39, 175 ],
-               const [ 47, 15, 16, 183, 34, 223, 49, 45, 183 ],
-               const [ 46, 17, 33, 183, 6, 98, 15, 32, 183 ],
-               const [ 57, 46, 22, 24, 128, 1, 54, 17, 37 ],
-               const [ 65, 32, 73, 115, 28, 128, 23, 128, 205 ],
-               const [ 40, 3, 9, 115, 51, 192, 18, 6, 223 ],
-               const [ 87, 37, 9, 115, 59, 77, 64, 21, 47 ] ],
-               const [ const [ 104, 55, 44, 218, 9, 54, 53, 130, 226 ],
-                 const [ 64, 90, 70, 205, 40, 41, 23, 26, 57 ],
-                 const [ 54, 57, 112, 184, 5, 41, 38, 166, 213 ],
-                 const [ 30, 34, 26, 133, 152, 116, 10, 32, 134 ],
-                 const [ 39, 19, 53, 221, 26, 114, 32, 73, 255 ],
-                 const [ 31, 9, 65, 234, 2, 15, 1, 118, 73 ],
-                 const [ 75, 32, 12, 51, 192, 255, 160, 43, 51 ],
-                 const [ 88, 31, 35, 67, 102, 85, 55, 186, 85 ],
-                 const [ 56, 21, 23, 111, 59, 205, 45, 37, 192 ],
-                 const [ 55, 38, 70, 124, 73, 102, 1, 34, 98 ] ],
-                 const [ const [ 125, 98, 42, 88, 104, 85, 117, 175, 82 ],
-                   const [ 95, 84, 53, 89, 128, 100, 113, 101, 45 ],
-                   const [ 75, 79, 123, 47, 51, 128, 81, 171, 1 ],
-                   const [ 57, 17, 5, 71, 102, 57, 53, 41, 49 ],
-                   const [ 38, 33, 13, 121, 57, 73, 26, 1, 85 ],
-                   const [ 41, 10, 67, 138, 77, 110, 90, 47, 114 ],
-                   const [ 115, 21, 2, 10, 102, 255, 166, 23, 6 ],
-                   const [ 101, 29, 16, 10, 85, 128, 101, 196, 26 ],
-                   const [ 57, 18, 10, 102, 102, 213, 34, 20, 43 ],
-                   const [ 117, 20, 15, 36, 163, 128, 68, 1, 26 ] ],
-                   const [ const [ 102, 61, 71, 37, 34, 53, 31, 243, 192 ],
-                     const [ 69, 60, 71, 38, 73, 119, 28, 222, 37 ],
-                     const [ 68, 45, 128, 34, 1, 47, 11, 245, 171 ],
-                     const [ 62, 17, 19, 70, 146, 85, 55, 62, 70 ],
-                     const [ 37, 43, 37, 154, 100, 163, 85, 160, 1 ],
-                     const [ 63, 9, 92, 136, 28, 64, 32, 201, 85 ],
-                     const [ 75, 15, 9, 9, 64, 255, 184, 119, 16 ],
-                     const [ 86, 6, 28, 5, 64, 255, 25, 248, 1 ],
-                     const [ 56, 8, 17, 132, 137, 255, 55, 116, 128 ],
-                     const [ 58, 15, 20, 82, 135, 57, 26, 121, 40 ] ],
-                     const [ const [ 164, 50, 31, 137, 154, 133, 25, 35, 218 ],
-                       const [ 51, 103, 44, 131, 131, 123, 31, 6, 158 ],
-                       const [ 86, 40, 64, 135, 148, 224, 45, 183, 128 ],
-                       const [ 22, 26, 17, 131, 240, 154, 14, 1, 209 ],
-                       const [ 45, 16, 21, 91, 64, 222, 7, 1, 197 ],
-                       const [ 56, 21, 39, 155, 60, 138, 23, 102, 213 ],
-                       const [ 83, 12, 13, 54, 192, 255, 68, 47, 28 ],
-                       const [ 85, 26, 85, 85, 128, 128, 32, 146, 171 ],
-                       const [ 18, 11, 7, 63, 144, 171, 4, 4, 246 ],
-                       const [ 35, 27, 10, 146, 174, 171, 12, 26, 128 ] ],
-                       const [ const [ 190, 80, 35, 99, 180, 80, 126, 54, 45 ],
-                         const [ 85, 126, 47, 87, 176, 51, 41, 20, 32 ],
-                         const [ 101, 75, 128, 139, 118, 146, 116, 128, 85 ],
-                         const [ 56, 41, 15, 176, 236, 85, 37, 9, 62 ],
-                         const [ 71, 30, 17, 119, 118, 255, 17, 18, 138 ],
-                         const [ 101, 38, 60, 138, 55, 70, 43, 26, 142 ],
-                         const [ 146, 36, 19, 30, 171, 255, 97, 27, 20 ],
-                         const [ 138, 45, 61, 62, 219, 1, 81, 188, 64 ],
-                         const [ 32, 41, 20, 117, 151, 142, 20, 21, 163 ],
-                         const [ 112, 19, 12, 61, 195, 128, 48, 4, 24 ] ] ];
-
-  static const List COEFFS_PROBA_0 = const [
-  const [ const [ const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ]
-    ],
-    const [ const [ 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 ],
-      const [ 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 ],
-      const [ 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 ],
-      const [ 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 ],
-      const [ 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 ],
-    ],
-    const [ const [ 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 ],
-      const [ 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 ],
-      const [ 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 ],
-    ],
-    const [ const [ 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 ],
-      const [ 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 ],
-      const [ 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 ],
-      const [ 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 ],
-      const [ 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 ],
-      const [ 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 ],
-      const [ 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ]
-    ]
-  ],
-  const [ const [ const [ 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 ],
-      const [ 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 ],
-      const [ 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 ]
-    ],
-    const [ const [ 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 ],
-      const [ 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 ],
-      const [ 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 ]
-    ],
-    const [ const [ 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 ],
-      const [ 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 ],
-      const [ 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 ]
-    ],
-    const [ const [ 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 ],
-      const [ 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 ],
-      const [ 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 ],
-      const [ 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 ],
-      const [ 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 ],
-      const [ 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 ],
-      const [ 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 ],
-      const [ 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 ],
-      const [ 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 ],
-      const [ 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 ],
-      const [ 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 ]
-    ]
-  ],
-  const [ const [ const [ 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 ],
-      const [ 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 ],
-      const [ 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 ]
-    ],
-    const [ const [ 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 ],
-      const [ 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 ],
-      const [ 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 ],
-      const [ 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 ],
-      const [ 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 ],
-      const [ 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 ],
-      const [ 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 ],
-      const [ 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 ],
-      const [ 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 ],
-      const [ 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 ],
-      const [ 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]
-    ],
-    const [ const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ]
-    ]
-  ],
-  const [ const [ const [ 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 ],
-      const [ 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 ],
-      const [ 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 ]
-    ],
-    const [ const [ 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 ],
-      const [ 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 ],
-      const [ 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 ]
-    ],
-    const [ const [ 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 ],
-      const [ 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 ],
-      const [ 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 ]
-    ],
-    const [ const [ 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 ],
-      const [ 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 ],
-      const [ 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 ]
-    ],
-    const [ const [ 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 ],
-      const [ 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 ],
-      const [ 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 ],
-      const [ 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 ],
-      const [ 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 ],
-      const [ 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 ],
-      const [ 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 ]
-    ],
-    const [ const [ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],
-      const [ 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]
-    ]
-  ] ];
-
-
-  static const List COEFFS_UPDATE_PROBA = const [
-    const [ const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 ],
-      const [ 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ]
-    ],
-    const [ const [ const [ 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 ],
-      const [ 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ]
-    ],
-    const [ const [ const [ 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ]
-    ],
-    const [ const [ const [ 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ],
-    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
-      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
-    ] ] ];
-
-  // Paragraph 14.1
-  static const List<int> DC_TABLE = const [ // uint8
-      4,     5,   6,   7,   8,   9,  10,  10,
-      11,   12,  13,  14,  15,  16,  17,  17,
-      18,   19,  20,  20,  21,  21,  22,  22,
-      23,   23,  24,  25,  25,  26,  27,  28,
-      29,   30,  31,  32,  33,  34,  35,  36,
-      37,   37,  38,  39,  40,  41,  42,  43,
-      44,   45,  46,  46,  47,  48,  49,  50,
-      51,   52,  53,  54,  55,  56,  57,  58,
-      59,   60,  61,  62,  63,  64,  65,  66,
-      67,   68,  69,  70,  71,  72,  73,  74,
-      75,   76,  76,  77,  78,  79,  80,  81,
-      82,   83,  84,  85,  86,  87,  88,  89,
-      91,   93,  95,  96,  98, 100, 101, 102,
-      104, 106, 108, 110, 112, 114, 116, 118,
-      122, 124, 126, 128, 130, 132, 134, 136,
-      138, 140, 143, 145, 148, 151, 154, 157];
-
-  static const List<int> AC_TABLE = const [ // uint16
-       4,     5,   6,   7,   8,   9,  10,  11,
-       12,   13,  14,  15,  16,  17,  18,  19,
-       20,   21,  22,  23,  24,  25,  26,  27,
-       28,   29,  30,  31,  32,  33,  34,  35,
-       36,   37,  38,  39,  40,  41,  42,  43,
-       44,   45,  46,  47,  48,  49,  50,  51,
-       52,   53,  54,  55,  56,  57,  58,  60,
-       62,   64,  66,  68,  70,  72,  74,  76,
-       78,   80,  82,  84,  86,  88,  90,  92,
-       94,   96,  98, 100, 102, 104, 106, 108,
-       110, 112, 114, 116, 119, 122, 125, 128,
-       131, 134, 137, 140, 143, 146, 149, 152,
-       155, 158, 161, 164, 167, 170, 173, 177,
-       181, 185, 189, 193, 197, 201, 205, 209,
-       213, 217, 221, 225, 229, 234, 239, 245,
-       249, 254, 259, 264, 269, 274, 279, 284];
-
-  /**
-   * FILTER_EXTRA_ROWS = How many extra lines are needed on the MB boundary
-   * for caching, given a filtering level.
-   * Simple filter:  up to 2 luma samples are read and 1 is written.
-   * Complex filter: up to 4 luma samples are read and 3 are written. Same for
-   *               U/V, so it's 8 samples total (because of the 2x upsampling).
-   */
-  static const List<int> FILTER_EXTRA_ROWS = const [ 0, 2, 8 ];
-
-  static const int VP8_SIGNATURE = 0x2a019d;
-
-  static const int MB_FEATURE_TREE_PROBS = 3;
-  static const int NUM_MB_SEGMENTS = 4;
-  static const int NUM_REF_LF_DELTAS = 4;
-  static const int NUM_MODE_LF_DELTAS = 4;    // I4x4, ZERO, *, SPLIT
-  static const int MAX_NUM_PARTITIONS = 8;
-
-  static const int B_DC_PRED = 0;   // 4x4 modes
-  static const int B_TM_PRED = 1;
-  static const int B_VE_PRED = 2;
-  static const int B_HE_PRED = 3;
-  static const int B_RD_PRED = 4;
-  static const int B_VR_PRED = 5;
-  static const int B_LD_PRED = 6;
-  static const int B_VL_PRED = 7;
-  static const int B_HD_PRED = 8;
-  static const int B_HU_PRED = 9;
-  static const int NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED;
-
-  // Luma16 or UV modes
-  static const int DC_PRED = B_DC_PRED;
-  static const int V_PRED = B_VE_PRED;
-  static const int H_PRED = B_HE_PRED;
-  static const int TM_PRED = B_TM_PRED;
-  static const int B_PRED = NUM_BMODES;
-
-  // special modes
-  static const int B_DC_PRED_NOTOP = 4;
-  static const int B_DC_PRED_NOLEFT = 5;
-  static const int B_DC_PRED_NOTOPLEFT = 6;
-  static const int NUM_B_DC_MODES = 7;
-
-  // Probabilities
-  static const int NUM_TYPES = 4;
-  static const int NUM_BANDS = 8;
-  static const int NUM_CTX = 3;
-  static const int NUM_PROBAS = 11;
-
-  static const int BPS = 32; // this is the common stride used by yuv[]
-  static const int YUV_SIZE = (BPS * 17 + BPS * 9);
-  static const int Y_SIZE = (BPS * 17);
-  static const int Y_OFF = (BPS * 1 + 8);
-  static const int U_OFF = (Y_OFF + BPS * 16 + BPS);
-  static const int V_OFF = (U_OFF + 16);
-
-  static const int YUV_FIX = 16; // fixed-point precision for RGB->YUV
-  static const int YUV_HALF = 1 << (YUV_FIX - 1);
-  static const int YUV_MASK = (256 << YUV_FIX) - 1;
-  static const int YUV_RANGE_MIN = -227; // min value of r/g/b output
-  static const int YUV_RANGE_MAX = 256 + 226; // max value of r/g/b output
-  static const int YUV_FIX2 = 14; // fixed-point precision for YUV->RGB
-  static const int YUV_HALF2 = 1 << (YUV_FIX2 - 1);
-  static const int YUV_MASK2 = (256 << YUV_FIX2) - 1;
-  static const int XOR_YUV_MASK2 = (-YUV_MASK2 - 1);
-
-  // These constants are 14b fixed-point version of ITU-R BT.601 constants.
-  static const int kYScale = 19077;    // 1.164 = 255 / 219
-  static const int kVToR = 26149;    // 1.596 = 255 / 112 * 0.701
-  static const int kUToG = 6419;    // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587
-  static const int kVToG = 13320;    // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587
-  static const int kUToB = 33050;    // 2.018 = 255 / 112 * 0.886
-  static const int kRCst = (-kYScale * 16 - kVToR * 128 + YUV_HALF2);
-  static const int kGCst = (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF2);
-  static const int kBCst = (-kYScale * 16 - kUToB * 128 + YUV_HALF2);
-}
+import 'dart:typed_data';

+

+import '../../image.dart';

+import '../../util/input_buffer.dart';

+import 'vp8_bit_reader.dart';

+import 'vp8_filter.dart';

+import 'vp8_types.dart';

+import 'webp_alpha.dart';

+import 'webp_info.dart';

+

+/**

+ * WebP lossy format.

+ */

+class VP8 {

+  InputBuffer input;

+  InternalWebPInfo _webp;

+

+  VP8(InputBuffer input, this._webp) :

+    this.input = input;

+

+  WebPInfo get webp => _webp;

+

+  bool decodeHeader() {

+    int bits = input.readUint24();

+

+    final bool keyFrame = (bits & 1) == 0;

+    if (!keyFrame) {

+      return false;

+    }

+

+    if (((bits >> 1) & 7) > 3) {

+      return false; // unknown profile

+    }

+

+    if (((bits >> 4) & 1) == 0) {

+      return false; // first frame is invisible!

+    }

+

+    _frameHeader.keyFrame = (bits & 1) == 0;

+    _frameHeader.profile = (bits >> 1) & 7;

+    _frameHeader.show = (bits >> 4) & 1;

+    _frameHeader.partitionLength = (bits >> 5);

+

+    int signature = input.readUint24();

+    if (signature != VP8_SIGNATURE) {

+      return false;

+    }

+

+    webp.width = input.readUint16();

+    webp.height = input.readUint16();

+

+    return true;

+  }

+

+  Image decode() {

+    if (!_getHeaders()) {

+      return null;

+    }

+

+    output = Image(webp.width, webp.height);

+

+    // Will allocate memory and prepare everything.

+    if (!_initFrame()) {

+      return null;

+    }

+

+    // Main decoding loop

+    if (!_parseFrame()) {

+      return null;

+    }

+

+    return output;

+  }

+

+  bool _getHeaders() {

+    if (!decodeHeader()) {

+      return false;

+    }

+

+    _proba = VP8Proba();

+    for (int i = 0; i < NUM_MB_SEGMENTS; ++i) {

+      _dqm[i] = VP8QuantMatrix();

+    }

+

+    _picHeader.width = webp.width;

+    _picHeader.height = webp.height;

+    _picHeader.xscale = (webp.width >> 8) >> 6;

+    _picHeader.yscale = (webp.height >> 8) >> 6;

+

+    _cropTop = 0;

+    _cropLeft = 0;

+    _cropRight = webp.width;

+    _cropBottom = webp.height;

+

+    _mbWidth = (webp.width + 15) >> 4;

+    _mbHeight = (webp.height + 15) >> 4;

+

+    _segment = 0;

+

+    br = VP8BitReader(input.subset(_frameHeader.partitionLength));

+    input.skip(_frameHeader.partitionLength);

+

+    _picHeader.colorspace = br.get();

+    _picHeader.clampType = br.get();

+

+    if (!_parseSegmentHeader(_segmentHeader, _proba)) {

+      return false;

+    }

+

+    // Filter specs

+    if (!_parseFilterHeader()) {

+      return false;

+    }

+

+    if (!_parsePartitions(input)) {

+      return false;

+    }

+

+    // quantizer change

+    _parseQuant();

+

+    // Frame buffer marking

+    br.get();   // ignore the value of update_proba_

+

+    _parseProba();

+

+    return true;

+  }

+

+  bool _parseSegmentHeader(VP8SegmentHeader hdr, VP8Proba proba) {

+    hdr.useSegment = br.get() != 0;

+    if (hdr.useSegment) {

+      hdr.updateMap = br.get() != 0;

+      if (br.get() != 0) {   // update data

+        hdr.absoluteDelta = br.get() != 0;

+        for (int s = 0; s < NUM_MB_SEGMENTS; ++s) {

+          hdr.quantizer[s] = br.get() != 0 ? br.getSignedValue(7) : 0;

+        }

+        for (int s = 0; s < NUM_MB_SEGMENTS; ++s) {

+          hdr.filterStrength[s] = br.get() != 0 ? br.getSignedValue(6) : 0;

+        }

+      }

+      if (hdr.updateMap) {

+        for (int s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {

+          proba.segments[s] = br.get() != 0 ? br.getValue(8) : 255;

+        }

+      }

+    } else {

+      hdr.updateMap = false;

+    }

+

+    return true;

+  }

+

+  bool _parseFilterHeader() {

+    VP8FilterHeader hdr = _filterHeader;

+    hdr.simple = br.get() != 0;

+    hdr.level = br.getValue(6);

+    hdr.sharpness = br.getValue(3);

+    hdr.useLfDelta = br.get() != 0;

+    if (hdr.useLfDelta) {

+      if (br.get() != 0) {   // update lf-delta?

+        for (int i = 0; i < NUM_REF_LF_DELTAS; ++i) {

+          if (br.get() != 0) {

+            hdr.refLfDelta[i] = br.getSignedValue(6);

+          }

+        }

+

+        for (int i = 0; i < NUM_MODE_LF_DELTAS; ++i) {

+          if (br.get() != 0) {

+            hdr.modeLfDelta[i] = br.getSignedValue(6);

+          }

+        }

+      }

+    }

+

+    _filterType = (hdr.level == 0) ? 0 : hdr.simple ? 1 : 2;

+

+    return true;

+  }

+

+  /**

+   * This function returns VP8_STATUS_SUSPENDED if we don't have all the

+   * necessary data in 'buf'.

+   * This case is not necessarily an error (for incremental decoding).

+   * Still, no bitreader is ever initialized to make it possible to read

+   * unavailable memory.

+   * If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA

+   * is returned, and this is an unrecoverable error.

+   * If the partitions were positioned ok, VP8_STATUS_OK is returned.

+   */

+  bool _parsePartitions(InputBuffer input) {

+    int sz = 0;

+    int bufEnd = input.length;

+

+    _numPartitions = 1 << br.getValue(2);

+    int lastPart = _numPartitions - 1;

+    int partStart = lastPart * 3;

+    if (bufEnd < partStart) {

+      // we can't even read the sizes with sz[]! That's a failure.

+      return false;

+    }

+

+    for (int p = 0; p < lastPart; ++p) {

+      InputBuffer szb = input.peekBytes(3, sz);

+      final int psize = szb[0] | (szb[1] << 8) | (szb[2] << 16);

+      int partEnd = partStart + psize;

+      if (partEnd > bufEnd) {

+        partEnd = bufEnd;

+      }

+

+      InputBuffer pin = input.subset(partEnd - partStart, position: partStart);

+      _partitions[p] = VP8BitReader(pin);

+      partStart = partEnd;

+      sz += 3;

+    }

+

+    InputBuffer pin = input.subset(bufEnd - partStart,

+                                   position: input.position + partStart);

+    _partitions[lastPart] = VP8BitReader(pin);

+

+    // Init is ok, but there's not enough data

+    return (partStart < bufEnd) ? true : false;

+  }

+

+  void _parseQuant() {

+    final int base_q0 = br.getValue(7);

+    final int dqy1_dc = br.get() != 0 ? br.getSignedValue(4) : 0;

+    final int dqy2_dc = br.get() != 0 ? br.getSignedValue(4) : 0;

+    final int dqy2_ac = br.get() != 0 ? br.getSignedValue(4) : 0;

+    final int dquv_dc = br.get() != 0 ? br.getSignedValue(4) : 0;

+    final int dquv_ac = br.get() != 0 ? br.getSignedValue(4) : 0;

+

+    VP8SegmentHeader hdr = _segmentHeader;

+

+    for (int i = 0; i < NUM_MB_SEGMENTS; ++i) {

+      int q;

+      if (hdr.useSegment) {

+        q = hdr.quantizer[i];

+        if (!hdr.absoluteDelta) {

+          q += base_q0;

+        }

+      } else {

+        if (i > 0) {

+          _dqm[i] = _dqm[0];

+          continue;

+        } else {

+          q = base_q0;

+        }

+      }

+

+      VP8QuantMatrix m = _dqm[i];

+      m.y1Mat[0] = DC_TABLE[_clip(q + dqy1_dc, 127)];

+      m.y1Mat[1] = AC_TABLE[_clip(q + 0,       127)];

+

+      m.y2Mat[0] = DC_TABLE[_clip(q + dqy2_dc, 127)] * 2;

+      // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16.

+      // The smallest precision for that is '(x*6349) >> 12' but 16 is a good

+      // word size.

+      m.y2Mat[1] = (AC_TABLE[_clip(q + dqy2_ac, 127)] * 101581) >> 16;

+      if (m.y2Mat[1] < 8) {

+        m.y2Mat[1] = 8;

+      }

+

+      m.uvMat[0] = DC_TABLE[_clip(q + dquv_dc, 117)];

+      m.uvMat[1] = AC_TABLE[_clip(q + dquv_ac, 127)];

+

+      m.uvQuant = q + dquv_ac;   // for dithering strength evaluation

+    }

+  }

+

+  void _parseProba() {

+    VP8Proba proba = _proba;

+    for (int t = 0; t < NUM_TYPES; ++t) {

+      for (int b = 0; b < NUM_BANDS; ++b) {

+        for (int c = 0; c < NUM_CTX; ++c) {

+          for (int p = 0; p < NUM_PROBAS; ++p) {

+            final int v = br.getBit(COEFFS_UPDATE_PROBA[t][b][c][p]) != 0 ?

+                br.getValue(8) : COEFFS_PROBA_0[t][b][c][p];

+                proba.bands[t][b].probas[c][p] = v;

+          }

+        }

+      }

+    }

+

+    _useSkipProba = br.get() != 0;

+    if (_useSkipProba) {

+      _skipP = br.getValue(8);

+    }

+  }

+

+  /**

+   * Precompute the filtering strength for each segment and each i4x4/i16x16

+   * mode.

+   */

+  void _precomputeFilterStrengths() {

+    if (_filterType > 0) {

+      VP8FilterHeader hdr = _filterHeader;

+      for (int s = 0; s < NUM_MB_SEGMENTS; ++s) {

+        // First, compute the initial level

+        int baseLevel;

+        if (_segmentHeader.useSegment) {

+          baseLevel = _segmentHeader.filterStrength[s];

+          if (!_segmentHeader.absoluteDelta) {

+            baseLevel += hdr.level;

+          }

+        } else {

+          baseLevel = hdr.level;

+        }

+

+        for (int i4x4 = 0; i4x4 <= 1; ++i4x4) {

+          VP8FInfo info = _fStrengths[s][i4x4];

+          int level = baseLevel;

+          if (hdr.useLfDelta) {

+            level += hdr.refLfDelta[0];

+            if (i4x4 != 0) {

+              level += hdr.modeLfDelta[0];

+            }

+          }

+

+          level = (level < 0) ? 0 : (level > 63) ? 63 : level;

+          if (level > 0) {

+            int ilevel = level;

+            if (hdr.sharpness > 0) {

+              if (hdr.sharpness > 4) {

+                ilevel >>= 2;

+              } else {

+                ilevel >>= 1;

+              }

+

+              if (ilevel > 9 - hdr.sharpness) {

+                ilevel = 9 - hdr.sharpness;

+              }

+            }

+

+            if (ilevel < 1) {

+              ilevel = 1;

+            }

+

+            info.fInnerLevel = ilevel;

+            info.fLimit = 2 * level + ilevel;

+            info.hevThresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;

+          } else {

+            info.fLimit = 0;  // no filtering

+          }

+

+          info.fInner = i4x4 != 0;

+        }

+      }

+    }

+  }

+

+  bool _initFrame() {

+    if (_webp.alphaData != null) {

+      _alphaData = _webp.alphaData;

+    }

+

+    _fStrengths = List<List<VP8FInfo>>(NUM_MB_SEGMENTS);

+    for (int i = 0; i < NUM_MB_SEGMENTS; ++i) {

+      _fStrengths[i] = [new VP8FInfo(), new VP8FInfo()];

+    }

+

+    _yuvT = List<VP8TopSamples>(_mbWidth);

+    for (int i = 0; i < _mbWidth; ++i) {

+      _yuvT[i] = VP8TopSamples();

+    }

+

+    _yuvBlock = Uint8List(YUV_SIZE);

+

+    _intraT = Uint8List(4 * _mbWidth);

+

+    _cacheYStride = 16 * _mbWidth;

+    _cacheUVStride = 8 * _mbWidth;

+

+    final int extra_rows = FILTER_EXTRA_ROWS[_filterType];

+    final int extra_y = extra_rows * _cacheYStride;

+    final int extra_uv = (extra_rows ~/ 2) * _cacheUVStride;

+

+    _cacheY = InputBuffer(new Uint8List(16 * _cacheYStride + extra_y),

+                         offset: extra_y);

+

+    _cacheU = InputBuffer(new Uint8List(8 * _cacheUVStride + extra_uv),

+                         offset: extra_uv);

+

+    _cacheV = InputBuffer(new Uint8List(8 * _cacheUVStride + extra_uv),

+                         offset: extra_uv);

+

+    _tmpY = InputBuffer(new Uint8List(webp.width));

+

+    final int uvWidth = (webp.width + 1) >> 1;

+    _tmpU = InputBuffer(new Uint8List(uvWidth));

+    _tmpV = InputBuffer(new Uint8List(uvWidth));

+

+    // Define the area where we can skip in-loop filtering, in case of cropping.

+    //

+    // 'Simple' filter reads two luma samples outside of the macroblock

+    // and filters one. It doesn't filter the chroma samples. Hence, we can

+    // avoid doing the in-loop filtering before crop_top/crop_left position.

+    // For the 'Complex' filter, 3 samples are read and up to 3 are filtered.

+    // Means: there's a dependency chain that goes all the way up to the

+    // top-left corner of the picture (MB #0). We must filter all the previous

+    // macroblocks.

+    {

+      final int extraPixels = FILTER_EXTRA_ROWS[_filterType];

+      if (_filterType == 2) {

+        // For complex filter, we need to preserve the dependency chain.

+        _tlMbX = 0;

+        _tlMbY = 0;

+      } else {

+        // For simple filter, we can filter only the cropped region.

+        // We include 'extra_pixels' on the other side of the boundary, since

+        // vertical or horizontal filtering of the previous macroblock can

+        // modify some abutting pixels.

+        _tlMbX = (_cropLeft - extraPixels) ~/ 16;

+        _tlMbY = (_cropTop - extraPixels) ~/ 16;

+        if (_tlMbX < 0) {

+          _tlMbX = 0;

+        }

+        if (_tlMbY < 0) {

+          _tlMbY = 0;

+        }

+      }

+

+      // We need some 'extra' pixels on the right/bottom.

+      _brMbY = (_cropBottom + 15 + extraPixels) ~/ 16;

+      _brMbX = (_cropRight + 15 + extraPixels) ~/ 16;

+      if (_brMbX > _mbWidth) {

+        _brMbX = _mbWidth;

+      }

+      if (_brMbY > _mbHeight) {

+        _brMbY = _mbHeight;

+      }

+    }

+

+    _mbInfo = List<VP8MB>(_mbWidth + 1);

+    _mbData = List<VP8MBData>(_mbWidth);

+    _fInfo = List<VP8FInfo>(_mbWidth);

+

+    for (int i = 0; i < _mbWidth; ++i) {

+      _mbInfo[i] = VP8MB();

+      _mbData[i] = VP8MBData();

+    }

+    _mbInfo[_mbWidth] = VP8MB();

+

+    _precomputeFilterStrengths();

+

+    // Init critical function pointers and look-up tables.

+    _dsp = VP8Filter();

+    return true;

+  }

+

+  bool _parseFrame() {

+    for (_mbY = 0; _mbY < _brMbY; ++_mbY) {

+      // Parse bitstream for this row.

+      VP8BitReader tokenBr = _partitions[_mbY & (_numPartitions - 1)];

+      for (; _mbX < _mbWidth; ++_mbX) {

+        if (!_decodeMB(tokenBr)) {

+          return false;

+        }

+      }

+

+      // Prepare for next scanline

+      VP8MB left = _mbInfo[0];

+      left.nz = 0;

+      left.nzDc = 0;

+      _intraL.fillRange(0, _intraL.length, B_DC_PRED);

+      _mbX = 0;

+

+      // Reconstruct, filter and emit the row.

+      if (!_processRow()) {

+        return false;

+      }

+    }

+

+    return true;

+  }

+

+  bool _processRow() {

+    _reconstructRow();

+

+    bool useFilter = (_filterType > 0) && (_mbY >= _tlMbY) && (_mbY <= _brMbY);

+    return _finishRow(useFilter);

+  }

+

+  void _reconstructRow() {

+    int mb_y = _mbY;

+    InputBuffer y_dst = InputBuffer(_yuvBlock, offset: Y_OFF);

+    InputBuffer u_dst = InputBuffer(_yuvBlock, offset: U_OFF);

+    InputBuffer v_dst = InputBuffer(_yuvBlock, offset: V_OFF);

+

+    for (int mb_x = 0; mb_x < _mbWidth; ++mb_x) {

+      VP8MBData block = _mbData[mb_x];

+

+      // Rotate in the left samples from previously decoded block. We move four

+      // pixels at a time for alignment reason, and because of in-loop filter.

+      if (mb_x > 0) {

+        for (int j = -1; j < 16; ++j) {

+          y_dst.memcpy(j * BPS - 4, 4, y_dst, j * BPS + 12);

+        }

+

+        for (int j = -1; j < 8; ++j) {

+          u_dst.memcpy(j * BPS - 4, 4, u_dst, j * BPS + 4);

+          v_dst.memcpy(j * BPS - 4, 4, v_dst, j * BPS + 4);

+        }

+      } else {

+        for (int j = 0; j < 16; ++j) {

+          y_dst[j * BPS - 1] = 129;

+        }

+

+        for (int j = 0; j < 8; ++j) {

+          u_dst[j * BPS - 1] = 129;

+          v_dst[j * BPS - 1] = 129;

+        }

+

+        // Init top-left sample on left column too

+        if (mb_y > 0) {

+          y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129;

+        }

+      }

+

+      // bring top samples into the cache

+      VP8TopSamples top_yuv = _yuvT[mb_x];

+      Int16List coeffs = block.coeffs;

+      int bits = block.nonZeroY;

+

+      if (mb_y > 0) {

+        y_dst.memcpy(-BPS, 16, top_yuv.y);

+        u_dst.memcpy(-BPS, 8, top_yuv.u);

+        v_dst.memcpy(-BPS, 8, top_yuv.v);

+      } else if (mb_x == 0) {

+        // we only need to do this init once at block (0,0).

+        // Afterward, it remains valid for the whole topmost row.

+        y_dst.memset(-BPS - 1, 16 + 4 + 1, 127);

+        u_dst.memset(-BPS - 1, 8 + 1, 127);

+        v_dst.memset(-BPS - 1, 8 + 1, 127);

+      }

+

+      // predict and add residuals

+      if (block.isIntra4x4) {   // 4x4

+        InputBuffer topRight = InputBuffer.from(y_dst, offset: -BPS + 16);

+        Uint32List topRight32 = topRight.toUint32List();

+

+        if (mb_y > 0) {

+          if (mb_x >= _mbWidth - 1) { // on rightmost border

+            topRight.memset(0, 4, top_yuv.y[15]);

+          } else {

+            topRight.memcpy(0, 4, _yuvT[mb_x + 1].y);

+          }

+        }

+

+        // replicate the top-right pixels below

+        int p = topRight32[0];

+        topRight32[3 * BPS] = p;

+        topRight32[2 * BPS] = p;

+        topRight32[BPS] = p;

+

+        // predict and add residuals for all 4x4 blocks in turn.

+        for (int n = 0; n < 16; ++n, bits = (bits << 2) & 0xffffffff) {

+          InputBuffer dst = InputBuffer.from(y_dst, offset: kScan[n]);

+

+          VP8Filter.PredLuma4[block.imodes[n]](dst);

+

+          _doTransform(bits, new InputBuffer(coeffs, offset: n * 16), dst);

+        }

+      } else { // 16x16

+        int predFunc = _checkMode(mb_x, mb_y, block.imodes[0]);

+

+        VP8Filter.PredLuma16[predFunc](y_dst);

+        if (bits != 0) {

+          for (int n = 0; n < 16; ++n, bits = (bits << 2) & 0xffffffff) {

+            InputBuffer dst = InputBuffer.from(y_dst, offset: kScan[n]);

+

+            _doTransform(bits, new InputBuffer(coeffs, offset: n * 16), dst);

+          }

+        }

+      }

+

+      // Chroma

+      int bits_uv = block.nonZeroUV;

+      int pred_func = _checkMode(mb_x, mb_y, block.uvmode);

+      VP8Filter.PredChroma8[pred_func](u_dst);

+      VP8Filter.PredChroma8[pred_func](v_dst);

+

+      InputBuffer c1 = InputBuffer(coeffs, offset: 16 * 16);

+      _doUVTransform(bits_uv, c1, u_dst);

+

+      InputBuffer c2 = InputBuffer(coeffs, offset: 20 * 16);

+      _doUVTransform(bits_uv >> 8, c2, v_dst);

+

+      // stash away top samples for next block

+      if (mb_y < _mbHeight - 1) {

+        top_yuv.y.setRange(0, 16, y_dst.toUint8List(), 15 * BPS);

+        top_yuv.u.setRange(0, 8, u_dst.toUint8List(), 7 * BPS);

+        top_yuv.v.setRange(0, 8, v_dst.toUint8List(), 7 * BPS);

+      }

+

+      // Transfer reconstructed samples from yuv_b_ cache to final destination.

+      int y_out = mb_x * 16; // dec->cache_y_ +

+      int u_out = mb_x * 8; // dec->cache_u_ +

+      int v_out = mb_x * 8; // _dec->cache_v_ +

+

+      for (int j = 0; j < 16; ++j) {

+        int start = y_out + j * _cacheYStride;

+        _cacheY.memcpy(start, 16, y_dst, j * BPS);

+      }

+

+      for (int j = 0; j < 8; ++j) {

+        int start = u_out + j * _cacheUVStride;

+        _cacheU.memcpy(start, 8, u_dst, j * BPS);

+

+        start = v_out + j * _cacheUVStride;

+        _cacheV.memcpy(start, 8, v_dst, j * BPS);

+      }

+    }

+  }

+

+  static const List<int> kScan = const [

+    0 +  0 * BPS,  4 +  0 * BPS, 8 +  0 * BPS, 12 +  0 * BPS,

+    0 +  4 * BPS,  4 +  4 * BPS, 8 +  4 * BPS, 12 +  4 * BPS,

+    0 +  8 * BPS,  4 +  8 * BPS, 8 +  8 * BPS, 12 +  8 * BPS,

+    0 + 12 * BPS,  4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS ];

+

+  static int _checkMode(int mb_x, int mb_y, int mode) {

+    if (mode == B_DC_PRED) {

+      if (mb_x == 0) {

+        return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT;

+      } else {

+        return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED;

+      }

+    }

+    return mode;

+  }

+

+  void _doTransform(int bits, InputBuffer src, InputBuffer dst) {

+    switch (bits >> 30) {

+      case 3:

+        _dsp.transform(src, dst, false);

+        break;

+      case 2:

+        _dsp.transformAC3(src, dst);

+        break;

+      case 1:

+        _dsp.transformDC(src, dst);

+        break;

+      default:

+        break;

+    }

+  }

+

+  void _doUVTransform(int bits, InputBuffer src, InputBuffer dst) {

+    if (bits & 0xff != 0) { // any non-zero coeff at all?

+      if (bits & 0xaa != 0) { // any non-zero AC coefficient?

+        // note we don't use the AC3 variant for U/V

+        _dsp.transformUV(src, dst);

+      } else {

+        _dsp.transformDCUV(src, dst);

+      }

+    }

+  }

+

+  // vertical position of a MB

+  int MACROBLOCK_VPOS(int mb_y) => mb_y * 16;

+

+  /**

+   * kFilterExtraRows[] = How many extra lines are needed on the MB boundary

+   * for caching, given a filtering level.

+   * Simple filter:  up to 2 luma samples are read and 1 is written.

+   * Complex filter: up to 4 luma samples are read and 3 are written. Same for

+   *                U/V, so it's 8 samples total (because of the 2x upsampling).

+   */

+  static const List<int> kFilterExtraRows = const [ 0, 2, 8 ];

+

+  void _doFilter(int mbX, int mbY) {

+    final int yBps = _cacheYStride;

+    VP8FInfo fInfo = _fInfo[mbX];

+    InputBuffer yDst = InputBuffer.from(_cacheY, offset: mbX * 16);

+    final int ilevel = fInfo.fInnerLevel;

+    final int limit = fInfo.fLimit;

+    if (limit == 0) {

+      return;

+    }

+

+    if (_filterType == 1) {   // simple

+      if (mbX > 0) {

+        _dsp.simpleHFilter16(yDst, yBps, limit + 4);

+      }

+      if (fInfo.fInner) {

+        _dsp.simpleHFilter16i(yDst, yBps, limit);

+      }

+      if (mbY > 0) {

+        _dsp.simpleVFilter16(yDst, yBps, limit + 4);

+      }

+      if (fInfo.fInner) {

+        _dsp.simpleVFilter16i(yDst, yBps, limit);

+      }

+    } else {    // complex

+      final int uvBps = _cacheUVStride;

+      InputBuffer uDst = InputBuffer.from(_cacheU, offset: mbX * 8);

+      InputBuffer vDst = InputBuffer.from(_cacheV, offset: mbX * 8);

+

+      final int hevThresh = fInfo.hevThresh;

+      if (mbX > 0) {

+        _dsp.hFilter16(yDst, yBps, limit + 4, ilevel, hevThresh);

+        _dsp.hFilter8(uDst, vDst, uvBps, limit + 4, ilevel, hevThresh);

+      }

+      if (fInfo.fInner) {

+        _dsp.hFilter16i(yDst, yBps, limit, ilevel, hevThresh);

+        _dsp.hFilter8i(uDst, vDst, uvBps, limit, ilevel, hevThresh);

+      }

+      if (mbY > 0) {

+        _dsp.vFilter16(yDst, yBps, limit + 4, ilevel, hevThresh);

+        _dsp.vFilter8(uDst, vDst, uvBps, limit + 4, ilevel, hevThresh);

+      }

+      if (fInfo.fInner) {

+        _dsp.vFilter16i(yDst, yBps, limit, ilevel, hevThresh);

+        _dsp.vFilter8i(uDst, vDst, uvBps, limit, ilevel, hevThresh);

+      }

+    }

+  }

+

+  /**

+   * Filter the decoded macroblock row (if needed)

+   */

+  void _filterRow() {

+    for (int mbX = _tlMbX; mbX < _brMbX; ++mbX) {

+      _doFilter(mbX, _mbY);

+    }

+  }

+

+  void _ditherRow() {

+  }

+

+

+  /**

+   * This function is called after a row of macroblocks is finished decoding.

+   * It also takes into account the following restrictions:

+   *

+   * * In case of in-loop filtering, we must hold off sending some of the bottom

+   *    pixels as they are yet unfiltered. They will be when the next macroblock

+   *    row is decoded. Meanwhile, we must preserve them by rotating them in the

+   *    cache area. This doesn't hold for the very bottom row of the uncropped

+   *    picture of course.

+   *  * we must clip the remaining pixels against the cropping area. The VP8Io

+   *    struct must have the following fields set correctly before calling put():

+   */

+  bool _finishRow(bool useFilter) {

+    final int extraYRows = kFilterExtraRows[_filterType];

+    final int ySize = extraYRows * _cacheYStride;

+    final int uvSize = (extraYRows ~/ 2) * _cacheUVStride;

+    InputBuffer yDst = InputBuffer.from(_cacheY, offset: -ySize);

+    InputBuffer uDst = InputBuffer.from(_cacheU, offset: -uvSize);

+    InputBuffer vDst = InputBuffer.from(_cacheV, offset: -uvSize);

+    final int mbY = _mbY;

+    final bool isFirstRow = (mbY == 0);

+    final bool isLastRow = (mbY >= _brMbY - 1);

+    int yStart = MACROBLOCK_VPOS(mbY);

+    int yEnd = MACROBLOCK_VPOS(mbY + 1);

+

+    if (useFilter) {

+      _filterRow();

+    }

+

+    if (_dither) {

+      _ditherRow();

+    }

+

+    if (!isFirstRow) {

+      yStart -= extraYRows;

+      _y = InputBuffer.from(yDst);

+      _u = InputBuffer.from(uDst);

+      _v = InputBuffer.from(vDst);

+    } else {

+      _y = InputBuffer.from(_cacheY);

+      _u = InputBuffer.from(_cacheU);

+      _v = InputBuffer.from(_cacheV);

+    }

+

+    if (!isLastRow) {

+      yEnd -= extraYRows;

+    }

+

+    if (yEnd > _cropBottom) {

+      yEnd = _cropBottom;    // make sure we don't overflow on last row.

+    }

+

+    _a = null;

+    if (_alphaData != null && yStart < yEnd) {

+      _a = _decompressAlphaRows(yStart, yEnd - yStart);

+      if (_a == null) {

+        return false;

+      }

+    }

+

+    if (yStart < _cropTop) {

+      final int deltaY = _cropTop - yStart;

+      yStart = _cropTop;

+

+      _y.offset += _cacheYStride * deltaY;

+      _u.offset += _cacheUVStride * (deltaY >> 1);

+      _v.offset += _cacheUVStride * (deltaY >> 1);

+

+      if (_a != null) {

+        _a.offset += webp.width * deltaY;

+      }

+    }

+

+    if (yStart < yEnd) {

+      _y.offset += _cropLeft;

+      _u.offset += _cropLeft >> 1;

+      _v.offset += _cropLeft >> 1;

+      if (_a != null) {

+        _a.offset += _cropLeft;

+      }

+

+      _put(yStart - _cropTop, _cropRight - _cropLeft, yEnd - yStart);

+    }

+

+    // rotate top samples if needed

+    if (!isLastRow) {

+      _cacheY.memcpy(-ySize, ySize, yDst, 16 * _cacheYStride);

+      _cacheU.memcpy(-uvSize, uvSize, uDst, 8 * _cacheUVStride);

+      _cacheV.memcpy(-uvSize, uvSize, vDst, 8 * _cacheUVStride);

+    }

+

+    return true;

+  }

+

+  bool _put(int mbY, int mbW, int mbH) {

+    if (mbW <= 0 || mbH <= 0) {

+      return false;

+    }

+

+    /*int numLinesOut =*/ _emitFancyRGB(mbY, mbW, mbH);

+    _emitAlphaRGB(mbY, mbW, mbH);

+

+    //_lastY += numLinesOut;

+

+    return true;

+  }

+

+  int _clip8(int v) {

+    int d = ((v & XOR_YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255;

+    return d;

+  }

+

+  int _yuvToR(int y, int v) {

+    return _clip8(kYScale * y + kVToR * v + kRCst);

+  }

+

+  int _yuvToG(int y, int u, int v) {

+    return _clip8(kYScale * y - kUToG * u - kVToG * v + kGCst);

+  }

+

+  int _yuvToB(int y, int u) {

+    return _clip8(kYScale * y + kUToB * u + kBCst);

+  }

+

+  void _yuvToRgb(int y, int u, int v, InputBuffer rgb) {

+    rgb[2] = _yuvToR(y, v);

+    rgb[1] = _yuvToG(y, u, v);

+    rgb[0] = _yuvToB(y, u);

+  }

+

+  void _yuvToRgba(int y, int u, int v, InputBuffer rgba) {

+    _yuvToRgb(y, u, v, rgba);

+    rgba[3] = 0xff;

+  }

+

+  void _upsample(InputBuffer topY, InputBuffer bottomY,

+                 InputBuffer topU, InputBuffer topV,

+                 InputBuffer curU, InputBuffer curV,

+                 InputBuffer topDst, InputBuffer bottomDst,

+                 int len) {

+    int LOAD_UV(int u, int v) => ((u) | ((v) << 16));

+

+    final int lastPixelPair = (len - 1) >> 1;

+    int tl_uv = LOAD_UV(topU[0], topV[0]); // top-left sample

+    int l_uv  = LOAD_UV(curU[0], curV[0]); // left-sample

+

+    final int uv0 = (3 * tl_uv + l_uv + 0x00020002) >> 2;

+    _yuvToRgba(topY[0], uv0 & 0xff, (uv0 >> 16), topDst);

+

+    if (bottomY != null) {

+      final int uv0 = (3 * l_uv + tl_uv + 0x00020002) >> 2;

+      _yuvToRgba(bottomY[0], uv0 & 0xff, (uv0 >> 16), bottomDst);

+    }

+

+    for (int x = 1; x <= lastPixelPair; ++x) {

+      final int t_uv = LOAD_UV(topU[x], topV[x]); // top sample

+      final int uv   = LOAD_UV(curU[x], curV[x]); // sample

+      // precompute invariant values associated with first and second diagonals

+      final int avg = tl_uv + t_uv + l_uv + uv + 0x00080008;

+      final int diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3;

+      final int diag_03 = (avg + 2 * (tl_uv + uv)) >> 3;

+

+      int uv0 = (diag_12 + tl_uv) >> 1;

+      int uv1 = (diag_03 + t_uv) >> 1;

+

+      _yuvToRgba(topY[2 * x - 1], uv0 & 0xff, (uv0 >> 16),

+          new InputBuffer.from(topDst, offset: (2 * x - 1) * 4));

+

+      _yuvToRgba(topY[2 * x - 0], uv1 & 0xff, (uv1 >> 16),

+              new InputBuffer.from(topDst, offset: (2 * x - 0) * 4));

+

+      if (bottomY != null) {

+        uv0 = (diag_03 + l_uv) >> 1;

+        uv1 = (diag_12 + uv) >> 1;

+

+        _yuvToRgba(bottomY[2 * x - 1], uv0 & 0xff, (uv0 >> 16),

+            new InputBuffer.from(bottomDst, offset: (2 * x - 1) * 4));

+

+        _yuvToRgba(bottomY[2 * x], uv1 & 0xff, (uv1 >> 16),

+                new InputBuffer.from(bottomDst, offset: (2 * x + 0) * 4));

+      }

+

+      tl_uv = t_uv;

+      l_uv = uv;

+    }

+

+    if ((len & 1) == 0) {

+      final int uv0 = (3 * tl_uv + l_uv + 0x00020002) >> 2;

+      _yuvToRgba(topY[len - 1], uv0 & 0xff, (uv0 >> 16),

+           new InputBuffer.from(topDst, offset: (len - 1) * 4));

+

+      if (bottomY != null) {

+        final int uv0 = (3 * l_uv + tl_uv + 0x00020002) >> 2;

+        _yuvToRgba(bottomY[len - 1], uv0 & 0xff, (uv0 >> 16),

+             new InputBuffer.from(bottomDst, offset: (len - 1) * 4));

+      }

+    }

+  }

+

+  void _emitAlphaRGB(int mbY, int mbW, int mbH) {

+    if (_a == null) {

+      return;

+    }

+

+    final int stride = webp.width * 4;

+    InputBuffer alpha = InputBuffer.from(_a);

+    int startY = mbY;

+    int numRows = mbH;

+

+    // Compensate for the 1-line delay of the fancy upscaler.

+    // This is similar to EmitFancyRGB().

+    if (startY == 0) {

+      // We don't process the last row yet. It'll be done during the next call.

+      --numRows;

+    } else {

+      --startY;

+      // Fortunately, *alpha data is persistent, so we can go back

+      // one row and finish alpha blending, now that the fancy upscaler

+      // completed the YUV->RGB interpolation.

+      alpha.offset -= webp.width;

+    }

+

+    InputBuffer dst = InputBuffer(output.getBytes(), offset: startY * stride + 3);

+

+    if (_cropTop + mbY + mbH == _cropBottom) {

+      // If it's the very last call, we process all the remaining rows!

+      numRows = _cropBottom - _cropTop - startY;

+    }

+

+    for (int y = 0; y < numRows; ++y) {

+      for (int x = 0; x < mbW; ++x) {

+        final int alphaValue = alpha[x];

+        dst[4 * x] = alphaValue & 0xff;

+      }

+

+      alpha.offset += webp.width;

+      dst.offset += stride;

+    }

+  }

+

+

+  int _emitFancyRGB(int mbY, int mbW, int mbH) {

+    int numLinesOut = mbH;   // a priori guess

+    InputBuffer dst = InputBuffer(output.getBytes(), offset: mbY * webp.width * 4);

+    InputBuffer curY = InputBuffer.from(_y);

+    InputBuffer curU = InputBuffer.from(_u);

+    InputBuffer curV = InputBuffer.from(_v);

+    int y = mbY;

+    final int yEnd = mbY + mbH;

+    final int uvW = (mbW + 1) >> 1;

+    final int stride = webp.width * 4;

+    InputBuffer topU = InputBuffer.from(_tmpU);

+    InputBuffer topV = InputBuffer.from(_tmpV);

+

+    if (y == 0) {

+      // First line is special cased. We mirror the u/v samples at boundary.

+      _upsample(curY, null, curU, curV, curU, curV, dst, null, mbW);

+    } else {

+      // We can finish the left-over line from previous call.

+      _upsample(_tmpY, curY, topU, topV, curU, curV,

+                new InputBuffer.from(dst, offset: -stride), dst, mbW);

+      ++numLinesOut;

+    }

+

+    // Loop over each output pairs of row.

+    topU.buffer = curU.buffer;

+    topV.buffer = curV.buffer;

+    for (; y + 2 < yEnd; y += 2) {

+      topU.offset = curU.offset;

+      topV.offset = curV.offset;

+      curU.offset += _cacheUVStride;

+      curV.offset += _cacheUVStride;

+      dst.offset += 2 * stride;

+      curY.offset += 2 * _cacheYStride;

+      _upsample(new InputBuffer.from(curY, offset: -_cacheYStride), curY,

+          topU, topV, curU, curV,

+          new InputBuffer.from(dst, offset: -stride), dst, mbW);

+    }

+

+    // move to last row

+    curY.offset += _cacheYStride;

+    if (_cropTop + yEnd < _cropBottom) {

+      // Save the unfinished samples for next call (as we're not done yet).

+      _tmpY.memcpy(0, mbW, curY);

+      _tmpU.memcpy(0, uvW, curU);

+      _tmpV.memcpy(0, uvW, curV);

+      // The fancy upsampler leaves a row unfinished behind

+      // (except for the very last row)

+      numLinesOut--;

+    } else {

+      // Process the very last row of even-sized picture

+      if ((yEnd & 1) == 0) {

+        _upsample(curY, null, curU, curV, curU, curV,

+            new InputBuffer.from(dst, offset: stride), null, mbW);

+      }

+    }

+

+    return numLinesOut;

+  }

+

+  InputBuffer _decompressAlphaRows(int row, int numRows) {

+    final int width = webp.width;

+    final int height = webp.height;

+

+    if (row < 0 || numRows <= 0 || row + numRows > height) {

+      return null;    // sanity check.

+    }

+

+    if (row == 0) {

+      _alphaPlane = Uint8List(width * height);

+      _alpha = WebPAlpha(_alphaData, width, height);

+    }

+

+    if (!_alpha.isAlphaDecoded) {

+      if (!_alpha.decode(row, numRows, _alphaPlane)) {

+        return null;

+      }

+    }

+

+    // Return a pointer to the current decoded row.

+    return new InputBuffer(_alphaPlane, offset: row * width);

+  }

+

+  bool _decodeMB(VP8BitReader tokenBr) {

+    VP8MB left = _mbInfo[0];

+    VP8MB mb = _mbInfo[1 + _mbX];

+    VP8MBData block = _mbData[_mbX];

+    bool skip;

+

+    // Note: we don't save segment map (yet), as we don't expect

+    // to decode more than 1 keyframe.

+    if (_segmentHeader.updateMap) {

+      // Hardcoded tree parsing

+      _segment = br.getBit(_proba.segments[0]) == 0 ?

+            br.getBit(_proba.segments[1]) :

+            2 + br.getBit(_proba.segments[2]);

+    }

+

+    skip = _useSkipProba ? br.getBit(_skipP) != 0 : false;

+

+    _parseIntraMode();

+

+    if (!skip) {

+      skip = _parseResiduals(mb, tokenBr);

+    } else {

+      left.nz = mb.nz = 0;

+      if (!block.isIntra4x4) {

+        left.nzDc = mb.nzDc = 0;

+      }

+      block.nonZeroY = 0;

+      block.nonZeroUV = 0;

+    }

+

+    if (_filterType > 0) {  // store filter info

+      _fInfo[_mbX] = _fStrengths[_segment][block.isIntra4x4 ? 1 : 0];

+      VP8FInfo finfo = _fInfo[_mbX];

+      finfo.fInner = finfo.fInner || !skip;

+    }

+

+    return true;

+  }

+

+  bool _parseResiduals(VP8MB mb, VP8BitReader tokenBr) {

+    var bands = _proba.bands;

+    List<VP8BandProbas> acProba;

+    VP8QuantMatrix q = _dqm[_segment];

+    VP8MBData block = _mbData[_mbX];

+    InputBuffer dst = InputBuffer(block.coeffs);

+    //int di = 0;

+    VP8MB leftMb = _mbInfo[0];

+    int tnz;

+    int lnz;

+    int nonZeroY = 0;

+    int nonZeroUV = 0;

+    int outTopNz;

+    int outLeftNz;

+    int first;

+

+    dst.memset(0, dst.length, 0);

+

+    if (!block.isIntra4x4) {    // parse DC

+      InputBuffer dc = InputBuffer(new Int16List(16));

+      final int ctx = mb.nzDc + leftMb.nzDc;

+      final int nz = _getCoeffs(tokenBr, bands[1], ctx, q.y2Mat, 0, dc);

+      mb.nzDc = leftMb.nzDc = (nz > 0) ? 1 : 0;

+      if (nz > 1) {   // more than just the DC -> perform the full transform

+        _transformWHT(dc, dst);

+      } else {        // only DC is non-zero -> inlined simplified transform

+        final int dc0 = (dc[0] + 3) >> 3;

+        for (int i = 0; i < 16 * 16; i += 16) {

+          dst[i] = dc0;

+        }

+      }

+

+      first = 1;

+      acProba = bands[0];

+    } else {

+      first = 0;

+      acProba = bands[3];

+    }

+

+    tnz = mb.nz & 0x0f;

+    lnz = leftMb.nz & 0x0f;

+    for (int y = 0; y < 4; ++y) {

+      int l = lnz & 1;

+      int nzCoeffs = 0;

+      for (int x = 0; x < 4; ++x) {

+        final int ctx = l + (tnz & 1);

+        final int nz = _getCoeffs(tokenBr, acProba, ctx, q.y1Mat, first, dst);

+        l = (nz > first) ? 1 : 0;

+        tnz = (tnz >> 1) | (l << 7);

+        nzCoeffs = _nzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0);

+        dst.offset += 16;

+      }

+

+      tnz >>= 4;

+      lnz = (lnz >> 1) | (l << 7);

+      nonZeroY = (nonZeroY << 8) | nzCoeffs;

+    }

+    outTopNz = tnz;

+    outLeftNz = lnz >> 4;

+

+    for (int ch = 0; ch < 4; ch += 2) {

+      int nzCoeffs = 0;

+      tnz = mb.nz >> (4 + ch);

+      lnz = leftMb.nz >> (4 + ch);

+      for (int y = 0; y < 2; ++y) {

+        int l = lnz & 1;

+        for (int x = 0; x < 2; ++x) {

+          final int ctx = l + (tnz & 1);

+          final int nz = _getCoeffs(tokenBr, bands[2], ctx, q.uvMat, 0, dst);

+          l = (nz > 0) ? 1 : 0;

+          tnz = (tnz >> 1) | (l << 3);

+          nzCoeffs = _nzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0);

+          dst.offset += 16;

+        }

+

+        tnz >>= 2;

+        lnz = (lnz >> 1) | (l << 5);

+      }

+

+      // Note: we don't really need the per-4x4 details for U/V blocks.

+      nonZeroUV |= nzCoeffs << (4 * ch);

+      outTopNz |= (tnz << 4) << ch;

+      outLeftNz |= (lnz & 0xf0) << ch;

+    }

+

+    mb.nz = outTopNz;

+    leftMb.nz = outLeftNz;

+

+    block.nonZeroY = nonZeroY;

+    block.nonZeroUV = nonZeroUV;

+

+    // We look at the mode-code of each block and check if some blocks have less

+    // than three non-zero coeffs (code < 2). This is to avoid dithering flat and

+    // empty blocks.

+    block.dither = (nonZeroUV & 0xaaaa) != 0 ? 0 : q.dither;

+

+    // will be used for further optimization

+    return (nonZeroY | nonZeroUV) == 0;

+  }

+

+  void _transformWHT(InputBuffer src, InputBuffer out) {

+    Int32List tmp = Int32List(16);

+

+    int oi = 0;

+    for (int i = 0; i < 4; ++i) {

+      final int a0 = src[0 + i] + src[12 + i];

+      final int a1 = src[4 + i] + src[ 8 + i];

+      final int a2 = src[4 + i] - src[ 8 + i];

+      final int a3 = src[0 + i] - src[12 + i];

+      tmp[0  + i] = a0 + a1;

+      tmp[8  + i] = a0 - a1;

+      tmp[4  + i] = a3 + a2;

+      tmp[12 + i] = a3 - a2;

+    }

+

+    for (int i = 0; i < 4; ++i) {

+      final int dc = tmp[0 + i * 4] + 3;    // w/ rounder

+      final int a0 = dc             + tmp[3 + i * 4];

+      final int a1 = tmp[1 + i * 4] + tmp[2 + i * 4];

+      final int a2 = tmp[1 + i * 4] - tmp[2 + i * 4];

+      final int a3 = dc             - tmp[3 + i * 4];

+      out[oi + 0] = (a0 + a1) >> 3;

+      out[oi + 16] = (a3 + a2) >> 3;

+      out[oi + 32] = (a0 - a1) >> 3;

+      out[oi + 48] = (a3 - a2) >> 3;

+

+      oi += 64;

+    }

+  }

+

+  int _nzCodeBits(int nz_coeffs, int nz, int dc_nz) {

+    nz_coeffs <<= 2;

+    nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;

+    return nz_coeffs;

+  }

+

+  static const List<int> kBands = const [

+     0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0];

+

+  static const List<int> kCat3 = const [ 173, 148, 140 ];

+  static const List<int> kCat4 = const [ 176, 155, 140, 135 ];

+  static const List<int> kCat5 = const [ 180, 157, 141, 134, 130 ];

+  static const List<int> kCat6 = const [ 254, 254, 243, 230, 196, 177, 153,

+                                         140, 133, 130, 129 ];

+  static const List<List<int>> kCat3456 = const [ kCat3, kCat4, kCat5, kCat6 ];

+  static const List<int> kZigzag = const [ 0, 1, 4, 8,  5, 2, 3, 6,  9, 12,

+                                           13, 10,  7, 11, 14, 15 ];

+

+  /**

+   * See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2

+   */

+  int _getLargeValue(VP8BitReader br, List<int> p) {

+    int v;

+    if (br.getBit(p[3]) == 0) {

+      if (br.getBit(p[4]) == 0) {

+        v = 2;

+      } else {

+        v = 3 + br.getBit(p[5]);

+      }

+    } else {

+      if (br.getBit(p[6]) == 0) {

+        if (br.getBit(p[7]) == 0) {

+          v = 5 + br.getBit(159);

+        } else {

+          v = 7 + 2 * br.getBit(165);

+          v += br.getBit(145);

+        }

+      } else {

+        final int bit1 = br.getBit(p[8]);

+        final int bit0 = br.getBit(p[9 + bit1]);

+        final int cat = 2 * bit1 + bit0;

+        v = 0;

+        List<int> tab = kCat3456[cat];

+        for (int i = 0, len = tab.length; i < len; ++i) {

+          v += v + br.getBit(tab[i]);

+        }

+        v += 3 + (8 << cat);

+      }

+    }

+    return v;

+  }

+

+

+  /**

+   * Returns the position of the last non-zero coeff plus one

+   */

+  int _getCoeffs(VP8BitReader br, List<VP8BandProbas> prob,

+                 int ctx, List<int> dq, int n, InputBuffer out) {

+    // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'.

+    List<int> p = prob[n].probas[ctx];

+    for (; n < 16; ++n) {

+      if (br.getBit(p[0]) == 0) {

+        return n;  // previous coeff was last non-zero coeff

+      }

+

+      while (br.getBit(p[1]) == 0) { // sequence of zero coeffs

+        p = prob[kBands[++n]].probas[0];

+        if (n == 16) {

+          return 16;

+        }

+      }

+

+      { // non zero coeff

+        List<Uint8List> p_ctx = prob[kBands[n + 1]].probas;

+        int v;

+        if (br.getBit(p[2]) == 0) {

+          v = 1;

+          p = p_ctx[1];

+        } else {

+          v = _getLargeValue(br, p);

+          p = p_ctx[2];

+        }

+

+        out[kZigzag[n]] = br.getSigned(v) * dq[n > 0 ? 1 : 0];

+      }

+    }

+    return 16;

+  }

+

+  void _parseIntraMode() {

+    int ti = 4 * _mbX;

+    int li = 0;

+    Uint8List top = _intraT;

+    Uint8List left = _intraL;

+

+    VP8MBData block = _mbData[_mbX];

+

+    // decide for B_PRED first

+    block.isIntra4x4 = br.getBit(145) == 0;

+    if (!block.isIntra4x4) {

+      // Hardcoded 16x16 intra-mode decision tree.

+      final int ymode =

+          br.getBit(156) != 0 ?

+              (br.getBit(128) != 0 ? TM_PRED : H_PRED) :

+              (br.getBit(163) != 0 ? V_PRED : DC_PRED);

+      block.imodes[0] = ymode;

+

+      top.fillRange(ti, ti + 4, ymode);

+      left.fillRange(li, li + 4, ymode);

+    } else {

+      Uint8List modes = block.imodes;

+      int mi = 0;

+      for (int y = 0; y < 4; ++y) {

+        int ymode = left[y];

+        for (int x = 0; x < 4; ++x) {

+          List<int> prob = kBModesProba[top[ti + x]][ymode];

+

+          // Generic tree-parsing

+          int b = br.getBit(prob[0]);

+          int i = kYModesIntra4[b];

+

+          while (i > 0) {

+            i = kYModesIntra4[2 * i + br.getBit(prob[i])];

+          }

+

+          ymode = -i;

+          top[ti + x] = ymode;

+        }

+

+        modes.setRange(mi, mi + 4, top, ti);

+

+        mi += 4;

+        left[y] = ymode;

+      }

+    }

+

+    // Hardcoded UVMode decision tree

+    block.uvmode = br.getBit(142) == 0 ? DC_PRED

+        : br.getBit(114) == 0 ? V_PRED

+            : br.getBit(183) != 0 ? TM_PRED : H_PRED;

+  }

+

+  // Main data source

+  VP8BitReader br;

+

+  Image output;

+

+  VP8Filter _dsp;

+

+  // headers

+  VP8FrameHeader _frameHeader = VP8FrameHeader();

+  VP8PictureHeader _picHeader = VP8PictureHeader();

+  VP8FilterHeader _filterHeader = VP8FilterHeader();

+  VP8SegmentHeader _segmentHeader = VP8SegmentHeader();

+

+  int _cropLeft;

+  int _cropRight;

+  int _cropTop;

+  int _cropBottom;

+

+  /// Width in macroblock units.

+  int _mbWidth;

+  /// Height in macroblock units.

+  int _mbHeight;

+

+  // Macroblock to process/filter, depending on cropping and filter_type.

+  int _tlMbX; // top-left MB that must be in-loop filtered

+  int _tlMbY;

+  int _brMbX; // last bottom-right MB that must be decoded

+  int _brMbY;

+

+  // number of partitions.

+  int _numPartitions;

+  // per-partition boolean decoders.

+  List<VP8BitReader> _partitions = List<VP8BitReader>(MAX_NUM_PARTITIONS);

+

+  // Dithering strength, deduced from decoding options

+  bool _dither = false; // whether to use dithering or not

+  //VP8Random _ditheringRand; // random generator for dithering

+

+  // dequantization (one set of DC/AC dequant factor per segment)

+  List<VP8QuantMatrix> _dqm = List<VP8QuantMatrix>(NUM_MB_SEGMENTS);

+

+  // probabilities

+  VP8Proba _proba;

+  bool _useSkipProba;

+  int _skipP;

+

+  // Boundary data cache and persistent buffers.

+  /// top intra modes values: 4 * _mbWidth

+  Uint8List _intraT;

+  /// left intra modes values

+  Uint8List _intraL = Uint8List(4);

+

+  /// uint8, segment of the currently parsed block

+  int _segment;

+  /// top y/u/v samples

+  List<VP8TopSamples> _yuvT;

+

+  /// contextual macroblock info (mb_w_ + 1)

+  List<VP8MB> _mbInfo;

+  /// filter strength info

+  List<VP8FInfo> _fInfo;

+  /// main block for Y/U/V (size = YUV_SIZE)

+  Uint8List _yuvBlock;

+

+  /// macroblock row for storing unfiltered samples

+  InputBuffer _cacheY;

+  InputBuffer _cacheU;

+  InputBuffer _cacheV;

+  int _cacheYStride;

+  int _cacheUVStride;

+

+  InputBuffer _tmpY;

+  InputBuffer _tmpU;

+  InputBuffer _tmpV;

+

+  InputBuffer _y;

+  InputBuffer _u;

+  InputBuffer _v;

+  InputBuffer _a;

+

+  /// main memory chunk for the above data. Persistent.

+  //Uint8List _mem;

+

+  // Per macroblock non-persistent infos.

+  /// current position, in macroblock units

+  int _mbX = 0;

+  int _mbY = 0;

+  /// parsed reconstruction data

+  List<VP8MBData> _mbData;

+

+  /// 0=off, 1=simple, 2=complex

+  int _filterType;

+  /// precalculated per-segment/type

+  List<List<VP8FInfo>> _fStrengths;

+

+  // Alpha

+  /// alpha-plane decoder object

+  WebPAlpha _alpha;

+  /// compressed alpha data (if present)

+  InputBuffer _alphaData;

+  /// true if alpha_data_ is decoded in alpha_plane_

+  //int _isAlphaDecoded;

+  /// output. Persistent, contains the whole data.

+  Uint8List _alphaPlane;

+

+  // extensions

+  //int _layerColorspace;

+  /// compressed layer data (if present)

+  //Uint8List _layerData;

+

+  static int _clip(int v, int M) {

+    return v < 0 ? 0 : v > M ? M : v;

+  }

+

+  static const List<int> kYModesIntra4 = const [

+    -B_DC_PRED, 1,

+    -B_TM_PRED, 2,

+    -B_VE_PRED, 3,

+    4, 6,

+    -B_HE_PRED, 5,

+    -B_RD_PRED, -B_VR_PRED,

+    -B_LD_PRED, 7,

+    -B_VL_PRED, 8,

+    -B_HD_PRED, -B_HU_PRED ];

+

+  static const List<List<List<int>>> kBModesProba = const [

+     const [ const [ 231, 120, 48, 89, 115, 113, 120, 152, 112 ],

+       const [ 152, 179, 64, 126, 170, 118, 46, 70, 95 ],

+       const [ 175, 69, 143, 80, 85, 82, 72, 155, 103 ],

+       const [ 56, 58, 10, 171, 218, 189, 17, 13, 152 ],

+       const [ 114, 26, 17, 163, 44, 195, 21, 10, 173 ],

+       const [ 121, 24, 80, 195, 26, 62, 44, 64, 85 ],

+       const [ 144, 71, 10, 38, 171, 213, 144, 34, 26 ],

+       const [ 170, 46, 55, 19, 136, 160, 33, 206, 71 ],

+       const [ 63, 20, 8, 114, 114, 208, 12, 9, 226 ],

+       const [ 81, 40, 11, 96, 182, 84, 29, 16, 36 ] ],

+       const [ const [ 134, 183, 89, 137, 98, 101, 106, 165, 148 ],

+         const [ 72, 187, 100, 130, 157, 111, 32, 75, 80 ],

+         const [ 66, 102, 167, 99, 74, 62, 40, 234, 128 ],

+         const [ 41, 53, 9, 178, 241, 141, 26, 8, 107 ],

+         const [ 74, 43, 26, 146, 73, 166, 49, 23, 157 ],

+         const [ 65, 38, 105, 160, 51, 52, 31, 115, 128 ],

+         const [ 104, 79, 12, 27, 217, 255, 87, 17, 7 ],

+         const [ 87, 68, 71, 44, 114, 51, 15, 186, 23 ],

+         const [ 47, 41, 14, 110, 182, 183, 21, 17, 194 ],

+         const [ 66, 45, 25, 102, 197, 189, 23, 18, 22 ] ],

+         const [ const [ 88, 88, 147, 150, 42, 46, 45, 196, 205 ],

+           const [ 43, 97, 183, 117, 85, 38, 35, 179, 61 ],

+           const [ 39, 53, 200, 87, 26, 21, 43, 232, 171 ],

+           const [ 56, 34, 51, 104, 114, 102, 29, 93, 77 ],

+           const [ 39, 28, 85, 171, 58, 165, 90, 98, 64 ],

+           const [ 34, 22, 116, 206, 23, 34, 43, 166, 73 ],

+           const [ 107, 54, 32, 26, 51, 1, 81, 43, 31 ],

+           const [ 68, 25, 106, 22, 64, 171, 36, 225, 114 ],

+           const [ 34, 19, 21, 102, 132, 188, 16, 76, 124 ],

+           const [ 62, 18, 78, 95, 85, 57, 50, 48, 51 ] ],

+           const [ const [ 193, 101, 35, 159, 215, 111, 89, 46, 111 ],

+             const [ 60, 148, 31, 172, 219, 228, 21, 18, 111 ],

+             const [ 112, 113, 77, 85, 179, 255, 38, 120, 114 ],

+             const [ 40, 42, 1, 196, 245, 209, 10, 25, 109 ],

+             const [ 88, 43, 29, 140, 166, 213, 37, 43, 154 ],

+             const [ 61, 63, 30, 155, 67, 45, 68, 1, 209 ],

+             const [ 100, 80, 8, 43, 154, 1, 51, 26, 71 ],

+             const [ 142, 78, 78, 16, 255, 128, 34, 197, 171 ],

+             const [ 41, 40, 5, 102, 211, 183, 4, 1, 221 ],

+             const [ 51, 50, 17, 168, 209, 192, 23, 25, 82 ] ],

+             const [ const [ 138, 31, 36, 171, 27, 166, 38, 44, 229 ],

+               const [ 67, 87, 58, 169, 82, 115, 26, 59, 179 ],

+               const [ 63, 59, 90, 180, 59, 166, 93, 73, 154 ],

+               const [ 40, 40, 21, 116, 143, 209, 34, 39, 175 ],

+               const [ 47, 15, 16, 183, 34, 223, 49, 45, 183 ],

+               const [ 46, 17, 33, 183, 6, 98, 15, 32, 183 ],

+               const [ 57, 46, 22, 24, 128, 1, 54, 17, 37 ],

+               const [ 65, 32, 73, 115, 28, 128, 23, 128, 205 ],

+               const [ 40, 3, 9, 115, 51, 192, 18, 6, 223 ],

+               const [ 87, 37, 9, 115, 59, 77, 64, 21, 47 ] ],

+               const [ const [ 104, 55, 44, 218, 9, 54, 53, 130, 226 ],

+                 const [ 64, 90, 70, 205, 40, 41, 23, 26, 57 ],

+                 const [ 54, 57, 112, 184, 5, 41, 38, 166, 213 ],

+                 const [ 30, 34, 26, 133, 152, 116, 10, 32, 134 ],

+                 const [ 39, 19, 53, 221, 26, 114, 32, 73, 255 ],

+                 const [ 31, 9, 65, 234, 2, 15, 1, 118, 73 ],

+                 const [ 75, 32, 12, 51, 192, 255, 160, 43, 51 ],

+                 const [ 88, 31, 35, 67, 102, 85, 55, 186, 85 ],

+                 const [ 56, 21, 23, 111, 59, 205, 45, 37, 192 ],

+                 const [ 55, 38, 70, 124, 73, 102, 1, 34, 98 ] ],

+                 const [ const [ 125, 98, 42, 88, 104, 85, 117, 175, 82 ],

+                   const [ 95, 84, 53, 89, 128, 100, 113, 101, 45 ],

+                   const [ 75, 79, 123, 47, 51, 128, 81, 171, 1 ],

+                   const [ 57, 17, 5, 71, 102, 57, 53, 41, 49 ],

+                   const [ 38, 33, 13, 121, 57, 73, 26, 1, 85 ],

+                   const [ 41, 10, 67, 138, 77, 110, 90, 47, 114 ],

+                   const [ 115, 21, 2, 10, 102, 255, 166, 23, 6 ],

+                   const [ 101, 29, 16, 10, 85, 128, 101, 196, 26 ],

+                   const [ 57, 18, 10, 102, 102, 213, 34, 20, 43 ],

+                   const [ 117, 20, 15, 36, 163, 128, 68, 1, 26 ] ],

+                   const [ const [ 102, 61, 71, 37, 34, 53, 31, 243, 192 ],

+                     const [ 69, 60, 71, 38, 73, 119, 28, 222, 37 ],

+                     const [ 68, 45, 128, 34, 1, 47, 11, 245, 171 ],

+                     const [ 62, 17, 19, 70, 146, 85, 55, 62, 70 ],

+                     const [ 37, 43, 37, 154, 100, 163, 85, 160, 1 ],

+                     const [ 63, 9, 92, 136, 28, 64, 32, 201, 85 ],

+                     const [ 75, 15, 9, 9, 64, 255, 184, 119, 16 ],

+                     const [ 86, 6, 28, 5, 64, 255, 25, 248, 1 ],

+                     const [ 56, 8, 17, 132, 137, 255, 55, 116, 128 ],

+                     const [ 58, 15, 20, 82, 135, 57, 26, 121, 40 ] ],

+                     const [ const [ 164, 50, 31, 137, 154, 133, 25, 35, 218 ],

+                       const [ 51, 103, 44, 131, 131, 123, 31, 6, 158 ],

+                       const [ 86, 40, 64, 135, 148, 224, 45, 183, 128 ],

+                       const [ 22, 26, 17, 131, 240, 154, 14, 1, 209 ],

+                       const [ 45, 16, 21, 91, 64, 222, 7, 1, 197 ],

+                       const [ 56, 21, 39, 155, 60, 138, 23, 102, 213 ],

+                       const [ 83, 12, 13, 54, 192, 255, 68, 47, 28 ],

+                       const [ 85, 26, 85, 85, 128, 128, 32, 146, 171 ],

+                       const [ 18, 11, 7, 63, 144, 171, 4, 4, 246 ],

+                       const [ 35, 27, 10, 146, 174, 171, 12, 26, 128 ] ],

+                       const [ const [ 190, 80, 35, 99, 180, 80, 126, 54, 45 ],

+                         const [ 85, 126, 47, 87, 176, 51, 41, 20, 32 ],

+                         const [ 101, 75, 128, 139, 118, 146, 116, 128, 85 ],

+                         const [ 56, 41, 15, 176, 236, 85, 37, 9, 62 ],

+                         const [ 71, 30, 17, 119, 118, 255, 17, 18, 138 ],

+                         const [ 101, 38, 60, 138, 55, 70, 43, 26, 142 ],

+                         const [ 146, 36, 19, 30, 171, 255, 97, 27, 20 ],

+                         const [ 138, 45, 61, 62, 219, 1, 81, 188, 64 ],

+                         const [ 32, 41, 20, 117, 151, 142, 20, 21, 163 ],

+                         const [ 112, 19, 12, 61, 195, 128, 48, 4, 24 ] ] ];

+

+  static const List COEFFS_PROBA_0 = const [

+  const [ const [ const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ]

+    ],

+    const [ const [ 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 ],

+      const [ 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 ],

+      const [ 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 ],

+      const [ 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 ],

+      const [ 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 ],

+    ],

+    const [ const [ 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 ],

+      const [ 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 ],

+      const [ 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 ],

+    ],

+    const [ const [ 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 ],

+      const [ 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 ],

+      const [ 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 ],

+      const [ 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 ],

+      const [ 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 ],

+      const [ 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 ],

+      const [ 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ]

+    ]

+  ],

+  const [ const [ const [ 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 ],

+      const [ 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 ],

+      const [ 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 ]

+    ],

+    const [ const [ 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 ],

+      const [ 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 ],

+      const [ 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 ]

+    ],

+    const [ const [ 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 ],

+      const [ 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 ],

+      const [ 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 ]

+    ],

+    const [ const [ 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 ],

+      const [ 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 ],

+      const [ 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 ],

+      const [ 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 ],

+      const [ 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 ],

+      const [ 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 ],

+      const [ 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 ],

+      const [ 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 ],

+      const [ 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 ],

+      const [ 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 ],

+      const [ 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 ]

+    ]

+  ],

+  const [ const [ const [ 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 ],

+      const [ 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 ],

+      const [ 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 ]

+    ],

+    const [ const [ 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 ],

+      const [ 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 ],

+      const [ 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 ],

+      const [ 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 ],

+      const [ 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 ],

+      const [ 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 ],

+      const [ 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 ],

+      const [ 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 ],

+      const [ 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 ],

+      const [ 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 ],

+      const [ 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]

+    ],

+    const [ const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 ]

+    ]

+  ],

+  const [ const [ const [ 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 ],

+      const [ 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 ],

+      const [ 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 ]

+    ],

+    const [ const [ 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 ],

+      const [ 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 ],

+      const [ 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 ]

+    ],

+    const [ const [ 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 ],

+      const [ 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 ],

+      const [ 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 ]

+    ],

+    const [ const [ 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 ],

+      const [ 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 ],

+      const [ 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 ]

+    ],

+    const [ const [ 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 ],

+      const [ 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 ],

+      const [ 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 ],

+      const [ 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 ],

+      const [ 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 ],

+      const [ 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 ],

+      const [ 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 ]

+    ],

+    const [ const [ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ],

+      const [ 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 ]

+    ]

+  ] ];

+

+

+  static const List COEFFS_UPDATE_PROBA = const [

+    const [ const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 ],

+      const [ 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ]

+    ],

+    const [ const [ const [ 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 ],

+      const [ 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ]

+    ],

+    const [ const [ const [ 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ]

+    ],

+    const [ const [ const [ 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ],

+    const [ const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],

+      const [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]

+    ] ] ];

+

+  // Paragraph 14.1

+  static const List<int> DC_TABLE = const [ // uint8

+      4,     5,   6,   7,   8,   9,  10,  10,

+      11,   12,  13,  14,  15,  16,  17,  17,

+      18,   19,  20,  20,  21,  21,  22,  22,

+      23,   23,  24,  25,  25,  26,  27,  28,

+      29,   30,  31,  32,  33,  34,  35,  36,

+      37,   37,  38,  39,  40,  41,  42,  43,

+      44,   45,  46,  46,  47,  48,  49,  50,

+      51,   52,  53,  54,  55,  56,  57,  58,

+      59,   60,  61,  62,  63,  64,  65,  66,

+      67,   68,  69,  70,  71,  72,  73,  74,

+      75,   76,  76,  77,  78,  79,  80,  81,

+      82,   83,  84,  85,  86,  87,  88,  89,

+      91,   93,  95,  96,  98, 100, 101, 102,

+      104, 106, 108, 110, 112, 114, 116, 118,

+      122, 124, 126, 128, 130, 132, 134, 136,

+      138, 140, 143, 145, 148, 151, 154, 157];

+

+  static const List<int> AC_TABLE = const [ // uint16

+       4,     5,   6,   7,   8,   9,  10,  11,

+       12,   13,  14,  15,  16,  17,  18,  19,

+       20,   21,  22,  23,  24,  25,  26,  27,

+       28,   29,  30,  31,  32,  33,  34,  35,

+       36,   37,  38,  39,  40,  41,  42,  43,

+       44,   45,  46,  47,  48,  49,  50,  51,

+       52,   53,  54,  55,  56,  57,  58,  60,

+       62,   64,  66,  68,  70,  72,  74,  76,

+       78,   80,  82,  84,  86,  88,  90,  92,

+       94,   96,  98, 100, 102, 104, 106, 108,

+       110, 112, 114, 116, 119, 122, 125, 128,

+       131, 134, 137, 140, 143, 146, 149, 152,

+       155, 158, 161, 164, 167, 170, 173, 177,

+       181, 185, 189, 193, 197, 201, 205, 209,

+       213, 217, 221, 225, 229, 234, 239, 245,

+       249, 254, 259, 264, 269, 274, 279, 284];

+

+  /**

+   * FILTER_EXTRA_ROWS = How many extra lines are needed on the MB boundary

+   * for caching, given a filtering level.

+   * Simple filter:  up to 2 luma samples are read and 1 is written.

+   * Complex filter: up to 4 luma samples are read and 3 are written. Same for

+   *               U/V, so it's 8 samples total (because of the 2x upsampling).

+   */

+  static const List<int> FILTER_EXTRA_ROWS = const [ 0, 2, 8 ];

+

+  static const int VP8_SIGNATURE = 0x2a019d;

+

+  static const int MB_FEATURE_TREE_PROBS = 3;

+  static const int NUM_MB_SEGMENTS = 4;

+  static const int NUM_REF_LF_DELTAS = 4;

+  static const int NUM_MODE_LF_DELTAS = 4;    // I4x4, ZERO, *, SPLIT

+  static const int MAX_NUM_PARTITIONS = 8;

+

+  static const int B_DC_PRED = 0;   // 4x4 modes

+  static const int B_TM_PRED = 1;

+  static const int B_VE_PRED = 2;

+  static const int B_HE_PRED = 3;

+  static const int B_RD_PRED = 4;

+  static const int B_VR_PRED = 5;

+  static const int B_LD_PRED = 6;

+  static const int B_VL_PRED = 7;

+  static const int B_HD_PRED = 8;

+  static const int B_HU_PRED = 9;

+  static const int NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED;

+

+  // Luma16 or UV modes

+  static const int DC_PRED = B_DC_PRED;

+  static const int V_PRED = B_VE_PRED;

+  static const int H_PRED = B_HE_PRED;

+  static const int TM_PRED = B_TM_PRED;

+  static const int B_PRED = NUM_BMODES;

+

+  // special modes

+  static const int B_DC_PRED_NOTOP = 4;

+  static const int B_DC_PRED_NOLEFT = 5;

+  static const int B_DC_PRED_NOTOPLEFT = 6;

+  static const int NUM_B_DC_MODES = 7;

+

+  // Probabilities

+  static const int NUM_TYPES = 4;

+  static const int NUM_BANDS = 8;

+  static const int NUM_CTX = 3;

+  static const int NUM_PROBAS = 11;

+

+  static const int BPS = 32; // this is the common stride used by yuv[]

+  static const int YUV_SIZE = (BPS * 17 + BPS * 9);

+  static const int Y_SIZE = (BPS * 17);

+  static const int Y_OFF = (BPS * 1 + 8);

+  static const int U_OFF = (Y_OFF + BPS * 16 + BPS);

+  static const int V_OFF = (U_OFF + 16);

+

+  static const int YUV_FIX = 16; // fixed-point precision for RGB->YUV

+  static const int YUV_HALF = 1 << (YUV_FIX - 1);

+  static const int YUV_MASK = (256 << YUV_FIX) - 1;

+  static const int YUV_RANGE_MIN = -227; // min value of r/g/b output

+  static const int YUV_RANGE_MAX = 256 + 226; // max value of r/g/b output

+  static const int YUV_FIX2 = 14; // fixed-point precision for YUV->RGB

+  static const int YUV_HALF2 = 1 << (YUV_FIX2 - 1);

+  static const int YUV_MASK2 = (256 << YUV_FIX2) - 1;

+  static const int XOR_YUV_MASK2 = (-YUV_MASK2 - 1);

+

+  // These constants are 14b fixed-point version of ITU-R BT.601 constants.

+  static const int kYScale = 19077;    // 1.164 = 255 / 219

+  static const int kVToR = 26149;    // 1.596 = 255 / 112 * 0.701

+  static const int kUToG = 6419;    // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587

+  static const int kVToG = 13320;    // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587

+  static const int kUToB = 33050;    // 2.018 = 255 / 112 * 0.886

+  static const int kRCst = (-kYScale * 16 - kVToR * 128 + YUV_HALF2);

+  static const int kGCst = (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF2);

+  static const int kBCst = (-kYScale * 16 - kUToB * 128 + YUV_HALF2);

+}

diff --git a/image/lib/src/formats/webp/vp8_bit_reader.dart b/image/lib/src/formats/webp/vp8_bit_reader.dart
old mode 100644
new mode 100755
index dcd962b..70bc97b
--- a/image/lib/src/formats/webp/vp8_bit_reader.dart
+++ b/image/lib/src/formats/webp/vp8_bit_reader.dart
@@ -1,132 +1,132 @@
-import '../../util/input_buffer.dart';
-
-class VP8BitReader {
-  InputBuffer input;
-
-  // boolean decoder
-  int _range; // current range minus 1. In [127, 254] interval.
-  int _value; // current value
-  int _bits; // number of valid bits left
-  bool _eof = false;
-
-  VP8BitReader(this.input) {
-    _range = 255 - 1;
-    _value = 0;
-    _bits = -8; // to load the very first 8bits
-  }
-
-  int getValue(int bits) {
-    int v = 0;
-    while (bits-- > 0) {
-      v |= getBit(0x80) << bits;
-    }
-    return v;
-  }
-
-  int getSigned(int v) {
-    final int split = (_range >> 1);
-    final int bit = _bitUpdate(split);
-    _shift();
-    return bit != 0 ? -v : v;
-  }
-
-  int getSignedValue(int bits) {
-    final int value = getValue(bits);
-    return get() == 1 ? -value : value;
-  }
-
-  int get() {
-    return getValue(1);
-  }
-
-  int getBit(int prob) {
-    final int split = (_range * prob) >> 8;
-    final int bit = _bitUpdate(split);
-    if (_range <= 0x7e) {
-      _shift();
-    }
-    return bit;
-  }
-
-  int _bitUpdate(int split) {
-    // Make sure we have a least BITS bits in 'value_'
-    if (_bits < 0) {
-      _loadNewBytes();
-    }
-
-    final int pos = _bits;
-    final int value = (_value >> pos);
-    if (value > split) {
-      _range -= split + 1;
-      _value -= (split + 1) << pos;
-      return 1;
-    } else {
-      _range = split;
-      return 0;
-    }
-  }
-
-  void _shift() {
-    final int shift = LOG_2_RANGE[_range];
-    _range = NEW_RANGE[_range];
-    _bits -= shift;
-  }
-
-  void _loadNewBytes() {
-    // Read 'BITS' bits at a time if possible.
-    if (input.length >= 1) {
-      // convert memory type to register type (with some zero'ing!)
-      int bits = input.readByte();
-      _value = bits | (_value << BITS);
-      _bits += (BITS);
-    } else {
-      _loadFinalBytes();    // no need to be inlined
-    }
-  }
-
-  void _loadFinalBytes() {
-    // Only read 8bits at a time
-    if (!input.isEOS) {
-      _value = input.readByte() | (_value << 8);
-      _bits += 8;
-    } else if (!_eof) {
-      // These are not strictly needed, but it makes the behaviour
-      // consistent for both USE_RIGHT_JUSTIFY and !USE_RIGHT_JUSTIFY.
-      _value <<= 8;
-      _bits += 8;
-      _eof = true;
-    }
-  }
-
-  static const int BITS = 8;
-
-  // Read a bit with proba 'prob'. Speed-critical function!
-  static const List<int> LOG_2_RANGE = const [
-      7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
-      3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-      0];
-
-  static const List<int> NEW_RANGE = const [
-      127, 127, 191, 127, 159, 191, 223, 127,
-      143, 159, 175, 191, 207, 223, 239, 127,
-      135, 143, 151, 159, 167, 175, 183, 191,
-      199, 207, 215, 223, 231, 239, 247, 127,
-      131, 135, 139, 143, 147, 151, 155, 159,
-      163, 167, 171, 175, 179, 183, 187, 191,
-      195, 199, 203, 207, 211, 215, 219, 223,
-      227, 231, 235, 239, 243, 247, 251, 127,
-      129, 131, 133, 135, 137, 139, 141, 143,
-      145, 147, 149, 151, 153, 155, 157, 159,
-      161, 163, 165, 167, 169, 171, 173, 175,
-      177, 179, 181, 183, 185, 187, 189, 191,
-      193, 195, 197, 199, 201, 203, 205, 207,
-      209, 211, 213, 215, 217, 219, 221, 223,
-      225, 227, 229, 231, 233, 235, 237, 239,
-      241, 243, 245, 247, 249, 251, 253, 127];
-}
+import '../../util/input_buffer.dart';

+

+class VP8BitReader {

+  InputBuffer input;

+

+  // boolean decoder

+  int _range; // current range minus 1. In [127, 254] interval.

+  int _value; // current value

+  int _bits; // number of valid bits left

+  bool _eof = false;

+

+  VP8BitReader(this.input) {

+    _range = 255 - 1;

+    _value = 0;

+    _bits = -8; // to load the very first 8bits

+  }

+

+  int getValue(int bits) {

+    int v = 0;

+    while (bits-- > 0) {

+      v |= getBit(0x80) << bits;

+    }

+    return v;

+  }

+

+  int getSigned(int v) {

+    final int split = (_range >> 1);

+    final int bit = _bitUpdate(split);

+    _shift();

+    return bit != 0 ? -v : v;

+  }

+

+  int getSignedValue(int bits) {

+    final int value = getValue(bits);

+    return get() == 1 ? -value : value;

+  }

+

+  int get() {

+    return getValue(1);

+  }

+

+  int getBit(int prob) {

+    final int split = (_range * prob) >> 8;

+    final int bit = _bitUpdate(split);

+    if (_range <= 0x7e) {

+      _shift();

+    }

+    return bit;

+  }

+

+  int _bitUpdate(int split) {

+    // Make sure we have a least BITS bits in 'value_'

+    if (_bits < 0) {

+      _loadNewBytes();

+    }

+

+    final int pos = _bits;

+    final int value = (_value >> pos);

+    if (value > split) {

+      _range -= split + 1;

+      _value -= (split + 1) << pos;

+      return 1;

+    } else {

+      _range = split;

+      return 0;

+    }

+  }

+

+  void _shift() {

+    final int shift = LOG_2_RANGE[_range];

+    _range = NEW_RANGE[_range];

+    _bits -= shift;

+  }

+

+  void _loadNewBytes() {

+    // Read 'BITS' bits at a time if possible.

+    if (input.length >= 1) {

+      // convert memory type to register type (with some zero'ing!)

+      int bits = input.readByte();

+      _value = bits | (_value << BITS);

+      _bits += (BITS);

+    } else {

+      _loadFinalBytes();    // no need to be inlined

+    }

+  }

+

+  void _loadFinalBytes() {

+    // Only read 8bits at a time

+    if (!input.isEOS) {

+      _value = input.readByte() | (_value << 8);

+      _bits += 8;

+    } else if (!_eof) {

+      // These are not strictly needed, but it makes the behaviour

+      // consistent for both USE_RIGHT_JUSTIFY and !USE_RIGHT_JUSTIFY.

+      _value <<= 8;

+      _bits += 8;

+      _eof = true;

+    }

+  }

+

+  static const int BITS = 8;

+

+  // Read a bit with proba 'prob'. Speed-critical function!

+  static const List<int> LOG_2_RANGE = const [

+      7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,

+      3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

+      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

+      0];

+

+  static const List<int> NEW_RANGE = const [

+      127, 127, 191, 127, 159, 191, 223, 127,

+      143, 159, 175, 191, 207, 223, 239, 127,

+      135, 143, 151, 159, 167, 175, 183, 191,

+      199, 207, 215, 223, 231, 239, 247, 127,

+      131, 135, 139, 143, 147, 151, 155, 159,

+      163, 167, 171, 175, 179, 183, 187, 191,

+      195, 199, 203, 207, 211, 215, 219, 223,

+      227, 231, 235, 239, 243, 247, 251, 127,

+      129, 131, 133, 135, 137, 139, 141, 143,

+      145, 147, 149, 151, 153, 155, 157, 159,

+      161, 163, 165, 167, 169, 171, 173, 175,

+      177, 179, 181, 183, 185, 187, 189, 191,

+      193, 195, 197, 199, 201, 203, 205, 207,

+      209, 211, 213, 215, 217, 219, 221, 223,

+      225, 227, 229, 231, 233, 235, 237, 239,

+      241, 243, 245, 247, 249, 251, 253, 127];

+}

diff --git a/image/lib/src/formats/webp/vp8_filter.dart b/image/lib/src/formats/webp/vp8_filter.dart
old mode 100644
new mode 100755
index 4a11a80..2ab6f3a
--- a/image/lib/src/formats/webp/vp8_filter.dart
+++ b/image/lib/src/formats/webp/vp8_filter.dart
@@ -1,720 +1,720 @@
-import 'dart:typed_data';
-
-import '../../internal/bit_operators.dart';
-import '../../util/input_buffer.dart';
-import 'vp8.dart';
-
-class VP8Filter {
-  VP8Filter() {
-    _initTables();
-  }
-
-  void simpleVFilter16(InputBuffer p, int stride, int thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    for (int i = 0; i < 16; ++i) {
-      p2.offset = p.offset + i;
-      if (_needsFilter(p2, stride, thresh)) {
-        _doFilter2(p2, stride);
-      }
-    }
-  }
-
-  void simpleHFilter16(InputBuffer p, int stride, int thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    for (int i = 0; i < 16; ++i) {
-      p2.offset = p.offset + i * stride;
-      if (_needsFilter(p2, 1, thresh)) {
-        _doFilter2(p2, 1);
-      }
-    }
-  }
-
-  void simpleVFilter16i(InputBuffer p, int stride, int thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    for (int k = 3; k > 0; --k) {
-      p2.offset += 4 * stride;
-      simpleVFilter16(p2, stride, thresh);
-    }
-  }
-
-  void simpleHFilter16i(InputBuffer p, int stride, int thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    for (int k = 3; k > 0; --k) {
-      p2.offset += 4;
-      simpleHFilter16(p2, stride, thresh);
-    }
-  }
-
-  // on macroblock edges
-  void vFilter16(InputBuffer p, int stride, int thresh, int ithresh,
-                 int hev_thresh) {
-    _filterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
-  }
-
-  void hFilter16(InputBuffer p, int stride, int thresh, int ithresh,
-                 int hev_thresh) {
-    _filterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
-  }
-
-  // on three inner edges
-  void vFilter16i(InputBuffer p, int stride, int thresh, int ithresh,
-                  int hev_thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    for (int k = 3; k > 0; --k) {
-      p2.offset += 4 * stride;
-      _filterLoop24(p2, stride, 1, 16, thresh, ithresh, hev_thresh);
-    }
-  }
-
-  void hFilter16i(InputBuffer p, int stride, int thresh, int ithresh,
-                  int hev_thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    for (int k = 3; k > 0; --k) {
-      p2.offset += 4;
-      _filterLoop24(p2, 1, stride, 16, thresh, ithresh, hev_thresh);
-    }
-  }
-
-  /**
-   * 8-pixels wide variant, for chroma filtering
-   */
-  void vFilter8(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,
-                int hev_thresh) {
-    _filterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
-    _filterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
-  }
-
-  void hFilter8(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,
-                int hev_thresh) {
-    _filterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
-    _filterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
-  }
-
-  void vFilter8i(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,
-                 int hev_thresh) {
-    InputBuffer u2 = new InputBuffer.from(u, offset: 4 * stride);
-    InputBuffer v2 = new InputBuffer.from(v, offset: 4 * stride);
-    _filterLoop24(u2, stride, 1, 8, thresh, ithresh, hev_thresh);
-    _filterLoop24(v2, stride, 1, 8, thresh, ithresh, hev_thresh);
-  }
-
-  void hFilter8i(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,
-                 int hev_thresh) {
-    InputBuffer u2 = new InputBuffer.from(u, offset: 4);
-    InputBuffer v2 = new InputBuffer.from(v, offset: 4);
-    _filterLoop24(u2, 1, stride, 8, thresh, ithresh, hev_thresh);
-    _filterLoop24(v2, 1, stride, 8, thresh, ithresh, hev_thresh);
-  }
-
-  void _filterLoop26(InputBuffer p, int hstride, int vstride, int size,
-                     int thresh, int ithresh, int hev_thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    while (size-- > 0) {
-      if (_needsFilter2(p2, hstride, thresh, ithresh)) {
-        if (_hev(p2, hstride, hev_thresh)) {
-          _doFilter2(p2, hstride);
-        } else {
-          _doFilter6(p2, hstride);
-        }
-      }
-      p2.offset += vstride;
-    }
-  }
-
-  void _filterLoop24(InputBuffer p, int hstride, int vstride, int size,
-                     int thresh, int ithresh, int hev_thresh) {
-    InputBuffer p2 = new InputBuffer.from(p);
-    while (size-- > 0) {
-      if (_needsFilter2(p2, hstride, thresh, ithresh)) {
-        if (_hev(p2, hstride, hev_thresh)) {
-          _doFilter2(p2, hstride);
-        } else {
-          _doFilter4(p2, hstride);
-        }
-      }
-      p2.offset += vstride;
-    }
-  }
-
-  /**
-   * 4 pixels in, 2 pixels out
-   */
-  void _doFilter2(InputBuffer p, int step) {
-    final int p1 = p[-2 * step];
-    final int p0 = p[-step];
-    final int q0 = p[0];
-    final int q1 = p[step];
-    final int a = 3 * (q0 - p0) + sclip1[1020 + p1 - q1];
-    final int a1 = sclip2[112 + shiftR((a + 4), 3)];
-    final int a2 = sclip2[112 + shiftR((a + 3), 3)];
-    p[-step] = clip1[255 + p0 + a2];
-    p[0] = clip1[255 + q0 - a1];
-  }
-
-  /**
-   * 4 pixels in, 4 pixels out
-   */
-  void _doFilter4(InputBuffer p, int step) {
-    final int p1 = p[-2 * step];
-    final int p0 = p[-step];
-    final int q0 = p[0];
-    final int q1 = p[step];
-    final int a = 3 * (q0 - p0);
-    final int a1 = sclip2[112 + shiftR((a + 4), 3)];
-    final int a2 = sclip2[112 + shiftR((a + 3), 3)];
-    final int a3 = shiftR(a1 + 1, 1);
-    p[-2 * step] = clip1[255 + p1 + a3];
-    p[-step] = clip1[255 + p0 + a2];
-    p[0] = clip1[255 + q0 - a1];
-    p[step] = clip1[255 + q1 - a3];
-  }
-
-  /**
-   * 6 pixels in, 6 pixels out
-   */
-  void _doFilter6(InputBuffer p, int step) {
-    final int p2 = p[-3 * step];
-    final int p1 = p[-2 * step];
-    final int p0 = p[-step];
-    final int q0 = p[0];
-    final int q1 = p[step];
-    final int q2 = p[2 * step];
-    final int a = sclip1[1020 + 3 * (q0 - p0) + sclip1[1020 + p1 - q1]];
-    final int a1 = shiftR(27 * a + 63, 7); // eq. to ((3 * a + 7) * 9) >> 7
-    final int a2 = shiftR(18 * a + 63, 7); // eq. to ((2 * a + 7) * 9) >> 7
-    final int a3 = shiftR(9  * a + 63, 7); // eq. to ((1 * a + 7) * 9) >> 7
-    p[-3 * step] = clip1[255 + p2 + a3];
-    p[-2 * step] = clip1[255 + p1 + a2];
-    p[-step] = clip1[255 + p0 + a1];
-    p[0] = clip1[255 + q0 - a1];
-    p[step] = clip1[255 + q1 - a2];
-    p[2 * step] = clip1[255 + q2 - a3];
-  }
-
-  bool _hev(InputBuffer p, int step, int thresh) {
-    final int p1 = p[-2 * step];
-    final int p0 = p[-step];
-    final int q0 = p[0];
-    final int q1 = p[step];
-    return (abs0[255 + p1 - p0] > thresh) || (abs0[255 + q1 - q0] > thresh);
-  }
-
-  bool _needsFilter(InputBuffer p, int step, int thresh) {
-    final int p1 = p[-2 * step];
-    final int p0 = p[-step];
-    final int q0 = p[0];
-    final int q1 = p[step];
-    return (2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) <= thresh;
-  }
-
-  bool _needsFilter2(InputBuffer p, int step, int t, int it) {
-    final int p3 = p[-4 * step];
-    final int p2 = p[-3 * step];
-    final int p1 = p[-2 * step];
-    final int p0 = p[-step];
-    final int q0 = p[0];
-    final int q1 = p[step];
-    final int q2 = p[2 * step];
-    final int q3 = p[3 * step];
-    if ((2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) > t) {
-      return false;
-    }
-
-    return abs0[255 + p3 - p2] <= it && abs0[255 + p2 - p1] <= it &&
-           abs0[255 + p1 - p0] <= it && abs0[255 + q3 - q2] <= it &&
-           abs0[255 + q2 - q1] <= it && abs0[255 + q1 - q0] <= it;
-  }
-
-  void transformOne(InputBuffer src, InputBuffer dst) {
-    Int32List C = new Int32List(4 * 4);
-    int si = 0;
-    int di = 0;
-    int tmp = 0;
-    for (int i = 0; i < 4; ++i) { // vertical pass
-      final int a = src[si] + src[si + 8]; // [-4096, 4094]
-      final int b = src[si] - src[si + 8]; // [-4095, 4095]
-      final int c = _mul(src[si + 4], kC2) - _mul(src[si + 12], kC1); // [-3783, 3783]
-      final int d = _mul(src[si + 4], kC1) + _mul(src[si + 12], kC2); // [-3785, 3781]
-      C[tmp++] = a + d;   // [-7881, 7875]
-      C[tmp++] = b + c;   // [-7878, 7878]
-      C[tmp++] = b - c;   // [-7878, 7878]
-      C[tmp++] = a - d;   // [-7877, 7879]
-      si++;
-    }
-
-    // Each pass is expanding the dynamic range by ~3.85 (upper bound).
-    // The exact value is (2. + (kC1 + kC2) / 65536).
-    // After the second pass, maximum interval is [-3794, 3794], assuming
-    // an input in [-2048, 2047] interval. We then need to add a dst value
-    // in the [0, 255] range.
-    // In the worst case scenario, the input to clip_8b() can be as large as
-    // [-60713, 60968].
-    tmp = 0;
-    for (int i = 0; i < 4; ++i) { // horizontal pass
-      final int dc = C[tmp] + 4;
-      final int a =  dc +  C[tmp + 8];
-      final int b =  dc -  C[tmp + 8];
-      final int c = _mul(C[tmp + 4], kC2) - _mul(C[tmp + 12], kC1);
-      final int d = _mul(C[tmp + 4], kC1) + _mul(C[tmp + 12], kC2);
-      _store(dst, di, 0, 0, a + d);
-      _store(dst, di, 1, 0, b + c);
-      _store(dst, di, 2, 0, b - c);
-      _store(dst, di, 3, 0, a - d);
-      tmp++;
-      di += VP8.BPS;
-    }
-  }
-
-
-  void transform(InputBuffer src, InputBuffer dst, bool doTwo) {
-    transformOne(src, dst);
-    if (doTwo) {
-      transformOne(new InputBuffer.from(src, offset: 16),
-                   new InputBuffer.from(dst, offset: 4));
-    }
-  }
-
-  void transformUV(InputBuffer src, InputBuffer dst) {
-    transform(src, dst, true);
-    transform(new InputBuffer.from(src, offset: 2 * 16),
-              new InputBuffer.from(dst, offset: 4 * VP8.BPS), true);
-  }
-
-  void transformDC(InputBuffer src, InputBuffer dst) {
-    final int DC = src[0] + 4;
-    for (int j = 0; j < 4; ++j) {
-      for (int i = 0; i < 4; ++i) {
-        _store(dst, 0, i, j, DC);
-      }
-    }
-  }
-
-  void transformDCUV(InputBuffer src, InputBuffer dst) {
-    if (src[0 * 16] != 0) {
-      transformDC(src, dst);
-    }
-    if (src[1 * 16] != 0) {
-      transformDC(new InputBuffer.from(src, offset: 1 * 16),
-                  new InputBuffer.from(dst, offset: 4));
-    }
-    if (src[2 * 16] != 0) {
-      transformDC(new InputBuffer.from(src, offset: 2 * 16),
-                  new InputBuffer.from(dst, offset: 4 * VP8.BPS));
-    }
-    if (src[3 * 16] != 0) {
-      transformDC(new InputBuffer.from(src, offset: 3 * 16),
-                  new InputBuffer.from(dst, offset: 4 * VP8.BPS + 4));
-    }
-  }
-
-  /**
-   * Simplified transform when only in[0], in[1] and in[4] are non-zero
-   */
-  void transformAC3(InputBuffer src, InputBuffer dst) {
-    final int a = src[0] + 4;
-    final int c4 = _mul(src[4], kC2);
-    final int d4 = _mul(src[4], kC1);
-    final int c1 = _mul(src[1], kC2);
-    final int d1 = _mul(src[1], kC1);
-    _store2(dst, 0, a + d4, d1, c1);
-    _store2(dst, 1, a + c4, d1, c1);
-    _store2(dst, 2, a - c4, d1, c1);
-    _store2(dst, 3, a - d4, d1, c1);
-  }
-
-  static int AVG3(a, b, c) => shiftR(((a) + 2 * (b) + (c) + 2), 2);
-  static int AVG2(a, b) => shiftR(((a) + (b) + 1), 1);
-
-  static void VE4(InputBuffer dst) {
-    int top = -VP8.BPS; // dst +
-    final List<int> vals = [
-       AVG3(dst[top - 1], dst[top],     dst[top + 1]),
-       AVG3(dst[top],     dst[top + 1], dst[top + 2]),
-       AVG3(dst[top + 1], dst[top + 2], dst[top + 3]),
-       AVG3(dst[top + 2], dst[top + 3], dst[top + 4])];
-
-    for (int i = 0; i < 4; ++i) {
-      dst.memcpy(i * VP8.BPS, 4, vals);
-    }
-  }
-
-  static void HE4(InputBuffer dst) {
-    final int A = dst[-1 - VP8.BPS];
-    final int B = dst[-1];
-    final int C = dst[-1 + VP8.BPS];
-    final int D = dst[-1 + 2 * VP8.BPS];
-    final int E = dst[-1 + 3 * VP8.BPS];
-
-    InputBuffer d2 = new InputBuffer.from(dst);
-
-    d2.toUint32List()[0] = 0x01010101 * AVG3(A, B, C);
-    d2.offset += VP8.BPS;
-    d2.toUint32List()[0] = 0x01010101 * AVG3(B, C, D);
-    d2.offset += VP8.BPS;
-    d2.toUint32List()[0] = 0x01010101 * AVG3(C, D, E);
-    d2.offset += VP8.BPS;
-    d2.toUint32List()[0] = 0x01010101 * AVG3(D, E, E);
-  }
-
-  static void DC4(InputBuffer dst) {   // DC
-    int dc = 4;
-    for (int i = 0; i < 4; ++i) {
-      dc += dst[i - VP8.BPS] + dst[-1 + i * VP8.BPS];
-    }
-    dc >>= 3;
-    for (int i = 0; i < 4; ++i) {
-      dst.memset(i * VP8.BPS, 4, dc);
-    }
-  }
-
-  static void trueMotion(InputBuffer dst, int size) {
-    int di = 0;
-    int top = -VP8.BPS; // dst +
-    int clip0 = 255 - dst[top - 1]; // clip1 +
-
-    for (int y = 0; y < size; ++y) {
-      int clip = clip0 + dst[di - 1];
-      for (int x = 0; x < size; ++x) {
-        dst[di + x] = clip1[clip + dst[top + x]];
-      }
-
-      di += VP8.BPS;
-    }
-  }
-
-  static void TM4(InputBuffer dst) {
-    trueMotion(dst, 4);
-  }
-
-  static void TM8uv(InputBuffer dst) {
-    trueMotion(dst, 8);
-  }
-
-  static void TM16(InputBuffer dst) {
-    trueMotion(dst, 16);
-  }
-
-  static int DST(x, y) => x + y * VP8.BPS;
-
-  /**
-   * Down-right
-   */
-  static void RD4(InputBuffer dst) {
-    final int I = dst[-1 + 0 * VP8.BPS];
-    final int J = dst[-1 + 1 * VP8.BPS];
-    final int K = dst[-1 + 2 * VP8.BPS];
-    final int L = dst[-1 + 3 * VP8.BPS];
-    final int X = dst[-1 - VP8.BPS];
-    final int A = dst[0 - VP8.BPS];
-    final int B = dst[1 - VP8.BPS];
-    final int C = dst[2 - VP8.BPS];
-    final int D = dst[3 - VP8.BPS];
-
-    dst[DST(0, 3)] = AVG3(J, K, L);
-    dst[DST(0, 2)] = dst[DST(1, 3)] = AVG3(I, J, K);
-    dst[DST(0, 1)] = dst[DST(1, 2)] = dst[DST(2, 3)] = AVG3(X, I, J);
-    dst[DST(0, 0)] = dst[DST(1, 1)] = dst[DST(2, 2)] = dst[DST(3, 3)] = AVG3(A, X, I);
-    dst[DST(1, 0)] = dst[DST(2, 1)] = dst[DST(3, 2)] = AVG3(B, A, X);
-    dst[DST(2, 0)] = dst[DST(3, 1)] = AVG3(C, B, A);
-    dst[DST(3, 0)] = AVG3(D, C, B);
-  }
-
-  /**
-   * Down-Left
-   */
-  static void LD4(InputBuffer dst) {
-    final int A = dst[0 - VP8.BPS];
-    final int B = dst[1 - VP8.BPS];
-    final int C = dst[2 - VP8.BPS];
-    final int D = dst[3 - VP8.BPS];
-    final int E = dst[4 - VP8.BPS];
-    final int F = dst[5 - VP8.BPS];
-    final int G = dst[6 - VP8.BPS];
-    final int H = dst[7 - VP8.BPS];
-    dst[DST(0, 0)] = AVG3(A, B, C);
-    dst[DST(1, 0)] = dst[DST(0, 1)] = AVG3(B, C, D);
-    dst[DST(2, 0)] = dst[DST(1, 1)] = dst[DST(0, 2)] = AVG3(C, D, E);
-    dst[DST(3, 0)] = dst[DST(2, 1)] = dst[DST(1, 2)] = dst[DST(0, 3)] = AVG3(D, E, F);
-    dst[DST(3, 1)] = dst[DST(2, 2)] = dst[DST(1, 3)] = AVG3(E, F, G);
-    dst[DST(3, 2)] = dst[DST(2, 3)] = AVG3(F, G, H);
-    dst[DST(3, 3)] = AVG3(G, H, H);
-  }
-
-  /**
-   * Vertical-Right
-   */
-  static void VR4(InputBuffer dst) {
-    final int I = dst[-1 + 0 * VP8.BPS];
-    final int J = dst[-1 + 1 * VP8.BPS];
-    final int K = dst[-1 + 2 * VP8.BPS];
-    final int X = dst[-1 - VP8.BPS];
-    final int A = dst[0 - VP8.BPS];
-    final int B = dst[1 - VP8.BPS];
-    final int C = dst[2 - VP8.BPS];
-    final int D = dst[3 - VP8.BPS];
-    dst[DST(0, 0)] = dst[DST(1, 2)] = AVG2(X, A);
-    dst[DST(1, 0)] = dst[DST(2, 2)] = AVG2(A, B);
-    dst[DST(2, 0)] = dst[DST(3, 2)] = AVG2(B, C);
-    dst[DST(3, 0)] = AVG2(C, D);
-
-    dst[DST(0, 3)] = AVG3(K, J, I);
-    dst[DST(0, 2)] = AVG3(J, I, X);
-    dst[DST(0, 1)] = dst[DST(1, 3)] = AVG3(I, X, A);
-    dst[DST(1, 1)] = dst[DST(2, 3)] = AVG3(X, A, B);
-    dst[DST(2, 1)] = dst[DST(3, 3)] = AVG3(A, B, C);
-    dst[DST(3, 1)] = AVG3(B, C, D);
-  }
-
-  /**
-   * Vertical-Left
-   */
-  static void VL4(InputBuffer dst) {
-    final int A = dst[0 - VP8.BPS];
-    final int B = dst[1 - VP8.BPS];
-    final int C = dst[2 - VP8.BPS];
-    final int D = dst[3 - VP8.BPS];
-    final int E = dst[4 - VP8.BPS];
-    final int F = dst[5 - VP8.BPS];
-    final int G = dst[6 - VP8.BPS];
-    final int H = dst[7 - VP8.BPS];
-    dst[DST(0, 0)] = AVG2(A, B);
-    dst[DST(1, 0)] = dst[DST(0, 2)] = AVG2(B, C);
-    dst[DST(2, 0)] = dst[DST(1, 2)] = AVG2(C, D);
-    dst[DST(3, 0)] = dst[DST(2, 2)] = AVG2(D, E);
-
-    dst[DST(0, 1)] = AVG3(A, B, C);
-    dst[DST(1, 1)] = dst[DST(0, 3)] = AVG3(B, C, D);
-    dst[DST(2, 1)] = dst[DST(1, 3)] = AVG3(C, D, E);
-    dst[DST(3, 1)] = dst[DST(2, 3)] = AVG3(D, E, F);
-    dst[DST(3, 2)] = AVG3(E, F, G);
-    dst[DST(3, 3)] = AVG3(F, G, H);
-  }
-
-  /**
-   * Horizontal-Up
-   */
-  static void HU4(InputBuffer dst) {
-    final int I = dst[-1 + 0 * VP8.BPS];
-    final int J = dst[-1 + 1 * VP8.BPS];
-    final int K = dst[-1 + 2 * VP8.BPS];
-    final int L = dst[-1 + 3 * VP8.BPS];
-    dst[DST(0, 0)] = AVG2(I, J);
-    dst[DST(2, 0)] = dst[DST(0, 1)] = AVG2(J, K);
-    dst[DST(2, 1)] = dst[DST(0, 2)] = AVG2(K, L);
-    dst[DST(1, 0)] = AVG3(I, J, K);
-    dst[DST(3, 0)] = dst[DST(1, 1)] = AVG3(J, K, L);
-    dst[DST(3, 1)] = dst[DST(1, 2)] = AVG3(K, L, L);
-    dst[DST(3, 2)] = dst[DST(2, 2)] = dst[DST(0, 3)] = dst[DST(1, 3)] =
-                     dst[DST(2, 3)] = dst[DST(3, 3)] = L;
-  }
-
-  /**
-   * Horizontal-Down
-   */
-  static void HD4(InputBuffer dst) {
-    final int I = dst[-1 + 0 * VP8.BPS];
-    final int J = dst[-1 + 1 * VP8.BPS];
-    final int K = dst[-1 + 2 * VP8.BPS];
-    final int L = dst[-1 + 3 * VP8.BPS];
-    final int X = dst[-1 - VP8.BPS];
-    final int A = dst[0 - VP8.BPS];
-    final int B = dst[1 - VP8.BPS];
-    final int C = dst[2 - VP8.BPS];
-
-    dst[DST(0, 0)] = dst[DST(2, 1)] = AVG2(I, X);
-    dst[DST(0, 1)] = dst[DST(2, 2)] = AVG2(J, I);
-    dst[DST(0, 2)] = dst[DST(2, 3)] = AVG2(K, J);
-    dst[DST(0, 3)] = AVG2(L, K);
-
-    dst[DST(3, 0)] = AVG3(A, B, C);
-    dst[DST(2, 0)] = AVG3(X, A, B);
-    dst[DST(1, 0)] = dst[DST(3, 1)] = AVG3(I, X, A);
-    dst[DST(1, 1)] = dst[DST(3, 2)] = AVG3(J, I, X);
-    dst[DST(1, 2)] = dst[DST(3, 3)] = AVG3(K, J, I);
-    dst[DST(1, 3)] = AVG3(L, K, J);
-  }
-
-  static void VE16(InputBuffer dst) { // vertical
-    for (int j = 0; j < 16; ++j) {
-      dst.memcpy(j * VP8.BPS, 16, dst, -VP8.BPS);
-    }
-  }
-
-  static void HE16(InputBuffer dst) { // horizontal
-    int di = 0;
-    for (int j = 16; j > 0; --j) {
-      dst.memset(di, 16, dst[di - 1]);
-      di += VP8.BPS;
-    }
-  }
-
-  static void Put16(int v, InputBuffer dst) {
-    for (int j = 0; j < 16; ++j) {
-      dst.memset(j * VP8.BPS, 16, v);
-    }
-  }
-
-  static void DC16(InputBuffer dst) { // DC
-    int DC = 16;
-    for (int j = 0; j < 16; ++j) {
-      DC += dst[-1 + j * VP8.BPS] + dst[j - VP8.BPS];
-    }
-    Put16(DC >> 5, dst);
-  }
-
-  /**
-   * DC with top samples not available
-   */
-  static void DC16NoTop(InputBuffer dst) {
-    int DC = 8;
-    for (int j = 0; j < 16; ++j) {
-      DC += dst[-1 + j * VP8.BPS];
-    }
-    Put16(DC >> 4, dst);
-  }
-
-  /**
-   * DC with left samples not available
-   */
-  static void DC16NoLeft(InputBuffer dst) {
-    int DC = 8;
-    for (int i = 0; i < 16; ++i) {
-      DC += dst[i - VP8.BPS];
-    }
-    Put16(DC >> 4, dst);
-  }
-
-  /**
-   * DC with no top and left samples
-   */
-  static void DC16NoTopLeft(InputBuffer dst) {
-    Put16(0x80, dst);
-  }
-
-  static void VE8uv(InputBuffer dst) {
-    for (int j = 0; j < 8; ++j) {
-      dst.memcpy(j * VP8.BPS, 8, dst, -VP8.BPS);
-    }
-  }
-
-  static void HE8uv(InputBuffer dst) {
-    int di = 0;
-    for (int j = 0; j < 8; ++j) {
-      dst.memset(di, 8, dst[di - 1]);
-      di += VP8.BPS;
-    }
-  }
-
-  /**
-   * helper for chroma-DC predictions
-   */
-  static void Put8x8uv(int value, InputBuffer dst) {
-    for (int j = 0; j < 8; ++j) {
-      dst.memset(j * VP8.BPS, 8, value);
-    }
-  }
-
-  static void DC8uv(InputBuffer dst) {
-    int dc0 = 8;
-    for (int i = 0; i < 8; ++i) {
-      dc0 += dst[i - VP8.BPS] + dst[-1 + i * VP8.BPS];
-    }
-    Put8x8uv(dc0 >> 4, dst);
-  }
-
-  /**
-   * DC with no left samples
-   */
-  static void DC8uvNoLeft(InputBuffer dst) {
-    int dc0 = 4;
-    for (int i = 0; i < 8; ++i) {
-      dc0 += dst[i - VP8.BPS];
-    }
-    Put8x8uv(dc0 >> 3, dst);
-  }
-
-  /**
-   * DC with no top samples
-   */
-  static void DC8uvNoTop(InputBuffer dst) {
-    int dc0 = 4;
-    for (int i = 0; i < 8; ++i) {
-      dc0 += dst[-1 + i * VP8.BPS];
-    }
-    Put8x8uv(dc0 >> 3, dst);
-  }
-
-  /**
-   * DC with nothing
-   */
-  static void DC8uvNoTopLeft(InputBuffer dst) {
-    Put8x8uv(0x80, dst);
-  }
-
-  static const List PredLuma4 = const [
-      DC4, TM4, VE4, HE4, RD4, VR4, LD4, VL4, HD4, HU4 ];
-
-  static const List PredLuma16 = const [
-      DC16, TM16, VE16, HE16, DC16NoTop, DC16NoLeft, DC16NoTopLeft ];
-
-  static const List PredChroma8 = const [
-      DC8uv, TM8uv, VE8uv, HE8uv, DC8uvNoTop, DC8uvNoLeft, DC8uvNoTopLeft ];
-
-
-  static const int kC1 = 20091 + (1 << 16);
-  static const int kC2 = 35468;
-
-  static int _mul(int a, int b) {
-    int c = a * b;
-    return shiftR(c, 16);
-  }
-
-  static void _store(InputBuffer dst, int di, int x, int y, int v) {
-    dst[di + x + y * VP8.BPS] = _clip8b(dst[di + x + y * VP8.BPS] + (v >> 3));
-  }
-
-  static void _store2(InputBuffer dst, int y, int dc, int d, int c) {
-    _store(dst, 0, 0, y, dc + d);
-    _store(dst, 0, 1, y, dc + c);
-    _store(dst, 0, 2, y, dc - c);
-    _store(dst, 0, 3, y, dc - d);
-  }
-
-  /// abs(i)
-  static Uint8List abs0 = new Uint8List(255 + 255 + 1);
-  /// abs(i)>>1
-  static Uint8List abs1 = new Uint8List(255 + 255 + 1);
-  /// clips [-1020, 1020] to [-128, 127]
-  static Int8List sclip1 = new Int8List(1020 + 1020 + 1);
-  /// clips [-112, 112] to [-16, 15]
-  static Int8List sclip2 = new Int8List(112 + 112 + 1);
-  /// clips [-255,510] to [0,255]
-  static Uint8List clip1 = new Uint8List(255 + 510 + 1);
-
-  static void _initTables() {
-    if (!_tablesInitialized) {
-      for (int i = -255; i <= 255; ++i) {
-        abs0[255 + i] = (i < 0) ? -i : i;
-        abs1[255 + i] = abs0[255 + i] >> 1;
-      }
-      for (int i = -1020; i <= 1020; ++i) {
-        sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
-      }
-      for (int i = -112; i <= 112; ++i) {
-        sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
-      }
-      for (int i = -255; i <= 255 + 255; ++i) {
-        clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
-      }
-      _tablesInitialized = true;
-    }
-  }
-
-  static int _clip8b(int v) {
-    return ((v & -256) == 0) ? v : (v < 0) ? 0 : 255;
-  }
-
-  //static int __maxN = 0;
-
-  static bool _tablesInitialized = false;
-}
+import 'dart:typed_data';

+

+import '../../internal/bit_operators.dart';

+import '../../util/input_buffer.dart';

+import 'vp8.dart';

+

+class VP8Filter {

+  VP8Filter() {

+    _initTables();

+  }

+

+  void simpleVFilter16(InputBuffer p, int stride, int thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    for (int i = 0; i < 16; ++i) {

+      p2.offset = p.offset + i;

+      if (_needsFilter(p2, stride, thresh)) {

+        _doFilter2(p2, stride);

+      }

+    }

+  }

+

+  void simpleHFilter16(InputBuffer p, int stride, int thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    for (int i = 0; i < 16; ++i) {

+      p2.offset = p.offset + i * stride;

+      if (_needsFilter(p2, 1, thresh)) {

+        _doFilter2(p2, 1);

+      }

+    }

+  }

+

+  void simpleVFilter16i(InputBuffer p, int stride, int thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    for (int k = 3; k > 0; --k) {

+      p2.offset += 4 * stride;

+      simpleVFilter16(p2, stride, thresh);

+    }

+  }

+

+  void simpleHFilter16i(InputBuffer p, int stride, int thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    for (int k = 3; k > 0; --k) {

+      p2.offset += 4;

+      simpleHFilter16(p2, stride, thresh);

+    }

+  }

+

+  // on macroblock edges

+  void vFilter16(InputBuffer p, int stride, int thresh, int ithresh,

+                 int hev_thresh) {

+    _filterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);

+  }

+

+  void hFilter16(InputBuffer p, int stride, int thresh, int ithresh,

+                 int hev_thresh) {

+    _filterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);

+  }

+

+  // on three inner edges

+  void vFilter16i(InputBuffer p, int stride, int thresh, int ithresh,

+                  int hev_thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    for (int k = 3; k > 0; --k) {

+      p2.offset += 4 * stride;

+      _filterLoop24(p2, stride, 1, 16, thresh, ithresh, hev_thresh);

+    }

+  }

+

+  void hFilter16i(InputBuffer p, int stride, int thresh, int ithresh,

+                  int hev_thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    for (int k = 3; k > 0; --k) {

+      p2.offset += 4;

+      _filterLoop24(p2, 1, stride, 16, thresh, ithresh, hev_thresh);

+    }

+  }

+

+  /**

+   * 8-pixels wide variant, for chroma filtering

+   */

+  void vFilter8(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,

+                int hev_thresh) {

+    _filterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);

+    _filterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);

+  }

+

+  void hFilter8(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,

+                int hev_thresh) {

+    _filterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);

+    _filterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);

+  }

+

+  void vFilter8i(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,

+                 int hev_thresh) {

+    InputBuffer u2 = InputBuffer.from(u, offset: 4 * stride);

+    InputBuffer v2 = InputBuffer.from(v, offset: 4 * stride);

+    _filterLoop24(u2, stride, 1, 8, thresh, ithresh, hev_thresh);

+    _filterLoop24(v2, stride, 1, 8, thresh, ithresh, hev_thresh);

+  }

+

+  void hFilter8i(InputBuffer u, InputBuffer v, int stride, int thresh, int ithresh,

+                 int hev_thresh) {

+    InputBuffer u2 = InputBuffer.from(u, offset: 4);

+    InputBuffer v2 = InputBuffer.from(v, offset: 4);

+    _filterLoop24(u2, 1, stride, 8, thresh, ithresh, hev_thresh);

+    _filterLoop24(v2, 1, stride, 8, thresh, ithresh, hev_thresh);

+  }

+

+  void _filterLoop26(InputBuffer p, int hstride, int vstride, int size,

+                     int thresh, int ithresh, int hev_thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    while (size-- > 0) {

+      if (_needsFilter2(p2, hstride, thresh, ithresh)) {

+        if (_hev(p2, hstride, hev_thresh)) {

+          _doFilter2(p2, hstride);

+        } else {

+          _doFilter6(p2, hstride);

+        }

+      }

+      p2.offset += vstride;

+    }

+  }

+

+  void _filterLoop24(InputBuffer p, int hstride, int vstride, int size,

+                     int thresh, int ithresh, int hev_thresh) {

+    InputBuffer p2 = InputBuffer.from(p);

+    while (size-- > 0) {

+      if (_needsFilter2(p2, hstride, thresh, ithresh)) {

+        if (_hev(p2, hstride, hev_thresh)) {

+          _doFilter2(p2, hstride);

+        } else {

+          _doFilter4(p2, hstride);

+        }

+      }

+      p2.offset += vstride;

+    }

+  }

+

+  /**

+   * 4 pixels in, 2 pixels out

+   */

+  void _doFilter2(InputBuffer p, int step) {

+    final int p1 = p[-2 * step];

+    final int p0 = p[-step];

+    final int q0 = p[0];

+    final int q1 = p[step];

+    final int a = 3 * (q0 - p0) + sclip1[1020 + p1 - q1];

+    final int a1 = sclip2[112 + shiftR((a + 4), 3)];

+    final int a2 = sclip2[112 + shiftR((a + 3), 3)];

+    p[-step] = clip1[255 + p0 + a2];

+    p[0] = clip1[255 + q0 - a1];

+  }

+

+  /**

+   * 4 pixels in, 4 pixels out

+   */

+  void _doFilter4(InputBuffer p, int step) {

+    final int p1 = p[-2 * step];

+    final int p0 = p[-step];

+    final int q0 = p[0];

+    final int q1 = p[step];

+    final int a = 3 * (q0 - p0);

+    final int a1 = sclip2[112 + shiftR((a + 4), 3)];

+    final int a2 = sclip2[112 + shiftR((a + 3), 3)];

+    final int a3 = shiftR(a1 + 1, 1);

+    p[-2 * step] = clip1[255 + p1 + a3];

+    p[-step] = clip1[255 + p0 + a2];

+    p[0] = clip1[255 + q0 - a1];

+    p[step] = clip1[255 + q1 - a3];

+  }

+

+  /**

+   * 6 pixels in, 6 pixels out

+   */

+  void _doFilter6(InputBuffer p, int step) {

+    final int p2 = p[-3 * step];

+    final int p1 = p[-2 * step];

+    final int p0 = p[-step];

+    final int q0 = p[0];

+    final int q1 = p[step];

+    final int q2 = p[2 * step];

+    final int a = sclip1[1020 + 3 * (q0 - p0) + sclip1[1020 + p1 - q1]];

+    final int a1 = shiftR(27 * a + 63, 7); // eq. to ((3 * a + 7) * 9) >> 7

+    final int a2 = shiftR(18 * a + 63, 7); // eq. to ((2 * a + 7) * 9) >> 7

+    final int a3 = shiftR(9  * a + 63, 7); // eq. to ((1 * a + 7) * 9) >> 7

+    p[-3 * step] = clip1[255 + p2 + a3];

+    p[-2 * step] = clip1[255 + p1 + a2];

+    p[-step] = clip1[255 + p0 + a1];

+    p[0] = clip1[255 + q0 - a1];

+    p[step] = clip1[255 + q1 - a2];

+    p[2 * step] = clip1[255 + q2 - a3];

+  }

+

+  bool _hev(InputBuffer p, int step, int thresh) {

+    final int p1 = p[-2 * step];

+    final int p0 = p[-step];

+    final int q0 = p[0];

+    final int q1 = p[step];

+    return (abs0[255 + p1 - p0] > thresh) || (abs0[255 + q1 - q0] > thresh);

+  }

+

+  bool _needsFilter(InputBuffer p, int step, int thresh) {

+    final int p1 = p[-2 * step];

+    final int p0 = p[-step];

+    final int q0 = p[0];

+    final int q1 = p[step];

+    return (2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) <= thresh;

+  }

+

+  bool _needsFilter2(InputBuffer p, int step, int t, int it) {

+    final int p3 = p[-4 * step];

+    final int p2 = p[-3 * step];

+    final int p1 = p[-2 * step];

+    final int p0 = p[-step];

+    final int q0 = p[0];

+    final int q1 = p[step];

+    final int q2 = p[2 * step];

+    final int q3 = p[3 * step];

+    if ((2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) > t) {

+      return false;

+    }

+

+    return abs0[255 + p3 - p2] <= it && abs0[255 + p2 - p1] <= it &&

+           abs0[255 + p1 - p0] <= it && abs0[255 + q3 - q2] <= it &&

+           abs0[255 + q2 - q1] <= it && abs0[255 + q1 - q0] <= it;

+  }

+

+  void transformOne(InputBuffer src, InputBuffer dst) {

+    Int32List C = Int32List(4 * 4);

+    int si = 0;

+    int di = 0;

+    int tmp = 0;

+    for (int i = 0; i < 4; ++i) { // vertical pass

+      final int a = src[si] + src[si + 8]; // [-4096, 4094]

+      final int b = src[si] - src[si + 8]; // [-4095, 4095]

+      final int c = _mul(src[si + 4], kC2) - _mul(src[si + 12], kC1); // [-3783, 3783]

+      final int d = _mul(src[si + 4], kC1) + _mul(src[si + 12], kC2); // [-3785, 3781]

+      C[tmp++] = a + d;   // [-7881, 7875]

+      C[tmp++] = b + c;   // [-7878, 7878]

+      C[tmp++] = b - c;   // [-7878, 7878]

+      C[tmp++] = a - d;   // [-7877, 7879]

+      si++;

+    }

+

+    // Each pass is expanding the dynamic range by ~3.85 (upper bound).

+    // The exact value is (2. + (kC1 + kC2) / 65536).

+    // After the second pass, maximum interval is [-3794, 3794], assuming

+    // an input in [-2048, 2047] interval. We then need to add a dst value

+    // in the [0, 255] range.

+    // In the worst case scenario, the input to clip_8b() can be as large as

+    // [-60713, 60968].

+    tmp = 0;

+    for (int i = 0; i < 4; ++i) { // horizontal pass

+      final int dc = C[tmp] + 4;

+      final int a =  dc +  C[tmp + 8];

+      final int b =  dc -  C[tmp + 8];

+      final int c = _mul(C[tmp + 4], kC2) - _mul(C[tmp + 12], kC1);

+      final int d = _mul(C[tmp + 4], kC1) + _mul(C[tmp + 12], kC2);

+      _store(dst, di, 0, 0, a + d);

+      _store(dst, di, 1, 0, b + c);

+      _store(dst, di, 2, 0, b - c);

+      _store(dst, di, 3, 0, a - d);

+      tmp++;

+      di += VP8.BPS;

+    }

+  }

+

+

+  void transform(InputBuffer src, InputBuffer dst, bool doTwo) {

+    transformOne(src, dst);

+    if (doTwo) {

+      transformOne(new InputBuffer.from(src, offset: 16),

+                   new InputBuffer.from(dst, offset: 4));

+    }

+  }

+

+  void transformUV(InputBuffer src, InputBuffer dst) {

+    transform(src, dst, true);

+    transform(new InputBuffer.from(src, offset: 2 * 16),

+              new InputBuffer.from(dst, offset: 4 * VP8.BPS), true);

+  }

+

+  void transformDC(InputBuffer src, InputBuffer dst) {

+    final int DC = src[0] + 4;

+    for (int j = 0; j < 4; ++j) {

+      for (int i = 0; i < 4; ++i) {

+        _store(dst, 0, i, j, DC);

+      }

+    }

+  }

+

+  void transformDCUV(InputBuffer src, InputBuffer dst) {

+    if (src[0 * 16] != 0) {

+      transformDC(src, dst);

+    }

+    if (src[1 * 16] != 0) {

+      transformDC(new InputBuffer.from(src, offset: 1 * 16),

+                  new InputBuffer.from(dst, offset: 4));

+    }

+    if (src[2 * 16] != 0) {

+      transformDC(new InputBuffer.from(src, offset: 2 * 16),

+                  new InputBuffer.from(dst, offset: 4 * VP8.BPS));

+    }

+    if (src[3 * 16] != 0) {

+      transformDC(new InputBuffer.from(src, offset: 3 * 16),

+                  new InputBuffer.from(dst, offset: 4 * VP8.BPS + 4));

+    }

+  }

+

+  /**

+   * Simplified transform when only in[0], in[1] and in[4] are non-zero

+   */

+  void transformAC3(InputBuffer src, InputBuffer dst) {

+    final int a = src[0] + 4;

+    final int c4 = _mul(src[4], kC2);

+    final int d4 = _mul(src[4], kC1);

+    final int c1 = _mul(src[1], kC2);

+    final int d1 = _mul(src[1], kC1);

+    _store2(dst, 0, a + d4, d1, c1);

+    _store2(dst, 1, a + c4, d1, c1);

+    _store2(dst, 2, a - c4, d1, c1);

+    _store2(dst, 3, a - d4, d1, c1);

+  }

+

+  static int AVG3(a, b, c) => shiftR(((a) + 2 * (b) + (c) + 2), 2);

+  static int AVG2(a, b) => shiftR(((a) + (b) + 1), 1);

+

+  static void VE4(InputBuffer dst) {

+    int top = -VP8.BPS; // dst +

+    final List<int> vals = [

+       AVG3(dst[top - 1], dst[top],     dst[top + 1]),

+       AVG3(dst[top],     dst[top + 1], dst[top + 2]),

+       AVG3(dst[top + 1], dst[top + 2], dst[top + 3]),

+       AVG3(dst[top + 2], dst[top + 3], dst[top + 4])];

+

+    for (int i = 0; i < 4; ++i) {

+      dst.memcpy(i * VP8.BPS, 4, vals);

+    }

+  }

+

+  static void HE4(InputBuffer dst) {

+    final int A = dst[-1 - VP8.BPS];

+    final int B = dst[-1];

+    final int C = dst[-1 + VP8.BPS];

+    final int D = dst[-1 + 2 * VP8.BPS];

+    final int E = dst[-1 + 3 * VP8.BPS];

+

+    InputBuffer d2 = InputBuffer.from(dst);

+

+    d2.toUint32List()[0] = 0x01010101 * AVG3(A, B, C);

+    d2.offset += VP8.BPS;

+    d2.toUint32List()[0] = 0x01010101 * AVG3(B, C, D);

+    d2.offset += VP8.BPS;

+    d2.toUint32List()[0] = 0x01010101 * AVG3(C, D, E);

+    d2.offset += VP8.BPS;

+    d2.toUint32List()[0] = 0x01010101 * AVG3(D, E, E);

+  }

+

+  static void DC4(InputBuffer dst) {   // DC

+    int dc = 4;

+    for (int i = 0; i < 4; ++i) {

+      dc += dst[i - VP8.BPS] + dst[-1 + i * VP8.BPS];

+    }

+    dc >>= 3;

+    for (int i = 0; i < 4; ++i) {

+      dst.memset(i * VP8.BPS, 4, dc);

+    }

+  }

+

+  static void trueMotion(InputBuffer dst, int size) {

+    int di = 0;

+    int top = -VP8.BPS; // dst +

+    int clip0 = 255 - dst[top - 1]; // clip1 +

+

+    for (int y = 0; y < size; ++y) {

+      int clip = clip0 + dst[di - 1];

+      for (int x = 0; x < size; ++x) {

+        dst[di + x] = clip1[clip + dst[top + x]];

+      }

+

+      di += VP8.BPS;

+    }

+  }

+

+  static void TM4(InputBuffer dst) {

+    trueMotion(dst, 4);

+  }

+

+  static void TM8uv(InputBuffer dst) {

+    trueMotion(dst, 8);

+  }

+

+  static void TM16(InputBuffer dst) {

+    trueMotion(dst, 16);

+  }

+

+  static int DST(x, y) => x + y * VP8.BPS;

+

+  /**

+   * Down-right

+   */

+  static void RD4(InputBuffer dst) {

+    final int I = dst[-1 + 0 * VP8.BPS];

+    final int J = dst[-1 + 1 * VP8.BPS];

+    final int K = dst[-1 + 2 * VP8.BPS];

+    final int L = dst[-1 + 3 * VP8.BPS];

+    final int X = dst[-1 - VP8.BPS];

+    final int A = dst[0 - VP8.BPS];

+    final int B = dst[1 - VP8.BPS];

+    final int C = dst[2 - VP8.BPS];

+    final int D = dst[3 - VP8.BPS];

+

+    dst[DST(0, 3)] = AVG3(J, K, L);

+    dst[DST(0, 2)] = dst[DST(1, 3)] = AVG3(I, J, K);

+    dst[DST(0, 1)] = dst[DST(1, 2)] = dst[DST(2, 3)] = AVG3(X, I, J);

+    dst[DST(0, 0)] = dst[DST(1, 1)] = dst[DST(2, 2)] = dst[DST(3, 3)] = AVG3(A, X, I);

+    dst[DST(1, 0)] = dst[DST(2, 1)] = dst[DST(3, 2)] = AVG3(B, A, X);

+    dst[DST(2, 0)] = dst[DST(3, 1)] = AVG3(C, B, A);

+    dst[DST(3, 0)] = AVG3(D, C, B);

+  }

+

+  /**

+   * Down-Left

+   */

+  static void LD4(InputBuffer dst) {

+    final int A = dst[0 - VP8.BPS];

+    final int B = dst[1 - VP8.BPS];

+    final int C = dst[2 - VP8.BPS];

+    final int D = dst[3 - VP8.BPS];

+    final int E = dst[4 - VP8.BPS];

+    final int F = dst[5 - VP8.BPS];

+    final int G = dst[6 - VP8.BPS];

+    final int H = dst[7 - VP8.BPS];

+    dst[DST(0, 0)] = AVG3(A, B, C);

+    dst[DST(1, 0)] = dst[DST(0, 1)] = AVG3(B, C, D);

+    dst[DST(2, 0)] = dst[DST(1, 1)] = dst[DST(0, 2)] = AVG3(C, D, E);

+    dst[DST(3, 0)] = dst[DST(2, 1)] = dst[DST(1, 2)] = dst[DST(0, 3)] = AVG3(D, E, F);

+    dst[DST(3, 1)] = dst[DST(2, 2)] = dst[DST(1, 3)] = AVG3(E, F, G);

+    dst[DST(3, 2)] = dst[DST(2, 3)] = AVG3(F, G, H);

+    dst[DST(3, 3)] = AVG3(G, H, H);

+  }

+

+  /**

+   * Vertical-Right

+   */

+  static void VR4(InputBuffer dst) {

+    final int I = dst[-1 + 0 * VP8.BPS];

+    final int J = dst[-1 + 1 * VP8.BPS];

+    final int K = dst[-1 + 2 * VP8.BPS];

+    final int X = dst[-1 - VP8.BPS];

+    final int A = dst[0 - VP8.BPS];

+    final int B = dst[1 - VP8.BPS];

+    final int C = dst[2 - VP8.BPS];

+    final int D = dst[3 - VP8.BPS];

+    dst[DST(0, 0)] = dst[DST(1, 2)] = AVG2(X, A);

+    dst[DST(1, 0)] = dst[DST(2, 2)] = AVG2(A, B);

+    dst[DST(2, 0)] = dst[DST(3, 2)] = AVG2(B, C);

+    dst[DST(3, 0)] = AVG2(C, D);

+

+    dst[DST(0, 3)] = AVG3(K, J, I);

+    dst[DST(0, 2)] = AVG3(J, I, X);

+    dst[DST(0, 1)] = dst[DST(1, 3)] = AVG3(I, X, A);

+    dst[DST(1, 1)] = dst[DST(2, 3)] = AVG3(X, A, B);

+    dst[DST(2, 1)] = dst[DST(3, 3)] = AVG3(A, B, C);

+    dst[DST(3, 1)] = AVG3(B, C, D);

+  }

+

+  /**

+   * Vertical-Left

+   */

+  static void VL4(InputBuffer dst) {

+    final int A = dst[0 - VP8.BPS];

+    final int B = dst[1 - VP8.BPS];

+    final int C = dst[2 - VP8.BPS];

+    final int D = dst[3 - VP8.BPS];

+    final int E = dst[4 - VP8.BPS];

+    final int F = dst[5 - VP8.BPS];

+    final int G = dst[6 - VP8.BPS];

+    final int H = dst[7 - VP8.BPS];

+    dst[DST(0, 0)] = AVG2(A, B);

+    dst[DST(1, 0)] = dst[DST(0, 2)] = AVG2(B, C);

+    dst[DST(2, 0)] = dst[DST(1, 2)] = AVG2(C, D);

+    dst[DST(3, 0)] = dst[DST(2, 2)] = AVG2(D, E);

+

+    dst[DST(0, 1)] = AVG3(A, B, C);

+    dst[DST(1, 1)] = dst[DST(0, 3)] = AVG3(B, C, D);

+    dst[DST(2, 1)] = dst[DST(1, 3)] = AVG3(C, D, E);

+    dst[DST(3, 1)] = dst[DST(2, 3)] = AVG3(D, E, F);

+    dst[DST(3, 2)] = AVG3(E, F, G);

+    dst[DST(3, 3)] = AVG3(F, G, H);

+  }

+

+  /**

+   * Horizontal-Up

+   */

+  static void HU4(InputBuffer dst) {

+    final int I = dst[-1 + 0 * VP8.BPS];

+    final int J = dst[-1 + 1 * VP8.BPS];

+    final int K = dst[-1 + 2 * VP8.BPS];

+    final int L = dst[-1 + 3 * VP8.BPS];

+    dst[DST(0, 0)] = AVG2(I, J);

+    dst[DST(2, 0)] = dst[DST(0, 1)] = AVG2(J, K);

+    dst[DST(2, 1)] = dst[DST(0, 2)] = AVG2(K, L);

+    dst[DST(1, 0)] = AVG3(I, J, K);

+    dst[DST(3, 0)] = dst[DST(1, 1)] = AVG3(J, K, L);

+    dst[DST(3, 1)] = dst[DST(1, 2)] = AVG3(K, L, L);

+    dst[DST(3, 2)] = dst[DST(2, 2)] = dst[DST(0, 3)] = dst[DST(1, 3)] =

+                     dst[DST(2, 3)] = dst[DST(3, 3)] = L;

+  }

+

+  /**

+   * Horizontal-Down

+   */

+  static void HD4(InputBuffer dst) {

+    final int I = dst[-1 + 0 * VP8.BPS];

+    final int J = dst[-1 + 1 * VP8.BPS];

+    final int K = dst[-1 + 2 * VP8.BPS];

+    final int L = dst[-1 + 3 * VP8.BPS];

+    final int X = dst[-1 - VP8.BPS];

+    final int A = dst[0 - VP8.BPS];

+    final int B = dst[1 - VP8.BPS];

+    final int C = dst[2 - VP8.BPS];

+

+    dst[DST(0, 0)] = dst[DST(2, 1)] = AVG2(I, X);

+    dst[DST(0, 1)] = dst[DST(2, 2)] = AVG2(J, I);

+    dst[DST(0, 2)] = dst[DST(2, 3)] = AVG2(K, J);

+    dst[DST(0, 3)] = AVG2(L, K);

+

+    dst[DST(3, 0)] = AVG3(A, B, C);

+    dst[DST(2, 0)] = AVG3(X, A, B);

+    dst[DST(1, 0)] = dst[DST(3, 1)] = AVG3(I, X, A);

+    dst[DST(1, 1)] = dst[DST(3, 2)] = AVG3(J, I, X);

+    dst[DST(1, 2)] = dst[DST(3, 3)] = AVG3(K, J, I);

+    dst[DST(1, 3)] = AVG3(L, K, J);

+  }

+

+  static void VE16(InputBuffer dst) { // vertical

+    for (int j = 0; j < 16; ++j) {

+      dst.memcpy(j * VP8.BPS, 16, dst, -VP8.BPS);

+    }

+  }

+

+  static void HE16(InputBuffer dst) { // horizontal

+    int di = 0;

+    for (int j = 16; j > 0; --j) {

+      dst.memset(di, 16, dst[di - 1]);

+      di += VP8.BPS;

+    }

+  }

+

+  static void Put16(int v, InputBuffer dst) {

+    for (int j = 0; j < 16; ++j) {

+      dst.memset(j * VP8.BPS, 16, v);

+    }

+  }

+

+  static void DC16(InputBuffer dst) { // DC

+    int DC = 16;

+    for (int j = 0; j < 16; ++j) {

+      DC += dst[-1 + j * VP8.BPS] + dst[j - VP8.BPS];

+    }

+    Put16(DC >> 5, dst);

+  }

+

+  /**

+   * DC with top samples not available

+   */

+  static void DC16NoTop(InputBuffer dst) {

+    int DC = 8;

+    for (int j = 0; j < 16; ++j) {

+      DC += dst[-1 + j * VP8.BPS];

+    }

+    Put16(DC >> 4, dst);

+  }

+

+  /**

+   * DC with left samples not available

+   */

+  static void DC16NoLeft(InputBuffer dst) {

+    int DC = 8;

+    for (int i = 0; i < 16; ++i) {

+      DC += dst[i - VP8.BPS];

+    }

+    Put16(DC >> 4, dst);

+  }

+

+  /**

+   * DC with no top and left samples

+   */

+  static void DC16NoTopLeft(InputBuffer dst) {

+    Put16(0x80, dst);

+  }

+

+  static void VE8uv(InputBuffer dst) {

+    for (int j = 0; j < 8; ++j) {

+      dst.memcpy(j * VP8.BPS, 8, dst, -VP8.BPS);

+    }

+  }

+

+  static void HE8uv(InputBuffer dst) {

+    int di = 0;

+    for (int j = 0; j < 8; ++j) {

+      dst.memset(di, 8, dst[di - 1]);

+      di += VP8.BPS;

+    }

+  }

+

+  /**

+   * helper for chroma-DC predictions

+   */

+  static void Put8x8uv(int value, InputBuffer dst) {

+    for (int j = 0; j < 8; ++j) {

+      dst.memset(j * VP8.BPS, 8, value);

+    }

+  }

+

+  static void DC8uv(InputBuffer dst) {

+    int dc0 = 8;

+    for (int i = 0; i < 8; ++i) {

+      dc0 += dst[i - VP8.BPS] + dst[-1 + i * VP8.BPS];

+    }

+    Put8x8uv(dc0 >> 4, dst);

+  }

+

+  /**

+   * DC with no left samples

+   */

+  static void DC8uvNoLeft(InputBuffer dst) {

+    int dc0 = 4;

+    for (int i = 0; i < 8; ++i) {

+      dc0 += dst[i - VP8.BPS];

+    }

+    Put8x8uv(dc0 >> 3, dst);

+  }

+

+  /**

+   * DC with no top samples

+   */

+  static void DC8uvNoTop(InputBuffer dst) {

+    int dc0 = 4;

+    for (int i = 0; i < 8; ++i) {

+      dc0 += dst[-1 + i * VP8.BPS];

+    }

+    Put8x8uv(dc0 >> 3, dst);

+  }

+

+  /**

+   * DC with nothing

+   */

+  static void DC8uvNoTopLeft(InputBuffer dst) {

+    Put8x8uv(0x80, dst);

+  }

+

+  static const List PredLuma4 = const [

+      DC4, TM4, VE4, HE4, RD4, VR4, LD4, VL4, HD4, HU4 ];

+

+  static const List PredLuma16 = const [

+      DC16, TM16, VE16, HE16, DC16NoTop, DC16NoLeft, DC16NoTopLeft ];

+

+  static const List PredChroma8 = const [

+      DC8uv, TM8uv, VE8uv, HE8uv, DC8uvNoTop, DC8uvNoLeft, DC8uvNoTopLeft ];

+

+

+  static const int kC1 = 20091 + (1 << 16);

+  static const int kC2 = 35468;

+

+  static int _mul(int a, int b) {

+    int c = a * b;

+    return shiftR(c, 16);

+  }

+

+  static void _store(InputBuffer dst, int di, int x, int y, int v) {

+    dst[di + x + y * VP8.BPS] = _clip8b(dst[di + x + y * VP8.BPS] + (v >> 3));

+  }

+

+  static void _store2(InputBuffer dst, int y, int dc, int d, int c) {

+    _store(dst, 0, 0, y, dc + d);

+    _store(dst, 0, 1, y, dc + c);

+    _store(dst, 0, 2, y, dc - c);

+    _store(dst, 0, 3, y, dc - d);

+  }

+

+  /// abs(i)

+  static Uint8List abs0 = Uint8List(255 + 255 + 1);

+  /// abs(i)>>1

+  static Uint8List abs1 = Uint8List(255 + 255 + 1);

+  /// clips [-1020, 1020] to [-128, 127]

+  static Int8List sclip1 = Int8List(1020 + 1020 + 1);

+  /// clips [-112, 112] to [-16, 15]

+  static Int8List sclip2 = Int8List(112 + 112 + 1);

+  /// clips [-255,510] to [0,255]

+  static Uint8List clip1 = Uint8List(255 + 510 + 1);

+

+  static void _initTables() {

+    if (!_tablesInitialized) {

+      for (int i = -255; i <= 255; ++i) {

+        abs0[255 + i] = (i < 0) ? -i : i;

+        abs1[255 + i] = abs0[255 + i] >> 1;

+      }

+      for (int i = -1020; i <= 1020; ++i) {

+        sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;

+      }

+      for (int i = -112; i <= 112; ++i) {

+        sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;

+      }

+      for (int i = -255; i <= 255 + 255; ++i) {

+        clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;

+      }

+      _tablesInitialized = true;

+    }

+  }

+

+  static int _clip8b(int v) {

+    return ((v & -256) == 0) ? v : (v < 0) ? 0 : 255;

+  }

+

+  //static int __maxN = 0;

+

+  static bool _tablesInitialized = false;

+}

diff --git a/image/lib/src/formats/webp/vp8_types.dart b/image/lib/src/formats/webp/vp8_types.dart
old mode 100644
new mode 100755
index ce329bd..de08bd1
--- a/image/lib/src/formats/webp/vp8_types.dart
+++ b/image/lib/src/formats/webp/vp8_types.dart
@@ -1,214 +1,214 @@
-import 'dart:typed_data';
-
-import 'vp8.dart';
-
-class VP8FrameHeader {
-  bool keyFrame;
-  int profile; // uint8
-  int show; // uint8
-  int partitionLength; // uint32
-}
-
-class VP8PictureHeader {
-  int width; // uint16
-  int height; // uint16
-  int xscale; // uint8
-  int yscale; // uint8
-  int colorspace; // uint8, 0 = YCbCr
-  int clampType; // uint8
-}
-
-/**
- * Segment features
- */
-class VP8SegmentHeader {
-  bool useSegment = false;
-  /// whether to update the segment map or not
-  bool updateMap = false;
-  /// absolute or delta values for quantizer and filter
-  bool absoluteDelta = true;
-  /// quantization changes
-  Int8List quantizer = new Int8List(VP8.NUM_MB_SEGMENTS);
-  /// filter strength for segments
-  Int8List filterStrength = new Int8List(VP8.NUM_MB_SEGMENTS);
-}
-
-/**
- * All the probas associated to one band
- */
-class VP8BandProbas {
-  List<Uint8List> probas = new List<Uint8List>(VP8.NUM_CTX);
-  VP8BandProbas() {
-    for (int i = 0; i < VP8.NUM_CTX; ++i) {
-      probas[i] = new Uint8List(VP8.NUM_PROBAS);
-    }
-  }
-}
-
-/**
- * Struct collecting all frame-persistent probabilities.
- */
-class VP8Proba {
-  Uint8List segments = new Uint8List(VP8.MB_FEATURE_TREE_PROBS);
-  /// Type: 0:Intra16-AC  1:Intra16-DC   2:Chroma   3:Intra4
-  List<List<VP8BandProbas>> bands = new List(VP8.NUM_TYPES);
-
-  VP8Proba() {
-    for (int i = 0; i < VP8.NUM_TYPES; ++i) {
-      bands[i] = new List<VP8BandProbas>(VP8.NUM_BANDS);
-      for (int j = 0; j < VP8.NUM_BANDS; ++j) {
-        bands[i][j] = new VP8BandProbas();
-      }
-    }
-
-    segments.fillRange(0, segments.length, 255);
-  }
-}
-
-/**
- * Filter parameters
- */
-class VP8FilterHeader {
-  bool simple; // 0=complex, 1=simple
-  int level; // [0..63]
-  int sharpness; // [0..7]
-  bool useLfDelta;
-  Int32List refLfDelta = new Int32List(VP8.NUM_REF_LF_DELTAS);
-  Int32List modeLfDelta = new Int32List(VP8.NUM_MODE_LF_DELTAS);
-}
-
-//------------------------------------------------------------------------------
-// Informations about the macroblocks.
-
-/**
- * filter specs
- */
-class VP8FInfo {
-  int fLimit = 0; // uint8_t, filter limit in [3..189], or 0 if no filtering
-  int fInnerLevel = 0; // uint8_t, inner limit in [1..63]
-  bool fInner = false; // uint8_t, do inner filtering?
-  int hevThresh = 0; // uint8_t, high edge variance threshold in [0..2]
-}
-
-/**
- * Top/Left Contexts used for syntax-parsing
- */
-class VP8MB{
-  int nz = 0; // uint8_t, non-zero AC/DC coeffs (4bit for luma + 4bit for chroma)
-  int nzDc = 0; // uint8_t, non-zero DC coeff (1bit)
-}
-
-/**
- * Dequantization matrices
- */
-class VP8QuantMatrix {
-  Int32List y1Mat = new Int32List(2);
-  Int32List y2Mat = new Int32List(2);
-  Int32List uvMat = new Int32List(2);
-
-  int uvQuant; // U/V quantizer value
-  int dither; // dithering amplitude (0 = off, max=255)
-}
-
-/**
- * Data needed to reconstruct a macroblock
- */
-class VP8MBData {
-  /// 384 coeffs = (16+4+4) * 4*4
-  Int16List coeffs = new Int16List(384);
-  bool isIntra4x4; // true if intra4x4
-  /// one 16x16 mode (#0) or sixteen 4x4 modes
-  Uint8List imodes = new Uint8List(16);
-  /// chroma prediction mode
-  int uvmode;
-  // bit-wise info about the content of each sub-4x4 blocks (in decoding order).
-  // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to:
-  //   code=0 -> no coefficient
-  //   code=1 -> only DC
-  //   code=2 -> first three coefficients are non-zero
-  //   code=3 -> more than three coefficients are non-zero
-  // This allows to call specialized transform functions.
-  int nonZeroY;
-  int nonZeroUV;
-  /// uint8_t, local dithering strength (deduced from non_zero_*)
-  int dither;
-}
-
-/**
- * Saved top samples, per macroblock. Fits into a cache-line.
- */
-class VP8TopSamples {
-  Uint8List y = new Uint8List(16);
-  Uint8List u = new Uint8List(8);
-  Uint8List v = new Uint8List(8);
-}
-
-class VP8Random {
-  int _index1;
-  int _index2;
-  Uint32List _table = new Uint32List(RANDOM_TABLE_SIZE);
-  int _amplitude;
-
-  /**
-   * Initializes random generator with an amplitude 'dithering' in range [0..1].
-   */
-  VP8Random(double dithering) {
-    _table.setRange(0, RANDOM_TABLE_SIZE, _RANDOM_TABLE);
-    _index1 = 0;
-    _index2 = 31;
-    _amplitude = (dithering < 0.0) ? 0 :
-                 (dithering > 1.0) ? (1 << RANDOM_DITHER_FIX) :
-                 ((1 << RANDOM_DITHER_FIX) * dithering).toInt();
-  }
-
-  /**
-   * Returns a centered pseudo-random number with 'num_bits' amplitude.
-   * (uses D.Knuth's Difference-based random generator).
-   * 'amp' is in RANDOM_DITHER_FIX fixed-point precision.
-   */
-  int randomBits2(int numBits, int amp) {
-    int diff = _table[_index1] - _table[_index2];
-    if (diff < 0) {
-      diff += (1 << 31);
-    }
-
-    _table[_index1] = diff;
-
-    if (++_index1 == RANDOM_TABLE_SIZE) {
-      _index1 = 0;
-    }
-    if (++_index2 == RANDOM_TABLE_SIZE) {
-      _index2 = 0;
-    }
-
-    // sign-extend, 0-center
-    diff = (diff << 1) >> (32 - numBits);
-    // restrict range
-    diff = (diff * amp) >> RANDOM_DITHER_FIX;
-    // shift back to 0.5-center
-    diff += 1 << (numBits - 1);
-
-    return diff;
-  }
-
-  int randomBits(int numBits) {
-    return randomBits2(numBits, _amplitude);
-  }
-
-  /// fixed-point precision for dithering
-  static const int RANDOM_DITHER_FIX = 8;
-  static const int RANDOM_TABLE_SIZE = 55;
-
-  // 31b-range values
-  static const List<int> _RANDOM_TABLE = const [
-    0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828,
-    0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da,
-    0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f,
-    0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2,
-    0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c,
-    0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd,
-    0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3,
-    0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b,
-    0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494,
-    0x27e5ed3c];
-}
+import 'dart:typed_data';

+

+import 'vp8.dart';

+

+class VP8FrameHeader {

+  bool keyFrame;

+  int profile; // uint8

+  int show; // uint8

+  int partitionLength; // uint32

+}

+

+class VP8PictureHeader {

+  int width; // uint16

+  int height; // uint16

+  int xscale; // uint8

+  int yscale; // uint8

+  int colorspace; // uint8, 0 = YCbCr

+  int clampType; // uint8

+}

+

+/**

+ * Segment features

+ */

+class VP8SegmentHeader {

+  bool useSegment = false;

+  /// whether to update the segment map or not

+  bool updateMap = false;

+  /// absolute or delta values for quantizer and filter

+  bool absoluteDelta = true;

+  /// quantization changes

+  Int8List quantizer = Int8List(VP8.NUM_MB_SEGMENTS);

+  /// filter strength for segments

+  Int8List filterStrength = Int8List(VP8.NUM_MB_SEGMENTS);

+}

+

+/**

+ * All the probas associated to one band

+ */

+class VP8BandProbas {

+  List<Uint8List> probas = List<Uint8List>(VP8.NUM_CTX);

+  VP8BandProbas() {

+    for (int i = 0; i < VP8.NUM_CTX; ++i) {

+      probas[i] = Uint8List(VP8.NUM_PROBAS);

+    }

+  }

+}

+

+/**

+ * Struct collecting all frame-persistent probabilities.

+ */

+class VP8Proba {

+  Uint8List segments = Uint8List(VP8.MB_FEATURE_TREE_PROBS);

+  /// Type: 0:Intra16-AC  1:Intra16-DC   2:Chroma   3:Intra4

+  List<List<VP8BandProbas>> bands = List(VP8.NUM_TYPES);

+

+  VP8Proba() {

+    for (int i = 0; i < VP8.NUM_TYPES; ++i) {

+      bands[i] = List<VP8BandProbas>(VP8.NUM_BANDS);

+      for (int j = 0; j < VP8.NUM_BANDS; ++j) {

+        bands[i][j] = VP8BandProbas();

+      }

+    }

+

+    segments.fillRange(0, segments.length, 255);

+  }

+}

+

+/**

+ * Filter parameters

+ */

+class VP8FilterHeader {

+  bool simple; // 0=complex, 1=simple

+  int level; // [0..63]

+  int sharpness; // [0..7]

+  bool useLfDelta;

+  Int32List refLfDelta = Int32List(VP8.NUM_REF_LF_DELTAS);

+  Int32List modeLfDelta = Int32List(VP8.NUM_MODE_LF_DELTAS);

+}

+

+//------------------------------------------------------------------------------

+// Informations about the macroblocks.

+

+/**

+ * filter specs

+ */

+class VP8FInfo {

+  int fLimit = 0; // uint8_t, filter limit in [3..189], or 0 if no filtering

+  int fInnerLevel = 0; // uint8_t, inner limit in [1..63]

+  bool fInner = false; // uint8_t, do inner filtering?

+  int hevThresh = 0; // uint8_t, high edge variance threshold in [0..2]

+}

+

+/**

+ * Top/Left Contexts used for syntax-parsing

+ */

+class VP8MB{

+  int nz = 0; // uint8_t, non-zero AC/DC coeffs (4bit for luma + 4bit for chroma)

+  int nzDc = 0; // uint8_t, non-zero DC coeff (1bit)

+}

+

+/**

+ * Dequantization matrices

+ */

+class VP8QuantMatrix {

+  Int32List y1Mat = Int32List(2);

+  Int32List y2Mat = Int32List(2);

+  Int32List uvMat = Int32List(2);

+

+  int uvQuant; // U/V quantizer value

+  int dither; // dithering amplitude (0 = off, max=255)

+}

+

+/**

+ * Data needed to reconstruct a macroblock

+ */

+class VP8MBData {

+  /// 384 coeffs = (16+4+4) * 4*4

+  Int16List coeffs = Int16List(384);

+  bool isIntra4x4; // true if intra4x4

+  /// one 16x16 mode (#0) or sixteen 4x4 modes

+  Uint8List imodes = Uint8List(16);

+  /// chroma prediction mode

+  int uvmode;

+  // bit-wise info about the content of each sub-4x4 blocks (in decoding order).

+  // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to:

+  //   code=0 -> no coefficient

+  //   code=1 -> only DC

+  //   code=2 -> first three coefficients are non-zero

+  //   code=3 -> more than three coefficients are non-zero

+  // This allows to call specialized transform functions.

+  int nonZeroY;

+  int nonZeroUV;

+  /// uint8_t, local dithering strength (deduced from non_zero_*)

+  int dither;

+}

+

+/**

+ * Saved top samples, per macroblock. Fits into a cache-line.

+ */

+class VP8TopSamples {

+  Uint8List y = Uint8List(16);

+  Uint8List u = Uint8List(8);

+  Uint8List v = Uint8List(8);

+}

+

+class VP8Random {

+  int _index1;

+  int _index2;

+  Uint32List _table = Uint32List(RANDOM_TABLE_SIZE);

+  int _amplitude;

+

+  /**

+   * Initializes random generator with an amplitude 'dithering' in range [0..1].

+   */

+  VP8Random(double dithering) {

+    _table.setRange(0, RANDOM_TABLE_SIZE, _RANDOM_TABLE);

+    _index1 = 0;

+    _index2 = 31;

+    _amplitude = (dithering < 0.0) ? 0 :

+                 (dithering > 1.0) ? (1 << RANDOM_DITHER_FIX) :

+                 ((1 << RANDOM_DITHER_FIX) * dithering).toInt();

+  }

+

+  /**

+   * Returns a centered pseudo-random number with 'num_bits' amplitude.

+   * (uses D.Knuth's Difference-based random generator).

+   * 'amp' is in RANDOM_DITHER_FIX fixed-point precision.

+   */

+  int randomBits2(int numBits, int amp) {

+    int diff = _table[_index1] - _table[_index2];

+    if (diff < 0) {

+      diff += (1 << 31);

+    }

+

+    _table[_index1] = diff;

+

+    if (++_index1 == RANDOM_TABLE_SIZE) {

+      _index1 = 0;

+    }

+    if (++_index2 == RANDOM_TABLE_SIZE) {

+      _index2 = 0;

+    }

+

+    // sign-extend, 0-center

+    diff = (diff << 1) >> (32 - numBits);

+    // restrict range

+    diff = (diff * amp) >> RANDOM_DITHER_FIX;

+    // shift back to 0.5-center

+    diff += 1 << (numBits - 1);

+

+    return diff;

+  }

+

+  int randomBits(int numBits) {

+    return randomBits2(numBits, _amplitude);

+  }

+

+  /// fixed-point precision for dithering

+  static const int RANDOM_DITHER_FIX = 8;

+  static const int RANDOM_TABLE_SIZE = 55;

+

+  // 31b-range values

+  static const List<int> _RANDOM_TABLE = const [

+    0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828,

+    0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da,

+    0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f,

+    0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2,

+    0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c,

+    0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd,

+    0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3,

+    0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b,

+    0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494,

+    0x27e5ed3c];

+}

diff --git a/image/lib/src/formats/webp/vp8l.dart b/image/lib/src/formats/webp/vp8l.dart
old mode 100644
new mode 100755
index f7b068e..84c6736
--- a/image/lib/src/formats/webp/vp8l.dart
+++ b/image/lib/src/formats/webp/vp8l.dart
@@ -1,900 +1,901 @@
-import 'dart:typed_data';
-
-import '../../color.dart';
-import '../../image.dart';
-import '../../image_exception.dart';
-import '../../internal/internal.dart';
-import '../../util/input_buffer.dart';
-import 'vp8l_bit_reader.dart';
-import 'vp8l_color_cache.dart';
-import 'vp8l_transform.dart';
-import 'webp_huffman.dart';
-import 'webp_info.dart';
-
-/**
- * WebP lossless format.
- */
-class VP8L {
-  InputBuffer input;
-  VP8LBitReader br;
-  WebPInfo webp;
-  Image image;
-
-  VP8L(InputBuffer input, WebPInfo webp) :
-    this.input = input,
-    this.webp = webp,
-    this.br = new VP8LBitReader(input) {
-  }
-
-  bool decodeHeader() {
-    int signature = br.readBits(8);
-    if (signature != VP8L_MAGIC_BYTE) {
-      return false;
-    }
-
-    webp.format = WebPInfo.FORMAT_LOSSLESS;
-    webp.width = br.readBits(14) + 1;
-    webp.height = br.readBits(14) + 1;
-    webp.hasAlpha = br.readBits(1) != 0;
-    int version = br.readBits(3);
-
-    if (version != VP8L_VERSION) {
-      return false;
-    }
-
-    return true;
-  }
-
-  Image decode() {
-    _lastPixel = 0;
-
-    if (!decodeHeader()) {
-      return null;
-    }
-
-    _decodeImageStream(webp.width, webp.height, true);
-
-    _allocateInternalBuffers32b();
-
-    image = new Image(webp.width, webp.height);
-
-    if (!_decodeImageData(_pixels, webp.width, webp.height,
-                          webp.height, _processRows)) {
-      return null;
-    }
-
-    return image;
-  }
-
-  bool _allocateInternalBuffers32b() {
-    final int numPixels = webp.width * webp.height;
-    // Scratch buffer corresponding to top-prediction row for transforming the
-    // first row in the row-blocks. Not needed for paletted alpha.
-    final int cacheTopPixels = webp.width;
-    // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
-    final int cachePixels = webp.width * _NUM_ARGB_CACHE_ROWS;
-    final int totalNumPixels = numPixels + cacheTopPixels + cachePixels;
-
-    Uint32List pixels32 = new Uint32List(totalNumPixels);
-    _pixels = pixels32;
-    _pixels8 = new Uint8List.view(pixels32.buffer);
-    _argbCache = numPixels + cacheTopPixels;
-
-    return true;
-  }
-
-  bool _allocateInternalBuffers8b() {
-    final int totalNumPixels = webp.width * webp.height;
-    _argbCache = 0;
-    // pad the byteBuffer to a multiple of 4
-    int n = totalNumPixels + (4 - (totalNumPixels % 4));
-    _pixels8 = new Uint8List(n);
-    _pixels = new Uint32List.view(_pixels8.buffer);
-    return true;
-  }
-
-  bool _readTransform(List<int> transformSize) {
-    bool ok = true;
-
-    int type = br.readBits(2);
-
-    // Each transform type can only be present once in the stream.
-    if ((_transformsSeen & (1 << type)) != 0) {
-      return false;
-    }
-    _transformsSeen |= (1 << type);
-
-    VP8LTransform transform = new VP8LTransform();
-    _transforms.add(transform);
-
-    transform.type = type;
-    transform.xsize = transformSize[0];
-    transform.ysize = transformSize[1];
-
-    switch (type) {
-      case VP8LTransform.PREDICTOR_TRANSFORM:
-      case VP8LTransform.CROSS_COLOR_TRANSFORM:
-        transform.bits = br.readBits(3) + 2;
-        transform.data = _decodeImageStream(
-                _subSampleSize(transform.xsize, transform.bits),
-                _subSampleSize(transform.ysize, transform.bits), false);
-        break;
-      case VP8LTransform.COLOR_INDEXING_TRANSFORM:
-        final int numColors = br.readBits(8) + 1;
-        final int bits = (numColors > 16) ? 0 :
-                         (numColors > 4) ? 1 :
-                         (numColors > 2) ? 2 : 3;
-        transformSize[0] = _subSampleSize(transform.xsize, bits);
-        transform.bits = bits;
-        transform.data = _decodeImageStream(numColors, 1, false);
-        ok = _expandColorMap(numColors, transform);
-        break;
-      case VP8LTransform.SUBTRACT_GREEN:
-        break;
-      default:
-        throw new ImageException('Invalid WebP tranform type: $type');
-    }
-
-    return ok;
-  }
-
-  Uint32List _decodeImageStream(int xsize, int ysize, bool isLevel0) {
-    int transformXsize = xsize;
-    int transformYsize = ysize;
-    int colorCacheBits = 0;
-
-    // Read the transforms (may recurse).
-    if (isLevel0) {
-      while (br.readBits(1) != 0) {
-        List<int> sizes = [transformXsize, transformYsize];
-        if (!_readTransform(sizes)) {
-          throw new ImageException('Invalid Transform');
-        }
-        transformXsize = sizes[0];
-        transformYsize = sizes[1];
-      }
-    }
-
-    // Color cache
-    if (br.readBits(1) != 0) {
-      colorCacheBits = br.readBits(4);
-      bool ok = (colorCacheBits >= 1 && colorCacheBits <= MAX_CACHE_BITS);
-      if (!ok) {
-        throw new ImageException('Invalid Color Cache');
-      }
-    }
-
-    // Read the Huffman codes (may recurse).
-    if (!_readHuffmanCodes(transformXsize, transformYsize,
-                           colorCacheBits, isLevel0)) {
-      throw new ImageException('Invalid Huffman Codes');
-    }
-
-    // Finish setting up the color-cache
-    if (colorCacheBits > 0) {
-      _colorCacheSize = 1 << colorCacheBits;
-      _colorCache = new VP8LColorCache(colorCacheBits);
-    } else {
-      _colorCacheSize = 0;
-    }
-
-    webp.width = transformXsize;
-    webp.height = transformYsize;
-    final int numBits = _huffmanSubsampleBits;
-    _huffmanXsize = _subSampleSize(transformXsize, numBits);
-    _huffmanMask = (numBits == 0) ? ~0 : (1 << numBits) - 1;
-
-    if (isLevel0) {
-      // Reset for future DECODE_DATA_FUNC() calls.
-      _lastPixel = 0;
-      return null;
-    }
-
-    final int totalSize = transformXsize * transformYsize;
-    Uint32List data = new Uint32List(totalSize);
-
-    // Use the Huffman trees to decode the LZ77 encoded data.
-    if (!_decodeImageData(data, transformXsize, transformYsize,
-                          transformYsize, null)) {
-      throw new ImageException('Failed to decode image data.');
-    }
-
-    // Reset for future DECODE_DATA_FUNC() calls.
-    _lastPixel = 0;
-
-    return data;
-  }
-
-  bool _decodeImageData(data, int width, int height,
-                        int lastRow, processFunc) {
-    int row = _lastPixel ~/ width;
-    int col = _lastPixel % width;
-
-    HTreeGroup htreeGroup = _getHtreeGroupForPos(col, row);
-
-    int src = _lastPixel;
-    int lastCached = src;
-    int srcEnd = width * height; // End of data
-    int srcLast = width * lastRow; // Last pixel to decode
-
-    const int lenCodeLimit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
-    final int colorCacheLimit = lenCodeLimit + _colorCacheSize;
-
-    VP8LColorCache colorCache = (_colorCacheSize > 0) ? _colorCache : null;
-    final int mask = _huffmanMask;
-
-    while (!br.isEOS && src < srcLast) {
-      // Only update when changing tile. Note we could use this test:
-      // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
-      // but that's actually slower and needs storing the previous col/row.
-      if ((col & mask) == 0) {
-        htreeGroup = _getHtreeGroupForPos(col, row);
-      }
-
-      br.fillBitWindow();
-      int code = htreeGroup.htrees[_GREEN].readSymbol(br);
-
-      if (code < NUM_LITERAL_CODES) {  // Literal
-        int red = htreeGroup.htrees[_RED].readSymbol(br);
-        int green = code;
-        br.fillBitWindow();
-        int blue = htreeGroup.htrees[_BLUE].readSymbol(br);
-        int alpha = htreeGroup.htrees[_ALPHA].readSymbol(br);
-
-        int c = (alpha << 24) | (red << 16) | (green << 8) | blue;
-        data[src] = c;
-
-        ++src;
-        ++col;
-
-        if (col >= width) {
-          col = 0;
-          ++row;
-          if ((row % _NUM_ARGB_CACHE_ROWS == 0) && (processFunc != null)) {
-            processFunc(row);
-          }
-
-          if (colorCache != null) {
-            while (lastCached < src) {
-              colorCache.insert(data[lastCached]);
-              lastCached++;
-            }
-          }
-        }
-      } else if (code < lenCodeLimit) {  // Backward reference
-        final int lengthSym = code - NUM_LITERAL_CODES;
-        final int length = _getCopyLength(lengthSym);
-        final int distSymbol = htreeGroup.htrees[_DIST].readSymbol(br);
-
-        br.fillBitWindow();
-        int distCode = _getCopyDistance(distSymbol);
-        int dist = _planeCodeToDistance(width, distCode);
-
-        if (src < dist || srcEnd - src < length) {
-          return false;
-        } else {
-          for (int i = 0; i < length; ++i) {
-            data[src + i] = data[src + (i - dist)];
-          }
-          src += length;
-        }
-        col += length;
-        while (col >= width) {
-          col -= width;
-          ++row;
-          if ((row % _NUM_ARGB_CACHE_ROWS == 0) && (processFunc != null)) {
-            processFunc(row);
-          }
-        }
-        if (src < srcLast) {
-          if ((col & mask) != 0) {
-            htreeGroup = _getHtreeGroupForPos(col, row);
-          }
-          if (colorCache != null) {
-            while (lastCached < src) {
-              colorCache.insert(data[lastCached]);
-              lastCached++;
-            }
-          }
-        }
-      } else if (code < colorCacheLimit) {  // Color cache
-        final int key = code - lenCodeLimit;
-
-        while (lastCached < src) {
-          colorCache.insert(data[lastCached]);
-          lastCached++;
-        }
-
-        data[src] = colorCache.lookup(key);
-
-        ++src;
-        ++col;
-
-        if (col >= width) {
-          col = 0;
-          ++row;
-          if ((row % _NUM_ARGB_CACHE_ROWS == 0) && (processFunc != null)) {
-            processFunc(row);
-          }
-
-          if (colorCache != null) {
-            while (lastCached < src) {
-              colorCache.insert(data[lastCached]);
-              lastCached++;
-            }
-          }
-        }
-      } else {  // Not reached
-        return false;
-      }
-    }
-
-    // Process the remaining rows corresponding to last row-block.
-    if (processFunc != null) {
-      processFunc(row);
-    }
-
-    if (br.isEOS && src < srcEnd) {
-      return false;
-    }
-
-    _lastPixel = src;
-
-    return true;
-  }
-
-  /**
-   * Row-processing for the special case when alpha data contains only one
-   * transform (color indexing), and trivial non-green literals.
-   */
-  bool _is8bOptimizable() {
-    if (_colorCacheSize > 0) {
-      return false;
-    }
-    // When the Huffman tree contains only one symbol, we can skip the
-    // call to ReadSymbol() for red/blue/alpha channels.
-    for (int i = 0; i < _numHtreeGroups; ++i) {
-      List<HuffmanTree> htrees = _htreeGroups[i].htrees;
-      if (htrees[_RED].numNodes > 1) {
-        return false;
-      }
-      if (htrees[_BLUE].numNodes > 1) {
-        return false;
-      }
-      if (htrees[_ALPHA].numNodes > 1) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Special row-processing that only stores the alpha data.
-   */
-  void _extractAlphaRows(int row) {
-    final int numRows = row - _lastRow;
-    if (numRows <= 0) {
-      return;  // Nothing to be done.
-    }
-
-    _applyInverseTransforms(numRows, webp.width * _lastRow);
-
-    // Extract alpha (which is stored in the green plane).
-    final int width = webp.width;      // the final width (!= dec->width_)
-    final int cachePixs = width * numRows;
-
-    final int di = width * _lastRow;
-    InputBuffer src = new InputBuffer(_pixels, offset: _argbCache);
-
-    for (int i = 0; i < cachePixs; ++i) {
-      _opaque[di + i] = (src[i] >> 8) & 0xff;
-    }
-
-    _lastRow = row;
-  }
-
-  bool _decodeAlphaData(int width, int height, int lastRow) {
-    int row = _lastPixel ~/ width;
-    int col = _lastPixel % width;
-
-    HTreeGroup htreeGroup = _getHtreeGroupForPos(col, row);
-    int pos = _lastPixel; // current position
-    final int end = width * height; // End of data
-    final int last = width * lastRow; // Last pixel to decode
-    final int lenCodeLimit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
-    final int mask = _huffmanMask;
-
-    while (!br.isEOS && pos < last) {
-      // Only update when changing tile.
-      if ((col & mask) == 0) {
-        htreeGroup = _getHtreeGroupForPos(col, row);
-      }
-
-      br.fillBitWindow();
-
-      int code = htreeGroup.htrees[_GREEN].readSymbol(br);
-      if (code < NUM_LITERAL_CODES) {  // Literal
-        _pixels8[pos] = code;
-        ++pos;
-        ++col;
-        if (col >= width) {
-          col = 0;
-          ++row;
-          if (row % _NUM_ARGB_CACHE_ROWS == 0) {
-            _extractPalettedAlphaRows(row);
-          }
-        }
-      } else if (code < lenCodeLimit) {  // Backward reference
-        final int lengthSym = code - NUM_LITERAL_CODES;
-        final int length = _getCopyLength(lengthSym);
-        final int distSymbol = htreeGroup.htrees[_DIST].readSymbol(br);
-
-        br.fillBitWindow();
-
-        int distCode = _getCopyDistance(distSymbol);
-        int dist = _planeCodeToDistance(width, distCode);
-
-        if (pos >= dist && end - pos >= length) {
-          for (int i = 0; i < length; ++i) {
-            _pixels8[pos + i] = _pixels8[pos + i - dist];
-          }
-        } else {
-          _lastPixel = pos;
-          return true;
-        }
-
-        pos += length;
-        col += length;
-
-        while (col >= width) {
-          col -= width;
-          ++row;
-          if (row % _NUM_ARGB_CACHE_ROWS == 0) {
-            _extractPalettedAlphaRows(row);
-          }
-        }
-
-        if (pos < last && (col & mask) != 0) {
-          htreeGroup = _getHtreeGroupForPos(col, row);
-        }
-      } else {  // Not reached
-        return false;
-      }
-    }
-
-    // Process the remaining rows corresponding to last row-block.
-    _extractPalettedAlphaRows(row);
-
-    _lastPixel = pos;
-
-    return true;
-  }
-
-  void _extractPalettedAlphaRows(int row) {
-    final int numRows = row - _lastRow;
-    InputBuffer pIn = new InputBuffer(_pixels8, offset: webp.width * _lastRow);
-    if (numRows > 0) {
-      _applyInverseTransformsAlpha(numRows, pIn);
-    }
-    _lastRow = row;
-  }
-
-  /**
-   * Special method for paletted alpha data.
-   */
-  void _applyInverseTransformsAlpha(int numRows, InputBuffer rows) {
-    final int startRow = _lastRow;
-    final int endRow = startRow + numRows;
-    InputBuffer rowsOut = new InputBuffer(_opaque, offset: _ioWidth * startRow);
-    VP8LTransform transform = _transforms[0];
-
-    transform.colorIndexInverseTransformAlpha(startRow, endRow, rows, rowsOut);
-  }
-
-  /**
-   * Processes (transforms, scales & color-converts) the rows decoded after the
-   * last call.
-   */
-  //static int __count = 0;
-  void _processRows(int row) {
-    int rows = webp.width * _lastRow; // offset into _pixels
-    final int numRows = row - _lastRow;
-
-    if (numRows <= 0) {
-      return;  // Nothing to be done.
-    }
-
-    _applyInverseTransforms(numRows, rows);
-
-    //int count = 0;
-    //int di = rows;
-    for (int y = 0, pi = _argbCache, dy = _lastRow; y < numRows; ++y, ++dy) {
-      for (int x = 0; x < webp.width; ++x, ++pi) {
-        int c = _pixels[pi];
-        int r = getRed(c);
-        int g = getGreen(c);
-        int b = getBlue(c);
-        int a = getAlpha(c);
-        // rearrange the ARGB webp color to RGBA image color.
-        image.setPixel(x, dy, getColor(b, g, r, a));
-      }
-    }
-
-    _lastRow = row;
-  }
-
-  void _applyInverseTransforms(int numRows, int rows) {
-    int n = _transforms.length;
-    final int cachePixs = webp.width * numRows;
-    final int startRow = _lastRow;
-    final int endRow = startRow + numRows;
-    int rowsIn = rows;
-    int rowsOut = _argbCache;
-
-    // Inverse transforms.
-    _pixels.setRange(rowsOut, rowsOut + cachePixs, _pixels, rowsIn);
-
-    while (n-- > 0) {
-      VP8LTransform transform = _transforms[n];
-      transform.inverseTransform(startRow, endRow, _pixels, rowsIn,
-                                 _pixels, rowsOut);
-      rowsIn = rowsOut;
-    }
-  }
-
-  bool _readHuffmanCodes(int xsize, int ysize, int colorCacheBits,
-                         bool allowRecursion) {
-    Uint32List huffmanImage;
-    int numHtreeGroups = 1;
-
-    if (allowRecursion && br.readBits(1) != 0) {
-      // use meta Huffman codes.
-      final int huffmanPrecision = br.readBits(3) + 2;
-      final int huffmanXsize = _subSampleSize(xsize, huffmanPrecision);
-      final int huffmanYsize = _subSampleSize(ysize, huffmanPrecision);
-      final int huffmanPixs = huffmanXsize * huffmanYsize;
-
-      huffmanImage = _decodeImageStream(huffmanXsize, huffmanYsize, false);
-
-      _huffmanSubsampleBits = huffmanPrecision;
-
-      for (int i = 0; i < huffmanPixs; ++i) {
-        // The huffman data is stored in red and green bytes.
-        final int group = (huffmanImage[i] >> 8) & 0xffff;
-        huffmanImage[i] = group;
-        if (group >= numHtreeGroups) {
-          numHtreeGroups = group + 1;
-        }
-      }
-    }
-
-    assert(numHtreeGroups <= 0x10000);
-
-    List<HTreeGroup> htreeGroups = new List<HTreeGroup>(numHtreeGroups);
-    for (int i = 0; i < numHtreeGroups; ++i) {
-      htreeGroups[i] = new HTreeGroup();
-
-      for (int j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
-        int alphabetSize = ALPHABET_SIZE[j];
-        if (j == 0 && colorCacheBits > 0) {
-          alphabetSize += 1 << colorCacheBits;
-        }
-
-        if (!_readHuffmanCode(alphabetSize, htreeGroups[i].htrees[j])) {
-          return false;
-        }
-      }
-    }
-
-    // All OK. Finalize pointers and return.
-    _huffmanImage = huffmanImage;
-    _numHtreeGroups = numHtreeGroups;
-    _htreeGroups = htreeGroups;
-
-    return true;
-  }
-
-  bool _readHuffmanCode(int alphabetSize, HuffmanTree tree) {
-    bool ok = false;
-    final int simpleCode = br.readBits(1);
-
-    // Read symbols, codes & code lengths directly.
-    if (simpleCode != 0) {
-      List<int> symbols = [0, 0];
-      List<int> codes = [0, 0];
-      List<int> codeLengths = [0, 0];
-
-      final int numSymbols = br.readBits(1) + 1;
-      final int firstSymbolLenCode = br.readBits(1);
-
-      // The first code is either 1 bit or 8 bit code.
-      symbols[0] = br.readBits((firstSymbolLenCode == 0) ? 1 : 8);
-      codes[0] = 0;
-      codeLengths[0] = numSymbols - 1;
-
-      // The second code (if present), is always 8 bit long.
-      if (numSymbols == 2) {
-        symbols[1] = br.readBits(8);
-        codes[1] = 1;
-        codeLengths[1] = numSymbols - 1;
-      }
-
-      ok = tree.buildExplicit(codeLengths, codes, symbols,
-                              alphabetSize, numSymbols);
-    } else {
-      // Decode Huffman-coded code lengths.
-      Int32List codeLengthCodeLengths =
-          new Int32List(_NUM_CODE_LENGTH_CODES);
-
-      final int numCodes = br.readBits(4) + 4;
-      if (numCodes > _NUM_CODE_LENGTH_CODES) {
-        return false;
-      }
-
-      Int32List codeLengths = new Int32List(alphabetSize);
-
-      for (int i = 0; i < numCodes; ++i) {
-        codeLengthCodeLengths[_CODE_LENGTH_CODE_ORDER[i]] = br.readBits(3);
-      }
-
-      ok = _readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSize,
-                                   codeLengths);
-
-      if (ok) {
-        ok = tree.buildImplicit(codeLengths, alphabetSize);
-      }
-    }
-
-    return ok;
-  }
-
-  bool _readHuffmanCodeLengths(List<int> codeLengthCodeLengths,
-                               int numSymbols, List<int> codeLengths) {
-    //bool ok = false;
-    int symbol;
-    int max_symbol;
-    int prev_code_len = DEFAULT_CODE_LENGTH;
-    HuffmanTree tree = new HuffmanTree();
-
-    if (!tree.buildImplicit(codeLengthCodeLengths, _NUM_CODE_LENGTH_CODES)) {
-      return false;
-    }
-
-    if (br.readBits(1) != 0) {    // use length
-      final int length_nbits = 2 + 2 * br.readBits(3);
-      max_symbol = 2 + br.readBits(length_nbits);
-      if (max_symbol > numSymbols) {
-        return false;
-      }
-    } else {
-      max_symbol = numSymbols;
-    }
-
-    symbol = 0;
-    while (symbol < numSymbols) {
-      int code_len;
-      if (max_symbol-- == 0) {
-        break;
-      }
-
-      br.fillBitWindow();
-
-      code_len = tree.readSymbol(br);
-
-      if (code_len < _CODE_LENGTH_LITERALS) {
-        codeLengths[symbol++] = code_len;
-        if (code_len != 0) {
-          prev_code_len = code_len;
-        }
-      } else {
-        final bool usePrev = (code_len == _CODE_LENGTH_REPEAT_CODE);
-        final int slot = code_len - _CODE_LENGTH_LITERALS;
-        final int extra_bits = _CODE_LENGTH_EXTRA_BITS[slot];
-        final int repeat_offset = _CODE_LENGTH_REPEAT_OFFSETS[slot];
-        int repeat = br.readBits(extra_bits) + repeat_offset;
-
-        if (symbol + repeat > numSymbols) {
-          return false;
-        } else {
-          final int length = usePrev ? prev_code_len : 0;
-          while (repeat-- > 0) {
-            codeLengths[symbol++] = length;
-          }
-        }
-      }
-    }
-
-    return true;
-  }
-
-  int _getCopyDistance(int distanceSymbol) {
-    if (distanceSymbol < 4) {
-      return distanceSymbol + 1;
-    }
-    int extraBits = (distanceSymbol - 2) >> 1;
-    int offset = (2 + (distanceSymbol & 1)) << extraBits;
-    return offset + br.readBits(extraBits) + 1;
-  }
-
-  int _getCopyLength(int lengthSymbol) {
-    // Length and distance prefixes are encoded the same way.
-    return _getCopyDistance(lengthSymbol);
-  }
-
-  int _planeCodeToDistance(int xsize, int planeCode) {
-    if (planeCode > _CODE_TO_PLANE_CODES) {
-      return planeCode - _CODE_TO_PLANE_CODES;
-    } else {
-      final int distCode = _CODE_TO_PLANE[planeCode - 1];
-      final int yoffset = distCode >> 4;
-      final int xoffset = 8 - (distCode & 0xf);
-      final int dist = yoffset * xsize + xoffset;
-      // dist<1 can happen if xsize is very small
-      return (dist >= 1) ? dist : 1;
-    }
-  }
-
-  /**
-   * Computes sampled size of 'size' when sampling using 'sampling bits'.
-   */
-  static int _subSampleSize(int size, int samplingBits) {
-    return (size + (1 << samplingBits) - 1) >> samplingBits;
-  }
-
-  /**
-   * For security reason, we need to remap the color map to span
-   * the total possible bundled values, and not just the num_colors.
-   */
-  bool _expandColorMap(int numColors, VP8LTransform transform) {
-    final int finalNumColors = 1 << (8 >> transform.bits);
-    Uint32List newColorMap = new Uint32List(finalNumColors);
-    Uint8List data = new Uint8List.view(transform.data.buffer);
-    Uint8List newData = new Uint8List.view(newColorMap.buffer);
-
-    newColorMap[0] = transform.data[0];
-
-    int len = 4 * numColors;
-
-    int i;
-    for (i = 4; i < len; ++i) {
-      // Equivalent to AddPixelEq(), on a byte-basis.
-      newData[i] = (data[i] + newData[i - 4]) & 0xff;
-    }
-
-    for (len = 4 * finalNumColors; i < len; ++i) {
-      newData[i] = 0;
-    }
-
-    transform.data = newColorMap;
-
-    return true;
-  }
-
-  int _getMetaIndex(Uint32List image, int xsize, int bits, int x, int y) {
-    if (bits == 0) {
-      return 0;
-    }
-    return image[xsize * (y >> bits) + (x >> bits)];
-  }
-
-  HTreeGroup _getHtreeGroupForPos(int x, int y) {
-    int metaIndex = _getMetaIndex(_huffmanImage, _huffmanXsize,
-                                  _huffmanSubsampleBits, x, y);
-    if (_htreeGroups[metaIndex] == null) {
-      _htreeGroups[metaIndex] = new HTreeGroup();
-    }
-    return _htreeGroups[metaIndex];
-  }
-
-  static const int _GREEN = 0;
-  static const int _RED = 1;
-  static const int _BLUE = 2;
-  static const int _ALPHA = 3;
-  static const int _DIST = 4;
-
-  static const int _NUM_ARGB_CACHE_ROWS = 16;
-
-  static const int _NUM_CODE_LENGTH_CODES = 19;
-
-  static const List<int> _CODE_LENGTH_CODE_ORDER = const [
-      17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
-
-  static const int _CODE_TO_PLANE_CODES = 120;
-  static const List<int> _CODE_TO_PLANE = const [
-      0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
-      0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
-      0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
-      0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
-      0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
-      0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
-      0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
-      0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
-      0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
-      0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
-      0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
-      0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70];
-
-  static const int _CODE_LENGTH_LITERALS = 16;
-  static const int _CODE_LENGTH_REPEAT_CODE = 16;
-  static const List<int> _CODE_LENGTH_EXTRA_BITS = const [2, 3, 7];
-  static const List<int> _CODE_LENGTH_REPEAT_OFFSETS = const [ 3, 3, 11 ];
-
-  static const List<int> ALPHABET_SIZE = const [
-    NUM_LITERAL_CODES + NUM_LENGTH_CODES,
-    NUM_LITERAL_CODES, NUM_LITERAL_CODES,
-    NUM_LITERAL_CODES, NUM_DISTANCE_CODES];
-
-  static const int VP8L_MAGIC_BYTE = 0x2f;
-  static const int VP8L_VERSION = 0;
-
-  int _lastPixel = 0;
-  int _lastRow = 0;
-
-  int _colorCacheSize = 0;
-  VP8LColorCache  _colorCache;
-
-  int _huffmanMask = 0;
-  int _huffmanSubsampleBits = 0;
-  int _huffmanXsize = 0;
-  Uint32List _huffmanImage;
-  int _numHtreeGroups = 0;
-  List<HTreeGroup> _htreeGroups = [];
-  List<VP8LTransform> _transforms = [];
-  int _transformsSeen = 0;
-
-  Uint32List _pixels;
-  Uint8List _pixels8;
-  int _argbCache;
-
-  Uint8List _opaque;
-
-  int _ioWidth;
-  int _ioHeight;
-
-  static const int ARGB_BLACK = 0xff000000;
-  static const int MAX_CACHE_BITS = 11;
-  static const int HUFFMAN_CODES_PER_META_CODE = 5;
-
-  static const int DEFAULT_CODE_LENGTH = 8;
-  static const int MAX_ALLOWED_CODE_LENGTH = 15;
-
-  static const int NUM_LITERAL_CODES = 256;
-  static const int NUM_LENGTH_CODES = 24;
-  static const int NUM_DISTANCE_CODES = 40;
-  static const int CODE_LENGTH_CODES = 19;
-}
-
-@internal
-class InternalVP8L extends VP8L {
-  InternalVP8L(InputBuffer input, WebPInfo webp) : super(input, webp);
-
-  List<VP8LTransform> get transforms => _transforms;
-  Uint32List get pixels => _pixels;
-
-  Uint8List get opaque => _opaque;
-  set opaque(Uint8List value) => _opaque = value;
-
-  int get ioWidth => _ioWidth;
-  set ioWidth(int width) => _ioWidth = width;
-  int get ioHeight => _ioHeight;
-  set ioHeight(int height) => _ioHeight = height;
-
-  bool decodeImageData(data, int width, int height, int lastRow, processFunc) =>
-      _decodeImageData(data, width, height, lastRow, processFunc);
-
-  Uint32List decodeImageStream(int xsize, int ysize, bool isLevel0) =>
-      _decodeImageStream(xsize, ysize, isLevel0);
-
-  bool allocateInternalBuffers32b() => _allocateInternalBuffers32b();
-
-  bool allocateInternalBuffers8b() => _allocateInternalBuffers8b();
-
-  bool decodeAlphaData(int width, int height, int lastRow) =>
-      _decodeAlphaData(width, height, lastRow);
-
-  bool is8bOptimizable() => _is8bOptimizable();
-
-  void extractAlphaRows(int row) => _extractAlphaRows(row);
-
-  static int subSampleSize(int size, int samplingBits) => VP8L._subSampleSize(size, samplingBits);
-}
+import 'dart:typed_data';

+

+import '../../color.dart';

+import '../../image.dart';

+import '../../image_exception.dart';

+import '../../internal/internal.dart';

+import '../../util/input_buffer.dart';

+import 'vp8l_bit_reader.dart';

+import 'vp8l_color_cache.dart';

+import 'vp8l_transform.dart';

+import 'webp_huffman.dart';

+import 'webp_info.dart';

+

+/**

+ * WebP lossless format.

+ */

+class VP8L {

+  InputBuffer input;

+  VP8LBitReader br;

+  WebPInfo webp;

+  Image image;

+

+  VP8L(InputBuffer input, WebPInfo webp) :

+    this.input = input,

+    this.webp = webp,

+    this.br = VP8LBitReader(input) {

+  }

+

+  bool decodeHeader() {

+    int signature = br.readBits(8);

+    if (signature != VP8L_MAGIC_BYTE) {

+      return false;

+    }

+

+    webp.format = WebPInfo.FORMAT_LOSSLESS;

+    webp.width = br.readBits(14) + 1;

+    webp.height = br.readBits(14) + 1;

+    webp.hasAlpha = br.readBits(1) != 0;

+    int version = br.readBits(3);

+

+    if (version != VP8L_VERSION) {

+      return false;

+    }

+

+    return true;

+  }

+

+  Image decode() {

+    _lastPixel = 0;

+

+    if (!decodeHeader()) {

+      return null;

+    }

+

+    _decodeImageStream(webp.width, webp.height, true);

+

+    _allocateInternalBuffers32b();

+

+    image = Image(webp.width, webp.height);

+

+    if (!_decodeImageData(_pixels, webp.width, webp.height,

+                          webp.height, _processRows)) {

+      return null;

+    }

+

+    return image;

+  }

+

+  bool _allocateInternalBuffers32b() {

+    final int numPixels = webp.width * webp.height;

+    // Scratch buffer corresponding to top-prediction row for transforming the

+    // first row in the row-blocks. Not needed for paletted alpha.

+    final int cacheTopPixels = webp.width;

+    // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.

+    final int cachePixels = webp.width * _NUM_ARGB_CACHE_ROWS;

+    final int totalNumPixels = numPixels + cacheTopPixels + cachePixels;

+

+    Uint32List pixels32 = Uint32List(totalNumPixels);

+    _pixels = pixels32;

+    _pixels8 = Uint8List.view(pixels32.buffer);

+    _argbCache = numPixels + cacheTopPixels;

+

+    return true;

+  }

+

+  bool _allocateInternalBuffers8b() {

+    final int totalNumPixels = webp.width * webp.height;

+    _argbCache = 0;

+    // pad the byteBuffer to a multiple of 4

+    int n = totalNumPixels + (4 - (totalNumPixels % 4));

+    _pixels8 = Uint8List(n);

+    _pixels = Uint32List.view(_pixels8.buffer);

+    return true;

+  }

+

+  bool _readTransform(List<int> transformSize) {

+    bool ok = true;

+

+    int type = br.readBits(2);

+

+    // Each transform type can only be present once in the stream.

+    if ((_transformsSeen & (1 << type)) != 0) {

+      return false;

+    }

+    _transformsSeen |= (1 << type);

+

+    VP8LTransform transform = VP8LTransform();

+    _transforms.add(transform);

+

+    transform.type = type;

+    transform.xsize = transformSize[0];

+    transform.ysize = transformSize[1];

+

+    switch (type) {

+      case VP8LTransform.PREDICTOR_TRANSFORM:

+      case VP8LTransform.CROSS_COLOR_TRANSFORM:

+        transform.bits = br.readBits(3) + 2;

+        transform.data = _decodeImageStream(

+                _subSampleSize(transform.xsize, transform.bits),

+                _subSampleSize(transform.ysize, transform.bits), false);

+        break;

+      case VP8LTransform.COLOR_INDEXING_TRANSFORM:

+        final int numColors = br.readBits(8) + 1;

+        final int bits = (numColors > 16) ? 0 :

+                         (numColors > 4) ? 1 :

+                         (numColors > 2) ? 2 : 3;

+        transformSize[0] = _subSampleSize(transform.xsize, bits);

+        transform.bits = bits;

+        transform.data = _decodeImageStream(numColors, 1, false);

+        ok = _expandColorMap(numColors, transform);

+        break;

+      case VP8LTransform.SUBTRACT_GREEN:

+        break;

+      default:

+        throw new ImageException('Invalid WebP tranform type: $type');

+    }

+

+    return ok;

+  }

+

+  Uint32List _decodeImageStream(int xsize, int ysize, bool isLevel0) {

+    int transformXsize = xsize;

+    int transformYsize = ysize;

+    int colorCacheBits = 0;

+

+    // Read the transforms (may recurse).

+    if (isLevel0) {

+      while (br.readBits(1) != 0) {

+        List<int> sizes = [transformXsize, transformYsize];

+        if (!_readTransform(sizes)) {

+          throw new ImageException('Invalid Transform');

+        }

+        transformXsize = sizes[0];

+        transformYsize = sizes[1];

+      }

+    }

+

+    // Color cache

+    if (br.readBits(1) != 0) {

+      colorCacheBits = br.readBits(4);

+      bool ok = (colorCacheBits >= 1 && colorCacheBits <= MAX_CACHE_BITS);

+      if (!ok) {

+        throw new ImageException('Invalid Color Cache');

+      }

+    }

+

+    // Read the Huffman codes (may recurse).

+    if (!_readHuffmanCodes(transformXsize, transformYsize,

+                           colorCacheBits, isLevel0)) {

+      throw new ImageException('Invalid Huffman Codes');

+    }

+

+    // Finish setting up the color-cache

+    if (colorCacheBits > 0) {

+      _colorCacheSize = 1 << colorCacheBits;

+      _colorCache = VP8LColorCache(colorCacheBits);

+    } else {

+      _colorCacheSize = 0;

+    }

+

+    webp.width = transformXsize;

+    webp.height = transformYsize;

+    final int numBits = _huffmanSubsampleBits;

+    _huffmanXsize = _subSampleSize(transformXsize, numBits);

+    _huffmanMask = (numBits == 0) ? ~0 : (1 << numBits) - 1;

+

+    if (isLevel0) {

+      // Reset for future DECODE_DATA_FUNC() calls.

+      _lastPixel = 0;

+      return null;

+    }

+

+    final int totalSize = transformXsize * transformYsize;

+    Uint32List data = Uint32List(totalSize);

+

+    // Use the Huffman trees to decode the LZ77 encoded data.

+    if (!_decodeImageData(data, transformXsize, transformYsize,

+                          transformYsize, null)) {

+      throw new ImageException('Failed to decode image data.');

+    }

+

+    // Reset for future DECODE_DATA_FUNC() calls.

+    _lastPixel = 0;

+

+    return data;

+  }

+

+  bool _decodeImageData(data, int width, int height,

+                        int lastRow, processFunc) {

+    int row = _lastPixel ~/ width;

+    int col = _lastPixel % width;

+

+    HTreeGroup htreeGroup = _getHtreeGroupForPos(col, row);

+

+    int src = _lastPixel;

+    int lastCached = src;

+    int srcEnd = width * height; // End of data

+    int srcLast = width * lastRow; // Last pixel to decode

+

+    const int lenCodeLimit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;

+    final int colorCacheLimit = lenCodeLimit + _colorCacheSize;

+

+    VP8LColorCache colorCache = (_colorCacheSize > 0) ? _colorCache : null;

+    final int mask = _huffmanMask;

+

+    while (!br.isEOS && src < srcLast) {

+      // Only update when changing tile. Note we could use this test:

+      // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed

+      // but that's actually slower and needs storing the previous col/row.

+      if ((col & mask) == 0) {

+        htreeGroup = _getHtreeGroupForPos(col, row);

+      }

+

+      br.fillBitWindow();

+      int code = htreeGroup.htrees[_GREEN].readSymbol(br);

+

+      if (code < NUM_LITERAL_CODES) {  // Literal

+        int red = htreeGroup.htrees[_RED].readSymbol(br);

+        int green = code;

+        br.fillBitWindow();

+        int blue = htreeGroup.htrees[_BLUE].readSymbol(br);

+        int alpha = htreeGroup.htrees[_ALPHA].readSymbol(br);

+

+        int c = getColor(red, green, blue, alpha);

+        data[src] = c;

+

+        ++src;

+        ++col;

+

+        if (col >= width) {

+          col = 0;

+          ++row;

+          if ((row % _NUM_ARGB_CACHE_ROWS == 0) && (processFunc != null)) {

+            processFunc(row);

+          }

+

+          if (colorCache != null) {

+            while (lastCached < src) {

+              colorCache.insert(data[lastCached]);

+              lastCached++;

+            }

+          }

+        }

+      } else if (code < lenCodeLimit) {  // Backward reference

+        final int lengthSym = code - NUM_LITERAL_CODES;

+        final int length = _getCopyLength(lengthSym);

+        final int distSymbol = htreeGroup.htrees[_DIST].readSymbol(br);

+

+        br.fillBitWindow();

+        int distCode = _getCopyDistance(distSymbol);

+        int dist = _planeCodeToDistance(width, distCode);

+

+        if (src < dist || srcEnd - src < length) {

+          return false;

+        } else {

+          for (int i = 0; i < length; ++i) {

+            data[src + i] = data[src + (i - dist)];

+          }

+          src += length;

+        }

+        col += length;

+        while (col >= width) {

+          col -= width;

+          ++row;

+          if ((row % _NUM_ARGB_CACHE_ROWS == 0) && (processFunc != null)) {

+            processFunc(row);

+          }

+        }

+        if (src < srcLast) {

+          if ((col & mask) != 0) {

+            htreeGroup = _getHtreeGroupForPos(col, row);

+          }

+          if (colorCache != null) {

+            while (lastCached < src) {

+              colorCache.insert(data[lastCached]);

+              lastCached++;

+            }

+          }

+        }

+      } else if (code < colorCacheLimit) {  // Color cache

+        final int key = code - lenCodeLimit;

+

+        while (lastCached < src) {

+          colorCache.insert(data[lastCached]);

+          lastCached++;

+        }

+

+        data[src] = colorCache.lookup(key);

+

+        ++src;

+        ++col;

+

+        if (col >= width) {

+          col = 0;

+          ++row;

+          if ((row % _NUM_ARGB_CACHE_ROWS == 0) && (processFunc != null)) {

+            processFunc(row);

+          }

+

+          if (colorCache != null) {

+            while (lastCached < src) {

+              colorCache.insert(data[lastCached]);

+              lastCached++;

+            }

+          }

+        }

+      } else {  // Not reached

+        return false;

+      }

+    }

+

+    // Process the remaining rows corresponding to last row-block.

+    if (processFunc != null) {

+      processFunc(row);

+    }

+

+    if (br.isEOS && src < srcEnd) {

+      return false;

+    }

+

+    _lastPixel = src;

+

+    return true;

+  }

+

+  /**

+   * Row-processing for the special case when alpha data contains only one

+   * transform (color indexing), and trivial non-green literals.

+   */

+  bool _is8bOptimizable() {

+    if (_colorCacheSize > 0) {

+      return false;

+    }

+    // When the Huffman tree contains only one symbol, we can skip the

+    // call to ReadSymbol() for red/blue/alpha channels.

+    for (int i = 0; i < _numHtreeGroups; ++i) {

+      List<HuffmanTree> htrees = _htreeGroups[i].htrees;

+      if (htrees[_RED].numNodes > 1) {

+        return false;

+      }

+      if (htrees[_BLUE].numNodes > 1) {

+        return false;

+      }

+      if (htrees[_ALPHA].numNodes > 1) {

+        return false;

+      }

+    }

+    return true;

+  }

+

+  /**

+   * Special row-processing that only stores the alpha data.

+   */

+  void _extractAlphaRows(int row) {

+    final int numRows = row - _lastRow;

+    if (numRows <= 0) {

+      return;  // Nothing to be done.

+    }

+

+    _applyInverseTransforms(numRows, webp.width * _lastRow);

+

+    // Extract alpha (which is stored in the green plane).

+    final int width = webp.width;      // the final width (!= dec->width_)

+    final int cachePixs = width * numRows;

+

+    final int di = width * _lastRow;

+    InputBuffer src = InputBuffer(_pixels, offset: _argbCache);

+

+    for (int i = 0; i < cachePixs; ++i) {

+      _opaque[di + i] = (src[i] >> 8) & 0xff;

+    }

+

+    _lastRow = row;

+  }

+

+  bool _decodeAlphaData(int width, int height, int lastRow) {

+    int row = _lastPixel ~/ width;

+    int col = _lastPixel % width;

+

+    HTreeGroup htreeGroup = _getHtreeGroupForPos(col, row);

+    int pos = _lastPixel; // current position

+    final int end = width * height; // End of data

+    final int last = width * lastRow; // Last pixel to decode

+    final int lenCodeLimit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;

+    final int mask = _huffmanMask;

+

+    while (!br.isEOS && pos < last) {

+      // Only update when changing tile.

+      if ((col & mask) == 0) {

+        htreeGroup = _getHtreeGroupForPos(col, row);

+      }

+

+      br.fillBitWindow();

+

+      int code = htreeGroup.htrees[_GREEN].readSymbol(br);

+      if (code < NUM_LITERAL_CODES) {  // Literal

+        _pixels8[pos] = code;

+        ++pos;

+        ++col;

+        if (col >= width) {

+          col = 0;

+          ++row;

+          if (row % _NUM_ARGB_CACHE_ROWS == 0) {

+            _extractPalettedAlphaRows(row);

+          }

+        }

+      } else if (code < lenCodeLimit) {  // Backward reference

+        final int lengthSym = code - NUM_LITERAL_CODES;

+        final int length = _getCopyLength(lengthSym);

+        final int distSymbol = htreeGroup.htrees[_DIST].readSymbol(br);

+

+        br.fillBitWindow();

+

+        int distCode = _getCopyDistance(distSymbol);

+        int dist = _planeCodeToDistance(width, distCode);

+

+        if (pos >= dist && end - pos >= length) {

+          for (int i = 0; i < length; ++i) {

+            _pixels8[pos + i] = _pixels8[pos + i - dist];

+          }

+        } else {

+          _lastPixel = pos;

+          return true;

+        }

+

+        pos += length;

+        col += length;

+

+        while (col >= width) {

+          col -= width;

+          ++row;

+          if (row % _NUM_ARGB_CACHE_ROWS == 0) {

+            _extractPalettedAlphaRows(row);

+          }

+        }

+

+        if (pos < last && (col & mask) != 0) {

+          htreeGroup = _getHtreeGroupForPos(col, row);

+        }

+      } else {  // Not reached

+        return false;

+      }

+    }

+

+    // Process the remaining rows corresponding to last row-block.

+    _extractPalettedAlphaRows(row);

+

+    _lastPixel = pos;

+

+    return true;

+  }

+

+  void _extractPalettedAlphaRows(int row) {

+    final int numRows = row - _lastRow;

+    InputBuffer pIn = InputBuffer(_pixels8, offset: webp.width * _lastRow);

+    if (numRows > 0) {

+      _applyInverseTransformsAlpha(numRows, pIn);

+    }

+    _lastRow = row;

+  }

+

+  /**

+   * Special method for paletted alpha data.

+   */

+  void _applyInverseTransformsAlpha(int numRows, InputBuffer rows) {

+    final int startRow = _lastRow;

+    final int endRow = startRow + numRows;

+    InputBuffer rowsOut = InputBuffer(_opaque, offset: _ioWidth * startRow);

+    VP8LTransform transform = _transforms[0];

+

+    transform.colorIndexInverseTransformAlpha(startRow, endRow, rows, rowsOut);

+  }

+

+  /**

+   * Processes (transforms, scales & color-converts) the rows decoded after the

+   * last call.

+   */

+  //static int __count = 0;

+  void _processRows(int row) {

+    int rows = webp.width * _lastRow; // offset into _pixels

+    final int numRows = row - _lastRow;

+

+    if (numRows <= 0) {

+      return;  // Nothing to be done.

+    }

+

+    _applyInverseTransforms(numRows, rows);

+

+    //int count = 0;

+    //int di = rows;

+    for (int y = 0, pi = _argbCache, dy = _lastRow; y < numRows; ++y, ++dy) {

+      for (int x = 0; x < webp.width; ++x, ++pi) {

+        int c = _pixels[pi];

+        image.setPixel(x, dy, c);

+        //int r = getRed(c);

+        //int g = getGreen(c);

+        //int b = getBlue(c);

+        //int a = getAlpha(c);

+        // rearrange the ARGB webp color to RGBA image color.

+        //image.setPixel(x, dy, getColor(r, g, b, a));

+      }

+    }

+

+    _lastRow = row;

+  }

+

+  void _applyInverseTransforms(int numRows, int rows) {

+    int n = _transforms.length;

+    final int cachePixs = webp.width * numRows;

+    final int startRow = _lastRow;

+    final int endRow = startRow + numRows;

+    int rowsIn = rows;

+    int rowsOut = _argbCache;

+

+    // Inverse transforms.

+    _pixels.setRange(rowsOut, rowsOut + cachePixs, _pixels, rowsIn);

+

+    while (n-- > 0) {

+      VP8LTransform transform = _transforms[n];

+      transform.inverseTransform(startRow, endRow, _pixels, rowsIn,

+                                 _pixels, rowsOut);

+      rowsIn = rowsOut;

+    }

+  }

+

+  bool _readHuffmanCodes(int xsize, int ysize, int colorCacheBits,

+                         bool allowRecursion) {

+    Uint32List huffmanImage;

+    int numHtreeGroups = 1;

+

+    if (allowRecursion && br.readBits(1) != 0) {

+      // use meta Huffman codes.

+      final int huffmanPrecision = br.readBits(3) + 2;

+      final int huffmanXsize = _subSampleSize(xsize, huffmanPrecision);

+      final int huffmanYsize = _subSampleSize(ysize, huffmanPrecision);

+      final int huffmanPixs = huffmanXsize * huffmanYsize;

+

+      huffmanImage = _decodeImageStream(huffmanXsize, huffmanYsize, false);

+

+      _huffmanSubsampleBits = huffmanPrecision;

+

+      for (int i = 0; i < huffmanPixs; ++i) {

+        // The huffman data is stored in red and green bytes.

+        final int group = (huffmanImage[i] >> 8) & 0xffff;

+        huffmanImage[i] = group;

+        if (group >= numHtreeGroups) {

+          numHtreeGroups = group + 1;

+        }

+      }

+    }

+

+    assert(numHtreeGroups <= 0x10000);

+

+    List<HTreeGroup> htreeGroups = List<HTreeGroup>(numHtreeGroups);

+    for (int i = 0; i < numHtreeGroups; ++i) {

+      htreeGroups[i] = HTreeGroup();

+

+      for (int j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {

+        int alphabetSize = ALPHABET_SIZE[j];

+        if (j == 0 && colorCacheBits > 0) {

+          alphabetSize += 1 << colorCacheBits;

+        }

+

+        if (!_readHuffmanCode(alphabetSize, htreeGroups[i].htrees[j])) {

+          return false;

+        }

+      }

+    }

+

+    // All OK. Finalize pointers and return.

+    _huffmanImage = huffmanImage;

+    _numHtreeGroups = numHtreeGroups;

+    _htreeGroups = htreeGroups;

+

+    return true;

+  }

+

+  bool _readHuffmanCode(int alphabetSize, HuffmanTree tree) {

+    bool ok = false;

+    final int simpleCode = br.readBits(1);

+

+    // Read symbols, codes & code lengths directly.

+    if (simpleCode != 0) {

+      List<int> symbols = [0, 0];

+      List<int> codes = [0, 0];

+      List<int> codeLengths = [0, 0];

+

+      final int numSymbols = br.readBits(1) + 1;

+      final int firstSymbolLenCode = br.readBits(1);

+

+      // The first code is either 1 bit or 8 bit code.

+      symbols[0] = br.readBits((firstSymbolLenCode == 0) ? 1 : 8);

+      codes[0] = 0;

+      codeLengths[0] = numSymbols - 1;

+

+      // The second code (if present), is always 8 bit long.

+      if (numSymbols == 2) {

+        symbols[1] = br.readBits(8);

+        codes[1] = 1;

+        codeLengths[1] = numSymbols - 1;

+      }

+

+      ok = tree.buildExplicit(codeLengths, codes, symbols,

+                              alphabetSize, numSymbols);

+    } else {

+      // Decode Huffman-coded code lengths.

+      Int32List codeLengthCodeLengths =

+          new Int32List(_NUM_CODE_LENGTH_CODES);

+

+      final int numCodes = br.readBits(4) + 4;

+      if (numCodes > _NUM_CODE_LENGTH_CODES) {

+        return false;

+      }

+

+      Int32List codeLengths = Int32List(alphabetSize);

+

+      for (int i = 0; i < numCodes; ++i) {

+        codeLengthCodeLengths[_CODE_LENGTH_CODE_ORDER[i]] = br.readBits(3);

+      }

+

+      ok = _readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSize,

+                                   codeLengths);

+

+      if (ok) {

+        ok = tree.buildImplicit(codeLengths, alphabetSize);

+      }

+    }

+

+    return ok;

+  }

+

+  bool _readHuffmanCodeLengths(List<int> codeLengthCodeLengths,

+                               int numSymbols, List<int> codeLengths) {

+    //bool ok = false;

+    int symbol;

+    int max_symbol;

+    int prev_code_len = DEFAULT_CODE_LENGTH;

+    HuffmanTree tree = HuffmanTree();

+

+    if (!tree.buildImplicit(codeLengthCodeLengths, _NUM_CODE_LENGTH_CODES)) {

+      return false;

+    }

+

+    if (br.readBits(1) != 0) {    // use length

+      final int length_nbits = 2 + 2 * br.readBits(3);

+      max_symbol = 2 + br.readBits(length_nbits);

+      if (max_symbol > numSymbols) {

+        return false;

+      }

+    } else {

+      max_symbol = numSymbols;

+    }

+

+    symbol = 0;

+    while (symbol < numSymbols) {

+      int code_len;

+      if (max_symbol-- == 0) {

+        break;

+      }

+

+      br.fillBitWindow();

+

+      code_len = tree.readSymbol(br);

+

+      if (code_len < _CODE_LENGTH_LITERALS) {

+        codeLengths[symbol++] = code_len;

+        if (code_len != 0) {

+          prev_code_len = code_len;

+        }

+      } else {

+        final bool usePrev = (code_len == _CODE_LENGTH_REPEAT_CODE);

+        final int slot = code_len - _CODE_LENGTH_LITERALS;

+        final int extra_bits = _CODE_LENGTH_EXTRA_BITS[slot];

+        final int repeat_offset = _CODE_LENGTH_REPEAT_OFFSETS[slot];

+        int repeat = br.readBits(extra_bits) + repeat_offset;

+

+        if (symbol + repeat > numSymbols) {

+          return false;

+        } else {

+          final int length = usePrev ? prev_code_len : 0;

+          while (repeat-- > 0) {

+            codeLengths[symbol++] = length;

+          }

+        }

+      }

+    }

+

+    return true;

+  }

+

+  int _getCopyDistance(int distanceSymbol) {

+    if (distanceSymbol < 4) {

+      return distanceSymbol + 1;

+    }

+    int extraBits = (distanceSymbol - 2) >> 1;

+    int offset = (2 + (distanceSymbol & 1)) << extraBits;

+    return offset + br.readBits(extraBits) + 1;

+  }

+

+  int _getCopyLength(int lengthSymbol) {

+    // Length and distance prefixes are encoded the same way.

+    return _getCopyDistance(lengthSymbol);

+  }

+

+  int _planeCodeToDistance(int xsize, int planeCode) {

+    if (planeCode > _CODE_TO_PLANE_CODES) {

+      return planeCode - _CODE_TO_PLANE_CODES;

+    } else {

+      final int distCode = _CODE_TO_PLANE[planeCode - 1];

+      final int yoffset = distCode >> 4;

+      final int xoffset = 8 - (distCode & 0xf);

+      final int dist = yoffset * xsize + xoffset;

+      // dist<1 can happen if xsize is very small

+      return (dist >= 1) ? dist : 1;

+    }

+  }

+

+  /**

+   * Computes sampled size of 'size' when sampling using 'sampling bits'.

+   */

+  static int _subSampleSize(int size, int samplingBits) {

+    return (size + (1 << samplingBits) - 1) >> samplingBits;

+  }

+

+  /**

+   * For security reason, we need to remap the color map to span

+   * the total possible bundled values, and not just the num_colors.

+   */

+  bool _expandColorMap(int numColors, VP8LTransform transform) {

+    final int finalNumColors = 1 << (8 >> transform.bits);

+    Uint32List newColorMap = Uint32List(finalNumColors);

+    Uint8List data = Uint8List.view(transform.data.buffer);

+    Uint8List newData = Uint8List.view(newColorMap.buffer);

+

+    newColorMap[0] = transform.data[0];

+

+    int len = 4 * numColors;

+

+    int i;

+    for (i = 4; i < len; ++i) {

+      // Equivalent to AddPixelEq(), on a byte-basis.

+      newData[i] = (data[i] + newData[i - 4]) & 0xff;

+    }

+

+    for (len = 4 * finalNumColors; i < len; ++i) {

+      newData[i] = 0;

+    }

+

+    transform.data = newColorMap;

+

+    return true;

+  }

+

+  int _getMetaIndex(Uint32List image, int xsize, int bits, int x, int y) {

+    if (bits == 0) {

+      return 0;

+    }

+    return image[xsize * (y >> bits) + (x >> bits)];

+  }

+

+  HTreeGroup _getHtreeGroupForPos(int x, int y) {

+    int metaIndex = _getMetaIndex(_huffmanImage, _huffmanXsize,

+                                  _huffmanSubsampleBits, x, y);

+    if (_htreeGroups[metaIndex] == null) {

+      _htreeGroups[metaIndex] = HTreeGroup();

+    }

+    return _htreeGroups[metaIndex];

+  }

+

+  static const int _GREEN = 0;

+  static const int _RED = 1;

+  static const int _BLUE = 2;

+  static const int _ALPHA = 3;

+  static const int _DIST = 4;

+

+  static const int _NUM_ARGB_CACHE_ROWS = 16;

+

+  static const int _NUM_CODE_LENGTH_CODES = 19;

+

+  static const List<int> _CODE_LENGTH_CODE_ORDER = const [

+      17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];

+

+  static const int _CODE_TO_PLANE_CODES = 120;

+  static const List<int> _CODE_TO_PLANE = const [

+      0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,

+      0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,

+      0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,

+      0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,

+      0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,

+      0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,

+      0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,

+      0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,

+      0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,

+      0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,

+      0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,

+      0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70];

+

+  static const int _CODE_LENGTH_LITERALS = 16;

+  static const int _CODE_LENGTH_REPEAT_CODE = 16;

+  static const List<int> _CODE_LENGTH_EXTRA_BITS = const [2, 3, 7];

+  static const List<int> _CODE_LENGTH_REPEAT_OFFSETS = const [ 3, 3, 11 ];

+

+  static const List<int> ALPHABET_SIZE = const [

+    NUM_LITERAL_CODES + NUM_LENGTH_CODES,

+    NUM_LITERAL_CODES, NUM_LITERAL_CODES,

+    NUM_LITERAL_CODES, NUM_DISTANCE_CODES];

+

+  static const int VP8L_MAGIC_BYTE = 0x2f;

+  static const int VP8L_VERSION = 0;

+

+  int _lastPixel = 0;

+  int _lastRow = 0;

+

+  int _colorCacheSize = 0;

+  VP8LColorCache  _colorCache;

+

+  int _huffmanMask = 0;

+  int _huffmanSubsampleBits = 0;

+  int _huffmanXsize = 0;

+  Uint32List _huffmanImage;

+  int _numHtreeGroups = 0;

+  List<HTreeGroup> _htreeGroups = [];

+  List<VP8LTransform> _transforms = [];

+  int _transformsSeen = 0;

+

+  Uint32List _pixels;

+  Uint8List _pixels8;

+  int _argbCache;

+

+  Uint8List _opaque;

+

+  int _ioWidth;

+  int _ioHeight;

+

+  static const int ARGB_BLACK = 0xff000000;

+  static const int MAX_CACHE_BITS = 11;

+  static const int HUFFMAN_CODES_PER_META_CODE = 5;

+

+  static const int DEFAULT_CODE_LENGTH = 8;

+  static const int MAX_ALLOWED_CODE_LENGTH = 15;

+

+  static const int NUM_LITERAL_CODES = 256;

+  static const int NUM_LENGTH_CODES = 24;

+  static const int NUM_DISTANCE_CODES = 40;

+  static const int CODE_LENGTH_CODES = 19;

+}

+

+@internal

+class InternalVP8L extends VP8L {

+  InternalVP8L(InputBuffer input, WebPInfo webp) : super(input, webp);

+

+  List<VP8LTransform> get transforms => _transforms;

+  Uint32List get pixels => _pixels;

+

+  Uint8List get opaque => _opaque;

+  set opaque(Uint8List value) => _opaque = value;

+

+  int get ioWidth => _ioWidth;

+  set ioWidth(int width) => _ioWidth = width;

+  int get ioHeight => _ioHeight;

+  set ioHeight(int height) => _ioHeight = height;

+

+  bool decodeImageData(data, int width, int height, int lastRow, processFunc) =>

+      _decodeImageData(data, width, height, lastRow, processFunc);

+

+  Uint32List decodeImageStream(int xsize, int ysize, bool isLevel0) =>

+      _decodeImageStream(xsize, ysize, isLevel0);

+

+  bool allocateInternalBuffers32b() => _allocateInternalBuffers32b();

+

+  bool allocateInternalBuffers8b() => _allocateInternalBuffers8b();

+

+  bool decodeAlphaData(int width, int height, int lastRow) =>

+      _decodeAlphaData(width, height, lastRow);

+

+  bool is8bOptimizable() => _is8bOptimizable();

+

+  void extractAlphaRows(int row) => _extractAlphaRows(row);

+

+  static int subSampleSize(int size, int samplingBits) => VP8L._subSampleSize(size, samplingBits);

+}

diff --git a/image/lib/src/formats/webp/vp8l_bit_reader.dart b/image/lib/src/formats/webp/vp8l_bit_reader.dart
old mode 100644
new mode 100755
index 716b0ac..0a6359b
--- a/image/lib/src/formats/webp/vp8l_bit_reader.dart
+++ b/image/lib/src/formats/webp/vp8l_bit_reader.dart
@@ -1,98 +1,98 @@
-import 'dart:typed_data';
-
-import '../../image_exception.dart';
-import '../../util/input_buffer.dart';
-
-class VP8LBitReader {
-  int bitPos = 0;
-
-  VP8LBitReader(this._input) {
-    _buffer8 = new Uint8List.view(_buffer.buffer);
-    _buffer8[0] = _input.readByte();
-    _buffer8[1] = _input.readByte();
-    _buffer8[2] = _input.readByte();
-    _buffer8[3] = _input.readByte();
-    _buffer8[4] = _input.readByte();
-    _buffer8[5] = _input.readByte();
-    _buffer8[6] = _input.readByte();
-    _buffer8[7] = _input.readByte();
-  }
-
-  /**
-   * Return the prefetched bits, so they can be looked up.
-   */
-  int prefetchBits() {
-    int b2 = 0;
-    if (bitPos < 32) {
-      b2 = (_buffer[0] >> bitPos) +
-           ((_buffer[1] & BIT_MASK[bitPos]) * (BIT_MASK[32 - bitPos] + 1));
-    } else if (bitPos == 32) {
-      b2 = _buffer[1];
-    } else {
-      b2 = _buffer[1] >> (bitPos - 32);
-    }
-    return b2;
-  }
-
-  bool get isEOS => (_input.isEOS && bitPos >= LBITS);
-
-  /**
-   * Advances the read buffer by 4 bytes to make room for reading next 32 bits.
-   */
-  void fillBitWindow() {
-    if (bitPos >= WBITS) {
-      _shiftBytes();
-    }
-  }
-
-  /**
-   * Reads the specified number of bits from Read Buffer.
-   */
-  int readBits(int numBits) {
-    // Flag an error if end_of_stream or n_bits is more than allowed limit.
-    if (!isEOS && numBits < MAX_NUM_BIT_READ) {
-      //final int value = (buffer >> bitPos) & BIT_MASK[numBits];
-      final int value = prefetchBits() & BIT_MASK[numBits];
-      bitPos += numBits;
-      _shiftBytes();
-      return value;
-    } else {
-      throw new ImageException('Not enough data in input.');
-    }
-  }
-
-  /**
-   * If not at EOS, reload up to LBITS byte-by-byte
-   */
-  void _shiftBytes() {
-    while (bitPos >= 8 && !_input.isEOS) {
-      int b = _input.readByte();
-      // buffer >>= 8
-      _buffer[0] = (_buffer[0] >> 8) + ((_buffer[1] & 0xff) * 0x1000000);
-      _buffer[1] >>= 8;
-      // buffer |= b << (LBITS - 8)
-      _buffer[1] |= b * 0x1000000;
-      bitPos -= 8;
-    }
-  }
-
-  InputBuffer _input;
-  Uint32List _buffer = new Uint32List(2);
-  Uint8List _buffer8;
-
-  /// The number of bytes used for the bit buffer.
-  static const int VALUE_SIZE = 8;
-  static const int MAX_NUM_BIT_READ = 25;
-  /// Number of bits prefetched.
-  static const int LBITS = 64;
-  /// Minimum number of bytes needed after fillBitWindow.
-  static const int WBITS = 32;
-  /// Number of bytes needed to store WBITS bits.
-  static const int LOG8_WBITS = 4;
-
-  static const List<int> BIT_MASK = const [
-      0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383,
-      32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607,
-      16777215, 33554431, 67108863, 134217727, 268435455, 536870911,
-      1073741823, 2147483647, 4294967295];
-}
+import 'dart:typed_data';

+

+import '../../image_exception.dart';

+import '../../util/input_buffer.dart';

+

+class VP8LBitReader {

+  int bitPos = 0;

+

+  VP8LBitReader(this._input) {

+    _buffer8 = Uint8List.view(_buffer.buffer);

+    _buffer8[0] = _input.readByte();

+    _buffer8[1] = _input.readByte();

+    _buffer8[2] = _input.readByte();

+    _buffer8[3] = _input.readByte();

+    _buffer8[4] = _input.readByte();

+    _buffer8[5] = _input.readByte();

+    _buffer8[6] = _input.readByte();

+    _buffer8[7] = _input.readByte();

+  }

+

+  /**

+   * Return the prefetched bits, so they can be looked up.

+   */

+  int prefetchBits() {

+    int b2 = 0;

+    if (bitPos < 32) {

+      b2 = (_buffer[0] >> bitPos) +

+           ((_buffer[1] & BIT_MASK[bitPos]) * (BIT_MASK[32 - bitPos] + 1));

+    } else if (bitPos == 32) {

+      b2 = _buffer[1];

+    } else {

+      b2 = _buffer[1] >> (bitPos - 32);

+    }

+    return b2;

+  }

+

+  bool get isEOS => (_input.isEOS && bitPos >= LBITS);

+

+  /**

+   * Advances the read buffer by 4 bytes to make room for reading next 32 bits.

+   */

+  void fillBitWindow() {

+    if (bitPos >= WBITS) {

+      _shiftBytes();

+    }

+  }

+

+  /**

+   * Reads the specified number of bits from Read Buffer.

+   */

+  int readBits(int numBits) {

+    // Flag an error if end_of_stream or n_bits is more than allowed limit.

+    if (!isEOS && numBits < MAX_NUM_BIT_READ) {

+      //final int value = (buffer >> bitPos) & BIT_MASK[numBits];

+      final int value = prefetchBits() & BIT_MASK[numBits];

+      bitPos += numBits;

+      _shiftBytes();

+      return value;

+    } else {

+      throw new ImageException('Not enough data in input.');

+    }

+  }

+

+  /**

+   * If not at EOS, reload up to LBITS byte-by-byte

+   */

+  void _shiftBytes() {

+    while (bitPos >= 8 && !_input.isEOS) {

+      int b = _input.readByte();

+      // buffer >>= 8

+      _buffer[0] = (_buffer[0] >> 8) + ((_buffer[1] & 0xff) * 0x1000000);

+      _buffer[1] >>= 8;

+      // buffer |= b << (LBITS - 8)

+      _buffer[1] |= b * 0x1000000;

+      bitPos -= 8;

+    }

+  }

+

+  InputBuffer _input;

+  Uint32List _buffer = Uint32List(2);

+  Uint8List _buffer8;

+

+  /// The number of bytes used for the bit buffer.

+  static const int VALUE_SIZE = 8;

+  static const int MAX_NUM_BIT_READ = 25;

+  /// Number of bits prefetched.

+  static const int LBITS = 64;

+  /// Minimum number of bytes needed after fillBitWindow.

+  static const int WBITS = 32;

+  /// Number of bytes needed to store WBITS bits.

+  static const int LOG8_WBITS = 4;

+

+  static const List<int> BIT_MASK = const [

+      0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383,

+      32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607,

+      16777215, 33554431, 67108863, 134217727, 268435455, 536870911,

+      1073741823, 2147483647, 4294967295];

+}

diff --git a/image/lib/src/formats/webp/vp8l_color_cache.dart b/image/lib/src/formats/webp/vp8l_color_cache.dart
old mode 100644
new mode 100755
index c4e04a2..2b3c41a
--- a/image/lib/src/formats/webp/vp8l_color_cache.dart
+++ b/image/lib/src/formats/webp/vp8l_color_cache.dart
@@ -1,22 +1,22 @@
-import 'dart:typed_data';
-
-class VP8LColorCache {
-  final Uint32List colors; // color entries
-  final int hashShift; // Hash shift: 32 - hash_bits.
-
-  VP8LColorCache(int hashBits) :
-    colors = new Uint32List(1 << hashBits),
-    hashShift = 32 - hashBits;
-
-  void insert(int argb) {
-    final int a = (argb * _HASH_MUL) & 0xffffffff;
-    final int key = (a >> hashShift);
-    colors[key] = argb;
-  }
-
-  int lookup(int key) {
-    return colors[key];
-  }
-
-  static const int _HASH_MUL = 0x1e35a7bd;
-}
+import 'dart:typed_data';

+

+class VP8LColorCache {

+  final Uint32List colors; // color entries

+  final int hashShift; // Hash shift: 32 - hash_bits.

+

+  VP8LColorCache(int hashBits) :

+    colors = Uint32List(1 << hashBits),

+    hashShift = 32 - hashBits;

+

+  void insert(int argb) {

+    final int a = (argb * _HASH_MUL) & 0xffffffff;

+    final int key = (a >> hashShift);

+    colors[key] = argb;

+  }

+

+  int lookup(int key) {

+    return colors[key];

+  }

+

+  static const int _HASH_MUL = 0x1e35a7bd;

+}

diff --git a/image/lib/src/formats/webp/vp8l_transform.dart b/image/lib/src/formats/webp/vp8l_transform.dart
old mode 100644
new mode 100755
index 8b683cf..340a83f
--- a/image/lib/src/formats/webp/vp8l_transform.dart
+++ b/image/lib/src/formats/webp/vp8l_transform.dart
@@ -1,472 +1,472 @@
-import 'dart:typed_data';
-
-import '../../internal/bit_operators.dart';
-import '../../util/input_buffer.dart';
-import 'vp8l.dart';
-
-class VP8LTransform {
-  // enum VP8LImageTransformType
-  static const int PREDICTOR_TRANSFORM  = 0;
-  static const int CROSS_COLOR_TRANSFORM = 1;
-  static const int SUBTRACT_GREEN = 2;
-  static const int COLOR_INDEXING_TRANSFORM = 3;
-
-  int type = 0;
-  int xsize = 0;
-  int ysize = 0;
-  Uint32List data;
-  int bits = 0;
-
-  void inverseTransform(int rowStart, int rowEnd,
-                        Uint32List inData,
-                        int rowsIn,
-                        Uint32List outData,
-                        int rowsOut) {
-    final int width = xsize;
-
-    switch (type) {
-      case SUBTRACT_GREEN:
-        addGreenToBlueAndRed(outData, rowsOut,
-                             rowsOut + (rowEnd - rowStart) * width);
-        break;
-      case PREDICTOR_TRANSFORM:
-        predictorInverseTransform(rowStart, rowEnd, outData, rowsOut);
-        if (rowEnd != ysize) {
-          // The last predicted row in this iteration will be the top-pred row
-          // for the first row in next iteration.
-          int start = rowsOut - width;
-          int end = start + width;
-          int offset = rowsOut + (rowEnd - rowStart - 1) * width;
-          outData.setRange(start, end, inData, offset);
-        }
-        break;
-      case CROSS_COLOR_TRANSFORM:
-        colorSpaceInverseTransform(rowStart, rowEnd, outData, rowsOut);
-        break;
-      case COLOR_INDEXING_TRANSFORM:
-        if (rowsIn == rowsOut && bits > 0) {
-          // Move packed pixels to the end of unpacked region, so that unpacking
-          // can occur seamlessly.
-          // Also, note that this is the only transform that applies on
-          // the effective width of VP8LSubSampleSize(xsize_, bits_). All other
-          // transforms work on effective width of xsize_.
-          final int outStride = (rowEnd - rowStart) * width;
-          final int inStride = (rowEnd - rowStart) *
-              InternalVP8L.subSampleSize(xsize, bits);
-
-          int src = rowsOut + outStride - inStride;
-          outData.setRange(src, src + inStride, inData, rowsOut);
-
-          colorIndexInverseTransform(rowStart, rowEnd, inData, src,
-                                      outData, rowsOut);
-        } else {
-          colorIndexInverseTransform(rowStart, rowEnd, inData, rowsIn,
-                                      outData, rowsOut);
-        }
-        break;
-    }
-  }
-
-  void colorIndexInverseTransformAlpha(int yStart, int yEnd,
-                                           InputBuffer src, InputBuffer dst) {
-    final int bitsPerPixel = 8 >> bits;
-    final int width = xsize;
-    Uint32List colorMap = this.data;
-    if (bitsPerPixel < 8) {
-      final int pixelsPerByte = 1 << bits;
-      final int countMask = pixelsPerByte - 1;
-      final bit_mask = (1 << bitsPerPixel) - 1;
-      for (int y = yStart; y < yEnd; ++y) {
-        int packed_pixels = 0;
-        for (int x = 0; x < width; ++x) {
-          // We need to load fresh 'packed_pixels' once every
-          // 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte
-          // is a power of 2, so can just use a mask for that, instead of
-          // decrementing a counter.
-          if ((x & countMask) == 0) {
-            packed_pixels = _getAlphaIndex(src[0]);
-            src.offset++;
-          }
-          int p = _getAlphaValue(colorMap[packed_pixels & bit_mask]);;
-          dst[0] = p;
-          dst.offset++;
-          packed_pixels >>= bitsPerPixel;
-        }
-      }
-    } else {
-      for (int y = yStart; y < yEnd; ++y) {
-        for (int x = 0; x < width; ++x) {
-          int index = _getAlphaIndex(src[0]);
-          src.offset++;
-          dst[0] = _getAlphaValue(colorMap[index]);
-          dst.offset++;
-        }
-      }
-    }
-  }
-
-  void colorIndexInverseTransform(int yStart, int yEnd,
-                                  Uint32List inData, int src,
-                                  Uint32List outData, int dst) {
-    final int bitsPerPixel = 8 >> bits;
-    final int width = xsize;
-    Uint32List colorMap = this.data;
-    if (bitsPerPixel < 8) {
-      final int pixelsPerByte = 1 << bits;
-      final int countMask = pixelsPerByte - 1;
-      final bit_mask = (1 << bitsPerPixel) - 1;
-      for (int y = yStart; y < yEnd; ++y) {
-        int packed_pixels = 0;
-        for (int x = 0; x < width; ++x) {
-          // We need to load fresh 'packed_pixels' once every
-          // 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte
-          // is a power of 2, so can just use a mask for that, instead of
-          // decrementing a counter.
-          if ((x & countMask) == 0) {
-            packed_pixels = _getARGBIndex(inData[src++]);
-          }
-          outData[dst++] = _getARGBValue(colorMap[packed_pixels & bit_mask]);
-          packed_pixels >>= bitsPerPixel;
-        }
-      }
-    } else {
-      for (int y = yStart; y < yEnd; ++y) {
-        for (int x = 0; x < width; ++x) {
-          outData[dst++] = _getARGBValue(colorMap[_getARGBIndex(inData[src++])]);
-        }
-      }
-    }
-  }
-
-  /**
-   * Color space inverse transform.
-   */
-  void colorSpaceInverseTransform(int yStart, int yEnd, Uint32List outData,
-                                  int data) {
-    final int width = xsize;
-    final int mask = (1 << bits) - 1;
-    final int tilesPerRow = InternalVP8L.subSampleSize(width, bits);
-    int y = yStart;
-    int predRow = (y >> bits) * tilesPerRow; //this.data +
-
-    while (y < yEnd) {
-      int pred = predRow; // this.data+
-      _VP8LMultipliers m = new _VP8LMultipliers();
-
-      for (int x = 0; x < width; ++x) {
-        if ((x & mask) == 0) {
-          m.colorCode = this.data[pred++];
-        }
-
-        outData[data + x] = m.transformColor(outData[data + x], true);
-      }
-
-      data += width;
-      ++y;
-
-      if ((y & mask) == 0) {
-        predRow += tilesPerRow;;
-      }
-    }
-  }
-
-  /**
-   * Inverse prediction.
-   */
-  void predictorInverseTransform(int yStart, int yEnd, Uint32List outData,
-                                 int data) {
-    final int width = xsize;
-    if (yStart == 0) {  // First Row follows the L (mode=1) mode.
-      final int pred0 = _predictor0(outData, outData[data - 1], 0);
-      _addPixelsEq(outData, data, pred0);
-      for (int x = 1; x < width; ++x) {
-        final int pred1 = _predictor1(outData, outData[data + x - 1], 0);
-        _addPixelsEq(outData, data + x, pred1);
-      }
-      data += width;
-      ++yStart;
-    }
-
-    int y = yStart;
-    final int mask = (1 << bits) - 1;
-    final int tilesPerRow = InternalVP8L.subSampleSize(width, bits);
-    int predModeBase = (y >> bits) * tilesPerRow; //this.data +
-
-    while (y < yEnd) {
-      final int pred2 = _predictor2(outData, outData[data - 1], data - width);
-      int predModeSrc = predModeBase; //this.data +
-
-      // First pixel follows the T (mode=2) mode.
-      _addPixelsEq(outData, data, pred2);
-
-      // .. the rest:
-      int k = (this.data[predModeSrc++] >> 8) & 0xf;
-
-      var predFunc = PREDICTORS[k];
-      for (int x = 1; x < width; ++x) {
-        if ((x & mask) == 0) {    // start of tile. Read predictor function.
-          int k = ((this.data[predModeSrc++]) >> 8) & 0xf;
-          predFunc = PREDICTORS[k];
-        }
-        int d = outData[data + x - 1];
-        int pred = predFunc(outData, d, data + x - width);
-        _addPixelsEq(outData, data + x, pred);
-      }
-
-      data += width;
-      ++y;
-
-      if ((y & mask) == 0) {   // Use the same mask, since tiles are squares.
-        predModeBase += tilesPerRow;
-      }
-    }
-  }
-
-  /**
-   * Add green to blue and red channels (i.e. perform the inverse transform of
-   * 'subtract green').
-   */
-  void addGreenToBlueAndRed(Uint32List pixels, int data, int dataEnd) {
-    while (data < dataEnd) {
-      final int argb = pixels[data];
-      final int green = ((argb >> 8) & 0xff);
-      int redBlue = (argb & 0x00ff00ff);
-      redBlue += (green << 16) | green;
-      redBlue &= 0x00ff00ff;
-      pixels[data++] = (argb & 0xff00ff00) | redBlue;
-    }
-  }
-
-  static int _getARGBIndex(int idx) {
-    return (idx >> 8) & 0xff;
-  }
-
-  static int _getAlphaIndex(int idx) {
-    return idx;
-  }
-
-  static int _getARGBValue(int val) {
-    return val;
-  }
-
-  static int _getAlphaValue(int val) {
-    return (val >> 8) & 0xff;
-  }
-
-  /**
-   * In-place sum of each component with mod 256.
-   */
-  static void _addPixelsEq(Uint32List pixels, int a, int b) {
-    int pa = pixels[a];
-    final int alphaAndGreen = (pa & 0xff00ff00) + (b & 0xff00ff00);
-    final int redAndBlue = (pa & 0x00ff00ff) + (b & 0x00ff00ff);
-    pixels[a] = (alphaAndGreen & 0xff00ff00) | (redAndBlue & 0x00ff00ff);
-  }
-
-  static int _average2(int a0, int a1) {
-    return (((a0 ^ a1) & 0xfefefefe) >> 1) + (a0 & a1);
-  }
-
-  static int _average3(int a0, int a1, int a2) {
-    return _average2(_average2(a0, a2), a1);
-  }
-
-  static int _average4(int a0, int a1, int a2, int a3) {
-    return _average2(_average2(a0, a1), _average2(a2, a3));
-  }
-
-  /**
-   * Return 0, when a is a negative integer.
-   * Return 255, when a is positive.
-   */
-  static int _clip255(int a) {
-    if (a < 0) {
-      return 0;
-    }
-    if (a > 255) {
-      return 255;
-    }
-    return a;
-  }
-
-  static int _addSubtractComponentFull(int a, int b, int c) {
-    return _clip255(a + b - c);
-  }
-
-
-  static int _clampedAddSubtractFull(int c0, int c1, int c2) {
-    final int a = _addSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
-    final int r = _addSubtractComponentFull((c0 >> 16) & 0xff,
-        (c1 >> 16) & 0xff,
-        (c2 >> 16) & 0xff);
-    final int g = _addSubtractComponentFull((c0 >> 8) & 0xff,
-        (c1 >> 8) & 0xff,
-        (c2 >> 8) & 0xff);
-    final int b = _addSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
-    return (a << 24) | (r << 16) | (g << 8) | b;
-  }
-
-  static int _addSubtractComponentHalf(int a, int b) {
-    return _clip255(a + (a - b) ~/ 2);
-  }
-
-  static int _clampedAddSubtractHalf(int c0, int c1, int c2) {
-    final int avg = _average2(c0, c1);
-    final int a = _addSubtractComponentHalf(avg >> 24, c2 >> 24);
-    final int r = _addSubtractComponentHalf((avg >> 16) & 0xff, (c2 >> 16) & 0xff);
-    final int g = _addSubtractComponentHalf((avg >> 8) & 0xff, (c2 >> 8) & 0xff);
-    final int b = _addSubtractComponentHalf((avg >> 0) & 0xff, (c2 >> 0) & 0xff);
-    return (a << 24) | (r << 16) | (g << 8) | b;
-  }
-
-  static int _sub3(int a, int b, int c) {
-    final int pb = b - c;
-    final int pa = a - c;
-    return pb.abs() - pa.abs();
-  }
-
-  static int _select(int a, int b, int c) {
-    final int pa_minus_pb =
-        _sub3((a >> 24)       , (b >> 24)       , (c >> 24)       ) +
-        _sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
-        _sub3((a >>  8) & 0xff, (b >>  8) & 0xff, (c >>  8) & 0xff) +
-        _sub3((a      ) & 0xff, (b      ) & 0xff, (c      ) & 0xff);
-    return (pa_minus_pb <= 0) ? a : b;
-  }
-
-  //--------------------------------------------------------------------------
-  // Predictors
-
-  static int _predictor0(Uint32List pixels, int left, int top) {
-    return VP8L.ARGB_BLACK;
-  }
-
-  static int _predictor1(Uint32List pixels, int left, int top) {
-    return left;
-  }
-
-  static int _predictor2(Uint32List pixels, int left, int top) {
-    return pixels[top];
-  }
-
-  static int _predictor3(Uint32List pixels, int left, int top) {
-    return pixels[top + 1];
-  }
-
-  static int _predictor4(Uint32List pixels, int left, int top) {
-    return pixels[top -1];
-  }
-
-  static int _predictor5(Uint32List pixels, int left, int top) {
-    return _average3(left, pixels[top], pixels[top + 1]);
-  }
-
-  static int _predictor6(Uint32List pixels, int left, int top) {
-    return _average2(left, pixels[top - 1]);
-  }
-
-  static int _predictor7(Uint32List pixels, int left, int top) {
-    return _average2(left, pixels[top]);
-  }
-
-  static int _predictor8(Uint32List pixels, int left, int top) {
-    return _average2(pixels[top -1], pixels[top]);
-  }
-
-  static int _predictor9(Uint32List pixels, int left, int top) {
-    return _average2(pixels[top], pixels[top + 1]);
-  }
-
-  static int _predictor10(Uint32List pixels, int left, int top) {
-    return _average4(left, pixels[top -1], pixels[top], pixels[top + 1]);
-  }
-
-  static int _predictor11(Uint32List pixels, int left, int top) {
-    return _select(pixels[top], left, pixels[top - 1]);
-  }
-
-  static int _predictor12(Uint32List pixels, int left, int top) {
-    return _clampedAddSubtractFull(left, pixels[top], pixels[top - 1]);
-  }
-
-  static int _predictor13(Uint32List pixels, int left, int top) {
-    return _clampedAddSubtractHalf(left, pixels[top], pixels[top - 1]);
-  }
-
-  static final List PREDICTORS = [
-    _predictor0, _predictor1, _predictor2, _predictor3,
-    _predictor4, _predictor5, _predictor6, _predictor7,
-    _predictor8, _predictor9, _predictor10, _predictor11,
-    _predictor12, _predictor13,
-    _predictor0, _predictor0 ];
-}
-
-class _VP8LMultipliers {
-  final Uint8List data = new Uint8List(3);
-
-  // Note: the members are uint8_t, so that any negative values are
-  // automatically converted to "mod 256" values.
-  int get greenToRed => data[0];
-
-  set greenToRed(int m) => data[0] = m;
-
-  int get greenToBlue => data[1];
-
-  set greenToBlue(int m) => data[1] = m;
-
-  int get redToBlue => data[2];
-
-  set redToBlue(int m) => data[2] = m;
-
-  void clear() {
-    data[0] = 0;
-    data[1] = 0;
-    data[2] = 0;
-  }
-
-  void set colorCode(int colorCode) {
-    data[0] = (colorCode >> 0) & 0xff;
-    data[1] = (colorCode >> 8) & 0xff;
-    data[2] = (colorCode >> 16) & 0xff;
-  }
-
-  int get colorCode => 0xff000000 |
-      (data[2] << 16) |
-      (data[1] << 8) |
-      data[0];
-
-  int transformColor(int argb, bool inverse) {
-    final int green = (argb >> 8) & 0xff;
-    final int red = (argb >> 16) & 0xff;
-    int newRed = red;
-    int newBlue = argb & 0xff;
-
-    if (inverse) {
-      int g = colorTransformDelta(greenToRed, green);
-      newRed = (newRed + g) & 0xffffffff;
-      newRed &= 0xff;
-      newBlue = (newBlue + colorTransformDelta(greenToBlue, green)) & 0xffffffff;
-      newBlue = (newBlue + colorTransformDelta(redToBlue, newRed)) & 0xffffffff;
-      newBlue &= 0xff;
-    } else {
-      newRed -= colorTransformDelta(greenToRed, green);
-      newRed &= 0xff;
-      newBlue -= colorTransformDelta(greenToBlue, green);
-      newBlue -= colorTransformDelta(redToBlue, red);
-      newBlue &= 0xff;
-    }
-
-    int c = (argb & 0xff00ff00) | ((newRed << 16) & 0xffffffff) | (newBlue);
-    return c;
-  }
-
-  int colorTransformDelta(int colorPred, int color) {
-    // There's a bug in dart2js (issue 16497) that requires I do this a bit
-    // convoluted to avoid having the optimizer butcher the code.
-    int a = uint8ToInt8(colorPred);
-    int b = uint8ToInt8(color);
-    int d = int32ToUint32(a * b);
-    return d >> 5;
-  }
-}
-
+import 'dart:typed_data';

+

+import '../../internal/bit_operators.dart';

+import '../../util/input_buffer.dart';

+import 'vp8l.dart';

+

+class VP8LTransform {

+  // enum VP8LImageTransformType

+  static const int PREDICTOR_TRANSFORM  = 0;

+  static const int CROSS_COLOR_TRANSFORM = 1;

+  static const int SUBTRACT_GREEN = 2;

+  static const int COLOR_INDEXING_TRANSFORM = 3;

+

+  int type = 0;

+  int xsize = 0;

+  int ysize = 0;

+  Uint32List data;

+  int bits = 0;

+

+  void inverseTransform(int rowStart, int rowEnd,

+                        Uint32List inData,

+                        int rowsIn,

+                        Uint32List outData,

+                        int rowsOut) {

+    final int width = xsize;

+

+    switch (type) {

+      case SUBTRACT_GREEN:

+        addGreenToBlueAndRed(outData, rowsOut,

+                             rowsOut + (rowEnd - rowStart) * width);

+        break;

+      case PREDICTOR_TRANSFORM:

+        predictorInverseTransform(rowStart, rowEnd, outData, rowsOut);

+        if (rowEnd != ysize) {

+          // The last predicted row in this iteration will be the top-pred row

+          // for the first row in next iteration.

+          int start = rowsOut - width;

+          int end = start + width;

+          int offset = rowsOut + (rowEnd - rowStart - 1) * width;

+          outData.setRange(start, end, inData, offset);

+        }

+        break;

+      case CROSS_COLOR_TRANSFORM:

+        colorSpaceInverseTransform(rowStart, rowEnd, outData, rowsOut);

+        break;

+      case COLOR_INDEXING_TRANSFORM:

+        if (rowsIn == rowsOut && bits > 0) {

+          // Move packed pixels to the end of unpacked region, so that unpacking

+          // can occur seamlessly.

+          // Also, note that this is the only transform that applies on

+          // the effective width of VP8LSubSampleSize(xsize_, bits_). All other

+          // transforms work on effective width of xsize_.

+          final int outStride = (rowEnd - rowStart) * width;

+          final int inStride = (rowEnd - rowStart) *

+              InternalVP8L.subSampleSize(xsize, bits);

+

+          int src = rowsOut + outStride - inStride;

+          outData.setRange(src, src + inStride, inData, rowsOut);

+

+          colorIndexInverseTransform(rowStart, rowEnd, inData, src,

+                                      outData, rowsOut);

+        } else {

+          colorIndexInverseTransform(rowStart, rowEnd, inData, rowsIn,

+                                      outData, rowsOut);

+        }

+        break;

+    }

+  }

+

+  void colorIndexInverseTransformAlpha(int yStart, int yEnd,

+                                           InputBuffer src, InputBuffer dst) {

+    final int bitsPerPixel = 8 >> bits;

+    final int width = xsize;

+    Uint32List colorMap = this.data;

+    if (bitsPerPixel < 8) {

+      final int pixelsPerByte = 1 << bits;

+      final int countMask = pixelsPerByte - 1;

+      final bit_mask = (1 << bitsPerPixel) - 1;

+      for (int y = yStart; y < yEnd; ++y) {

+        int packed_pixels = 0;

+        for (int x = 0; x < width; ++x) {

+          // We need to load fresh 'packed_pixels' once every

+          // 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte

+          // is a power of 2, so can just use a mask for that, instead of

+          // decrementing a counter.

+          if ((x & countMask) == 0) {

+            packed_pixels = _getAlphaIndex(src[0]);

+            src.offset++;

+          }

+          int p = _getAlphaValue(colorMap[packed_pixels & bit_mask]);;

+          dst[0] = p;

+          dst.offset++;

+          packed_pixels >>= bitsPerPixel;

+        }

+      }

+    } else {

+      for (int y = yStart; y < yEnd; ++y) {

+        for (int x = 0; x < width; ++x) {

+          int index = _getAlphaIndex(src[0]);

+          src.offset++;

+          dst[0] = _getAlphaValue(colorMap[index]);

+          dst.offset++;

+        }

+      }

+    }

+  }

+

+  void colorIndexInverseTransform(int yStart, int yEnd,

+                                  Uint32List inData, int src,

+                                  Uint32List outData, int dst) {

+    final int bitsPerPixel = 8 >> bits;

+    final int width = xsize;

+    Uint32List colorMap = this.data;

+    if (bitsPerPixel < 8) {

+      final int pixelsPerByte = 1 << bits;

+      final int countMask = pixelsPerByte - 1;

+      final bit_mask = (1 << bitsPerPixel) - 1;

+      for (int y = yStart; y < yEnd; ++y) {

+        int packed_pixels = 0;

+        for (int x = 0; x < width; ++x) {

+          // We need to load fresh 'packed_pixels' once every

+          // 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte

+          // is a power of 2, so can just use a mask for that, instead of

+          // decrementing a counter.

+          if ((x & countMask) == 0) {

+            packed_pixels = _getARGBIndex(inData[src++]);

+          }

+          outData[dst++] = _getARGBValue(colorMap[packed_pixels & bit_mask]);

+          packed_pixels >>= bitsPerPixel;

+        }

+      }

+    } else {

+      for (int y = yStart; y < yEnd; ++y) {

+        for (int x = 0; x < width; ++x) {

+          outData[dst++] = _getARGBValue(colorMap[_getARGBIndex(inData[src++])]);

+        }

+      }

+    }

+  }

+

+  /**

+   * Color space inverse transform.

+   */

+  void colorSpaceInverseTransform(int yStart, int yEnd, Uint32List outData,

+                                  int data) {

+    final int width = xsize;

+    final int mask = (1 << bits) - 1;

+    final int tilesPerRow = InternalVP8L.subSampleSize(width, bits);

+    int y = yStart;

+    int predRow = (y >> bits) * tilesPerRow; //this.data +

+

+    while (y < yEnd) {

+      int pred = predRow; // this.data+

+      _VP8LMultipliers m = _VP8LMultipliers();

+

+      for (int x = 0; x < width; ++x) {

+        if ((x & mask) == 0) {

+          m.colorCode = this.data[pred++];

+        }

+

+        outData[data + x] = m.transformColor(outData[data + x], true);

+      }

+

+      data += width;

+      ++y;

+

+      if ((y & mask) == 0) {

+        predRow += tilesPerRow;;

+      }

+    }

+  }

+

+  /**

+   * Inverse prediction.

+   */

+  void predictorInverseTransform(int yStart, int yEnd, Uint32List outData,

+                                 int data) {

+    final int width = xsize;

+    if (yStart == 0) {  // First Row follows the L (mode=1) mode.

+      final int pred0 = _predictor0(outData, outData[data - 1], 0);

+      _addPixelsEq(outData, data, pred0);

+      for (int x = 1; x < width; ++x) {

+        final int pred1 = _predictor1(outData, outData[data + x - 1], 0);

+        _addPixelsEq(outData, data + x, pred1);

+      }

+      data += width;

+      ++yStart;

+    }

+

+    int y = yStart;

+    final int mask = (1 << bits) - 1;

+    final int tilesPerRow = InternalVP8L.subSampleSize(width, bits);

+    int predModeBase = (y >> bits) * tilesPerRow; //this.data +

+

+    while (y < yEnd) {

+      final int pred2 = _predictor2(outData, outData[data - 1], data - width);

+      int predModeSrc = predModeBase; //this.data +

+

+      // First pixel follows the T (mode=2) mode.

+      _addPixelsEq(outData, data, pred2);

+

+      // .. the rest:

+      int k = (this.data[predModeSrc++] >> 8) & 0xf;

+

+      var predFunc = PREDICTORS[k];

+      for (int x = 1; x < width; ++x) {

+        if ((x & mask) == 0) {    // start of tile. Read predictor function.

+          int k = ((this.data[predModeSrc++]) >> 8) & 0xf;

+          predFunc = PREDICTORS[k];

+        }

+        int d = outData[data + x - 1];

+        int pred = predFunc(outData, d, data + x - width);

+        _addPixelsEq(outData, data + x, pred);

+      }

+

+      data += width;

+      ++y;

+

+      if ((y & mask) == 0) {   // Use the same mask, since tiles are squares.

+        predModeBase += tilesPerRow;

+      }

+    }

+  }

+

+  /**

+   * Add green to blue and red channels (i.e. perform the inverse transform of

+   * 'subtract green').

+   */

+  void addGreenToBlueAndRed(Uint32List pixels, int data, int dataEnd) {

+    while (data < dataEnd) {

+      final int argb = pixels[data];

+      final int green = ((argb >> 8) & 0xff);

+      int redBlue = (argb & 0x00ff00ff);

+      redBlue += (green << 16) | green;

+      redBlue &= 0x00ff00ff;

+      pixels[data++] = (argb & 0xff00ff00) | redBlue;

+    }

+  }

+

+  static int _getARGBIndex(int idx) {

+    return (idx >> 8) & 0xff;

+  }

+

+  static int _getAlphaIndex(int idx) {

+    return idx;

+  }

+

+  static int _getARGBValue(int val) {

+    return val;

+  }

+

+  static int _getAlphaValue(int val) {

+    return (val >> 8) & 0xff;

+  }

+

+  /**

+   * In-place sum of each component with mod 256.

+   */

+  static void _addPixelsEq(Uint32List pixels, int a, int b) {

+    int pa = pixels[a];

+    final int alphaAndGreen = (pa & 0xff00ff00) + (b & 0xff00ff00);

+    final int redAndBlue = (pa & 0x00ff00ff) + (b & 0x00ff00ff);

+    pixels[a] = (alphaAndGreen & 0xff00ff00) | (redAndBlue & 0x00ff00ff);

+  }

+

+  static int _average2(int a0, int a1) {

+    return (((a0 ^ a1) & 0xfefefefe) >> 1) + (a0 & a1);

+  }

+

+  static int _average3(int a0, int a1, int a2) {

+    return _average2(_average2(a0, a2), a1);

+  }

+

+  static int _average4(int a0, int a1, int a2, int a3) {

+    return _average2(_average2(a0, a1), _average2(a2, a3));

+  }

+

+  /**

+   * Return 0, when a is a negative integer.

+   * Return 255, when a is positive.

+   */

+  static int _clip255(int a) {

+    if (a < 0) {

+      return 0;

+    }

+    if (a > 255) {

+      return 255;

+    }

+    return a;

+  }

+

+  static int _addSubtractComponentFull(int a, int b, int c) {

+    return _clip255(a + b - c);

+  }

+

+

+  static int _clampedAddSubtractFull(int c0, int c1, int c2) {

+    final int a = _addSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);

+    final int r = _addSubtractComponentFull((c0 >> 16) & 0xff,

+        (c1 >> 16) & 0xff,

+        (c2 >> 16) & 0xff);

+    final int g = _addSubtractComponentFull((c0 >> 8) & 0xff,

+        (c1 >> 8) & 0xff,

+        (c2 >> 8) & 0xff);

+    final int b = _addSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);

+    return (a << 24) | (r << 16) | (g << 8) | b;

+  }

+

+  static int _addSubtractComponentHalf(int a, int b) {

+    return _clip255(a + (a - b) ~/ 2);

+  }

+

+  static int _clampedAddSubtractHalf(int c0, int c1, int c2) {

+    final int avg = _average2(c0, c1);

+    final int a = _addSubtractComponentHalf(avg >> 24, c2 >> 24);

+    final int r = _addSubtractComponentHalf((avg >> 16) & 0xff, (c2 >> 16) & 0xff);

+    final int g = _addSubtractComponentHalf((avg >> 8) & 0xff, (c2 >> 8) & 0xff);

+    final int b = _addSubtractComponentHalf((avg >> 0) & 0xff, (c2 >> 0) & 0xff);

+    return (a << 24) | (r << 16) | (g << 8) | b;

+  }

+

+  static int _sub3(int a, int b, int c) {

+    final int pb = b - c;

+    final int pa = a - c;

+    return pb.abs() - pa.abs();

+  }

+

+  static int _select(int a, int b, int c) {

+    final int pa_minus_pb =

+        _sub3((a >> 24)       , (b >> 24)       , (c >> 24)       ) +

+        _sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +

+        _sub3((a >>  8) & 0xff, (b >>  8) & 0xff, (c >>  8) & 0xff) +

+        _sub3((a      ) & 0xff, (b      ) & 0xff, (c      ) & 0xff);

+    return (pa_minus_pb <= 0) ? a : b;

+  }

+

+  //--------------------------------------------------------------------------

+  // Predictors

+

+  static int _predictor0(Uint32List pixels, int left, int top) {

+    return VP8L.ARGB_BLACK;

+  }

+

+  static int _predictor1(Uint32List pixels, int left, int top) {

+    return left;

+  }

+

+  static int _predictor2(Uint32List pixels, int left, int top) {

+    return pixels[top];

+  }

+

+  static int _predictor3(Uint32List pixels, int left, int top) {

+    return pixels[top + 1];

+  }

+

+  static int _predictor4(Uint32List pixels, int left, int top) {

+    return pixels[top -1];

+  }

+

+  static int _predictor5(Uint32List pixels, int left, int top) {

+    return _average3(left, pixels[top], pixels[top + 1]);

+  }

+

+  static int _predictor6(Uint32List pixels, int left, int top) {

+    return _average2(left, pixels[top - 1]);

+  }

+

+  static int _predictor7(Uint32List pixels, int left, int top) {

+    return _average2(left, pixels[top]);

+  }

+

+  static int _predictor8(Uint32List pixels, int left, int top) {

+    return _average2(pixels[top -1], pixels[top]);

+  }

+

+  static int _predictor9(Uint32List pixels, int left, int top) {

+    return _average2(pixels[top], pixels[top + 1]);

+  }

+

+  static int _predictor10(Uint32List pixels, int left, int top) {

+    return _average4(left, pixels[top -1], pixels[top], pixels[top + 1]);

+  }

+

+  static int _predictor11(Uint32List pixels, int left, int top) {

+    return _select(pixels[top], left, pixels[top - 1]);

+  }

+

+  static int _predictor12(Uint32List pixels, int left, int top) {

+    return _clampedAddSubtractFull(left, pixels[top], pixels[top - 1]);

+  }

+

+  static int _predictor13(Uint32List pixels, int left, int top) {

+    return _clampedAddSubtractHalf(left, pixels[top], pixels[top - 1]);

+  }

+

+  static final List PREDICTORS = [

+    _predictor0, _predictor1, _predictor2, _predictor3,

+    _predictor4, _predictor5, _predictor6, _predictor7,

+    _predictor8, _predictor9, _predictor10, _predictor11,

+    _predictor12, _predictor13,

+    _predictor0, _predictor0 ];

+}

+

+class _VP8LMultipliers {

+  final Uint8List data = Uint8List(3);

+

+  // Note: the members are uint8_t, so that any negative values are

+  // automatically converted to "mod 256" values.

+  int get greenToRed => data[0];

+

+  set greenToRed(int m) => data[0] = m;

+

+  int get greenToBlue => data[1];

+

+  set greenToBlue(int m) => data[1] = m;

+

+  int get redToBlue => data[2];

+

+  set redToBlue(int m) => data[2] = m;

+

+  void clear() {

+    data[0] = 0;

+    data[1] = 0;

+    data[2] = 0;

+  }

+

+  void set colorCode(int colorCode) {

+    data[0] = (colorCode >> 0) & 0xff;

+    data[1] = (colorCode >> 8) & 0xff;

+    data[2] = (colorCode >> 16) & 0xff;

+  }

+

+  int get colorCode => 0xff000000 |

+      (data[2] << 16) |

+      (data[1] << 8) |

+      data[0];

+

+  int transformColor(int argb, bool inverse) {

+    final int green = (argb >> 8) & 0xff;

+    final int red = (argb >> 16) & 0xff;

+    int newRed = red;

+    int newBlue = argb & 0xff;

+

+    if (inverse) {

+      int g = colorTransformDelta(greenToRed, green);

+      newRed = (newRed + g) & 0xffffffff;

+      newRed &= 0xff;

+      newBlue = (newBlue + colorTransformDelta(greenToBlue, green)) & 0xffffffff;

+      newBlue = (newBlue + colorTransformDelta(redToBlue, newRed)) & 0xffffffff;

+      newBlue &= 0xff;

+    } else {

+      newRed -= colorTransformDelta(greenToRed, green);

+      newRed &= 0xff;

+      newBlue -= colorTransformDelta(greenToBlue, green);

+      newBlue -= colorTransformDelta(redToBlue, red);

+      newBlue &= 0xff;

+    }

+

+    int c = (argb & 0xff00ff00) | ((newRed << 16) & 0xffffffff) | (newBlue);

+    return c;

+  }

+

+  int colorTransformDelta(int colorPred, int color) {

+    // There's a bug in dart2js (issue 16497) that requires I do this a bit

+    // convoluted to avoid having the optimizer butcher the code.

+    int a = uint8ToInt8(colorPred);

+    int b = uint8ToInt8(color);

+    int d = int32ToUint32(a * b);

+    return d >> 5;

+  }

+}

+

diff --git a/image/lib/src/formats/webp/webp_alpha.dart b/image/lib/src/formats/webp/webp_alpha.dart
old mode 100644
new mode 100755
index 7d23c43..7767232
--- a/image/lib/src/formats/webp/webp_alpha.dart
+++ b/image/lib/src/formats/webp/webp_alpha.dart
@@ -1,146 +1,146 @@
-import 'dart:typed_data';
-
-import '../../util/input_buffer.dart';
-import 'vp8l.dart';
-import 'vp8l_transform.dart';
-import 'webp_filters.dart';
-import 'webp_info.dart';
-
-class WebPAlpha {
-  InputBuffer input;
-  int width = 0;
-  int height = 0;
-  int method = 0;
-  int filter = 0;
-  int preProcessing = 0;
-  int rsrv = 1;
-  bool isAlphaDecoded = false;
-
-  WebPAlpha(this.input, this.width, this.height) {
-    int b = input.readByte();
-    method = b & 0x03;
-    filter = (b >> 2) & 0x03;
-    preProcessing = (b >> 4) & 0x03;
-    rsrv = (b >> 6) & 0x03;
-
-    if (isValid) {
-      if (method == ALPHA_NO_COMPRESSION) {
-        final int alphaDecodedSize = width * height;
-        if (input.length < alphaDecodedSize) {
-          rsrv = 1;
-        }
-      } else if (method == ALPHA_LOSSLESS_COMPRESSION) {
-        if (!_decodeAlphaHeader()) {
-          rsrv = 1;
-        }
-      } else {
-        rsrv = 1;
-      }
-    }
-  }
-
-  bool get isValid {
-    if (method < ALPHA_NO_COMPRESSION ||
-        method > ALPHA_LOSSLESS_COMPRESSION ||
-        filter >= WebPFilters.FILTER_LAST ||
-        preProcessing > ALPHA_PREPROCESSED_LEVELS ||
-        rsrv != 0) {
-      return false;
-    }
-    return true;
-  }
-
-  bool decode(int row, int numRows, Uint8List output) {
-    if (!isValid) {
-      return false;
-    }
-
-    var unfilterFunc = WebPFilters.UNFILTERS[filter];
-
-    if (method == ALPHA_NO_COMPRESSION) {
-      final int offset = row * width;
-      final int numPixels = numRows * width;
-
-      output.setRange(offset, numPixels, input.buffer,
-                      input.position + offset);
-    } else {
-      if (!_decodeAlphaImageStream(row + numRows, output)) {
-        return false;
-      }
-    }
-
-    if (unfilterFunc != null) {
-      unfilterFunc(width, height, width, row, numRows, output);
-    }
-
-    if (preProcessing == ALPHA_PREPROCESSED_LEVELS) {
-      if (!_dequantizeLevels(output, width, height, row, numRows)) {
-        return false;
-      }
-    }
-
-    if (row + numRows == height) {
-      isAlphaDecoded = true;
-    }
-
-    return true;
-  }
-
-  bool _dequantizeLevels(Uint8List data, int width, int height,
-                         int row, int num_rows) {
-    if (data == null || width <= 0 || height <= 0 || row < 0 || num_rows < 0 ||
-        row + num_rows > height) {
-      return false;
-    }
-    return true;
-  }
-
-
-  bool _decodeAlphaImageStream(int lastRow, Uint8List output) {
-    _vp8l.opaque = output;
-    // Decode (with special row processing).
-    return _use8bDecode ?
-        _vp8l.decodeAlphaData(_vp8l.webp.width, _vp8l.webp.height, lastRow) :
-        _vp8l.decodeImageData(_vp8l.pixels, _vp8l.webp.width, _vp8l.webp.height,
-                               lastRow, _vp8l.extractAlphaRows);
-  }
-
-  bool _decodeAlphaHeader() {
-    WebPInfo webp = new WebPInfo();
-    webp.width = width;
-    webp.height = height;
-
-    _vp8l = new InternalVP8L(input, webp);
-    _vp8l.ioWidth = width;
-    _vp8l.ioHeight = height;
-
-    _vp8l.decodeImageStream(webp.width, webp.height, true);
-
-    // Special case: if alpha data uses only the color indexing transform and
-    // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
-    // method that only needs allocation of 1 byte per pixel (alpha channel).
-    if (_vp8l.transforms.length == 1 &&
-        _vp8l.transforms[0].type == VP8LTransform.COLOR_INDEXING_TRANSFORM &&
-        _vp8l.is8bOptimizable()) {
-      _use8bDecode = true;
-      _vp8l.allocateInternalBuffers8b();
-    } else {
-      _use8bDecode = false;
-      _vp8l.allocateInternalBuffers32b();
-    }
-
-    return true;
-  }
-
-  InternalVP8L _vp8l;
-  /// Although alpha channel
-  /// requires only 1 byte per
-  /// pixel, sometimes VP8LDecoder may need to allocate
-  /// 4 bytes per pixel internally during decode.
-  bool _use8bDecode = false;
-
-  // Alpha related constants.
-  static const int ALPHA_NO_COMPRESSION = 0;
-  static const int ALPHA_LOSSLESS_COMPRESSION = 1;
-  static const int ALPHA_PREPROCESSED_LEVELS = 1;
-}
+import 'dart:typed_data';

+

+import '../../util/input_buffer.dart';

+import 'vp8l.dart';

+import 'vp8l_transform.dart';

+import 'webp_filters.dart';

+import 'webp_info.dart';

+

+class WebPAlpha {

+  InputBuffer input;

+  int width = 0;

+  int height = 0;

+  int method = 0;

+  int filter = 0;

+  int preProcessing = 0;

+  int rsrv = 1;

+  bool isAlphaDecoded = false;

+

+  WebPAlpha(this.input, this.width, this.height) {

+    int b = input.readByte();

+    method = b & 0x03;

+    filter = (b >> 2) & 0x03;

+    preProcessing = (b >> 4) & 0x03;

+    rsrv = (b >> 6) & 0x03;

+

+    if (isValid) {

+      if (method == ALPHA_NO_COMPRESSION) {

+        final int alphaDecodedSize = width * height;

+        if (input.length < alphaDecodedSize) {

+          rsrv = 1;

+        }

+      } else if (method == ALPHA_LOSSLESS_COMPRESSION) {

+        if (!_decodeAlphaHeader()) {

+          rsrv = 1;

+        }

+      } else {

+        rsrv = 1;

+      }

+    }

+  }

+

+  bool get isValid {

+    if (method < ALPHA_NO_COMPRESSION ||

+        method > ALPHA_LOSSLESS_COMPRESSION ||

+        filter >= WebPFilters.FILTER_LAST ||

+        preProcessing > ALPHA_PREPROCESSED_LEVELS ||

+        rsrv != 0) {

+      return false;

+    }

+    return true;

+  }

+

+  bool decode(int row, int numRows, Uint8List output) {

+    if (!isValid) {

+      return false;

+    }

+

+    var unfilterFunc = WebPFilters.UNFILTERS[filter];

+

+    if (method == ALPHA_NO_COMPRESSION) {

+      final int offset = row * width;

+      final int numPixels = numRows * width;

+

+      output.setRange(offset, numPixels, input.buffer,

+                      input.position + offset);

+    } else {

+      if (!_decodeAlphaImageStream(row + numRows, output)) {

+        return false;

+      }

+    }

+

+    if (unfilterFunc != null) {

+      unfilterFunc(width, height, width, row, numRows, output);

+    }

+

+    if (preProcessing == ALPHA_PREPROCESSED_LEVELS) {

+      if (!_dequantizeLevels(output, width, height, row, numRows)) {

+        return false;

+      }

+    }

+

+    if (row + numRows == height) {

+      isAlphaDecoded = true;

+    }

+

+    return true;

+  }

+

+  bool _dequantizeLevels(Uint8List data, int width, int height,

+                         int row, int num_rows) {

+    if (data == null || width <= 0 || height <= 0 || row < 0 || num_rows < 0 ||

+        row + num_rows > height) {

+      return false;

+    }

+    return true;

+  }

+

+

+  bool _decodeAlphaImageStream(int lastRow, Uint8List output) {

+    _vp8l.opaque = output;

+    // Decode (with special row processing).

+    return _use8bDecode ?

+        _vp8l.decodeAlphaData(_vp8l.webp.width, _vp8l.webp.height, lastRow) :

+        _vp8l.decodeImageData(_vp8l.pixels, _vp8l.webp.width, _vp8l.webp.height,

+                               lastRow, _vp8l.extractAlphaRows);

+  }

+

+  bool _decodeAlphaHeader() {

+    WebPInfo webp = WebPInfo();

+    webp.width = width;

+    webp.height = height;

+

+    _vp8l = InternalVP8L(input, webp);

+    _vp8l.ioWidth = width;

+    _vp8l.ioHeight = height;

+

+    _vp8l.decodeImageStream(webp.width, webp.height, true);

+

+    // Special case: if alpha data uses only the color indexing transform and

+    // doesn't use color cache (a frequent case), we will use DecodeAlphaData()

+    // method that only needs allocation of 1 byte per pixel (alpha channel).

+    if (_vp8l.transforms.length == 1 &&

+        _vp8l.transforms[0].type == VP8LTransform.COLOR_INDEXING_TRANSFORM &&

+        _vp8l.is8bOptimizable()) {

+      _use8bDecode = true;

+      _vp8l.allocateInternalBuffers8b();

+    } else {

+      _use8bDecode = false;

+      _vp8l.allocateInternalBuffers32b();

+    }

+

+    return true;

+  }

+

+  InternalVP8L _vp8l;

+  /// Although alpha channel

+  /// requires only 1 byte per

+  /// pixel, sometimes VP8LDecoder may need to allocate

+  /// 4 bytes per pixel internally during decode.

+  bool _use8bDecode = false;

+

+  // Alpha related constants.

+  static const int ALPHA_NO_COMPRESSION = 0;

+  static const int ALPHA_LOSSLESS_COMPRESSION = 1;

+  static const int ALPHA_PREPROCESSED_LEVELS = 1;

+}

diff --git a/image/lib/src/formats/webp/webp_filters.dart b/image/lib/src/formats/webp/webp_filters.dart
old mode 100644
new mode 100755
index 497b150..e16e883
--- a/image/lib/src/formats/webp/webp_filters.dart
+++ b/image/lib/src/formats/webp/webp_filters.dart
@@ -1,188 +1,188 @@
-import 'dart:typed_data';
-
-import '../../util/input_buffer.dart';
-
-class WebPFilters {
-  // Filters.
-  static const int FILTER_NONE = 0;
-  static const int FILTER_HORIZONTAL = 1;
-  static const int FILTER_VERTICAL = 2;
-  static const int FILTER_GRADIENT = 3;
-  static const int FILTER_LAST = FILTER_GRADIENT + 1;  // end marker
-  static const int FILTER_BEST = 5;
-  static const int FILTER_FAST = 6;
-
-  static const List FILTERS = const [
-      null,              // WEBP_FILTER_NONE
-      horizontalFilter,  // WEBP_FILTER_HORIZONTAL
-      verticalFilter,    // WEBP_FILTER_VERTICAL
-      gradientFilter     // WEBP_FILTER_GRADIENT
-  ];
-
-
-  static const List UNFILTERS = const [
-      null,                // WEBP_FILTER_NONE
-      horizontalUnfilter,  // WEBP_FILTER_HORIZONTAL
-      verticalUnfilter,    // WEBP_FILTER_VERTICAL
-      gradientUnfilter     // WEBP_FILTER_GRADIENT
-  ];
-
-  static void horizontalFilter(Uint8List data, int width, int height,
-                               int stride, Uint8List filteredData) {
-    _doHorizontalFilter(data, width, height, stride, 0, height, false,
-                        filteredData);
-  }
-
-  static void horizontalUnfilter(int width, int height, int stride, int row,
-                                 int numRows, Uint8List data) {
-    _doHorizontalFilter(data, width, height, stride, row, numRows, true, data);
-  }
-
-  static void verticalFilter(Uint8List data, int width, int height,
-                             int stride, Uint8List filteredData) {
-    _doVerticalFilter(data, width, height, stride, 0, height, false,
-                      filteredData);
-  }
-
-  static void verticalUnfilter(int width, int height, int stride, int row,
-                               int num_rows, Uint8List data) {
-    _doVerticalFilter(data, width, height, stride, row, num_rows, true, data);
-  }
-
-  static void gradientFilter(Uint8List data, int width, int height,
-                             int stride, Uint8List filteredData) {
-    _doGradientFilter(data, width, height, stride, 0, height, false,
-                      filteredData);
-  }
-
-  static void gradientUnfilter(int width, int height, int stride, int row,
-                               int num_rows, Uint8List data) {
-    _doGradientFilter(data, width, height, stride, row, num_rows, true, data);
-  }
-
-  static void _predictLine(InputBuffer src, InputBuffer pred, InputBuffer dst, int length,
-                           bool inverse) {
-    if (inverse) {
-      for (int i = 0; i < length; ++i) {
-        dst[i] = src[i] + pred[i];
-      }
-    } else {
-      for (int i = 0; i < length; ++i) {
-        dst[i] = src[i] - pred[i];
-      }
-    }
-  }
-
-  static void _doHorizontalFilter(Uint8List src,
-                                  int width, int height, int stride,
-                                  int row, int numRows,
-                                  bool inverse, Uint8List out) {
-    final int startOffset = row * stride;
-    final int lastRow = row + numRows;
-    InputBuffer s = new InputBuffer(src, offset: startOffset);
-    InputBuffer o = new InputBuffer(src, offset: startOffset);
-    InputBuffer preds = new InputBuffer.from(inverse ? o : s);
-
-    if (row == 0) {
-      // Leftmost pixel is the same as input for topmost scanline.
-      o[0] = s[0];
-      _predictLine(new InputBuffer.from(s, offset: 1), preds,
-                   new InputBuffer.from(o, offset: 1), width - 1, inverse);
-      row = 1;
-      preds.offset += stride;
-      s.offset += stride;
-      o.offset += stride;
-    }
-
-    // Filter line-by-line.
-    while (row < lastRow) {
-      // Leftmost pixel is predicted from above.
-      _predictLine(s, new InputBuffer.from(preds, offset: -stride), o, 1, inverse);
-      _predictLine(new InputBuffer.from(s, offset: 1), preds,
-                   new InputBuffer.from(o, offset: 1), width - 1, inverse);
-      ++row;
-      preds.offset += stride;
-      s.offset += stride;
-      o.offset += stride;
-    }
-  }
-
-  static void _doVerticalFilter(Uint8List src,
-                               int width, int height, int stride,
-                               int row, int numRows,
-                               bool inverse, Uint8List out) {
-    final int startOffset = row * stride;
-    final int last_row = row + numRows;
-    InputBuffer s = new InputBuffer(src, offset: startOffset);
-    InputBuffer o = new InputBuffer(out, offset: startOffset);
-    InputBuffer preds = new InputBuffer.from(inverse ? o : s);
-
-    if (row == 0) {
-      // Very first top-left pixel is copied.
-      o[0] = s[0];
-      // Rest of top scan-line is left-predicted.
-      _predictLine(new InputBuffer.from(s, offset: 1), preds,
-                   new InputBuffer.from(o, offset: 1), width - 1,
-                   inverse);
-      row = 1;
-      s.offset += stride;
-      o.offset += stride;
-    } else {
-      // We are starting from in-between. Make sure 'preds' points to prev row.
-      preds.offset -= stride;
-    }
-
-    // Filter line-by-line.
-    while (row < last_row) {
-      _predictLine(s, preds, o, width, inverse);
-      ++row;
-      preds.offset += stride;
-      s.offset += stride;
-      o.offset += stride;
-    }
-  }
-
-  static int _gradientPredictor(int a, int b, int c) {
-    final int g = a + b - c;
-    return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255;  // clip to 8bit
-  }
-
-  static void _doGradientFilter(Uint8List src,
-                                int width, int height, int stride,
-                                int row, int numRows,
-                                bool inverse, Uint8List out) {
-    final int startOffset = row * stride;
-    final int lastRow = row + numRows;
-    InputBuffer s = new InputBuffer(src, offset: startOffset);
-    InputBuffer o = new InputBuffer(out, offset: startOffset);
-    InputBuffer preds = new InputBuffer.from(inverse ? o : s);
-
-    // left prediction for top scan-line
-    if (row == 0) {
-      o[0] = s[0];
-      _predictLine(new InputBuffer.from(s, offset: 1), preds,
-                   new InputBuffer.from(o, offset: 1), width - 1, inverse);
-      row = 1;
-      preds.offset += stride;
-      s.offset += stride;
-      o.offset += stride;
-    }
-
-    // Filter line-by-line.
-    while (row < lastRow) {
-      // leftmost pixel: predict from above.
-      _predictLine(s, new InputBuffer.from(preds, offset: -stride),
-                   o, 1, inverse);
-      for (int w = 1; w < width; ++w) {
-        final int pred = _gradientPredictor(preds[w - 1],
-            preds[w - stride],
-            preds[w - stride - 1]);
-        o[w] = s[w] + (inverse ? pred : -pred);
-      }
-      ++row;
-      preds.offset += stride;
-      s.offset += stride;
-      o.offset += stride;
-    }
-  }
-}
+import 'dart:typed_data';

+

+import '../../util/input_buffer.dart';

+

+class WebPFilters {

+  // Filters.

+  static const int FILTER_NONE = 0;

+  static const int FILTER_HORIZONTAL = 1;

+  static const int FILTER_VERTICAL = 2;

+  static const int FILTER_GRADIENT = 3;

+  static const int FILTER_LAST = FILTER_GRADIENT + 1;  // end marker

+  static const int FILTER_BEST = 5;

+  static const int FILTER_FAST = 6;

+

+  static const List FILTERS = const [

+      null,              // WEBP_FILTER_NONE

+      horizontalFilter,  // WEBP_FILTER_HORIZONTAL

+      verticalFilter,    // WEBP_FILTER_VERTICAL

+      gradientFilter     // WEBP_FILTER_GRADIENT

+  ];

+

+

+  static const List UNFILTERS = const [

+      null,                // WEBP_FILTER_NONE

+      horizontalUnfilter,  // WEBP_FILTER_HORIZONTAL

+      verticalUnfilter,    // WEBP_FILTER_VERTICAL

+      gradientUnfilter     // WEBP_FILTER_GRADIENT

+  ];

+

+  static void horizontalFilter(Uint8List data, int width, int height,

+                               int stride, Uint8List filteredData) {

+    _doHorizontalFilter(data, width, height, stride, 0, height, false,

+                        filteredData);

+  }

+

+  static void horizontalUnfilter(int width, int height, int stride, int row,

+                                 int numRows, Uint8List data) {

+    _doHorizontalFilter(data, width, height, stride, row, numRows, true, data);

+  }

+

+  static void verticalFilter(Uint8List data, int width, int height,

+                             int stride, Uint8List filteredData) {

+    _doVerticalFilter(data, width, height, stride, 0, height, false,

+                      filteredData);

+  }

+

+  static void verticalUnfilter(int width, int height, int stride, int row,

+                               int num_rows, Uint8List data) {

+    _doVerticalFilter(data, width, height, stride, row, num_rows, true, data);

+  }

+

+  static void gradientFilter(Uint8List data, int width, int height,

+                             int stride, Uint8List filteredData) {

+    _doGradientFilter(data, width, height, stride, 0, height, false,

+                      filteredData);

+  }

+

+  static void gradientUnfilter(int width, int height, int stride, int row,

+                               int num_rows, Uint8List data) {

+    _doGradientFilter(data, width, height, stride, row, num_rows, true, data);

+  }

+

+  static void _predictLine(InputBuffer src, InputBuffer pred, InputBuffer dst, int length,

+                           bool inverse) {

+    if (inverse) {

+      for (int i = 0; i < length; ++i) {

+        dst[i] = src[i] + pred[i];

+      }

+    } else {

+      for (int i = 0; i < length; ++i) {

+        dst[i] = src[i] - pred[i];

+      }

+    }

+  }

+

+  static void _doHorizontalFilter(Uint8List src,

+                                  int width, int height, int stride,

+                                  int row, int numRows,

+                                  bool inverse, Uint8List out) {

+    final int startOffset = row * stride;

+    final int lastRow = row + numRows;

+    InputBuffer s = InputBuffer(src, offset: startOffset);

+    InputBuffer o = InputBuffer(src, offset: startOffset);

+    InputBuffer preds = InputBuffer.from(inverse ? o : s);

+

+    if (row == 0) {

+      // Leftmost pixel is the same as input for topmost scanline.

+      o[0] = s[0];

+      _predictLine(new InputBuffer.from(s, offset: 1), preds,

+                   new InputBuffer.from(o, offset: 1), width - 1, inverse);

+      row = 1;

+      preds.offset += stride;

+      s.offset += stride;

+      o.offset += stride;

+    }

+

+    // Filter line-by-line.

+    while (row < lastRow) {

+      // Leftmost pixel is predicted from above.

+      _predictLine(s, new InputBuffer.from(preds, offset: -stride), o, 1, inverse);

+      _predictLine(new InputBuffer.from(s, offset: 1), preds,

+                   new InputBuffer.from(o, offset: 1), width - 1, inverse);

+      ++row;

+      preds.offset += stride;

+      s.offset += stride;

+      o.offset += stride;

+    }

+  }

+

+  static void _doVerticalFilter(Uint8List src,

+                               int width, int height, int stride,

+                               int row, int numRows,

+                               bool inverse, Uint8List out) {

+    final int startOffset = row * stride;

+    final int last_row = row + numRows;

+    InputBuffer s = InputBuffer(src, offset: startOffset);

+    InputBuffer o = InputBuffer(out, offset: startOffset);

+    InputBuffer preds = InputBuffer.from(inverse ? o : s);

+

+    if (row == 0) {

+      // Very first top-left pixel is copied.

+      o[0] = s[0];

+      // Rest of top scan-line is left-predicted.

+      _predictLine(new InputBuffer.from(s, offset: 1), preds,

+                   new InputBuffer.from(o, offset: 1), width - 1,

+                   inverse);

+      row = 1;

+      s.offset += stride;

+      o.offset += stride;

+    } else {

+      // We are starting from in-between. Make sure 'preds' points to prev row.

+      preds.offset -= stride;

+    }

+

+    // Filter line-by-line.

+    while (row < last_row) {

+      _predictLine(s, preds, o, width, inverse);

+      ++row;

+      preds.offset += stride;

+      s.offset += stride;

+      o.offset += stride;

+    }

+  }

+

+  static int _gradientPredictor(int a, int b, int c) {

+    final int g = a + b - c;

+    return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255;  // clip to 8bit

+  }

+

+  static void _doGradientFilter(Uint8List src,

+                                int width, int height, int stride,

+                                int row, int numRows,

+                                bool inverse, Uint8List out) {

+    final int startOffset = row * stride;

+    final int lastRow = row + numRows;

+    InputBuffer s = InputBuffer(src, offset: startOffset);

+    InputBuffer o = InputBuffer(out, offset: startOffset);

+    InputBuffer preds = InputBuffer.from(inverse ? o : s);

+

+    // left prediction for top scan-line

+    if (row == 0) {

+      o[0] = s[0];

+      _predictLine(new InputBuffer.from(s, offset: 1), preds,

+                   new InputBuffer.from(o, offset: 1), width - 1, inverse);

+      row = 1;

+      preds.offset += stride;

+      s.offset += stride;

+      o.offset += stride;

+    }

+

+    // Filter line-by-line.

+    while (row < lastRow) {

+      // leftmost pixel: predict from above.

+      _predictLine(s, new InputBuffer.from(preds, offset: -stride),

+                   o, 1, inverse);

+      for (int w = 1; w < width; ++w) {

+        final int pred = _gradientPredictor(preds[w - 1],

+            preds[w - stride],

+            preds[w - stride - 1]);

+        o[w] = s[w] + (inverse ? pred : -pred);

+      }

+      ++row;

+      preds.offset += stride;

+      s.offset += stride;

+      o.offset += stride;

+    }

+  }

+}

diff --git a/image/lib/src/formats/webp/webp_frame.dart b/image/lib/src/formats/webp/webp_frame.dart
old mode 100644
new mode 100755
index 1e88b78..ab1dd9e
--- a/image/lib/src/formats/webp/webp_frame.dart
+++ b/image/lib/src/formats/webp/webp_frame.dart
@@ -1,54 +1,54 @@
-import '../../internal/internal.dart';
-import '../../util/input_buffer.dart';
-
-/**
- * Decodes a frame from a WebP animation.
- */
-class WebPFrame {
-  /// The x coordinate of the upper left corner of the frame.
-  int x;
-  /// The y coordinate of the upper left corner of the frame.
-  int y;
-  /// The width of the frame.
-  int width;
-  /// The height of the frame.
-  int height;
-  /// How long the frame should be displayed, in milliseconds.
-  int duration;
-  /// Indicates how the current frame is to be treated after it has been
-  /// displayed (before rendering the next frame) on the canvas.
-  /// If true, the frame is cleared to the background color.  If false,
-  /// frame is left and the next frame drawn over it.
-  bool clearFrame;
-
-  WebPFrame(InputBuffer input, int size) {
-    x = input.readUint24() * 2;
-    y = input.readUint24() * 2;
-    width = input.readUint24() + 1;
-    height = input.readUint24() + 1;
-    duration = input.readUint24();
-    int b = input.readByte();
-    _reserved = (b & 0x7F) >> 7;
-    clearFrame = (b & 0x1) != 0;
-
-    _framePosition = input.position;
-    _frameSize = size - _ANIMF_HEADER_SIZE;
-  }
-
-  bool get isValid => _reserved == 0;
-
-  int _reserved = 1;
-  int _framePosition;
-  int _frameSize;
-
-  // Size of an animation frame header.
-  static const int _ANIMF_HEADER_SIZE = 16;
-}
-
-@internal
-class InternalWebPFrame extends WebPFrame {
-  InternalWebPFrame(InputBuffer input, int size) : super(input, size);
-
-  int get framePosition => _framePosition;
-  int get frameSize => _frameSize;
-}
+import '../../internal/internal.dart';

+import '../../util/input_buffer.dart';

+

+/**

+ * Decodes a frame from a WebP animation.

+ */

+class WebPFrame {

+  /// The x coordinate of the upper left corner of the frame.

+  int x;

+  /// The y coordinate of the upper left corner of the frame.

+  int y;

+  /// The width of the frame.

+  int width;

+  /// The height of the frame.

+  int height;

+  /// How long the frame should be displayed, in milliseconds.

+  int duration;

+  /// Indicates how the current frame is to be treated after it has been

+  /// displayed (before rendering the next frame) on the canvas.

+  /// If true, the frame is cleared to the background color.  If false,

+  /// frame is left and the next frame drawn over it.

+  bool clearFrame;

+

+  WebPFrame(InputBuffer input, int size) {

+    x = input.readUint24() * 2;

+    y = input.readUint24() * 2;

+    width = input.readUint24() + 1;

+    height = input.readUint24() + 1;

+    duration = input.readUint24();

+    int b = input.readByte();

+    _reserved = (b & 0x7F) >> 7;

+    clearFrame = (b & 0x1) != 0;

+

+    _framePosition = input.position;

+    _frameSize = size - _ANIMF_HEADER_SIZE;

+  }

+

+  bool get isValid => _reserved == 0;

+

+  int _reserved = 1;

+  int _framePosition;

+  int _frameSize;

+

+  // Size of an animation frame header.

+  static const int _ANIMF_HEADER_SIZE = 16;

+}

+

+@internal

+class InternalWebPFrame extends WebPFrame {

+  InternalWebPFrame(InputBuffer input, int size) : super(input, size);

+

+  int get framePosition => _framePosition;

+  int get frameSize => _frameSize;

+}

diff --git a/image/lib/src/formats/webp/webp_huffman.dart b/image/lib/src/formats/webp/webp_huffman.dart
old mode 100644
new mode 100755
index 9b4fa79..7ae311f
--- a/image/lib/src/formats/webp/webp_huffman.dart
+++ b/image/lib/src/formats/webp/webp_huffman.dart
@@ -1,328 +1,328 @@
-import 'dart:typed_data';
-
-import '../../internal/internal.dart';
-import 'vp8l.dart';
-import 'vp8l_bit_reader.dart';
-
-/**
- * Huffman Tree.
- */
-@internal
-class HuffmanTree {
-  static const int HUFF_LUT_BITS = 7;
-  static const int HUFF_LUT = (1 << HUFF_LUT_BITS);
-  // Fast lookup for short bit lengths.
-  Uint8List lutBits = new Uint8List(HUFF_LUT);
-  Int16List lutSymbol = new Int16List(HUFF_LUT);
-  Int16List lutJump = new Int16List(HUFF_LUT);
-
-  /// all the nodes, starting at root, stored as a single int array, where
-  /// each node occupies two ints as [symbol, children].
-  Int32List tree;
-  /// max number of nodes
-  int maxNodes = 0;
-  /// number of currently occupied nodes
-  int numNodes = 0;
-
-  HuffmanTree([int numLeaves = 0]) {
-    _init(numLeaves);
-  }
-
-  bool _init(int numLeaves) {
-    if (numLeaves == 0) {
-      return false;
-    }
-
-    maxNodes = (numLeaves << 1) - 1;
-    tree = new Int32List(maxNodes << 1);
-    tree[1] = -1;
-    numNodes = 1;
-    lutBits.fillRange(0, lutBits.length, 255);
-
-    return true;
-  }
-
-  bool buildImplicit(List<int> codeLengths, int codeLengthsSize) {
-    int numSymbols = 0;
-    int rootSymbol = 0;
-
-    // Find out number of symbols and the root symbol.
-    for (int symbol = 0; symbol < codeLengthsSize; ++symbol) {
-      if (codeLengths[symbol] > 0) {
-        // Note: code length = 0 indicates non-existent symbol.
-        ++numSymbols;
-        rootSymbol = symbol;
-      }
-    }
-
-    // Initialize the tree. Will fail for num_symbols = 0
-    if (!_init(numSymbols)) {
-      return false;
-    }
-
-    // Build tree.
-    if (numSymbols == 1) {
-      // Trivial case.
-      final int maxSymbol = codeLengthsSize;
-      if (rootSymbol < 0 || rootSymbol >= maxSymbol) {
-        return false;
-      }
-
-      return _addSymbol(rootSymbol, 0, 0);
-    }
-
-    // Normal case.
-
-    // Get Huffman codes from the code lengths.
-    Int32List codes = new Int32List(codeLengthsSize);
-
-    if (!_huffmanCodeLengthsToCodes(codeLengths, codeLengthsSize, codes)) {
-      return false;
-    }
-
-    // Add symbols one-by-one.
-    for (int symbol = 0; symbol < codeLengthsSize; ++symbol) {
-      if (codeLengths[symbol] > 0) {
-        if (!_addSymbol(symbol, codes[symbol], codeLengths[symbol])) {
-          return false;
-        }
-      }
-    }
-
-    return _isFull();
-  }
-
-  bool buildExplicit(List<int> codeLengths,
-                     List<int> codes,
-                     List<int> symbols,
-                     int maxSymbol,
-                     int numSymbols) {
-    // Initialize the tree. Will fail if num_symbols = 0.
-    if (!_init(numSymbols)) {
-      return false;
-    }
-
-    // Add symbols one-by-one.
-    for (int i = 0; i < numSymbols; ++i) {
-      if (codes[i] != -1) {
-        if (symbols[i] < 0 || symbols[i] >= maxSymbol) {
-          return _isFull();
-        }
-
-        if (!_addSymbol(symbols[i], codes[i], codeLengths[i])) {
-          return _isFull();
-        }
-      }
-    }
-
-    return _isFull();
-  }
-
-  /**
-   * Decodes the next Huffman code from bit-stream.
-   * input.fillBitWindow() needs to be called at minimum every second call
-   * to ReadSymbol, in order to pre-fetch enough bits.
-   */
-  int readSymbol(VP8LBitReader br) {
-    int node = 0;
-    int bits = br.prefetchBits();
-    int newBitPos = br.bitPos;
-    // Check if we find the bit combination from the Huffman lookup table.
-    int lut_ix = bits & (HUFF_LUT - 1);
-    int lut_bits = lutBits[lut_ix];
-
-    if (lut_bits <= HUFF_LUT_BITS) {
-      br.bitPos = br.bitPos + lut_bits;
-      return this.lutSymbol[lut_ix];
-    }
-
-    node += this.lutJump[lut_ix];
-    newBitPos += HUFF_LUT_BITS;
-    bits >>= HUFF_LUT_BITS;
-
-    // Decode the value from a binary tree.
-    do {
-      node = _nextNode(node, bits & 1);
-      bits >>= 1;
-      ++newBitPos;
-    } while (_nodeIsNotLeaf(node));
-
-    br.bitPos = newBitPos;
-
-    return _nodeSymbol(node);
-  }
-
-  bool _addSymbol(int symbol, int code, int codeLength) {
-    int step = HUFF_LUT_BITS;
-    int baseCode;
-    int node = 0;
-
-    if (codeLength <= HUFF_LUT_BITS) {
-      baseCode = _reverseBitsShort(code, codeLength);
-      for (int i = 0; i < (1 << (HUFF_LUT_BITS - codeLength)); ++i) {
-        final int idx = baseCode | (i << codeLength);
-        lutSymbol[idx] = symbol;
-        lutBits[idx] = codeLength;
-      }
-    } else {
-      baseCode = _reverseBitsShort((code >> (codeLength - HUFF_LUT_BITS)),
-                                   HUFF_LUT_BITS);
-    }
-
-    while (codeLength-- > 0) {
-      if (node >= maxNodes) {
-        return false;
-      }
-
-      if (_nodeIsEmpty(node)) {
-        if (_isFull()) {
-          // error: too many symbols.
-          return false;
-        }
-
-        _assignChildren(node);
-      } else if (!_nodeIsNotLeaf(node)) {
-        // leaf is already occupied.
-        return false;
-      }
-
-      node += _nodeChildren(node) + ((code >> codeLength) & 1);
-
-      if (--step == 0) {
-        lutJump[baseCode] = node;
-      }
-    }
-
-    if (_nodeIsEmpty(node)) {
-      // turn newly created node into a leaf.
-      _nodeSetChildren(node, 0);
-    } else if (_nodeIsNotLeaf(node)) {
-      // trying to assign a symbol to already used code.
-      return false;
-    }
-
-    // Add symbol in this node.
-    _nodeSetSymbol(node, symbol);
-
-    return true;
-  }
-
-  // Pre-reversed 4-bit values.
-  static const List<int> _REVERSED_BITS = const [
-    0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
-    0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf];
-
-  int _reverseBitsShort(int bits, int numBits) {
-    int v = (_REVERSED_BITS[bits & 0xf] << 4) | _REVERSED_BITS[bits >> 4];
-    return v >> (8 - numBits);
-  }
-
-  bool _isFull() {
-    return (numNodes == maxNodes);
-  }
-
-  int _nextNode(int node, int rightChild) {
-    return node + _nodeChildren(node) + rightChild;
-  }
-
-  int _nodeSymbol(int node) => tree[(node << 1)];
-
-  void _nodeSetSymbol(int node, int symbol) {
-    tree[(node << 1)] = symbol;
-  }
-
-  int _nodeChildren(int node) => tree[(node << 1) + 1];
-
-  void _nodeSetChildren(int node, int children) {
-    tree[(node << 1) + 1] = children;
-  }
-
-  bool _nodeIsNotLeaf(int node) => tree[(node << 1) + 1] != 0;
-
-  bool _nodeIsEmpty(int node) => tree[(node << 1) + 1] < 0;
-
-  void _assignChildren(int node) {
-    int children = numNodes;
-    _nodeSetChildren(node, children - node);
-
-    numNodes += 2;
-
-    _nodeSetChildren(children, -1);
-    _nodeSetChildren(children + 1, -1);
-  }
-
-  bool _huffmanCodeLengthsToCodes(List<int> codeLengths, int codeLengthsSize,
-                                  List<int> huffCodes) {
-    int symbol;
-    int codeLen;
-    Int32List codeLengthHist =
-        new Int32List(VP8L.MAX_ALLOWED_CODE_LENGTH + 1);
-    int currCode;
-    Int32List nextCodes =
-        new Int32List(VP8L.MAX_ALLOWED_CODE_LENGTH + 1);
-    int maxCodeLength = 0;
-
-    // Calculate max code length.
-    for (symbol = 0; symbol < codeLengthsSize; ++symbol) {
-      if (codeLengths[symbol] > maxCodeLength) {
-        maxCodeLength = codeLengths[symbol];
-      }
-    }
-
-    if (maxCodeLength > VP8L.MAX_ALLOWED_CODE_LENGTH) {
-      return false;
-    }
-
-    // Calculate code length histogram.
-    for (symbol = 0; symbol < codeLengthsSize; ++symbol) {
-      ++codeLengthHist[codeLengths[symbol]];
-    }
-
-    codeLengthHist[0] = 0;
-
-    // Calculate the initial values of 'next_codes' for each code length.
-    // next_codes[code_len] denotes the code to be assigned to the next symbol
-    // of code length 'code_len'.
-    currCode = 0;
-    // Unused, as code length = 0 implies code doesn't exist.
-    nextCodes[0] = -1;
-
-    for (codeLen = 1; codeLen <= maxCodeLength; ++codeLen) {
-      currCode = (currCode + codeLengthHist[codeLen - 1]) << 1;
-      nextCodes[codeLen] = currCode;
-    }
-
-    // Get symbols.
-    for (symbol = 0; symbol < codeLengthsSize; ++symbol) {
-      if (codeLengths[symbol] > 0) {
-        huffCodes[symbol] = nextCodes[codeLengths[symbol]]++;
-      } else {
-        huffCodes[symbol] = -1;
-      }
-    }
-
-    return true;
-  }
-}
-
-/**
- * A group of huffman trees.
- */
-@internal
-class HTreeGroup {
-  final List<HuffmanTree> htrees =
-      new List<HuffmanTree>(VP8L.HUFFMAN_CODES_PER_META_CODE);
-
-  HTreeGroup() {
-    for (int i = 0, len = htrees.length; i < len; ++i) {
-      htrees[i] = new HuffmanTree();
-    }
-  }
-
-  HuffmanTree operator[](int index) {
-    if (htrees[index] == null) {
-      htrees[index] = new HuffmanTree();
-    }
-    return htrees[index];
-  }
-}
+import 'dart:typed_data';

+

+import '../../internal/internal.dart';

+import 'vp8l.dart';

+import 'vp8l_bit_reader.dart';

+

+/**

+ * Huffman Tree.

+ */

+@internal

+class HuffmanTree {

+  static const int HUFF_LUT_BITS = 7;

+  static const int HUFF_LUT = (1 << HUFF_LUT_BITS);

+  // Fast lookup for short bit lengths.

+  Uint8List lutBits = Uint8List(HUFF_LUT);

+  Int16List lutSymbol = Int16List(HUFF_LUT);

+  Int16List lutJump = Int16List(HUFF_LUT);

+

+  /// all the nodes, starting at root, stored as a single int array, where

+  /// each node occupies two ints as [symbol, children].

+  Int32List tree;

+  /// max number of nodes

+  int maxNodes = 0;

+  /// number of currently occupied nodes

+  int numNodes = 0;

+

+  HuffmanTree([int numLeaves = 0]) {

+    _init(numLeaves);

+  }

+

+  bool _init(int numLeaves) {

+    if (numLeaves == 0) {

+      return false;

+    }

+

+    maxNodes = (numLeaves << 1) - 1;

+    tree = Int32List(maxNodes << 1);

+    tree[1] = -1;

+    numNodes = 1;

+    lutBits.fillRange(0, lutBits.length, 255);

+

+    return true;

+  }

+

+  bool buildImplicit(List<int> codeLengths, int codeLengthsSize) {

+    int numSymbols = 0;

+    int rootSymbol = 0;

+

+    // Find out number of symbols and the root symbol.

+    for (int symbol = 0; symbol < codeLengthsSize; ++symbol) {

+      if (codeLengths[symbol] > 0) {

+        // Note: code length = 0 indicates non-existent symbol.

+        ++numSymbols;

+        rootSymbol = symbol;

+      }

+    }

+

+    // Initialize the tree. Will fail for num_symbols = 0

+    if (!_init(numSymbols)) {

+      return false;

+    }

+

+    // Build tree.

+    if (numSymbols == 1) {

+      // Trivial case.

+      final int maxSymbol = codeLengthsSize;

+      if (rootSymbol < 0 || rootSymbol >= maxSymbol) {

+        return false;

+      }

+

+      return _addSymbol(rootSymbol, 0, 0);

+    }

+

+    // Normal case.

+

+    // Get Huffman codes from the code lengths.

+    Int32List codes = Int32List(codeLengthsSize);

+

+    if (!_huffmanCodeLengthsToCodes(codeLengths, codeLengthsSize, codes)) {

+      return false;

+    }

+

+    // Add symbols one-by-one.

+    for (int symbol = 0; symbol < codeLengthsSize; ++symbol) {

+      if (codeLengths[symbol] > 0) {

+        if (!_addSymbol(symbol, codes[symbol], codeLengths[symbol])) {

+          return false;

+        }

+      }

+    }

+

+    return _isFull();

+  }

+

+  bool buildExplicit(List<int> codeLengths,

+                     List<int> codes,

+                     List<int> symbols,

+                     int maxSymbol,

+                     int numSymbols) {

+    // Initialize the tree. Will fail if num_symbols = 0.

+    if (!_init(numSymbols)) {

+      return false;

+    }

+

+    // Add symbols one-by-one.

+    for (int i = 0; i < numSymbols; ++i) {

+      if (codes[i] != -1) {

+        if (symbols[i] < 0 || symbols[i] >= maxSymbol) {

+          return _isFull();

+        }

+

+        if (!_addSymbol(symbols[i], codes[i], codeLengths[i])) {

+          return _isFull();

+        }

+      }

+    }

+

+    return _isFull();

+  }

+

+  /**

+   * Decodes the next Huffman code from bit-stream.

+   * input.fillBitWindow() needs to be called at minimum every second call

+   * to ReadSymbol, in order to pre-fetch enough bits.

+   */

+  int readSymbol(VP8LBitReader br) {

+    int node = 0;

+    int bits = br.prefetchBits();

+    int newBitPos = br.bitPos;

+    // Check if we find the bit combination from the Huffman lookup table.

+    int lut_ix = bits & (HUFF_LUT - 1);

+    int lut_bits = lutBits[lut_ix];

+

+    if (lut_bits <= HUFF_LUT_BITS) {

+      br.bitPos = br.bitPos + lut_bits;

+      return this.lutSymbol[lut_ix];

+    }

+

+    node += this.lutJump[lut_ix];

+    newBitPos += HUFF_LUT_BITS;

+    bits >>= HUFF_LUT_BITS;

+

+    // Decode the value from a binary tree.

+    do {

+      node = _nextNode(node, bits & 1);

+      bits >>= 1;

+      ++newBitPos;

+    } while (_nodeIsNotLeaf(node));

+

+    br.bitPos = newBitPos;

+

+    return _nodeSymbol(node);

+  }

+

+  bool _addSymbol(int symbol, int code, int codeLength) {

+    int step = HUFF_LUT_BITS;

+    int baseCode;

+    int node = 0;

+

+    if (codeLength <= HUFF_LUT_BITS) {

+      baseCode = _reverseBitsShort(code, codeLength);

+      for (int i = 0; i < (1 << (HUFF_LUT_BITS - codeLength)); ++i) {

+        final int idx = baseCode | (i << codeLength);

+        lutSymbol[idx] = symbol;

+        lutBits[idx] = codeLength;

+      }

+    } else {

+      baseCode = _reverseBitsShort((code >> (codeLength - HUFF_LUT_BITS)),

+                                   HUFF_LUT_BITS);

+    }

+

+    while (codeLength-- > 0) {

+      if (node >= maxNodes) {

+        return false;

+      }

+

+      if (_nodeIsEmpty(node)) {

+        if (_isFull()) {

+          // error: too many symbols.

+          return false;

+        }

+

+        _assignChildren(node);

+      } else if (!_nodeIsNotLeaf(node)) {

+        // leaf is already occupied.

+        return false;

+      }

+

+      node += _nodeChildren(node) + ((code >> codeLength) & 1);

+

+      if (--step == 0) {

+        lutJump[baseCode] = node;

+      }

+    }

+

+    if (_nodeIsEmpty(node)) {

+      // turn newly created node into a leaf.

+      _nodeSetChildren(node, 0);

+    } else if (_nodeIsNotLeaf(node)) {

+      // trying to assign a symbol to already used code.

+      return false;

+    }

+

+    // Add symbol in this node.

+    _nodeSetSymbol(node, symbol);

+

+    return true;

+  }

+

+  // Pre-reversed 4-bit values.

+  static const List<int> _REVERSED_BITS = const [

+    0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,

+    0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf];

+

+  int _reverseBitsShort(int bits, int numBits) {

+    int v = (_REVERSED_BITS[bits & 0xf] << 4) | _REVERSED_BITS[bits >> 4];

+    return v >> (8 - numBits);

+  }

+

+  bool _isFull() {

+    return (numNodes == maxNodes);

+  }

+

+  int _nextNode(int node, int rightChild) {

+    return node + _nodeChildren(node) + rightChild;

+  }

+

+  int _nodeSymbol(int node) => tree[(node << 1)];

+

+  void _nodeSetSymbol(int node, int symbol) {

+    tree[(node << 1)] = symbol;

+  }

+

+  int _nodeChildren(int node) => tree[(node << 1) + 1];

+

+  void _nodeSetChildren(int node, int children) {

+    tree[(node << 1) + 1] = children;

+  }

+

+  bool _nodeIsNotLeaf(int node) => tree[(node << 1) + 1] != 0;

+

+  bool _nodeIsEmpty(int node) => tree[(node << 1) + 1] < 0;

+

+  void _assignChildren(int node) {

+    int children = numNodes;

+    _nodeSetChildren(node, children - node);

+

+    numNodes += 2;

+

+    _nodeSetChildren(children, -1);

+    _nodeSetChildren(children + 1, -1);

+  }

+

+  bool _huffmanCodeLengthsToCodes(List<int> codeLengths, int codeLengthsSize,

+                                  List<int> huffCodes) {

+    int symbol;

+    int codeLen;

+    Int32List codeLengthHist =

+        new Int32List(VP8L.MAX_ALLOWED_CODE_LENGTH + 1);

+    int currCode;

+    Int32List nextCodes =

+        new Int32List(VP8L.MAX_ALLOWED_CODE_LENGTH + 1);

+    int maxCodeLength = 0;

+

+    // Calculate max code length.

+    for (symbol = 0; symbol < codeLengthsSize; ++symbol) {

+      if (codeLengths[symbol] > maxCodeLength) {

+        maxCodeLength = codeLengths[symbol];

+      }

+    }

+

+    if (maxCodeLength > VP8L.MAX_ALLOWED_CODE_LENGTH) {

+      return false;

+    }

+

+    // Calculate code length histogram.

+    for (symbol = 0; symbol < codeLengthsSize; ++symbol) {

+      ++codeLengthHist[codeLengths[symbol]];

+    }

+

+    codeLengthHist[0] = 0;

+

+    // Calculate the initial values of 'next_codes' for each code length.

+    // next_codes[code_len] denotes the code to be assigned to the next symbol

+    // of code length 'code_len'.

+    currCode = 0;

+    // Unused, as code length = 0 implies code doesn't exist.

+    nextCodes[0] = -1;

+

+    for (codeLen = 1; codeLen <= maxCodeLength; ++codeLen) {

+      currCode = (currCode + codeLengthHist[codeLen - 1]) << 1;

+      nextCodes[codeLen] = currCode;

+    }

+

+    // Get symbols.

+    for (symbol = 0; symbol < codeLengthsSize; ++symbol) {

+      if (codeLengths[symbol] > 0) {

+        huffCodes[symbol] = nextCodes[codeLengths[symbol]]++;

+      } else {

+        huffCodes[symbol] = -1;

+      }

+    }

+

+    return true;

+  }

+}

+

+/**

+ * A group of huffman trees.

+ */

+@internal

+class HTreeGroup {

+  final List<HuffmanTree> htrees =

+      new List<HuffmanTree>(VP8L.HUFFMAN_CODES_PER_META_CODE);

+

+  HTreeGroup() {

+    for (int i = 0, len = htrees.length; i < len; ++i) {

+      htrees[i] = HuffmanTree();

+    }

+  }

+

+  HuffmanTree operator[](int index) {

+    if (htrees[index] == null) {

+      htrees[index] = HuffmanTree();

+    }

+    return htrees[index];

+  }

+}

diff --git a/image/lib/src/formats/webp/webp_info.dart b/image/lib/src/formats/webp/webp_info.dart
old mode 100644
new mode 100755
index 866c92b..f8b9305
--- a/image/lib/src/formats/webp/webp_info.dart
+++ b/image/lib/src/formats/webp/webp_info.dart
@@ -1,63 +1,63 @@
-import '../../internal/internal.dart';
-import '../../util/input_buffer.dart';
-import '../decode_info.dart';
-import 'webp_frame.dart';
-
-/**
- * Features gathered from the bitstream
- */
-class WebPInfo extends DecodeInfo {
-  // enum Format
-  static const int FORMAT_UNDEFINED = 0;
-  static const int FORMAT_LOSSY = 1;
-  static const int FORMAT_LOSSLESS = 2;
-  static const int FORMAT_ANIMATED = 3;
-
-  /// True if the bitstream contains an alpha channel.
-  bool hasAlpha = false;
-  /// True if the bitstream is an animation.
-  bool hasAnimation = false;
-  /// 0 = undefined (/mixed), 1 = lossy, 2 = lossless, 3 = animated
-  int format = FORMAT_UNDEFINED;
-  /// ICCP data string.
-  String iccp = '';
-  /// EXIF data string.
-  String exif = '';
-  /// XMP data string.
-  String xmp = '';
-  /// How many times the animation should loop.
-  int animLoopCount = 0;
-  /// Information about each animation frame.
-  List<WebPFrame> frames = [];
-
-  int get numFrames => frames.length;
-
-  int _frame;
-  int _numFrames;
-
-  InputBuffer _alphaData;
-  int _alphaSize;
-  int _vp8Position;
-  int _vp8Size;
-}
-
-@internal
-class InternalWebPInfo extends WebPInfo {
-  int get frame => _frame;
-  set frame(int value) => _frame = value;
-
-  int get numFrames => _numFrames;
-  set numFrames(int value) => _numFrames = value;
-
-  InputBuffer get alphaData => _alphaData;
-  set alphaData(InputBuffer buffer) => _alphaData = buffer;
-
-  int get alphaSize => _alphaSize;
-  set alphaSize(int value) => _alphaSize = value;
-
-  int get vp8Position => _vp8Position;
-  set vp8Position(int value) => _vp8Position = value;
-
-  int get vp8Size => _vp8Size;
-  set vp8Size(int value) => _vp8Size = value;
-}
+import '../../internal/internal.dart';

+import '../../util/input_buffer.dart';

+import '../decode_info.dart';

+import 'webp_frame.dart';

+

+/**

+ * Features gathered from the bitstream

+ */

+class WebPInfo extends DecodeInfo {

+  // enum Format

+  static const int FORMAT_UNDEFINED = 0;

+  static const int FORMAT_LOSSY = 1;

+  static const int FORMAT_LOSSLESS = 2;

+  static const int FORMAT_ANIMATED = 3;

+

+  /// True if the bitstream contains an alpha channel.

+  bool hasAlpha = false;

+  /// True if the bitstream is an animation.

+  bool hasAnimation = false;

+  /// 0 = undefined (/mixed), 1 = lossy, 2 = lossless, 3 = animated

+  int format = FORMAT_UNDEFINED;

+  /// ICCP data string.

+  String iccp = '';

+  /// EXIF data string.

+  String exif = '';

+  /// XMP data string.

+  String xmp = '';

+  /// How many times the animation should loop.

+  int animLoopCount = 0;

+  /// Information about each animation frame.

+  List<WebPFrame> frames = [];

+

+  int get numFrames => frames.length;

+

+  int _frame;

+  int _numFrames;

+

+  InputBuffer _alphaData;

+  int _alphaSize;

+  int _vp8Position;

+  int _vp8Size;

+}

+

+@internal

+class InternalWebPInfo extends WebPInfo {

+  int get frame => _frame;

+  set frame(int value) => _frame = value;

+

+  int get numFrames => _numFrames;

+  set numFrames(int value) => _numFrames = value;

+

+  InputBuffer get alphaData => _alphaData;

+  set alphaData(InputBuffer buffer) => _alphaData = buffer;

+

+  int get alphaSize => _alphaSize;

+  set alphaSize(int value) => _alphaSize = value;

+

+  int get vp8Position => _vp8Position;

+  set vp8Position(int value) => _vp8Position = value;

+

+  int get vp8Size => _vp8Size;

+  set vp8Size(int value) => _vp8Size = value;

+}

diff --git a/image/lib/src/formats/webp_decoder.dart b/image/lib/src/formats/webp_decoder.dart
old mode 100644
new mode 100755
index 638396e..672928c
--- a/image/lib/src/formats/webp_decoder.dart
+++ b/image/lib/src/formats/webp_decoder.dart
@@ -1,365 +1,365 @@
-import '../animation.dart';
-import '../color.dart';
-import '../image.dart';
-import '../transform/copy_into.dart';
-import '../util/input_buffer.dart';
-import 'decoder.dart';
-import 'webp/vp8.dart';
-import 'webp/vp8l.dart';
-import 'webp/webp_frame.dart';
-import 'webp/webp_info.dart';
-
-/**
- * Decode a WebP formatted image. This supports lossless (vp8l), lossy (vp8),
- * lossy+alpha, and animated WebP images.
- */
-class WebPDecoder extends Decoder {
-  InternalWebPInfo _info;
-
-  WebPDecoder([List<int> bytes]) {
-    if (bytes != null) {
-      startDecode(bytes);
-    }
-  }
-
-  WebPInfo get info => _info;
-
-  /**
-   * Is the given file a valid WebP image?
-   */
-  bool isValidFile(List<int> bytes) {
-    _input = new InputBuffer(bytes);
-    if (!_getHeader(_input)) {
-      return false;
-    }
-    return true;
-  }
-
-  /**
-   * How many frames are available to decode?
-   *
-   * You should have prepared the decoder by either passing the file bytes
-   * to the constructor, or calling getInfo.
-   */
-  int numFrames() => (_info != null) ? _info.numFrames : 0;
-
-  /**
-   * Validate the file is a WebP image and get information about it.
-   * If the file is not a valid WebP image, null is returned.
-   */
-  WebPInfo startDecode(List<int> bytes) {
-    _input = new InputBuffer(bytes);
-
-    if (!_getHeader(_input)) {
-      return null;
-    }
-
-    _info = new InternalWebPInfo();
-    if (!_getInfo(_input, _info)) {
-      return null;
-    }
-
-    switch (_info.format) {
-      case WebPInfo.FORMAT_ANIMATED:
-        return _info;
-      case WebPInfo.FORMAT_LOSSLESS:
-        _input.offset = _info.vp8Position;
-        VP8L vp8l = new VP8L(_input, _info);
-        if (!vp8l.decodeHeader()) {
-          return null;
-        }
-        return _info;
-      case WebPInfo.FORMAT_LOSSY:
-        _input.offset = _info.vp8Position;
-        VP8 vp8 = new VP8(_input, _info);
-        if (!vp8.decodeHeader()) {
-          return null;
-        }
-        return _info;
-    }
-
-    return null;
-  }
-
-  Image decodeFrame(int frame) {
-    if (_input == null || _info == null) {
-      return null;
-    }
-
-    if (_info.hasAnimation) {
-      if (frame >= _info.frames.length || frame < 0) {
-        return null;
-      }
-
-      InternalWebPFrame f = _info.frames[frame];
-      InputBuffer frameData = _input.subset(f.frameSize,
-                                            position: f.framePosition);
-
-      return _decodeFrame(frameData, frame: frame);
-    }
-
-    if (_info.format == WebPInfo.FORMAT_LOSSLESS) {
-      InputBuffer data = _input.subset(_info.vp8Size,
-                                       position: _info.vp8Position);
-      return new VP8L(data, _info).decode();
-    } else if (_info.format == WebPInfo.FORMAT_LOSSY) {
-      InputBuffer data = _input.subset(_info.vp8Size,
-                                       position: _info.vp8Position);
-      return new VP8(data, _info).decode();
-    }
-
-    return null;
-  }
-
-  /**
-   * Decode a WebP formatted file stored in [bytes] into an Image.
-   * If it's not a valid webp file, null is returned.
-   * If the webp file stores animated frames, only the first image will
-   * be returned.  Use [decodeAnimation] to decode the full animation.
-   */
-  Image decodeImage(List<int> bytes, {int frame: 0}) {
-    startDecode(bytes);
-    _info.frame = 0;
-    _info.numFrames = 1;
-    return decodeFrame(frame);
-  }
-
-  /**
-   * Decode all of the frames of an animated webp. For single image webps,
-   * this will return an animation with a single frame.
-   */
-Animation decodeAnimation(List<int> bytes) {
-    if (startDecode(bytes) == null) {
-      return null;
-    }
-
-    _info.numFrames = _info.numFrames;
-
-    Animation anim = new Animation();
-    anim.width = _info.width;
-    anim.height = _info.height;
-    anim.loopCount = _info.animLoopCount;
-
-    if (_info.hasAnimation) {
-      Image lastImage = new Image(_info.width, _info.height);
-      for (int i = 0; i < _info.numFrames; ++i) {
-        _info.frame = i;
-        if (lastImage == null) {
-          lastImage = new Image(_info.width, _info.height);
-        } else {
-          lastImage = new Image.from(lastImage);
-        }
-
-        WebPFrame frame = _info.frames[i];
-        Image image = decodeFrame(i);
-        if (image == null) {
-          return null;
-        }
-
-        if (lastImage != null) {
-          if (frame.clearFrame) {
-            lastImage.fill(_info.backgroundColor);
-          }
-          copyInto(lastImage, image, dstX: frame.x, dstY: frame.y);
-        } else {
-          lastImage = image;
-        }
-
-        lastImage.duration = frame.duration;
-        anim.addFrame(lastImage);
-      }
-    } else {
-      Image image = decodeImage(bytes);
-      if (image == null) {
-        return null;
-      }
-
-      anim.addFrame(image);
-    }
-
-    return anim;
-  }
-
-
-  Image _decodeFrame(InputBuffer input, {int frame: 0}) {
-    InternalWebPInfo webp = new InternalWebPInfo();
-    if (!_getInfo(input, webp)) {
-      return null;
-    }
-
-    if (webp.format == 0) {
-      return null;
-    }
-
-    webp.frame = _info.frame;
-    webp.numFrames = _info.numFrames;
-
-    if (webp.hasAnimation) {
-      if (frame >= webp.frames.length || frame < 0) {
-        return null;
-      }
-      InternalWebPFrame f = webp.frames[frame];
-      InputBuffer frameData = input.subset(f.frameSize,
-                                           position: f.framePosition);
-
-      return _decodeFrame(frameData, frame: frame);
-    } else {
-      InputBuffer data = input.subset(webp.vp8Size,
-                                      position: webp.vp8Position);
-      if (webp.format == WebPInfo.FORMAT_LOSSLESS) {
-        return new VP8L(data, webp).decode();
-      } else if (webp.format == WebPInfo.FORMAT_LOSSY) {
-        return new VP8(data, webp).decode();
-      }
-    }
-
-    return null;
-  }
-
-  bool _getHeader(InputBuffer input) {
-    // Validate the webp format header
-    String tag = input.readString(4);
-    if (tag != 'RIFF') {
-      return false;
-    }
-
-    /*int fileSize =*/ input.readUint32();
-
-    tag = input.readString(4);
-    if (tag != 'WEBP') {
-      return false;
-    }
-
-    return true;
-  }
-
-  bool _getInfo(InputBuffer input, InternalWebPInfo webp) {
-    bool found = false;
-    while (!input.isEOS && !found) {
-      String tag = input.readString(4);
-      int size = input.readUint32();
-      // For odd sized chunks, there's a 1 byte padding at the end.
-      int diskSize = ((size + 1) >> 1) << 1;
-      int p = input.position;
-
-      switch (tag) {
-        case 'VP8X':
-          if (!_getVp8xInfo(input, webp)) {
-            return false;
-          }
-          break;
-        case 'VP8 ':
-          webp.vp8Position = input.position;
-          webp.vp8Size = size;
-          webp.format = WebPInfo.FORMAT_LOSSY;
-          found = true;
-          break;
-        case 'VP8L':
-          webp.vp8Position = input.position;
-          webp.vp8Size = size;
-          webp.format = WebPInfo.FORMAT_LOSSLESS;
-          found = true;
-          break;
-        case 'ALPH':
-          webp.alphaData = new InputBuffer(input.buffer,
-                                           bigEndian: input.bigEndian);
-          webp.alphaData.offset = input.offset;
-          webp.alphaSize = size;
-          input.skip(diskSize);
-          break;
-        case 'ANIM':
-          webp.format = WebPInfo.FORMAT_ANIMATED;
-          if (!_getAnimInfo(input, webp)) {
-            return false;
-          }
-          break;
-        case 'ANMF':
-          if (!_getAnimFrameInfo(input, webp, size)) {
-            return false;
-          }
-          break;
-        case 'ICCP':
-          webp.iccp = input.readString(size);
-          break;
-        case 'EXIF':
-          webp.exif = input.readString(size);
-          break;
-        case 'XMP ':
-          webp.xmp = input.readString(size);
-          break;
-        default:
-          print('UNKNOWN WEBP TAG: $tag');
-          input.skip(diskSize);
-          break;
-      }
-
-      int remainder = diskSize - (input.position - p);
-      if (remainder > 0) {
-        input.skip(remainder);
-      }
-    }
-
-    /**
-     * The alpha flag might not have been set, but it does in fact have alpha
-     * if there is an ALPH chunk.
-     */
-    if (!webp.hasAlpha) {
-      webp.hasAlpha = webp.alphaData != null;
-    }
-
-    return webp.format != 0;
-  }
-
-  bool _getVp8xInfo(InputBuffer input, WebPInfo webp) {
-    int b = input.readByte();
-    if ((b & 0xc0) != 0) {
-      return false;
-    }
-    //int icc = (b >> 5) & 0x1;
-    int alpha = (b >> 4) & 0x1;
-    //int exif = (b >> 3) & 0x1;
-    //int xmp = (b >> 2) & 0x1;
-    int a = (b >> 1) & 0x1;
-
-    if (b & 0x1 != 0) {
-      return false;
-    }
-
-    if (input.readUint24() != 0) {
-      return false;
-    }
-    int w = input.readUint24() + 1;
-    int h = input.readUint24() + 1;
-
-    webp.width = w;
-    webp.height = h;
-    webp.hasAnimation = a != 0;
-    webp.hasAlpha = alpha != 0;
-
-    return true;
-  }
-
-  bool _getAnimInfo(InputBuffer input, WebPInfo webp) {
-    int c = input.readUint32();
-    webp.animLoopCount = input.readUint16();
-
-    // Color is stored in blue,green,red,alpha order.
-    int a = getRed(c);
-    int r = getGreen(c);
-    int g = getBlue(c);
-    int b = getAlpha(c);
-    webp.backgroundColor = getColor(r, g, b, a);
-    return true;
-  }
-
-  bool _getAnimFrameInfo(InputBuffer input, WebPInfo webp, int size) {
-    InternalWebPFrame frame = new InternalWebPFrame(input, size);
-    if (!frame.isValid) {
-      return false;
-    }
-    webp.frames.add(frame);
-    return true;
-  }
-
-  InputBuffer _input;
-}
+import '../animation.dart';

+import '../color.dart';

+import '../image.dart';

+import '../transform/copy_into.dart';

+import '../util/input_buffer.dart';

+import 'decoder.dart';

+import 'webp/vp8.dart';

+import 'webp/vp8l.dart';

+import 'webp/webp_frame.dart';

+import 'webp/webp_info.dart';

+

+/**

+ * Decode a WebP formatted image. This supports lossless (vp8l), lossy (vp8),

+ * lossy+alpha, and animated WebP images.

+ */

+class WebPDecoder extends Decoder {

+  InternalWebPInfo _info;

+

+  WebPDecoder([List<int> bytes]) {

+    if (bytes != null) {

+      startDecode(bytes);

+    }

+  }

+

+  WebPInfo get info => _info;

+

+  /**

+   * Is the given file a valid WebP image?

+   */

+  bool isValidFile(List<int> bytes) {

+    _input = InputBuffer(bytes);

+    if (!_getHeader(_input)) {

+      return false;

+    }

+    return true;

+  }

+

+  /**

+   * How many frames are available to decode?

+   *

+   * You should have prepared the decoder by either passing the file bytes

+   * to the constructor, or calling getInfo.

+   */

+  int numFrames() => (_info != null) ? _info.numFrames : 0;

+

+  /**

+   * Validate the file is a WebP image and get information about it.

+   * If the file is not a valid WebP image, null is returned.

+   */

+  WebPInfo startDecode(List<int> bytes) {

+    _input = InputBuffer(bytes);

+

+    if (!_getHeader(_input)) {

+      return null;

+    }

+

+    _info = InternalWebPInfo();

+    if (!_getInfo(_input, _info)) {

+      return null;

+    }

+

+    switch (_info.format) {

+      case WebPInfo.FORMAT_ANIMATED:

+        return _info;

+      case WebPInfo.FORMAT_LOSSLESS:

+        _input.offset = _info.vp8Position;

+        VP8L vp8l = VP8L(_input, _info);

+        if (!vp8l.decodeHeader()) {

+          return null;

+        }

+        return _info;

+      case WebPInfo.FORMAT_LOSSY:

+        _input.offset = _info.vp8Position;

+        VP8 vp8 = VP8(_input, _info);

+        if (!vp8.decodeHeader()) {

+          return null;

+        }

+        return _info;

+    }

+

+    return null;

+  }

+

+  Image decodeFrame(int frame) {

+    if (_input == null || _info == null) {

+      return null;

+    }

+

+    if (_info.hasAnimation) {

+      if (frame >= _info.frames.length || frame < 0) {

+        return null;

+      }

+

+      InternalWebPFrame f = _info.frames[frame];

+      InputBuffer frameData = _input.subset(f.frameSize,

+                                            position: f.framePosition);

+

+      return _decodeFrame(frameData, frame: frame);

+    }

+

+    if (_info.format == WebPInfo.FORMAT_LOSSLESS) {

+      InputBuffer data = _input.subset(_info.vp8Size,

+                                       position: _info.vp8Position);

+      return new VP8L(data, _info).decode();

+    } else if (_info.format == WebPInfo.FORMAT_LOSSY) {

+      InputBuffer data = _input.subset(_info.vp8Size,

+                                       position: _info.vp8Position);

+      return new VP8(data, _info).decode();

+    }

+

+    return null;

+  }

+

+  /**

+   * Decode a WebP formatted file stored in [bytes] into an Image.

+   * If it's not a valid webp file, null is returned.

+   * If the webp file stores animated frames, only the first image will

+   * be returned.  Use [decodeAnimation] to decode the full animation.

+   */

+  Image decodeImage(List<int> bytes, {int frame: 0}) {

+    startDecode(bytes);

+    _info.frame = 0;

+    _info.numFrames = 1;

+    return decodeFrame(frame);

+  }

+

+  /**

+   * Decode all of the frames of an animated webp. For single image webps,

+   * this will return an animation with a single frame.

+   */

+Animation decodeAnimation(List<int> bytes) {

+    if (startDecode(bytes) == null) {

+      return null;

+    }

+

+    _info.numFrames = _info.numFrames;

+

+    Animation anim = Animation();

+    anim.width = _info.width;

+    anim.height = _info.height;

+    anim.loopCount = _info.animLoopCount;

+

+    if (_info.hasAnimation) {

+      Image lastImage = Image(_info.width, _info.height);

+      for (int i = 0; i < _info.numFrames; ++i) {

+        _info.frame = i;

+        if (lastImage == null) {

+          lastImage = Image(_info.width, _info.height);

+        } else {

+          lastImage = Image.from(lastImage);

+        }

+

+        WebPFrame frame = _info.frames[i];

+        Image image = decodeFrame(i);

+        if (image == null) {

+          return null;

+        }

+

+        if (lastImage != null) {

+          if (frame.clearFrame) {

+            lastImage.fill(_info.backgroundColor);

+          }

+          copyInto(lastImage, image, dstX: frame.x, dstY: frame.y);

+        } else {

+          lastImage = image;

+        }

+

+        lastImage.duration = frame.duration;

+        anim.addFrame(lastImage);

+      }

+    } else {

+      Image image = decodeImage(bytes);

+      if (image == null) {

+        return null;

+      }

+

+      anim.addFrame(image);

+    }

+

+    return anim;

+  }

+

+

+  Image _decodeFrame(InputBuffer input, {int frame: 0}) {

+    InternalWebPInfo webp = InternalWebPInfo();

+    if (!_getInfo(input, webp)) {

+      return null;

+    }

+

+    if (webp.format == 0) {

+      return null;

+    }

+

+    webp.frame = _info.frame;

+    webp.numFrames = _info.numFrames;

+

+    if (webp.hasAnimation) {

+      if (frame >= webp.frames.length || frame < 0) {

+        return null;

+      }

+      InternalWebPFrame f = webp.frames[frame];

+      InputBuffer frameData = input.subset(f.frameSize,

+                                           position: f.framePosition);

+

+      return _decodeFrame(frameData, frame: frame);

+    } else {

+      InputBuffer data = input.subset(webp.vp8Size,

+                                      position: webp.vp8Position);

+      if (webp.format == WebPInfo.FORMAT_LOSSLESS) {

+        return new VP8L(data, webp).decode();

+      } else if (webp.format == WebPInfo.FORMAT_LOSSY) {

+        return new VP8(data, webp).decode();

+      }

+    }

+

+    return null;

+  }

+

+  bool _getHeader(InputBuffer input) {

+    // Validate the webp format header

+    String tag = input.readString(4);

+    if (tag != 'RIFF') {

+      return false;

+    }

+

+    /*int fileSize =*/ input.readUint32();

+

+    tag = input.readString(4);

+    if (tag != 'WEBP') {

+      return false;

+    }

+

+    return true;

+  }

+

+  bool _getInfo(InputBuffer input, InternalWebPInfo webp) {

+    bool found = false;

+    while (!input.isEOS && !found) {

+      String tag = input.readString(4);

+      int size = input.readUint32();

+      // For odd sized chunks, there's a 1 byte padding at the end.

+      int diskSize = ((size + 1) >> 1) << 1;

+      int p = input.position;

+

+      switch (tag) {

+        case 'VP8X':

+          if (!_getVp8xInfo(input, webp)) {

+            return false;

+          }

+          break;

+        case 'VP8 ':

+          webp.vp8Position = input.position;

+          webp.vp8Size = size;

+          webp.format = WebPInfo.FORMAT_LOSSY;

+          found = true;

+          break;

+        case 'VP8L':

+          webp.vp8Position = input.position;

+          webp.vp8Size = size;

+          webp.format = WebPInfo.FORMAT_LOSSLESS;

+          found = true;

+          break;

+        case 'ALPH':

+          webp.alphaData = InputBuffer(input.buffer,

+                                           bigEndian: input.bigEndian);

+          webp.alphaData.offset = input.offset;

+          webp.alphaSize = size;

+          input.skip(diskSize);

+          break;

+        case 'ANIM':

+          webp.format = WebPInfo.FORMAT_ANIMATED;

+          if (!_getAnimInfo(input, webp)) {

+            return false;

+          }

+          break;

+        case 'ANMF':

+          if (!_getAnimFrameInfo(input, webp, size)) {

+            return false;

+          }

+          break;

+        case 'ICCP':

+          webp.iccp = input.readString(size);

+          break;

+        case 'EXIF':

+          webp.exif = input.readString(size);

+          break;

+        case 'XMP ':

+          webp.xmp = input.readString(size);

+          break;

+        default:

+          print('UNKNOWN WEBP TAG: $tag');

+          input.skip(diskSize);

+          break;

+      }

+

+      int remainder = diskSize - (input.position - p);

+      if (remainder > 0) {

+        input.skip(remainder);

+      }

+    }

+

+    /**

+     * The alpha flag might not have been set, but it does in fact have alpha

+     * if there is an ALPH chunk.

+     */

+    if (!webp.hasAlpha) {

+      webp.hasAlpha = webp.alphaData != null;

+    }

+

+    return webp.format != 0;

+  }

+

+  bool _getVp8xInfo(InputBuffer input, WebPInfo webp) {

+    int b = input.readByte();

+    if ((b & 0xc0) != 0) {

+      return false;

+    }

+    //int icc = (b >> 5) & 0x1;

+    int alpha = (b >> 4) & 0x1;

+    //int exif = (b >> 3) & 0x1;

+    //int xmp = (b >> 2) & 0x1;

+    int a = (b >> 1) & 0x1;

+

+    if (b & 0x1 != 0) {

+      return false;

+    }

+

+    if (input.readUint24() != 0) {

+      return false;

+    }

+    int w = input.readUint24() + 1;

+    int h = input.readUint24() + 1;

+

+    webp.width = w;

+    webp.height = h;

+    webp.hasAnimation = a != 0;

+    webp.hasAlpha = alpha != 0;

+

+    return true;

+  }

+

+  bool _getAnimInfo(InputBuffer input, WebPInfo webp) {

+    int c = input.readUint32();

+    webp.animLoopCount = input.readUint16();

+

+    // Color is stored in blue,green,red,alpha order.

+    int a = getRed(c);

+    int r = getGreen(c);

+    int g = getBlue(c);

+    int b = getAlpha(c);

+    webp.backgroundColor = getColor(r, g, b, a);

+    return true;

+  }

+

+  bool _getAnimFrameInfo(InputBuffer input, WebPInfo webp, int size) {

+    InternalWebPFrame frame = InternalWebPFrame(input, size);

+    if (!frame.isValid) {

+      return false;

+    }

+    webp.frames.add(frame);

+    return true;

+  }

+

+  InputBuffer _input;

+}

diff --git a/image/lib/src/formats/webp_encoder.dart b/image/lib/src/formats/webp_encoder.dart
old mode 100644
new mode 100755
index 1d246a0..5f4f8af
--- a/image/lib/src/formats/webp_encoder.dart
+++ b/image/lib/src/formats/webp_encoder.dart
@@ -1,126 +1,126 @@
-import 'dart:typed_data';
-
-import '../animation.dart';
-import '../image.dart';
-import '../util/output_buffer.dart';
-import 'encoder.dart';
-
-/**
- * Encode an image to the PNG format.
- */
-class WebPEncoder extends Encoder {
-  static const int LOSSLESS = 0;
-  static const int LOSSY = 1;
-
-  int format;
-  num quality;
-
-  /**
-   * [format] can be [LOSSY] or [LOSSLESS].
-   * [quality] is controls lossy compression, in the range
-   * 0 (smallest file) and 100 (biggest).
-   */
-  WebPEncoder({this.format: LOSSY,
-               this.quality: 100});
-
-  /**
-   * Add a frame to be encoded. Call [finish] to encode the added frames.
-   * If only one frame is added, a single-image WebP is encoded; otherwise
-   * if there are more than one frame, a multi-frame animated WebP is encoded.
-   */
-  void addFrame(Image image, {int duration}) {
-    if (output == null) {
-      output = new OutputBuffer();
-
-      if (duration != null) {
-        this.delay = duration;
-      }
-      _lastImage = _encodeImage(image);
-      _width = image.width;
-      _height = image.height;
-      return;
-    }
-
-    if (_encodedFrames == 0) {
-      _writeHeader(_width, _height);
-    }
-
-    _addImage(_lastImage, _width, _height);
-    _encodedFrames++;
-
-    if (duration != null) {
-      this.delay = duration;
-    }
-
-    _lastImage = _encodeImage(image);
-  }
-
-  /**
-   * Encode the images that were added with [addFrame].
-   */
-  List<int> finish() {
-    List<int> bytes;
-    if (output == null) {
-      return bytes;
-    }
-
-    /*if (_encodedFrames == 0) {
-      _writeHeader(_width, _height);
-    } else {
-      _writeGraphicsCtrlExt();
-    }
-
-    _addImage(_lastImage, _width, _height, _lastColorMap.colorMap, 256);
-
-    output.writeByte(TERMINATE_RECORD_TYPE);
-
-    _lastImage = null;
-    _encodedFrames = 0;*/
-
-    bytes = output.getBytes();
-    output = null;
-
-    return bytes;
-  }
-
-  /**
-   * Encode a single frame image.
-   */
-  List<int> encodeImage(Image image) {
-    addFrame(image);
-    return finish();
-  }
-
-  /**
-   * Does this encoder support animation?
-   */
-  bool get supportsAnimation => true;
-
-  /**
-   * Encode an animation.
-   */
-  List<int> encodeAnimation(Animation anim) {
-    for (Image f in anim) {
-      addFrame(f, duration: f.duration);
-    }
-    return finish();
-  }
-
-  Uint8List _encodeImage(Image image) {
-    return null;
-  }
-
-  void _writeHeader(int width, int height) {
-
-  }
-
-  void _addImage(Uint8List image, int width, int height) {
-  }
-
-  OutputBuffer output;
-  int delay;
-  Uint8List _lastImage;
-  int _width;
-  int _height;
-  int _encodedFrames = 0;
-}
+import 'dart:typed_data';

+

+import '../animation.dart';

+import '../image.dart';

+import '../util/output_buffer.dart';

+import 'encoder.dart';

+

+/**

+ * Encode an image to the PNG format.

+ */

+class WebPEncoder extends Encoder {

+  static const int LOSSLESS = 0;

+  static const int LOSSY = 1;

+

+  int format;

+  num quality;

+

+  /**

+   * [format] can be [LOSSY] or [LOSSLESS].

+   * [quality] is controls lossy compression, in the range

+   * 0 (smallest file) and 100 (biggest).

+   */

+  WebPEncoder({this.format: LOSSY,

+               this.quality: 100});

+

+  /**

+   * Add a frame to be encoded. Call [finish] to encode the added frames.

+   * If only one frame is added, a single-image WebP is encoded; otherwise

+   * if there are more than one frame, a multi-frame animated WebP is encoded.

+   */

+  void addFrame(Image image, {int duration}) {

+    if (output == null) {

+      output = OutputBuffer();

+

+      if (duration != null) {

+        this.delay = duration;

+      }

+      _lastImage = _encodeImage(image);

+      _width = image.width;

+      _height = image.height;

+      return;

+    }

+

+    if (_encodedFrames == 0) {

+      _writeHeader(_width, _height);

+    }

+

+    _addImage(_lastImage, _width, _height);

+    _encodedFrames++;

+

+    if (duration != null) {

+      this.delay = duration;

+    }

+

+    _lastImage = _encodeImage(image);

+  }

+

+  /**

+   * Encode the images that were added with [addFrame].

+   */

+  List<int> finish() {

+    List<int> bytes;

+    if (output == null) {

+      return bytes;

+    }

+

+    /*if (_encodedFrames == 0) {

+      _writeHeader(_width, _height);

+    } else {

+      _writeGraphicsCtrlExt();

+    }

+

+    _addImage(_lastImage, _width, _height, _lastColorMap.colorMap, 256);

+

+    output.writeByte(TERMINATE_RECORD_TYPE);

+

+    _lastImage = null;

+    _encodedFrames = 0;*/

+

+    bytes = output.getBytes();

+    output = null;

+

+    return bytes;

+  }

+

+  /**

+   * Encode a single frame image.

+   */

+  List<int> encodeImage(Image image) {

+    addFrame(image);

+    return finish();

+  }

+

+  /**

+   * Does this encoder support animation?

+   */

+  bool get supportsAnimation => true;

+

+  /**

+   * Encode an animation.

+   */

+  List<int> encodeAnimation(Animation anim) {

+    for (Image f in anim) {

+      addFrame(f, duration: f.duration);

+    }

+    return finish();

+  }

+

+  Uint8List _encodeImage(Image image) {

+    return null;

+  }

+

+  void _writeHeader(int width, int height) {

+

+  }

+

+  void _addImage(Uint8List image, int width, int height) {

+  }

+

+  OutputBuffer output;

+  int delay;

+  Uint8List _lastImage;

+  int _width;

+  int _height;

+  int _encodedFrames = 0;

+}

diff --git a/image/lib/src/hdr/half.dart b/image/lib/src/hdr/half.dart
old mode 100644
new mode 100755
index dfe879e..36b7b85
--- a/image/lib/src/hdr/half.dart
+++ b/image/lib/src/hdr/half.dart
@@ -1,384 +1,384 @@
-import 'dart:typed_data';
-
-import '../internal/bit_operators.dart';
-
-/**
- * A 16-bit floating-point number, used by high-dynamic-range image formats
- * as a more efficient storage for floating-point values that don't require
- * full 32-bit precision. A list of Half floats can be stored in a [Uint16List],
- * and converted to a double using the [HalfToDouble] static method.
- *
- * This class is derived from the OpenEXR library.
- */
-class Half {
-  Half([num f]) {
-    if (f != null) {
-      _h = DoubleToHalf(f);
-    }
-  }
-
-  Half.fromBits(int bits) :
-    _h = bits {
-    if (_toFloatFloat32 == null) {
-      _initialize();
-    }
-  }
-
-  static double HalfToDouble(int bits) {
-    if (_toFloatFloat32 == null) {
-      _initialize();
-    }
-    return _toFloatFloat32[bits];
-  }
-
-  static int DoubleToHalf(num f) {
-    if (_toFloatFloat32 == null) {
-      _initialize();
-    }
-
-    f = f.toDouble();
-    int x_i = float32ToUint32(f);
-    if (f == 0.0) {
-      // Common special case - zero.
-      // Preserve the zero's sign bit.
-      return x_i >> 16;
-    }
-
-    // We extract the combined sign and exponent, e, from our
-    // floating-point number, f.  Then we convert e to the sign
-    // and exponent of the half number via a table lookup.
-    //
-    // For the most common case, where a normalized half is produced,
-    // the table lookup returns a non-zero value; in this case, all
-    // we have to do is round f's significand to 10 bits and combine
-    // the result with e.
-    //
-    // For all other cases (overflow, zeroes, denormalized numbers
-    // resulting from underflow, infinities and NANs), the table
-    // lookup returns zero, and we call a longer, non-inline function
-    // to do the float-to-half conversion.
-    int e = (x_i >> 23) & 0x000001ff;
-
-    e = _eLut[e];
-
-    if (e != 0) {
-      // Simple case - round the significand, m, to 10
-      // bits and combine it with the sign and exponent.
-      int m = x_i & 0x007fffff;
-      return e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13);
-    }
-
-    // Difficult case - call a function.
-    return _convert(x_i);
-  }
-
-  double toDouble() => _toFloatFloat32[_h];
-
-  /**
-   * Unary minus
-   */
-  Half operator-() => new Half.fromBits(_h ^ 0x8000);
-
-  /**
-   * Addition operator for Half or num left operands.
-   */
-  Half operator+(f) {
-    return new Half(toDouble() + f.toDouble());
-  }
-
-  /**
-   * Subtraction operator for Half or num left operands.
-   */
-  Half operator-(f) {
-    return new Half(toDouble() - f.toDouble());
-  }
-
-  Half operator*(f) {
-    return new Half(toDouble() * f.toDouble());
-  }
-
-  Half operator/(f) {
-    return new Half(toDouble() / f.toDouble());
-  }
-
-  /**
-   * Round to n-bit precision (n should be between 0 and 10).
-   * After rounding, the significand's 10-n least significant
-   * bits will be zero.
-   */
-  Half round(int n) {
-    if (n >= 10) {
-      return this;
-    }
-
-    // Disassemble h into the sign, s,
-    // and the combined exponent and significand, e.
-    int s = _h & 0x8000;
-    int e = _h & 0x7fff;
-
-    // Round the exponent and significand to the nearest value
-    // where ones occur only in the (10-n) most significant bits.
-    // Note that the exponent adjusts automatically if rounding
-    // up causes the significand to overflow.
-
-    e >>= 9 - n;
-    e  += e & 1;
-    e <<= 9 - n;
-
-    // Check for exponent overflow.
-    if (e >= 0x7c00) {
-      // Overflow occurred -- truncate instead of rounding.
-      e = _h;
-      e >>= 10 - n;
-      e <<= 10 - n;
-    }
-
-    // Put the original sign bit back.
-
-    return new Half.fromBits(s | e);
-  }
-
-  /**
-   * Returns true if h is a normalized number, a denormalized number or zero.
-   */
-  bool isFinite() {
-    int e = (_h >> 10) & 0x001f;
-    return e < 31;
-  }
-
-  /**
-   * Returns true if h is a normalized number.
-   */
-  bool isNormalized() {
-    int e = (_h >> 10) & 0x001f;
-    return e > 0 && e < 31;
-  }
-
-  /**
-   * Returns true if h is a denormalized number.
-   */
-  bool isDenormalized() {
-    int e = (_h >> 10) & 0x001f;
-    int m =  _h & 0x3ff;
-    return e == 0 && m != 0;
-  }
-
-  /**
-   * Returns true if h is zero.
-   */
-  bool isZero() {
-    return (_h & 0x7fff) == 0;
-  }
-
-  /**
-   * Returns true if h is a NAN.
-   */
-  bool isNan() {
-    int e = (_h >> 10) & 0x001f;
-    int m =  _h & 0x3ff;
-    return e == 31 && m != 0;
-  }
-
-  /**
-   * Returns true if h is a positive or a negative infinity.
-   */
-  bool isInfinity() {
-    int e = (_h >> 10) & 0x001f;
-    int m =  _h & 0x3ff;
-    return e == 31 && m == 0;
-  }
-
-  /**
-   * Returns true if the sign bit of h is set (negative).
-   */
-  bool isNegative() {
-    return (_h & 0x8000) != 0;
-  }
-
-  /**
-   * Returns +infinity.
-   */
-  static Half posInf() => new Half.fromBits(0x7c00);
-
-  /**
-   * Returns -infinity.
-   */
-  static Half negInf() => new Half.fromBits(0xfc00);
-
-  /**
-   * Returns a NAN with the bit pattern 0111111111111111.
-   */
-  static Half qNan() => new Half.fromBits(0x7fff);
-
-  /**
-   * Returns a NAN with the bit pattern 0111110111111111.
-   */
-  static Half sNan() => new Half.fromBits(0x7dff);
-
-  int bits() => _h;
-
-  void setBits(int bits) {
-    _h = bits;
-  }
-
-  static int _convert(int i) {
-    // Our floating point number, f, is represented by the bit
-    // pattern in integer i.  Disassemble that bit pattern into
-    // the sign, s, the exponent, e, and the significand, m.
-    // Shift s into the position where it will go in in the
-    // resulting half number.
-    // Adjust e, accounting for the different exponent bias
-    // of float and half (127 versus 15).
-    int s =  (i >> 16) & 0x00008000;
-    int e = ((i >> 23) & 0x000000ff) - (127 - 15);
-    int m =   i        & 0x007fffff;
-
-    // Now reassemble s, e and m into a half:
-    if (e <= 0) {
-      if (e < -10) {
-        // E is less than -10.  The absolute value of f is
-        // less than HALF_MIN (f may be a small normalized
-        // float, a denormalized float or a zero).
-        //
-        // We convert f to a half zero with the same sign as f.
-        return s;
-      }
-
-      // E is between -10 and 0.  F is a normalized float
-      // whose magnitude is less than HALF_NRM_MIN.
-      //
-      // We convert f to a denormalized half.
-
-      // Add an explicit leading 1 to the significand.
-
-      m = m | 0x00800000;
-
-      // Round to m to the nearest (10+e)-bit value (with e between
-      // -10 and 0); in case of a tie, round to the nearest even value.
-      //
-      // Rounding may cause the significand to overflow and make
-      // our number normalized.  Because of the way a half's bits
-      // are laid out, we don't have to treat this case separately;
-      // the code below will handle it correctly.
-
-      int t = 14 - e;
-      int a = (1 << (t - 1)) - 1;
-      int b = (m >> t) & 1;
-
-      m = (m + a + b) >> t;
-
-      // Assemble the half from s, e (zero) and m.
-      return s | m;
-    } else if (e == 0xff - (127 - 15)) {
-      if (m == 0) {
-        // F is an infinity; convert f to a half
-        // infinity with the same sign as f.
-        return s | 0x7c00;
-      } else {
-        // F is a NAN; we produce a half NAN that preserves
-        // the sign bit and the 10 leftmost bits of the
-        // significand of f, with one exception: If the 10
-        // leftmost bits are all zero, the NAN would turn
-        // into an infinity, so we have to set at least one
-        // bit in the significand.
-
-        m >>= 13;
-        return s | 0x7c00 | m | ((m == 0) ? 1 : 0);
-      }
-    } else {
-      // E is greater than zero.  F is a normalized float.
-      // We try to convert f to a normalized half.
-
-      // Round to m to the nearest 10-bit value.  In case of
-      // a tie, round to the nearest even value.
-      m = m + 0x00000fff + ((m >> 13) & 1);
-
-      if (m & 0x00800000 != 0) {
-        m =  0;   // overflow in significand,
-        e += 1;   // adjust exponent
-      }
-
-      // Handle exponent overflow
-
-      if (e > 30) {
-        return s | 0x7c00;  // if this returns, the half becomes an
-      } // infinity with the same sign as f.
-
-      // Assemble the half from s, e and m.
-      return s | (e << 10) | (m >> 13);
-    }
-  }
-
-  static void _initialize() {
-    if (_toFloatUint32 != null) {
-      return;
-    }
-    _toFloatUint32 = new Uint32List(1 << 16);
-    _toFloatFloat32 = new Float32List.view(_toFloatUint32.buffer);
-    _eLut = new Uint16List(1 << 9);
-
-    // Init eLut
-    for (int i = 0; i < 0x100; i++) {
-      int e = (i & 0x0ff) - (127 - 15);
-
-      if (e <= 0 || e >= 30) {
-        // Special case
-        _eLut[i]         = 0;
-        _eLut[i | 0x100] = 0;
-      } else {
-        // Common case - normalized half, no exponent overflow possible
-        _eLut[i]         =  (e << 10);
-        _eLut[i | 0x100] = ((e << 10) | 0x8000);
-      }
-    }
-
-    // Init toFloat
-    const int iMax = (1 << 16);
-    for (int i = 0; i < iMax; i++) {
-      _toFloatUint32[i] = _halfToFloat(i);
-    }
-  }
-
-  static int _halfToFloat(int y) {
-    int s = (y >> 15) & 0x00000001;
-    int e = (y >> 10) & 0x0000001f;
-    int m =  y        & 0x000003ff;
-
-    if (e == 0) {
-      if (m == 0) {
-        // Plus or minus zero
-        return s << 31;
-      } else {
-        // Denormalized number -- renormalize it
-        while ((m & 0x00000400) == 0) {
-          m <<= 1;
-          e -=  1;
-        }
-
-        e += 1;
-        m &= ~0x00000400;
-      }
-    } else if (e == 31) {
-      if (m == 0) {
-        // Positive or negative infinity
-        return (s << 31) | 0x7f800000;
-      } else {
-        // Nan -- preserve sign and significand bits
-        return (s << 31) | 0x7f800000 | (m << 13);
-      }
-    }
-
-    // Normalized number
-    e = e + (127 - 15);
-    m = m << 13;
-
-    // Assemble s, e and m.
-    return (s << 31) | (e << 23) | m;
-  }
-
-  int _h;
-
-  static Uint32List _toFloatUint32;
-  static Float32List _toFloatFloat32;
-  static Uint16List _eLut;
-}
+import 'dart:typed_data';

+

+import '../internal/bit_operators.dart';

+

+/**

+ * A 16-bit floating-point number, used by high-dynamic-range image formats

+ * as a more efficient storage for floating-point values that don't require

+ * full 32-bit precision. A list of Half floats can be stored in a [Uint16List],

+ * and converted to a double using the [HalfToDouble] static method.

+ *

+ * This class is derived from the OpenEXR library.

+ */

+class Half {

+  Half([num f]) {

+    if (f != null) {

+      _h = DoubleToHalf(f);

+    }

+  }

+

+  Half.fromBits(int bits) :

+    _h = bits {

+    if (_toFloatFloat32 == null) {

+      _initialize();

+    }

+  }

+

+  static double HalfToDouble(int bits) {

+    if (_toFloatFloat32 == null) {

+      _initialize();

+    }

+    return _toFloatFloat32[bits];

+  }

+

+  static int DoubleToHalf(num f) {

+    if (_toFloatFloat32 == null) {

+      _initialize();

+    }

+

+    f = f.toDouble();

+    int x_i = float32ToUint32(f);

+    if (f == 0.0) {

+      // Common special case - zero.

+      // Preserve the zero's sign bit.

+      return x_i >> 16;

+    }

+

+    // We extract the combined sign and exponent, e, from our

+    // floating-point number, f.  Then we convert e to the sign

+    // and exponent of the half number via a table lookup.

+    //

+    // For the most common case, where a normalized half is produced,

+    // the table lookup returns a non-zero value; in this case, all

+    // we have to do is round f's significand to 10 bits and combine

+    // the result with e.

+    //

+    // For all other cases (overflow, zeroes, denormalized numbers

+    // resulting from underflow, infinities and NANs), the table

+    // lookup returns zero, and we call a longer, non-inline function

+    // to do the float-to-half conversion.

+    int e = (x_i >> 23) & 0x000001ff;

+

+    e = _eLut[e];

+

+    if (e != 0) {

+      // Simple case - round the significand, m, to 10

+      // bits and combine it with the sign and exponent.

+      int m = x_i & 0x007fffff;

+      return e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13);

+    }

+

+    // Difficult case - call a function.

+    return _convert(x_i);

+  }

+

+  double toDouble() => _toFloatFloat32[_h];

+

+  /**

+   * Unary minus

+   */

+  Half operator-() => new Half.fromBits(_h ^ 0x8000);

+

+  /**

+   * Addition operator for Half or num left operands.

+   */

+  Half operator+(f) {

+    return new Half(toDouble() + f.toDouble());

+  }

+

+  /**

+   * Subtraction operator for Half or num left operands.

+   */

+  Half operator-(f) {

+    return new Half(toDouble() - f.toDouble());

+  }

+

+  Half operator*(f) {

+    return new Half(toDouble() * f.toDouble());

+  }

+

+  Half operator/(f) {

+    return new Half(toDouble() / f.toDouble());

+  }

+

+  /**

+   * Round to n-bit precision (n should be between 0 and 10).

+   * After rounding, the significand's 10-n least significant

+   * bits will be zero.

+   */

+  Half round(int n) {

+    if (n >= 10) {

+      return this;

+    }

+

+    // Disassemble h into the sign, s,

+    // and the combined exponent and significand, e.

+    int s = _h & 0x8000;

+    int e = _h & 0x7fff;

+

+    // Round the exponent and significand to the nearest value

+    // where ones occur only in the (10-n) most significant bits.

+    // Note that the exponent adjusts automatically if rounding

+    // up causes the significand to overflow.

+

+    e >>= 9 - n;

+    e  += e & 1;

+    e <<= 9 - n;

+

+    // Check for exponent overflow.

+    if (e >= 0x7c00) {

+      // Overflow occurred -- truncate instead of rounding.

+      e = _h;

+      e >>= 10 - n;

+      e <<= 10 - n;

+    }

+

+    // Put the original sign bit back.

+

+    return new Half.fromBits(s | e);

+  }

+

+  /**

+   * Returns true if h is a normalized number, a denormalized number or zero.

+   */

+  bool isFinite() {

+    int e = (_h >> 10) & 0x001f;

+    return e < 31;

+  }

+

+  /**

+   * Returns true if h is a normalized number.

+   */

+  bool isNormalized() {

+    int e = (_h >> 10) & 0x001f;

+    return e > 0 && e < 31;

+  }

+

+  /**

+   * Returns true if h is a denormalized number.

+   */

+  bool isDenormalized() {

+    int e = (_h >> 10) & 0x001f;

+    int m =  _h & 0x3ff;

+    return e == 0 && m != 0;

+  }

+

+  /**

+   * Returns true if h is zero.

+   */

+  bool isZero() {

+    return (_h & 0x7fff) == 0;

+  }

+

+  /**

+   * Returns true if h is a NAN.

+   */

+  bool isNan() {

+    int e = (_h >> 10) & 0x001f;

+    int m =  _h & 0x3ff;

+    return e == 31 && m != 0;

+  }

+

+  /**

+   * Returns true if h is a positive or a negative infinity.

+   */

+  bool isInfinity() {

+    int e = (_h >> 10) & 0x001f;

+    int m =  _h & 0x3ff;

+    return e == 31 && m == 0;

+  }

+

+  /**

+   * Returns true if the sign bit of h is set (negative).

+   */

+  bool isNegative() {

+    return (_h & 0x8000) != 0;

+  }

+

+  /**

+   * Returns +infinity.

+   */

+  static Half posInf() => new Half.fromBits(0x7c00);

+

+  /**

+   * Returns -infinity.

+   */

+  static Half negInf() => new Half.fromBits(0xfc00);

+

+  /**

+   * Returns a NAN with the bit pattern 0111111111111111.

+   */

+  static Half qNan() => new Half.fromBits(0x7fff);

+

+  /**

+   * Returns a NAN with the bit pattern 0111110111111111.

+   */

+  static Half sNan() => new Half.fromBits(0x7dff);

+

+  int bits() => _h;

+

+  void setBits(int bits) {

+    _h = bits;

+  }

+

+  static int _convert(int i) {

+    // Our floating point number, f, is represented by the bit

+    // pattern in integer i.  Disassemble that bit pattern into

+    // the sign, s, the exponent, e, and the significand, m.

+    // Shift s into the position where it will go in in the

+    // resulting half number.

+    // Adjust e, accounting for the different exponent bias

+    // of float and half (127 versus 15).

+    int s =  (i >> 16) & 0x00008000;

+    int e = ((i >> 23) & 0x000000ff) - (127 - 15);

+    int m =   i        & 0x007fffff;

+

+    // Now reassemble s, e and m into a half:

+    if (e <= 0) {

+      if (e < -10) {

+        // E is less than -10.  The absolute value of f is

+        // less than HALF_MIN (f may be a small normalized

+        // float, a denormalized float or a zero).

+        //

+        // We convert f to a half zero with the same sign as f.

+        return s;

+      }

+

+      // E is between -10 and 0.  F is a normalized float

+      // whose magnitude is less than HALF_NRM_MIN.

+      //

+      // We convert f to a denormalized half.

+

+      // Add an explicit leading 1 to the significand.

+

+      m = m | 0x00800000;

+

+      // Round to m to the nearest (10+e)-bit value (with e between

+      // -10 and 0); in case of a tie, round to the nearest even value.

+      //

+      // Rounding may cause the significand to overflow and make

+      // our number normalized.  Because of the way a half's bits

+      // are laid out, we don't have to treat this case separately;

+      // the code below will handle it correctly.

+

+      int t = 14 - e;

+      int a = (1 << (t - 1)) - 1;

+      int b = (m >> t) & 1;

+

+      m = (m + a + b) >> t;

+

+      // Assemble the half from s, e (zero) and m.

+      return s | m;

+    } else if (e == 0xff - (127 - 15)) {

+      if (m == 0) {

+        // F is an infinity; convert f to a half

+        // infinity with the same sign as f.

+        return s | 0x7c00;

+      } else {

+        // F is a NAN; we produce a half NAN that preserves

+        // the sign bit and the 10 leftmost bits of the

+        // significand of f, with one exception: If the 10

+        // leftmost bits are all zero, the NAN would turn

+        // into an infinity, so we have to set at least one

+        // bit in the significand.

+

+        m >>= 13;

+        return s | 0x7c00 | m | ((m == 0) ? 1 : 0);

+      }

+    } else {

+      // E is greater than zero.  F is a normalized float.

+      // We try to convert f to a normalized half.

+

+      // Round to m to the nearest 10-bit value.  In case of

+      // a tie, round to the nearest even value.

+      m = m + 0x00000fff + ((m >> 13) & 1);

+

+      if (m & 0x00800000 != 0) {

+        m =  0;   // overflow in significand,

+        e += 1;   // adjust exponent

+      }

+

+      // Handle exponent overflow

+

+      if (e > 30) {

+        return s | 0x7c00;  // if this returns, the half becomes an

+      } // infinity with the same sign as f.

+

+      // Assemble the half from s, e and m.

+      return s | (e << 10) | (m >> 13);

+    }

+  }

+

+  static void _initialize() {

+    if (_toFloatUint32 != null) {

+      return;

+    }

+    _toFloatUint32 = Uint32List(1 << 16);

+    _toFloatFloat32 = Float32List.view(_toFloatUint32.buffer);

+    _eLut = Uint16List(1 << 9);

+

+    // Init eLut

+    for (int i = 0; i < 0x100; i++) {

+      int e = (i & 0x0ff) - (127 - 15);

+

+      if (e <= 0 || e >= 30) {

+        // Special case

+        _eLut[i]         = 0;

+        _eLut[i | 0x100] = 0;

+      } else {

+        // Common case - normalized half, no exponent overflow possible

+        _eLut[i]         =  (e << 10);

+        _eLut[i | 0x100] = ((e << 10) | 0x8000);

+      }

+    }

+

+    // Init toFloat

+    const int iMax = (1 << 16);

+    for (int i = 0; i < iMax; i++) {

+      _toFloatUint32[i] = _halfToFloat(i);

+    }

+  }

+

+  static int _halfToFloat(int y) {

+    int s = (y >> 15) & 0x00000001;

+    int e = (y >> 10) & 0x0000001f;

+    int m =  y        & 0x000003ff;

+

+    if (e == 0) {

+      if (m == 0) {

+        // Plus or minus zero

+        return s << 31;

+      } else {

+        // Denormalized number -- renormalize it

+        while ((m & 0x00000400) == 0) {

+          m <<= 1;

+          e -=  1;

+        }

+

+        e += 1;

+        m &= ~0x00000400;

+      }

+    } else if (e == 31) {

+      if (m == 0) {

+        // Positive or negative infinity

+        return (s << 31) | 0x7f800000;

+      } else {

+        // Nan -- preserve sign and significand bits

+        return (s << 31) | 0x7f800000 | (m << 13);

+      }

+    }

+

+    // Normalized number

+    e = e + (127 - 15);

+    m = m << 13;

+

+    // Assemble s, e and m.

+    return (s << 31) | (e << 23) | m;

+  }

+

+  int _h;

+

+  static Uint32List _toFloatUint32;

+  static Float32List _toFloatFloat32;

+  static Uint16List _eLut;

+}

diff --git a/image/lib/src/hdr/hdr_bloom.dart b/image/lib/src/hdr/hdr_bloom.dart
old mode 100644
new mode 100755
index 7b07283..8580117
--- a/image/lib/src/hdr/hdr_bloom.dart
+++ b/image/lib/src/hdr/hdr_bloom.dart
@@ -1,76 +1,76 @@
-import 'dart:math' as Math;
-import 'dart:typed_data';
-
-import 'hdr_image.dart';
-
-/**
- * Applies an HDR bloom filter to the image, in-place.
- */
-HdrImage hdrBloom(HdrImage hdr, {double radius: 0.01, double weight: 0.1}) {
-  double _lerp(double t, double a, double b) => (1.0 - t) * a + t * b;
-
-  //int nPix = xResolution * yResolution;
-  // Possibly apply bloom effect to image
-  if (radius > 0.0 && weight > 0.0) {
-    // Compute image-space extent of bloom effect
-    int bloomSupport = (radius * Math.max(hdr.width, hdr.height)).ceil();
-    int bloomWidth = bloomSupport ~/ 2;
-    // Initialize bloom filter table
-    Float32List bloomFilter = new Float32List(bloomWidth * bloomWidth);
-    for (int i = 0; i < bloomWidth * bloomWidth; ++i) {
-      double dist = Math.sqrt(i / bloomWidth);
-      bloomFilter[i] = Math.pow(Math.max(0.0, 1.0 - dist), 4.0);
-    }
-
-    // Apply bloom filter to image pixels
-    Float32List bloomImage = new Float32List(3 * hdr.width * hdr.height);
-    for (int y = 0, offset = 0; y < hdr.height; ++y) {
-      for (int x = 0; x < hdr.width; ++x, ++offset) {
-        // Compute bloom for pixel _(x,y)_
-        // Compute extent of pixels contributing bloom
-        int x0 = Math.max(0, x - bloomWidth);
-        int x1 = Math.min(x + bloomWidth, hdr.width - 1);
-        int y0 = Math.max(0, y - bloomWidth);
-        int y1 = Math.min(y + bloomWidth, hdr.height - 1);
-
-        double sumWt = 0.0;
-        for (int by = y0; by <= y1; ++by) {
-          for (int bx = x0; bx <= x1; ++bx) {
-            // Accumulate bloom from pixel $(bx,by)$
-            int dx = x - bx;
-            int dy = y - by;
-            if (dx == 0 && dy == 0) {
-              continue;
-            }
-            int dist2 = dx * dx + dy * dy;
-            if (dist2 < bloomWidth * bloomWidth) {
-              //int bloomOffset = bx + by * hdr.width;
-              double wt = bloomFilter[dist2];
-
-              sumWt += wt;
-
-              bloomImage[3 * offset] += wt * hdr.getRed(bx, by);
-              bloomImage[3 * offset + 1] += wt * hdr.getGreen(bx, by);
-              bloomImage[3 * offset + 2] += wt * hdr.getBlue(bx, by);
-            }
-          }
-        }
-
-        bloomImage[3 * offset] /= sumWt;
-        bloomImage[3 * offset + 1] /= sumWt;
-        bloomImage[3 * offset + 2] /= sumWt;
-      }
-    }
-
-    // Mix bloom effect into each pixel
-    for (int y = 0, offset = 0; y < hdr.height; ++y) {
-      for (int x = 0; x < hdr.width; ++x, offset += 3) {
-        hdr.setRed(x, y, _lerp(weight, hdr.getRed(x, y), bloomImage[offset]));
-        hdr.setGreen(x, y, _lerp(weight, hdr.getGreen(x, y), bloomImage[offset + 1]));
-        hdr.setBlue(x, y, _lerp(weight, hdr.getBlue(x, y), bloomImage[offset + 2]));
-      }
-    }
-  }
-
-  return hdr;
-}
+import 'dart:math' as Math;

+import 'dart:typed_data';

+

+import 'hdr_image.dart';

+

+/**

+ * Applies an HDR bloom filter to the image, in-place.

+ */

+HdrImage hdrBloom(HdrImage hdr, {double radius: 0.01, double weight: 0.1}) {

+  double _lerp(double t, double a, double b) => (1.0 - t) * a + t * b;

+

+  //int nPix = xResolution * yResolution;

+  // Possibly apply bloom effect to image

+  if (radius > 0.0 && weight > 0.0) {

+    // Compute image-space extent of bloom effect

+    int bloomSupport = (radius * Math.max(hdr.width, hdr.height)).ceil();

+    int bloomWidth = bloomSupport ~/ 2;

+    // Initialize bloom filter table

+    Float32List bloomFilter = Float32List(bloomWidth * bloomWidth);

+    for (int i = 0; i < bloomWidth * bloomWidth; ++i) {

+      double dist = Math.sqrt(i / bloomWidth);

+      bloomFilter[i] = Math.pow(Math.max(0.0, 1.0 - dist), 4.0);

+    }

+

+    // Apply bloom filter to image pixels

+    Float32List bloomImage = Float32List(3 * hdr.width * hdr.height);

+    for (int y = 0, offset = 0; y < hdr.height; ++y) {

+      for (int x = 0; x < hdr.width; ++x, ++offset) {

+        // Compute bloom for pixel _(x,y)_

+        // Compute extent of pixels contributing bloom

+        int x0 = Math.max(0, x - bloomWidth);

+        int x1 = Math.min(x + bloomWidth, hdr.width - 1);

+        int y0 = Math.max(0, y - bloomWidth);

+        int y1 = Math.min(y + bloomWidth, hdr.height - 1);

+

+        double sumWt = 0.0;

+        for (int by = y0; by <= y1; ++by) {

+          for (int bx = x0; bx <= x1; ++bx) {

+            // Accumulate bloom from pixel $(bx,by)$

+            int dx = x - bx;

+            int dy = y - by;

+            if (dx == 0 && dy == 0) {

+              continue;

+            }

+            int dist2 = dx * dx + dy * dy;

+            if (dist2 < bloomWidth * bloomWidth) {

+              //int bloomOffset = bx + by * hdr.width;

+              double wt = bloomFilter[dist2];

+

+              sumWt += wt;

+

+              bloomImage[3 * offset] += wt * hdr.getRed(bx, by);

+              bloomImage[3 * offset + 1] += wt * hdr.getGreen(bx, by);

+              bloomImage[3 * offset + 2] += wt * hdr.getBlue(bx, by);

+            }

+          }

+        }

+

+        bloomImage[3 * offset] /= sumWt;

+        bloomImage[3 * offset + 1] /= sumWt;

+        bloomImage[3 * offset + 2] /= sumWt;

+      }

+    }

+

+    // Mix bloom effect into each pixel

+    for (int y = 0, offset = 0; y < hdr.height; ++y) {

+      for (int x = 0; x < hdr.width; ++x, offset += 3) {

+        hdr.setRed(x, y, _lerp(weight, hdr.getRed(x, y), bloomImage[offset]));

+        hdr.setGreen(x, y, _lerp(weight, hdr.getGreen(x, y), bloomImage[offset + 1]));

+        hdr.setBlue(x, y, _lerp(weight, hdr.getBlue(x, y), bloomImage[offset + 2]));

+      }

+    }

+  }

+

+  return hdr;

+}

diff --git a/image/lib/src/hdr/hdr_gamma.dart b/image/lib/src/hdr/hdr_gamma.dart
old mode 100644
new mode 100755
index 731a7b9..caa92d3
--- a/image/lib/src/hdr/hdr_gamma.dart
+++ b/image/lib/src/hdr/hdr_gamma.dart
@@ -1,22 +1,22 @@
-import 'dart:math' as Math;
-
-import 'hdr_image.dart';
-
-/**
- * Apply gamma scaling to the HDR image, in-place.
- */
-HdrImage hdrGamma(HdrImage hdr, {double gamma: 2.2}) {
-  for (int y = 0; y < hdr.height; ++y) {
-    for (int x = 0; x < hdr.width; ++x) {
-      double r = Math.pow(hdr.getRed(x, y), 1.0 / gamma);
-      double g = Math.pow(hdr.getGreen(x, y), 1.0 / gamma);
-      double b = Math.pow(hdr.getBlue(x, y), 1.0 / gamma);
-
-      hdr.setRed(x, y, r);
-      hdr.setGreen(x, y, g);
-      hdr.setBlue(x, y, b);
-    }
-  }
-
-  return hdr;
-}
+import 'dart:math' as Math;

+

+import 'hdr_image.dart';

+

+/**

+ * Apply gamma scaling to the HDR image, in-place.

+ */

+HdrImage hdrGamma(HdrImage hdr, {double gamma: 2.2}) {

+  for (int y = 0; y < hdr.height; ++y) {

+    for (int x = 0; x < hdr.width; ++x) {

+      double r = Math.pow(hdr.getRed(x, y), 1.0 / gamma);

+      double g = Math.pow(hdr.getGreen(x, y), 1.0 / gamma);

+      double b = Math.pow(hdr.getBlue(x, y), 1.0 / gamma);

+

+      hdr.setRed(x, y, r);

+      hdr.setGreen(x, y, g);

+      hdr.setBlue(x, y, b);

+    }

+  }

+

+  return hdr;

+}

diff --git a/image/lib/src/hdr/hdr_image.dart b/image/lib/src/hdr/hdr_image.dart
old mode 100644
new mode 100755
index 125a292..d95299c
--- a/image/lib/src/hdr/hdr_image.dart
+++ b/image/lib/src/hdr/hdr_image.dart
@@ -1,273 +1,273 @@
-import 'dart:typed_data';
-
-import '../image.dart';
-import 'hdr_slice.dart';
-
-/**
- * A high dynamic range RGBA image stored in 16-bit or 32-bit floating-point
- * channels.
- */
-class HdrImage {
-  static const int HALF = 1;
-  static const int FLOAT = 2;
-  static const int UINT = 0;
-
-  /// Red value of a sample
-  static const String R = 'R';
-  /// Green value of a sample
-  static const String G = 'G';
-  /// Blue value of a sample
-  static const String B = 'B';
-  /// Alpha/opacity
-  static const String A = 'A';
-  /// Distance of the front of a sample from the viewer
-  static const String Z = 'Z';
-  /// A numerical identifier for the object represented by a sample.
-  static const String ID = 'id';
-
-  final Map<String, HdrSlice> slices = {};
-  HdrSlice red;
-  HdrSlice green;
-  HdrSlice blue;
-  HdrSlice alpha;
-  HdrSlice depth;
-
-  HdrImage() {
-  }
-
-  /**
-   * Create an RGB[A] image.
-   */
-  HdrImage.create(int width, int height, int channels, int format) {
-    if (channels < 0 || channels > 4) {
-      return;
-    }
-    if (format != HALF && format != FLOAT && format != UINT) {
-      return;
-    }
-
-    const List<String> channelList = const [R, G, B, A];
-    for (int i = 0; i < channels; ++i) {
-      addSlice(new HdrSlice(channelList[i], width, height, format));
-    }
-  }
-
-  /**
-   * Create a copy of the [other] HdrImage.
-   */
-  HdrImage.from(HdrImage other) {
-    for (String ch in other.slices.keys) {
-      HdrSlice slice = other.slices[ch];
-      addSlice(new HdrSlice.from(slice));
-    }
-  }
-
-  /**
-   * Create an HDR image from a LDR [Image] by transforming the channel values
-   * to the range [0, 1].
-   */
-  HdrImage.fromImage(Image other) {
-    addSlice(new HdrSlice(R, other.width, other.height, HALF));
-    addSlice(new HdrSlice(G, other.width, other.height, HALF));
-    addSlice(new HdrSlice(B, other.width, other.height, HALF));
-    if (other.format == Image.RGBA) {
-      addSlice(new HdrSlice(A, other.width, other.height, HALF));
-    }
-    Uint8List rgb = other.getBytes();
-    for (int y = 0, si = 0; y < other.height; ++y) {
-      for (int x = 0; x < other.width; ++x) {
-        red.setFloat(x, y, rgb[si++] / 255.0);
-        green.setFloat(x, y, rgb[si++] / 255.0);
-        blue.setFloat(x, y, rgb[si++] / 255.0);
-        if (alpha != null) {
-          alpha.setFloat(x, y, rgb[si++] / 255.0);
-        }
-      }
-    }
-  }
-
-  /**
-   * Does the image have any color channels?
-   */
-  bool get hasColor => red != null || green != null || blue != null;
-
-  /**
-   * Does the image have an alpha channel?
-   */
-  bool get hasAlpha => alpha != null;
-
-  /**
-   * Does the image have a depth channel?
-   */
-  bool get hasDepth => depth != null;
-
-  /**
-   * The width of the framebuffer.
-   */
-  int get width => slices.isEmpty ? 0 : slices.values.first.width;
-
-  /**
-   * The height of the framebuffer.
-   */
-  int get height => slices.isEmpty ? 0 : slices.values.first.height;
-
-  /**
-   * Get the value of the red channel at the given pixel coordinates [x], [y].
-   */
-  double getRed(int x, int y) {
-    return red != null ? red.getFloat(x, y) : 0.0;
-  }
-
-  /**
-   * Set the value of the red channel at the given pixel coordinates [x], [y].
-   */
-  void setRed(int x, int y, double c) {
-    if (red != null) {
-      red.setFloat(x, y, c);
-    }
-  }
-
-  void setRedInt(int x, int y, int c) {
-    if (red != null) {
-      red.setInt(x,  y, c);
-    }
-  }
-
-  /**
-   * Get the value of the green channel at the given pixel coordinates [x], [y].
-   */
-  double getGreen(int x, int y) {
-    return green != null ? green.getFloat(x, y) : 0.0;
-  }
-
-  /**
-   * Set the value of the green channel at the given pixel coordinates [x], [y].
-   */
-  void setGreen(int x, int y, double c) {
-    if (green != null) {
-      green.setFloat(x, y, c);
-    }
-  }
-
-  void setGreenInt(int x, int y, int c) {
-    if (green != null) {
-      green.setInt(x,  y, c);
-    }
-  }
-
-  /**
-   * Get the value of the blue channel at the given pixel coordinates [x], [y].
-   */
-  double getBlue(int x, int y) {
-    return blue != null ? blue.getFloat(x, y) : 0.0;
-  }
-
-  /**
-   * Set the value of the blue channel at the given pixel coordinates [x], [y].
-   */
-  void setBlue(int x, int y, double c) {
-    if (blue != null) {
-      blue.setFloat(x, y, c);
-    }
-  }
-
-  void setBlueInt(int x, int y, int c) {
-    if (blue != null) {
-      blue.setInt(x, y, c);
-    }
-  }
-
-  /**
-   * Get the value of the alpha channel at the given pixel coordinates [x], [y].
-   */
-  double getAlpha(int x, int y) {
-    return alpha != null ? alpha.getFloat(x, y) : 0.0;
-  }
-
-  /**
-   * Set the value of the alpha channel at the given pixel coordinates [x], [y].
-   */
-  void setAlpha(int x, int y, double c) {
-    if (alpha != null) {
-      alpha.setFloat(x, y, c);
-    }
-  }
-
-  void setAlphaInt(int x, int y, int c) {
-    if (alpha != null) {
-      alpha.setInt(x, y, c);
-    }
-  }
-
-  /**
-   * Get the value of the depth channel at the given pixel coordinates [x], [y].
-   */
-  double getDepth(int x, int y) {
-    return depth != null ? depth.getFloat(x, y) : 0.0;
-  }
-
-  /**
-   * Set the value of the depth channel at the given pixel coordinates [x], [y].
-   */
-  void setDepth(int x, int y, double c) {
-    if (depth != null) {
-      depth.setFloat(x, y, c);
-    }
-  }
-
-  /**
-   * Does this image contain the given channel?
-   */
-  bool hasChannel(String ch) => slices.containsKey(ch);
-
-  /**
-   * Access a framebuffer slice by name.
-   */
-  HdrSlice operator[](String ch) => slices[ch];
-
-  /**
-   * Add a channel [slice] to the
-   */
-  void addSlice(HdrSlice slice) {
-    String ch = slice.name;
-    slices[ch] = slice;
-    switch (ch) {
-      case R:
-        red = slice;
-        break;
-      case G:
-        green = slice;
-        break;
-      case B:
-        blue = slice;
-        break;
-      case A:
-        alpha = slice;
-        break;
-      case Z:
-        depth = slice;
-        break;
-    }
-  }
-
-  /**
-   * Convert the framebuffer to an floating-point image, as a sequence of
-   * floats in RGBA order.
-   */
-  Float32List toFloatRgba() {
-    Float32List rgba = new Float32List(width * height * 4);
-    int w = width;
-    int h = height;
-    for (int y = 0, di = 0; y < h; ++y) {
-      for (int x = 0; x < w; ++x) {
-        rgba[di++] = red == null ? 0.0 : red.getFloat(x, y);
-        rgba[di++] = green == null ? 0.0 : green.getFloat(x, y);
-        rgba[di++] = blue == null ? 0.0 : blue.getFloat(x, y);
-        rgba[di++] = alpha == null ? 1.0 : alpha.getFloat(x, y);
-      }
-    }
-
-    return rgba;
-  }
-}
-
+import 'dart:typed_data';

+

+import '../image.dart';

+import 'hdr_slice.dart';

+

+/**

+ * A high dynamic range RGBA image stored in 16-bit or 32-bit floating-point

+ * channels.

+ */

+class HdrImage {

+  static const int HALF = 1;

+  static const int FLOAT = 2;

+  static const int UINT = 0;

+

+  /// Red value of a sample

+  static const String R = 'R';

+  /// Green value of a sample

+  static const String G = 'G';

+  /// Blue value of a sample

+  static const String B = 'B';

+  /// Alpha/opacity

+  static const String A = 'A';

+  /// Distance of the front of a sample from the viewer

+  static const String Z = 'Z';

+  /// A numerical identifier for the object represented by a sample.

+  static const String ID = 'id';

+

+  final Map<String, HdrSlice> slices = {};

+  HdrSlice red;

+  HdrSlice green;

+  HdrSlice blue;

+  HdrSlice alpha;

+  HdrSlice depth;

+

+  HdrImage() {

+  }

+

+  /**

+   * Create an RGB[A] image.

+   */

+  HdrImage.create(int width, int height, int channels, int format) {

+    if (channels < 0 || channels > 4) {

+      return;

+    }

+    if (format != HALF && format != FLOAT && format != UINT) {

+      return;

+    }

+

+    const List<String> channelList = const [R, G, B, A];

+    for (int i = 0; i < channels; ++i) {

+      addSlice(new HdrSlice(channelList[i], width, height, format));

+    }

+  }

+

+  /**

+   * Create a copy of the [other] HdrImage.

+   */

+  HdrImage.from(HdrImage other) {

+    for (String ch in other.slices.keys) {

+      HdrSlice slice = other.slices[ch];

+      addSlice(new HdrSlice.from(slice));

+    }

+  }

+

+  /**

+   * Create an HDR image from a LDR [Image] by transforming the channel values

+   * to the range [0, 1].

+   */

+  HdrImage.fromImage(Image other) {

+    addSlice(new HdrSlice(R, other.width, other.height, HALF));

+    addSlice(new HdrSlice(G, other.width, other.height, HALF));

+    addSlice(new HdrSlice(B, other.width, other.height, HALF));

+    if (other.format == Image.RGBA) {

+      addSlice(new HdrSlice(A, other.width, other.height, HALF));

+    }

+    Uint8List rgb = other.getBytes();

+    for (int y = 0, si = 0; y < other.height; ++y) {

+      for (int x = 0; x < other.width; ++x) {

+        red.setFloat(x, y, rgb[si++] / 255.0);

+        green.setFloat(x, y, rgb[si++] / 255.0);

+        blue.setFloat(x, y, rgb[si++] / 255.0);

+        if (alpha != null) {

+          alpha.setFloat(x, y, rgb[si++] / 255.0);

+        }

+      }

+    }

+  }

+

+  /**

+   * Does the image have any color channels?

+   */

+  bool get hasColor => red != null || green != null || blue != null;

+

+  /**

+   * Does the image have an alpha channel?

+   */

+  bool get hasAlpha => alpha != null;

+

+  /**

+   * Does the image have a depth channel?

+   */

+  bool get hasDepth => depth != null;

+

+  /**

+   * The width of the framebuffer.

+   */

+  int get width => slices.isEmpty ? 0 : slices.values.first.width;

+

+  /**

+   * The height of the framebuffer.

+   */

+  int get height => slices.isEmpty ? 0 : slices.values.first.height;

+

+  /**

+   * Get the value of the red channel at the given pixel coordinates [x], [y].

+   */

+  double getRed(int x, int y) {

+    return red != null ? red.getFloat(x, y) : 0.0;

+  }

+

+  /**

+   * Set the value of the red channel at the given pixel coordinates [x], [y].

+   */

+  void setRed(int x, int y, double c) {

+    if (red != null) {

+      red.setFloat(x, y, c);

+    }

+  }

+

+  void setRedInt(int x, int y, int c) {

+    if (red != null) {

+      red.setInt(x,  y, c);

+    }

+  }

+

+  /**

+   * Get the value of the green channel at the given pixel coordinates [x], [y].

+   */

+  double getGreen(int x, int y) {

+    return green != null ? green.getFloat(x, y) : 0.0;

+  }

+

+  /**

+   * Set the value of the green channel at the given pixel coordinates [x], [y].

+   */

+  void setGreen(int x, int y, double c) {

+    if (green != null) {

+      green.setFloat(x, y, c);

+    }

+  }

+

+  void setGreenInt(int x, int y, int c) {

+    if (green != null) {

+      green.setInt(x,  y, c);

+    }

+  }

+

+  /**

+   * Get the value of the blue channel at the given pixel coordinates [x], [y].

+   */

+  double getBlue(int x, int y) {

+    return blue != null ? blue.getFloat(x, y) : 0.0;

+  }

+

+  /**

+   * Set the value of the blue channel at the given pixel coordinates [x], [y].

+   */

+  void setBlue(int x, int y, double c) {

+    if (blue != null) {

+      blue.setFloat(x, y, c);

+    }

+  }

+

+  void setBlueInt(int x, int y, int c) {

+    if (blue != null) {

+      blue.setInt(x, y, c);

+    }

+  }

+

+  /**

+   * Get the value of the alpha channel at the given pixel coordinates [x], [y].

+   */

+  double getAlpha(int x, int y) {

+    return alpha != null ? alpha.getFloat(x, y) : 0.0;

+  }

+

+  /**

+   * Set the value of the alpha channel at the given pixel coordinates [x], [y].

+   */

+  void setAlpha(int x, int y, double c) {

+    if (alpha != null) {

+      alpha.setFloat(x, y, c);

+    }

+  }

+

+  void setAlphaInt(int x, int y, int c) {

+    if (alpha != null) {

+      alpha.setInt(x, y, c);

+    }

+  }

+

+  /**

+   * Get the value of the depth channel at the given pixel coordinates [x], [y].

+   */

+  double getDepth(int x, int y) {

+    return depth != null ? depth.getFloat(x, y) : 0.0;

+  }

+

+  /**

+   * Set the value of the depth channel at the given pixel coordinates [x], [y].

+   */

+  void setDepth(int x, int y, double c) {

+    if (depth != null) {

+      depth.setFloat(x, y, c);

+    }

+  }

+

+  /**

+   * Does this image contain the given channel?

+   */

+  bool hasChannel(String ch) => slices.containsKey(ch);

+

+  /**

+   * Access a framebuffer slice by name.

+   */

+  HdrSlice operator[](String ch) => slices[ch];

+

+  /**

+   * Add a channel [slice] to the

+   */

+  void addSlice(HdrSlice slice) {

+    String ch = slice.name;

+    slices[ch] = slice;

+    switch (ch) {

+      case R:

+        red = slice;

+        break;

+      case G:

+        green = slice;

+        break;

+      case B:

+        blue = slice;

+        break;

+      case A:

+        alpha = slice;

+        break;

+      case Z:

+        depth = slice;

+        break;

+    }

+  }

+

+  /**

+   * Convert the framebuffer to an floating-point image, as a sequence of

+   * floats in RGBA order.

+   */

+  Float32List toFloatRgba() {

+    Float32List rgba = Float32List(width * height * 4);

+    int w = width;

+    int h = height;

+    for (int y = 0, di = 0; y < h; ++y) {

+      for (int x = 0; x < w; ++x) {

+        rgba[di++] = red == null ? 0.0 : red.getFloat(x, y);

+        rgba[di++] = green == null ? 0.0 : green.getFloat(x, y);

+        rgba[di++] = blue == null ? 0.0 : blue.getFloat(x, y);

+        rgba[di++] = alpha == null ? 1.0 : alpha.getFloat(x, y);

+      }

+    }

+

+    return rgba;

+  }

+}

+

diff --git a/image/lib/src/hdr/hdr_slice.dart b/image/lib/src/hdr/hdr_slice.dart
old mode 100644
new mode 100755
index af343ad..2da0002
--- a/image/lib/src/hdr/hdr_slice.dart
+++ b/image/lib/src/hdr/hdr_slice.dart
@@ -1,92 +1,92 @@
-import 'dart:typed_data';
-
-import 'half.dart';
-import 'hdr_image.dart';
-
-/**
- * A slice is the data for an image framebuffer for a single channel.
- */
-class HdrSlice {
-  final String name;
-  final int width;
-  final int height;
-  /// Indicates the type of data stored by the slice, either [HdrImage.HALF],
-  /// [HdrImage.FLOAT], or [HdrImage.UINT].
-  final int type;
-  /// [data] will be either Uint16List, Float32List, or Uint32List depending
-  /// on the type being HALF, FLOAT or UINT respectively.
-  final data;
-
-  HdrSlice(this.name, int width, int height, int type) :
-    this.width = width,
-    this.height = height,
-    this.type = type,
-    data = type == HdrImage.HALF ? new Uint16List(width * height) :
-           type == HdrImage.FLOAT ? new Float32List(width * height) :
-           new Uint32List(width * height);
-
-  /**
-   * Create a copy of the [other] HdrSlice.
-   */
-  HdrSlice.from(HdrSlice other) :
-    name = other.name ,
-    width = other.width,
-    height = other.height,
-    type = other.type,
-    data = other.type == HdrImage.HALF ? new Uint16List.fromList(other.data) :
-      other.type == HdrImage.FLOAT ? new Float32List.fromList(other.data) :
-      new Uint32List.fromList(other.data);
-
-  /**
-   * Get the raw bytes of the data buffer.
-   */
-  Uint8List getBytes() => new Uint8List.view(data.buffer);
-
-  /**
-   * Does this channel store floating-point data?
-   */
-  bool get isFloat => type == HdrImage.FLOAT || type == HdrImage.HALF;
-
-  /**
-   * Get the float value of the sample at the coordinates [x],[y].
-   * [Half] samples are converted to double.
-   * An exception will occur if the slice stores UINT data.
-   */
-  double getFloat(int x, int y) {
-    int pi = y * width + x;
-    double s = (type == HdrImage.HALF) ?
-               Half.HalfToDouble(data[pi]) : data[pi];
-    return s;
-  }
-
-  /**
-   * Set the float value of the sample at the coordinates [x],[y] for
-   * [FLOAT] or [HALF] slices.
-   */
-  void setFloat(int x, int y, double v) {
-    int pi = y * width + x;
-    if (type == HdrImage.FLOAT) {
-      data[pi] = v;
-    } else if (type == HdrImage.HALF) {
-      data[pi] = Half.DoubleToHalf(v);
-    }
-  }
-
-  /**
-   * Get the int value of the sample at the coordinates [x],[y].
-   * An exception will occur if the slice stores FLOAT or HALF data.
-   */
-  int getInt(int x, int y) {
-    int pi = y * width + x;
-    return data[pi];
-  }
-
-  /**
-   * Set the int value of the sample at the coordinates [x],[y] for [UINT]
-   * slices.
-   */
-  void setInt(int x, int y, int v) {
-    int pi = y * width + x;
-    data[pi] = v;
-  }
-}
+import 'dart:typed_data';

+

+import 'half.dart';

+import 'hdr_image.dart';

+

+/**

+ * A slice is the data for an image framebuffer for a single channel.

+ */

+class HdrSlice {

+  final String name;

+  final int width;

+  final int height;

+  /// Indicates the type of data stored by the slice, either [HdrImage.HALF],

+  /// [HdrImage.FLOAT], or [HdrImage.UINT].

+  final int type;

+  /// [data] will be either Uint16List, Float32List, or Uint32List depending

+  /// on the type being HALF, FLOAT or UINT respectively.

+  final data;

+

+  HdrSlice(this.name, int width, int height, int type) :

+    this.width = width,

+    this.height = height,

+    this.type = type,

+    data = type == HdrImage.HALF ? new Uint16List(width * height) :

+           type == HdrImage.FLOAT ? new Float32List(width * height) :

+           new Uint32List(width * height);

+

+  /**

+   * Create a copy of the [other] HdrSlice.

+   */

+  HdrSlice.from(HdrSlice other) :

+    name = other.name ,

+    width = other.width,

+    height = other.height,

+    type = other.type,

+    data = other.type == HdrImage.HALF ? new Uint16List.fromList(other.data) :

+      other.type == HdrImage.FLOAT ? new Float32List.fromList(other.data) :

+      new Uint32List.fromList(other.data);

+

+  /**

+   * Get the raw bytes of the data buffer.

+   */

+  Uint8List getBytes() => new Uint8List.view(data.buffer);

+

+  /**

+   * Does this channel store floating-point data?

+   */

+  bool get isFloat => type == HdrImage.FLOAT || type == HdrImage.HALF;

+

+  /**

+   * Get the float value of the sample at the coordinates [x],[y].

+   * [Half] samples are converted to double.

+   * An exception will occur if the slice stores UINT data.

+   */

+  double getFloat(int x, int y) {

+    int pi = y * width + x;

+    double s = (type == HdrImage.HALF) ?

+               Half.HalfToDouble(data[pi]) : data[pi];

+    return s;

+  }

+

+  /**

+   * Set the float value of the sample at the coordinates [x],[y] for

+   * [FLOAT] or [HALF] slices.

+   */

+  void setFloat(int x, int y, double v) {

+    int pi = y * width + x;

+    if (type == HdrImage.FLOAT) {

+      data[pi] = v;

+    } else if (type == HdrImage.HALF) {

+      data[pi] = Half.DoubleToHalf(v);

+    }

+  }

+

+  /**

+   * Get the int value of the sample at the coordinates [x],[y].

+   * An exception will occur if the slice stores FLOAT or HALF data.

+   */

+  int getInt(int x, int y) {

+    int pi = y * width + x;

+    return data[pi];

+  }

+

+  /**

+   * Set the int value of the sample at the coordinates [x],[y] for [UINT]

+   * slices.

+   */

+  void setInt(int x, int y, int v) {

+    int pi = y * width + x;

+    data[pi] = v;

+  }

+}

diff --git a/image/lib/src/hdr/hdr_to_image.dart b/image/lib/src/hdr/hdr_to_image.dart
old mode 100644
new mode 100755
index 3963c83..00d3da9
--- a/image/lib/src/hdr/hdr_to_image.dart
+++ b/image/lib/src/hdr/hdr_to_image.dart
@@ -1,90 +1,90 @@
-import 'dart:math' as Math;
-import 'dart:typed_data';
-
-import '../image.dart';
-import '../image_exception.dart';
-import 'hdr_image.dart';
-
-/**
- * Convert a high dynamic range image to a low dynamic range image,
- * with optional exposure control.
- */
-Image hdrToImage(HdrImage hdr, {double exposure}) {
-  double _knee(double x, double f) {
-    return Math.log(x * f + 1.0) / f;
-  }
-
-  double _gamma(double h, double m) {
-    double x = Math.max(0.0, h * m);
-
-    if (x > 1.0) {
-      x = 1.0 + _knee(x - 1, 0.184874);
-    }
-
-    return (Math.pow(x, 0.4545) * 84.66);
-  }
-
-  Image image = new Image(hdr.width, hdr.height);
-  Uint8List pixels = image.getBytes();
-
-  if (!hdr.hasColor) {
-    throw new ImageException('Only RGB[A] images are currently supported.');
-  }
-
-  double m = exposure != null ?
-             Math.pow(2.0, (exposure + 2.47393).clamp(-20.0, 20.0)) :
-             1.0;
-
-  for (int y = 0, di = 0; y < hdr.height; ++y) {
-    for (int x = 0; x < hdr.width; ++x) {
-      double r = hdr.getRed(x, y);
-      double g = hdr.getGreen(x, y);
-      double b = hdr.getBlue(x, y);
-
-      if (r.isInfinite || r.isNaN) {
-        r = 0.0;
-      }
-      if (g.isInfinite || g.isNaN) {
-        g = 0.0;
-      }
-      if (b.isInfinite || b.isNaN) {
-        b = 0.0;
-      }
-
-      double ri, gi, bi;
-      if (exposure != null) {
-        ri = _gamma(r, m);
-        gi = _gamma(g, m);
-        bi = _gamma(b, m);
-      } else {
-        ri = (r * 255.0);
-        gi = (g * 255.0);
-        bi = (b * 255.0);
-      }
-
-      // Normalize the color
-      double mi = Math.max(ri, Math.max(gi, bi));
-      if (mi > 255.0) {
-        ri = 255.0 * (ri / mi);
-        gi = 255.0 * (gi / mi);
-        bi = 255.0 * (bi / mi);
-      }
-
-      pixels[di++] = ri.toInt().clamp(0, 255);
-      pixels[di++] = gi.toInt().clamp(0, 255);
-      pixels[di++] = bi.toInt().clamp(0, 255);
-
-      if (hdr.alpha != null) {
-        double a = hdr.alpha.getFloat(x, y);
-        if (a.isInfinite || a.isNaN) {
-          a = 1.0;
-        }
-        pixels[di++] = (a * 255.0).toInt().clamp(0, 255);
-      } else {
-        pixels[di++] = 255;
-      }
-    }
-  }
-
-  return image;
-}
+import 'dart:math' as Math;

+import 'dart:typed_data';

+

+import '../image.dart';

+import '../image_exception.dart';

+import 'hdr_image.dart';

+

+/**

+ * Convert a high dynamic range image to a low dynamic range image,

+ * with optional exposure control.

+ */

+Image hdrToImage(HdrImage hdr, {double exposure}) {

+  double _knee(double x, double f) {

+    return Math.log(x * f + 1.0) / f;

+  }

+

+  double _gamma(double h, double m) {

+    double x = Math.max(0.0, h * m);

+

+    if (x > 1.0) {

+      x = 1.0 + _knee(x - 1, 0.184874);

+    }

+

+    return (Math.pow(x, 0.4545) * 84.66);

+  }

+

+  Image image = Image(hdr.width, hdr.height);

+  Uint8List pixels = image.getBytes();

+

+  if (!hdr.hasColor) {

+    throw new ImageException('Only RGB[A] images are currently supported.');

+  }

+

+  double m = exposure != null ?

+             Math.pow(2.0, (exposure + 2.47393).clamp(-20.0, 20.0)) :

+             1.0;

+

+  for (int y = 0, di = 0; y < hdr.height; ++y) {

+    for (int x = 0; x < hdr.width; ++x) {

+      double r = hdr.getRed(x, y);

+      double g = hdr.getGreen(x, y);

+      double b = hdr.getBlue(x, y);

+

+      if (r.isInfinite || r.isNaN) {

+        r = 0.0;

+      }

+      if (g.isInfinite || g.isNaN) {

+        g = 0.0;

+      }

+      if (b.isInfinite || b.isNaN) {

+        b = 0.0;

+      }

+

+      double ri, gi, bi;

+      if (exposure != null) {

+        ri = _gamma(r, m);

+        gi = _gamma(g, m);

+        bi = _gamma(b, m);

+      } else {

+        ri = (r * 255.0);

+        gi = (g * 255.0);

+        bi = (b * 255.0);

+      }

+

+      // Normalize the color

+      double mi = Math.max(ri, Math.max(gi, bi));

+      if (mi > 255.0) {

+        ri = 255.0 * (ri / mi);

+        gi = 255.0 * (gi / mi);

+        bi = 255.0 * (bi / mi);

+      }

+

+      pixels[di++] = ri.toInt().clamp(0, 255);

+      pixels[di++] = gi.toInt().clamp(0, 255);

+      pixels[di++] = bi.toInt().clamp(0, 255);

+

+      if (hdr.alpha != null) {

+        double a = hdr.alpha.getFloat(x, y);

+        if (a.isInfinite || a.isNaN) {

+          a = 1.0;

+        }

+        pixels[di++] = (a * 255.0).toInt().clamp(0, 255);

+      } else {

+        pixels[di++] = 255;

+      }

+    }

+  }

+

+  return image;

+}

diff --git a/image/lib/src/hdr/reinhard_tone_map.dart b/image/lib/src/hdr/reinhard_tone_map.dart
old mode 100644
new mode 100755
index 3627b0c..b32400e
--- a/image/lib/src/hdr/reinhard_tone_map.dart
+++ b/image/lib/src/hdr/reinhard_tone_map.dart
@@ -1,47 +1,47 @@
-import 'dart:math' as Math;
-
-import 'hdr_image.dart';
-
-/**
- * Applies Reinhard tone mapping to the hdr image, in-place.
- */
-HdrImage reinhardToneMap(HdrImage hdr) {
-  const List<double> yw = const [0.212671, 0.715160, 0.072169 ];
-
-  // Compute world adaptation luminance, _Ywa_
-  double Ywa = 0.0;
-  for (int y = 0; y < hdr.height; ++y) {
-    for (int x = 0; x < hdr.width; ++x) {
-      double r = hdr.getRed(x, y);
-      double g = hdr.getGreen(x, y);
-      double b = hdr.getBlue(x, y);
-
-      double lum = yw[0] * r + yw[1] * g + yw[2] * b;
-      if (lum > 1.0e-4) {
-        Ywa += Math.log(lum);
-      }
-    }
-  }
-
-  Ywa = Math.exp(Ywa / (hdr.width * hdr.height));
-
-  double invY2 = 1.0 / (Ywa * Ywa);
-
-  for (int y = 0; y < hdr.height; ++y) {
-    for (int x = 0; x < hdr.width; ++x) {
-      double r = hdr.getRed(x, y);
-      double g = hdr.getGreen(x, y);
-      double b = hdr.getBlue(x, y);
-
-      double lum = yw[0] * r + yw[1] * g + yw[2] * b;
-
-      double s = (1.0 + lum * invY2) / (1.0 + lum);
-
-      hdr.setRed(x, y, r * s);
-      hdr.setGreen(x, y, g * s);
-      hdr.setBlue(x, y, b * s);
-    }
-  }
-
-  return hdr;
-}
+import 'dart:math' as Math;

+

+import 'hdr_image.dart';

+

+/**

+ * Applies Reinhard tone mapping to the hdr image, in-place.

+ */

+HdrImage reinhardToneMap(HdrImage hdr) {

+  const List<double> yw = const [0.212671, 0.715160, 0.072169 ];

+

+  // Compute world adaptation luminance, _Ywa_

+  double Ywa = 0.0;

+  for (int y = 0; y < hdr.height; ++y) {

+    for (int x = 0; x < hdr.width; ++x) {

+      double r = hdr.getRed(x, y);

+      double g = hdr.getGreen(x, y);

+      double b = hdr.getBlue(x, y);

+

+      double lum = yw[0] * r + yw[1] * g + yw[2] * b;

+      if (lum > 1.0e-4) {

+        Ywa += Math.log(lum);

+      }

+    }

+  }

+

+  Ywa = Math.exp(Ywa / (hdr.width * hdr.height));

+

+  double invY2 = 1.0 / (Ywa * Ywa);

+

+  for (int y = 0; y < hdr.height; ++y) {

+    for (int x = 0; x < hdr.width; ++x) {

+      double r = hdr.getRed(x, y);

+      double g = hdr.getGreen(x, y);

+      double b = hdr.getBlue(x, y);

+

+      double lum = yw[0] * r + yw[1] * g + yw[2] * b;

+

+      double s = (1.0 + lum * invY2) / (1.0 + lum);

+

+      hdr.setRed(x, y, r * s);

+      hdr.setGreen(x, y, g * s);

+      hdr.setBlue(x, y, b * s);

+    }

+  }

+

+  return hdr;

+}

diff --git a/image/lib/src/icc_profile_data.dart b/image/lib/src/icc_profile_data.dart
old mode 100644
new mode 100755
index 8c40a04..823cceb
--- a/image/lib/src/icc_profile_data.dart
+++ b/image/lib/src/icc_profile_data.dart
@@ -1,45 +1,45 @@
-import 'dart:typed_data';
-import 'package:archive/archive.dart';
-
-enum ICCPCompression {
-  none,
-  deflate
-}
-
-/**
- * ICC Profile data stored with an image.
- */
-class ICCProfileData {
-  String name = "";
-  ICCPCompression compression;
-  Uint8List data;
-
-  ICCProfileData(this.name, this.compression, this.data);
-
-  ICCProfileData.from(ICCProfileData other)
-      : name = other.name,
-        compression = other.compression,
-        data = new Uint8List.fromList(other.data);
-
-  /// Returns the compressed data of the ICC Profile, compressing the stored
-  /// data as necessary.
-  Uint8List compressed() {
-    if (compression == ICCPCompression.deflate) {
-      return data;
-    }
-    data = ZLibEncoder().encode(data);
-    compression = ICCPCompression.deflate;
-    return data;
-  }
-
-  /// Returns the uncompressed data of the ICC Profile, decompressing the stored
-  /// data as necessary.
-  Uint8List decompressed() {
-    if (compression == ICCPCompression.deflate) {
-      return data;
-    }
-    data = ZLibDecoder().decodeBytes(data);
-    compression = ICCPCompression.none;
-    return data;
-  }
-}
+import 'dart:typed_data';

+import 'package:archive/archive.dart';

+

+enum ICCPCompression {

+  none,

+  deflate

+}

+

+/**

+ * ICC Profile data stored with an image.

+ */

+class ICCProfileData {

+  String name = "";

+  ICCPCompression compression;

+  Uint8List data;

+

+  ICCProfileData(this.name, this.compression, this.data);

+

+  ICCProfileData.from(ICCProfileData other)

+      : name = other.name,

+        compression = other.compression,

+        data = Uint8List.fromList(other.data);

+

+  /// Returns the compressed data of the ICC Profile, compressing the stored

+  /// data as necessary.

+  Uint8List compressed() {

+    if (compression == ICCPCompression.deflate) {

+      return data;

+    }

+    data = ZLibEncoder().encode(data);

+    compression = ICCPCompression.deflate;

+    return data;

+  }

+

+  /// Returns the uncompressed data of the ICC Profile, decompressing the stored

+  /// data as necessary.

+  Uint8List decompressed() {

+    if (compression == ICCPCompression.deflate) {

+      return data;

+    }

+    data = ZLibDecoder().decodeBytes(data);

+    compression = ICCPCompression.none;

+    return data;

+  }

+}

diff --git a/image/lib/src/image.dart b/image/lib/src/image.dart
old mode 100644
new mode 100755
index 762e805..d190340
--- a/image/lib/src/image.dart
+++ b/image/lib/src/image.dart
@@ -75,8 +75,8 @@
         ICCProfileData iccp]) :

     this.width = width,

     this.height = height,

-    data = new Uint32List(width * height),

-    exif = new ExifData.from(exif),

+    data = Uint32List(width * height),

+    exif = ExifData.from(exif),

     iccProfile = iccp;

 

   /**

@@ -91,8 +91,8 @@
     disposeMethod = other.disposeMethod,

     blendMethod = other.blendMethod,

     _format = other._format,

-    data = new Uint32List.fromList(other.data),

-    exif = new ExifData.from(other.exif),

+    data = Uint32List.fromList(other.data),

+    exif = ExifData.from(other.exif),

     iccProfile = other.iccProfile;

 

   /**

@@ -105,7 +105,7 @@
    * For example, given an Html Canvas, you could create an image:

    * var bytes = canvas.getContext('2d').getImageData(0, 0,

    *   canvas.width, canvas.height).data;

-   * Image image = new Image.fromBytes(canvas.width, canvas.height, bytes);

+   * Image image = Image.fromBytes(canvas.width, canvas.height, bytes);

    */

   Image.fromBytes(int width, int height, List<int> bytes,

                   [this._format = RGBA, ExifData exif, ICCProfileData iccp]) :

@@ -117,7 +117,7 @@
             bytes is Uint8ClampedList ? new Uint32List.view(bytes.buffer) :

             bytes is Uint32List ? new Uint32List.view(bytes.buffer) :

             new Uint32List.view(new Uint8List.fromList(bytes).buffer),

-    exif = new ExifData.from(exif),

+    exif = ExifData.from(exif),

     iccProfile = iccp;

 

   /**

diff --git a/image/lib/src/image_exception.dart b/image/lib/src/image_exception.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/internal/bit_operators.dart b/image/lib/src/internal/bit_operators.dart
old mode 100644
new mode 100755
index ab3f4e6..e5eae4a
--- a/image/lib/src/internal/bit_operators.dart
+++ b/image/lib/src/internal/bit_operators.dart
@@ -84,21 +84,21 @@
   return __float32ToUint32[0];

 }

 

-final Uint8List __uint8 = new Uint8List(1);

-final Int8List __uint8ToInt8 = new Int8List.view(__uint8.buffer);

+final Uint8List __uint8 = Uint8List(1);

+final Int8List __uint8ToInt8 = Int8List.view(__uint8.buffer);

 

-final Uint16List __uint16 = new Uint16List(1);

-final Int16List __uint16ToInt16 = new Int16List.view(__uint16.buffer);

+final Uint16List __uint16 = Uint16List(1);

+final Int16List __uint16ToInt16 = Int16List.view(__uint16.buffer);

 

-final Uint32List __uint32 = new Uint32List(1);

-final Int32List __uint32ToInt32 = new Int32List.view(__uint32.buffer);

-final Float32List __uint32ToFloat32 = new Float32List.view(__uint32.buffer);

+final Uint32List __uint32 = Uint32List(1);

+final Int32List __uint32ToInt32 = Int32List.view(__uint32.buffer);

+final Float32List __uint32ToFloat32 = Float32List.view(__uint32.buffer);

 

-final Int32List __int32 = new Int32List(1);

-final Uint32List __int32ToUint32 = new Uint32List.view(__int32.buffer);

+final Int32List __int32 = Int32List(1);

+final Uint32List __int32ToUint32 = Uint32List.view(__int32.buffer);

 

-final Float32List __float32 = new Float32List(1);

-final Uint32List __float32ToUint32 = new Uint32List.view(__float32.buffer);

+final Float32List __float32 = Float32List(1);

+final Uint32List __float32ToUint32 = Uint32List.view(__float32.buffer);

 

-final Uint64List __uint64 = new Uint64List(1);

-final Float64List __uint64ToFloat64 = new Float64List.view(__uint64.buffer);
\ No newline at end of file
+final Uint64List __uint64 = Uint64List(1);

+final Float64List __uint64ToFloat64 = Float64List.view(__uint64.buffer);
\ No newline at end of file
diff --git a/image/lib/src/internal/clamp.dart b/image/lib/src/internal/clamp.dart
old mode 100644
new mode 100755
index ec3157a..554bc6f
--- a/image/lib/src/internal/clamp.dart
+++ b/image/lib/src/internal/clamp.dart
@@ -1,3 +1,3 @@
-int clamp(int x, int a, int b) => x.clamp(a, b);
-
-int clamp255(int x) => x.clamp(0, 255);
+int clamp(int x, int a, int b) => x.clamp(a, b);

+

+int clamp255(int x) => x.clamp(0, 255);

diff --git a/image/lib/src/internal/internal.dart b/image/lib/src/internal/internal.dart
old mode 100644
new mode 100755
index 2289c3b..4c14ba7
--- a/image/lib/src/internal/internal.dart
+++ b/image/lib/src/internal/internal.dart
@@ -1,7 +1,7 @@
-/// Annotates a function or class that's for internal use within the image
-/// library and is not to be exported as part of the main API.
-const _Internal internal = const _Internal();
-
-class _Internal {
-  const _Internal();
-}
+/// Annotates a function or class that's for internal use within the image

+/// library and is not to be exported as part of the main API.

+const _Internal internal = const _Internal();

+

+class _Internal {

+  const _Internal();

+}

diff --git a/image/lib/src/transform/bake_orientation.dart b/image/lib/src/transform/bake_orientation.dart
old mode 100644
new mode 100755
index b05245b..13392e2
--- a/image/lib/src/transform/bake_orientation.dart
+++ b/image/lib/src/transform/bake_orientation.dart
@@ -1,38 +1,38 @@
-import '../image.dart';
-import '../exif_data.dart';
-import 'flip.dart';
-import 'copy_rotate.dart';
-
-/**
- * If [image] has an orientation value in its exif data, this will rotate the
- * image so that it physically matches its orientation. This can be used to
- * bake the orientation of the image for image formats that don't support exif
- * data.
- */
-Image bakeOrientation(Image image) {
-  Image bakedImage = new Image.from(image);
-  if (!image.exif.hasOrientation || image.exif.orientation == 1) {
-    return bakedImage;
-  }
-
-  // Clear the exif data.
-  // TODO: only clear the orientation property
-  bakedImage.exif = new ExifData();
-  switch (image.exif.orientation) {
-    case 2:
-      return flipHorizontal(bakedImage);
-    case 3:
-      return flip(bakedImage, FLIP_BOTH);
-    case 4:
-      return flipHorizontal(copyRotate(bakedImage, 180));
-    case 5:
-      return flipHorizontal(copyRotate(bakedImage, 90));
-    case 6:
-      return copyRotate(bakedImage, 90);
-    case 7:
-      return flipHorizontal(copyRotate(bakedImage, -90));
-    case 8:
-      return copyRotate(bakedImage, -90);
-  }
-  return bakedImage;
-}
+import '../image.dart';

+import '../exif_data.dart';

+import 'flip.dart';

+import 'copy_rotate.dart';

+

+/**

+ * If [image] has an orientation value in its exif data, this will rotate the

+ * image so that it physically matches its orientation. This can be used to

+ * bake the orientation of the image for image formats that don't support exif

+ * data.

+ */

+Image bakeOrientation(Image image) {

+  Image bakedImage = Image.from(image);

+  if (!image.exif.hasOrientation || image.exif.orientation == 1) {

+    return bakedImage;

+  }

+

+  // Clear the exif data.

+  // TODO: only clear the orientation property

+  bakedImage.exif = ExifData();

+  switch (image.exif.orientation) {

+    case 2:

+      return flipHorizontal(bakedImage);

+    case 3:

+      return flip(bakedImage, FLIP_BOTH);

+    case 4:

+      return flipHorizontal(copyRotate(bakedImage, 180));

+    case 5:

+      return flipHorizontal(copyRotate(bakedImage, 90));

+    case 6:

+      return copyRotate(bakedImage, 90);

+    case 7:

+      return flipHorizontal(copyRotate(bakedImage, -90));

+    case 8:

+      return copyRotate(bakedImage, -90);

+  }

+  return bakedImage;

+}

diff --git a/image/lib/src/transform/copy_crop.dart b/image/lib/src/transform/copy_crop.dart
old mode 100644
new mode 100755
index ea765ba..4c03c09
--- a/image/lib/src/transform/copy_crop.dart
+++ b/image/lib/src/transform/copy_crop.dart
@@ -4,7 +4,7 @@
  * Returns a cropped copy of [src].

  */

 Image copyCrop(Image src, int x, int y, int w, int h) {

-  Image dst = new Image(w, h, src.format, src.exif, src.iccProfile);

+  Image dst = Image(w, h, src.format, src.exif, src.iccProfile);

 

   for (int yi = 0, sy = y; yi < h; ++yi, ++sy) {

     for (int xi = 0, sx = x; xi < w; ++xi, ++sx) {

diff --git a/image/lib/src/transform/copy_into.dart b/image/lib/src/transform/copy_into.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/transform/copy_rectify.dart b/image/lib/src/transform/copy_rectify.dart
new file mode 100755
index 0000000..6eebcdb
--- /dev/null
+++ b/image/lib/src/transform/copy_rectify.dart
@@ -0,0 +1,25 @@
+import '../image.dart';

+import '../util/point.dart';

+

+/**

+ * Returns a copy of the [src] image, where the given rectangle

+ * has been mapped to the full image.

+ */

+Image copyRectify(Image src, {Point topLeft, Point topRight, Point bottomLeft,

+                  Point bottomRight, Image toImage = null}) {

+  Image dst = toImage == null ? Image.from(src) : toImage;

+  for (int y = 0; y < dst.height; ++y) {

+    double v = y / (dst.height - 1);

+    for (int x = 0; x < dst.width; ++x) {

+      double u = x / (dst.width - 1);

+      // bilinear interpolation

+      Point srcPixelCoord = topLeft * (1 - u) * (1 - v) +

+                            topRight * (u) * (1 - v) +

+                            bottomLeft * (1 - u) * (v) +

+                            bottomRight * (u) * (v);

+      var srcPixel = src.getPixel(srcPixelCoord.xi, srcPixelCoord.yi);

+      dst.setPixel(x, y, srcPixel);

+    }

+  }

+  return dst;

+}

diff --git a/image/lib/src/transform/copy_resize.dart b/image/lib/src/transform/copy_resize.dart
old mode 100644
new mode 100755
index 37856c9..03df52e
--- a/image/lib/src/transform/copy_resize.dart
+++ b/image/lib/src/transform/copy_resize.dart
@@ -14,7 +14,7 @@
  * of [src] and [height].

  */

 Image copyResize(Image src, int width, [int height = -1,

-                 int interpolation = LINEAR]) {

+                 int interpolation = NEAREST]) {

   if (width <= 0 && height <= 0) {

     throw new ImageException('Invalid size');

   }

@@ -29,7 +29,7 @@
     width = (height * (src.width / src.height)).toInt();

   }

 

-  Image dst = new Image(width, height, src.format, src.exif, src.iccProfile);

+  Image dst = Image(width, height, src.format, src.exif, src.iccProfile);

 

   double dy = src.height / height;

   double dx = src.width / width;

@@ -69,6 +69,17 @@
         dst.setPixel(x, y, getColor(r ~/ np, g ~/ np, b ~/ np, a ~/ np));

       }

     }

+  } else if (interpolation == NEAREST) {

+    final scaleX = Int32List(width);

+    for (int x = 0; x < width; ++x) {

+      scaleX[x] = (x * dx).toInt();

+    }

+    for (int y = 0; y < height; ++y) {

+      int y2 = (y * dy).toInt();

+      for (int x = 0; x < width; ++x) {

+        dst.setPixel(x, y, src.getPixel(scaleX[x], y2));

+      }

+    }

   } else {

     // Copy the pixels from this image to the new image.

     for (int y = 0; y < height; ++y) {

diff --git a/image/lib/src/transform/copy_rotate.dart b/image/lib/src/transform/copy_rotate.dart
old mode 100644
new mode 100755
index fd099f9..31e3c2f
--- a/image/lib/src/transform/copy_rotate.dart
+++ b/image/lib/src/transform/copy_rotate.dart
@@ -17,7 +17,7 @@
     int iangle = nangle ~/ 90.0;

     switch (iangle) {

       case 1: // 90 deg.

-        Image dst = new Image(src.height, src.width, src.format, src.exif,

+        Image dst = Image(src.height, src.width, src.format, src.exif,

                               src.iccProfile);

         for (int y = 0; y < dst.height; ++y) {

           for (int x = 0; x < dst.width; ++x) {

@@ -26,7 +26,7 @@
         }

         return dst;

       case 2: // 180 deg.

-        Image dst = new Image(src.width, src.height, src.format, src.exif,

+        Image dst = Image(src.width, src.height, src.format, src.exif,

                               src.iccProfile);

         for (int y = 0; y < dst.height; ++y) {

           for (int x = 0; x < dst.width; ++x) {

@@ -35,7 +35,7 @@
         }

         return dst;

       case 3: // 270 deg.

-        Image dst = new Image(src.height, src.width, src.format, src.exif,

+        Image dst = Image(src.height, src.width, src.format, src.exif,

                               src.iccProfile);

         for (int y = 0; y < dst.height; ++y) {

           for (int x = 0; x < dst.width; ++x) {

@@ -61,7 +61,7 @@
   double dw2 = 0.5 * (ux + vx);

   double dh2 = 0.5 * (uy + vy);

 

-  Image dst = new Image((ux + vx).toInt(), (uy + vy).toInt(), Image.RGBA,

+  Image dst = Image((ux + vx).toInt(), (uy + vy).toInt(), Image.RGBA,

                         src.exif, src.iccProfile);

 

   for (int y = 0; y < dst.height; ++y) {

diff --git a/image/lib/src/transform/flip.dart b/image/lib/src/transform/flip.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/transform/trim.dart b/image/lib/src/transform/trim.dart
old mode 100644
new mode 100755
index 9a88394..1fa9f54
--- a/image/lib/src/transform/trim.dart
+++ b/image/lib/src/transform/trim.dart
@@ -110,7 +110,7 @@
 

   List<int> crop = findTrim(src, mode: mode, sides: sides);

 

-  Image dst = new Image(crop[2], crop[3], Image.RGBA, src.exif, src.iccProfile);

+  Image dst = Image(crop[2], crop[3], Image.RGBA, src.exif, src.iccProfile);

   copyInto(dst, src, srcX: crop[0], srcY: crop[1],

            srcW: crop[2], srcH: crop[3], blend: false);

 

diff --git a/image/lib/src/util/clip_line.dart b/image/lib/src/util/clip_line.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/util/input_buffer.dart b/image/lib/src/util/input_buffer.dart
old mode 100644
new mode 100755
index 7d42795..ba5338e
--- a/image/lib/src/util/input_buffer.dart
+++ b/image/lib/src/util/input_buffer.dart
@@ -172,7 +172,7 @@
 

     InputBuffer s = readBytes(len);

     Uint8List bytes = s.toUint8List();

-    String str = new String.fromCharCodes(bytes);

+    String str = String.fromCharCodes(bytes);

     return str;

   }

 

diff --git a/image/lib/src/util/interpolation.dart b/image/lib/src/util/interpolation.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/util/min_max.dart b/image/lib/src/util/min_max.dart
old mode 100644
new mode 100755
diff --git a/image/lib/src/util/neural_quantizer.dart b/image/lib/src/util/neural_quantizer.dart
old mode 100644
new mode 100755
index fced820..1551bec
--- a/image/lib/src/util/neural_quantizer.dart
+++ b/image/lib/src/util/neural_quantizer.dart
@@ -1,8 +1,9 @@
+import 'dart:math';

 import 'dart:typed_data';

-

 import '../color.dart';

 import '../image.dart';

 import '../image_exception.dart';

+import 'quantizer.dart';

 

 /* NeuQuant Neural-Net Quantization Algorithm

  * ------------------------------------------

@@ -29,18 +30,20 @@
  */

 

 /**

- * Compute a 256 color map that best represents the given image.

+ * Compute a color map with a given number of colors that best represents

+ * the given image.

  */

-class NeuralQuantizer {

-  Uint8List colorMap = new Uint8List(NET_SIZE * 3);

+class NeuralQuantizer extends Quantizer {

+  Uint8List colorMap;

 

-  NeuralQuantizer(Image image) {

+  NeuralQuantizer(Image image, {int numberOfColors=256}) {

     if (image.width * image.height < MAX_PRIME) {

       throw new ImageException('Image is too small');

     }

 

-    _setupArrays();

+    _initialize(numberOfColors);

 

+    _setupArrays();

     addImage(image);

   }

 

@@ -100,13 +103,28 @@
    * Convert the [image] to an index map, mapping to this [colorMap].

    */

   Uint8List getIndexMap(Image image) {

-    Uint8List map = new Uint8List(image.width * image.height);

+    Uint8List map = Uint8List(image.width * image.height);

     for (int i = 0, len = image.length; i < len; ++i) {

       map[i] = lookup(image[i]);

     }

     return map;

   }

 

+  void _initialize(int numberOfColors) {

+    NET_SIZE = max(numberOfColors, 4); // number of colours used

+    CUT_NET_SIZE = NET_SIZE - SPECIALS;

+    MAX_NET_POS = NET_SIZE - 1;

+    INIT_RAD = NET_SIZE ~/ 8; // for 256 cols, radius starts at 32

+    INIT_BIAS_RADIUS = INIT_RAD * RADIUS_BIAS;

+    _network = List<double>(NET_SIZE * 3);

+    _colorMap = Int32List(NET_SIZE * 4);

+    _bias = List<double>(NET_SIZE);

+    _freq = List<double>(NET_SIZE);

+    colorMap = Uint8List(NET_SIZE * 3);

+    SPECIALS = 3; // number of reserved colours used

+    BG_COLOR = SPECIALS - 1;

+  }

+

   void _copyColorMap() {

     for (int i = 0, p = 0, q = 0; i < NET_SIZE; ++i) {

       colorMap[p++] = _colorMap[q + 2].abs() & 0xff;

@@ -259,7 +277,6 @@
     }

   }

 

-

   void _learn(Image image) {

     int biasRadius = INIT_BIAS_RADIUS;

     int alphadec = 30 + ((_sampleFac - 1) ~/ 3);

@@ -460,16 +477,16 @@
 

   static const int NUM_CYCLES = 100; // no. of learning cycles

 

-  static const int NET_SIZE = 256; // number of colours used

-  static const int SPECIALS = 3; // number of reserved colours used

-  static const int BG_COLOR = SPECIALS - 1; // reserved background colour

-  static const int CUT_NET_SIZE = NET_SIZE - SPECIALS;

-  static const int MAX_NET_POS = NET_SIZE - 1;

+  int NET_SIZE = 16; // number of colours used

+  int SPECIALS = 3; // number of reserved colours used

+  int BG_COLOR; // reserved background colour

+  int CUT_NET_SIZE;

+  int MAX_NET_POS;

 

-  static const int INIT_RAD = NET_SIZE ~/ 8; // for 256 cols, radius starts at 32

+  int INIT_RAD; // for 256 cols, radius starts at 32

   static const int RADIUS_BIAS_SHIFT = 6;

   static const int RADIUS_BIAS = 1 << RADIUS_BIAS_SHIFT;

-  static const int INIT_BIAS_RADIUS = INIT_RAD * RADIUS_BIAS;

+  int INIT_BIAS_RADIUS;

   static const int RADIUS_DEC = 30; // factor of 1/30 each cycle

 

   static const int ALPHA_BIAS_SHIFT = 10; // alpha starts at 1

@@ -480,12 +497,12 @@
   static const double BETA_GAMMA = BETA * GAMMA;

 

   /// the network itself

-  List<double> _network = new List<double>(NET_SIZE * 3);

-  Int32List _colorMap = new Int32List(NET_SIZE * 4);

-  Int32List _netIndex = new Int32List(256);

+  List<double> _network ;

+  Int32List _colorMap;

+  Int32List _netIndex = Int32List(256);

   // bias and freq arrays for learning

-  List<double> _bias = new List<double>(NET_SIZE);

-  List<double> _freq = new List<double>(NET_SIZE);

+  List<double> _bias;

+  List<double> _freq;

 

   // four primes near 500 - assume no image has a length so large

   // that it is divisible by all four primes

diff --git a/image/lib/src/util/octree_quantizer.dart b/image/lib/src/util/octree_quantizer.dart
new file mode 100755
index 0000000..ee1ed43
--- /dev/null
+++ b/image/lib/src/util/octree_quantizer.dart
@@ -0,0 +1,204 @@
+import '../color.dart';

+import '../image.dart';

+import 'quantizer.dart';

+

+// Color quantization using octree,

+// from https://rosettacode.org/wiki/Color_quantization/C

+class OctreeQuantizer extends Quantizer {

+  _OctreeNode _root;

+

+  OctreeQuantizer(Image image, {int numberOfColors=256}) {

+    _root = _OctreeNode(0, 0, null);

+

+    _HeapNode heap = _HeapNode();

+    for (int si = 0; si < image.length; ++si) {

+      int c = image[si];

+      int r = getRed(c);

+      int g = getGreen(c);

+      int b = getBlue(c);

+      _heapAdd(heap, _nodeInsert(_root, r, g, b));

+    }

+

+    int nc = numberOfColors + 1;

+    while (heap.n > nc) {

+      _heapAdd(heap, _nodeFold(_popHeap(heap)));

+    }

+

+    for (int i = 1; i < heap.n; i++) {

+      var got = heap.buf[i];

+      int c = got.count;

+      got.r = (got.r / c).round();

+      got.g = (got.g / c).round();

+      got.b = (got.b / c).round();

+    }

+  }

+

+  /**

+   * Find the index of the closest color to [c] in the [colorMap].

+   */

+  int getQuantizedColor(int c) {

+    int r = getRed(c);

+    int g = getGreen(c);

+    int b = getBlue(c);

+    var root = _root;

+

+    for (int bit = 1 << 7; bit != 0; bit >>= 1) {

+      int i = ((g & bit) != 0 ? 1 : 0) * 4 +

+              ((r & bit) != 0 ? 1 : 0) * 2 +

+              ((b & bit) != 0 ? 1 : 0);

+      if (root.children[i] == null) {

+        break;

+      }

+      root = root.children[i];

+    }

+

+    r = root.r;

+    g = root.g;

+    b = root.b;

+    return getColor(r, g, b, 255);

+  }

+

+  int _compareNode(_OctreeNode a, _OctreeNode b) {

+    if (a.childCount < b.childCount) {

+      return -1;

+    }

+    if (a.childCount > b.childCount) {

+      return 1;

+    }

+

+    int ac = a.count >> a.depth;

+    int bc = b.count >> b.depth;

+    return (ac < bc) ? -1 : (ac > bc) ? 1 : 0;

+  }

+

+

+  _OctreeNode _nodeInsert(_OctreeNode root, int r, int g, int b) {

+    int depth = 0;

+    for (int bit = 1 << 7; ++depth < 8; bit >>= 1) {

+      int i = ((g & bit) != 0 ? 1 : 0) * 4 +

+          ((r & bit) != 0 ? 1 : 0) * 2 + ((b & bit) != 0 ? 1 : 0);

+      if (root.children[i] == null) {

+        root.children[i] = _OctreeNode(i, depth, root);

+      }

+

+      root = root.children[i];

+    }

+

+    root.r += r;

+    root.g += g;

+    root.b += b;

+    root.count++;

+    return root;

+  }

+

+  _OctreeNode _nodeFold(_OctreeNode p) {

+    if (p.childCount > 0) {

+      return null;

+    }

+    var q = p.parent;

+    q.count += p.count;

+

+    q.r += p.r;

+    q.g += p.g;

+    q.b += p.b;

+    q.childCount--;

+    q.children[p.childIndex] = null;

+    return q;

+  }

+

+  static const _ON_INHEAP = 1;

+

+  _OctreeNode _popHeap(_HeapNode h) {

+    if (h.n <= 1) {

+      return null;

+    }

+

+    _OctreeNode ret = h.buf[1];

+    h.buf[1] = h.buf.removeLast();

+    h.buf[1].heap_idx = 1;

+    _downHeap(h, h.buf[1]);

+

+    return ret;

+  }

+

+  void _heapAdd(_HeapNode h, _OctreeNode p) {

+    if ((p.flags & _ON_INHEAP) != 0) {

+      _downHeap(h, p);

+      _upHeap(h, p);

+      return;

+    }

+

+    p.flags |= _ON_INHEAP;

+    p.heap_idx = h.n;

+    h.buf.add(p);

+    _upHeap(h, p);

+  }

+

+  void _downHeap(_HeapNode h, _OctreeNode p) {

+    int n = p.heap_idx;

+    while (true) {

+      int m = n * 2;

+      if (m >= h.n) {

+        break;

+      }

+      if ((m + 1) < h.n && _compareNode(h.buf[m], h.buf[m + 1]) > 0) {

+        m++;

+      }

+

+      if (_compareNode(p, h.buf[m]) <= 0) {

+        break;

+      }

+

+      h.buf[n] = h.buf[m];

+      h.buf[n].heap_idx = n;

+      n = m;

+    }

+

+    h.buf[n] = p;

+    p.heap_idx = n;

+  }

+

+  void _upHeap(_HeapNode h, _OctreeNode p) {

+    int n = p.heap_idx;

+    _OctreeNode prev;

+

+    while (n > 1) {

+      prev = h.buf[n ~/ 2];

+      if (_compareNode(p, prev) >= 0) {

+        break;

+      }

+

+      h.buf[n] = prev;

+      prev.heap_idx = n;

+      n ~/= 2;

+    }

+    h.buf[n] = p;

+    p.heap_idx = n;

+  }

+}

+

+class _OctreeNode {

+  // sum of all colors represented by this node.

+  int r = 0;

+  int g = 0;

+  int b = 0;

+  int count = 0;

+  int heap_idx = 0;

+  List<_OctreeNode> children = List<_OctreeNode>(8);

+  _OctreeNode parent = null;

+  int childCount = 0;

+  int childIndex = 0;

+  int flags = 0;

+  int depth = 0;

+

+  _OctreeNode(this.childIndex, this.depth, this.parent) {

+    if (parent != null) {

+      parent.childCount++;

+    }

+  }

+}

+

+class _HeapNode {

+  List<_OctreeNode> buf = [null];

+  int get n => buf.length;

+}

diff --git a/image/lib/src/util/output_buffer.dart b/image/lib/src/util/output_buffer.dart
old mode 100644
new mode 100755
index 855fa66..8de0a06
--- a/image/lib/src/util/output_buffer.dart
+++ b/image/lib/src/util/output_buffer.dart
@@ -10,7 +10,7 @@
    * Create a byte buffer for writing.

    */

   OutputBuffer({int size: _BLOCK_SIZE, this.bigEndian: false}) :

-    _buffer = new Uint8List(size == null ? _BLOCK_SIZE : size),

+    _buffer = Uint8List(size == null ? _BLOCK_SIZE : size),

     length = 0;

 

   void rewind() {

@@ -28,7 +28,7 @@
    * Clear the buffer.

    */

   void clear() {

-    _buffer = new Uint8List(_BLOCK_SIZE);

+    _buffer = Uint8List(_BLOCK_SIZE);

     length = 0;

   }

 

@@ -120,7 +120,7 @@
   void _expandBuffer([int required]) {

     int blockSize = (required != null) ? required :

                     (_buffer.length == 0) ? _BLOCK_SIZE : (_buffer.length * 2);

-    Uint8List newBuffer = new Uint8List(_buffer.length + blockSize);

+    Uint8List newBuffer = Uint8List(_buffer.length + blockSize);

     newBuffer.setRange(0, _buffer.length, _buffer);

     _buffer = newBuffer;

   }

diff --git a/image/lib/src/util/point.dart b/image/lib/src/util/point.dart
new file mode 100755
index 0000000..8378713
--- /dev/null
+++ b/image/lib/src/util/point.dart
@@ -0,0 +1,22 @@
+

+class Point {

+  num x;

+  num y;

+

+  get xi { return x.toInt(); }

+  get yi { return y.toInt(); }

+

+  Point([this.x = 0, this.y = 0]);

+

+  Point.from(Point other)

+    : x = other.x

+    , y = other.y;

+

+  Point operator*(double s) {

+    return Point(x * s, y * s);

+  }

+

+  Point operator+(Point rhs) {

+    return Point(x + rhs.x, y + rhs.y);

+  }

+}

diff --git a/image/lib/src/util/quantizer.dart b/image/lib/src/util/quantizer.dart
new file mode 100755
index 0000000..0770797
--- /dev/null
+++ b/image/lib/src/util/quantizer.dart
@@ -0,0 +1,7 @@
+

+abstract class Quantizer {

+  /**

+   * Find the index of the closest color to [c] in the [colorMap].

+   */

+  int getQuantizedColor(int c);

+}

diff --git a/image/lib/src/util/random.dart b/image/lib/src/util/random.dart
old mode 100644
new mode 100755
diff --git a/image/pubspec.yaml b/image/pubspec.yaml
old mode 100644
new mode 100755
index 5e7ec47..08b84c2
--- a/image/pubspec.yaml
+++ b/image/pubspec.yaml
@@ -1,13 +1,13 @@
-name: image
-version: 2.0.7
-author: Brendan Duncan <brendanduncan@gmail.com>
-description: Provides server and web apps the ability to load, manipulate, and save images with various image file formats including PNG, JPEG, GIF, WebP, TIFF, TGA, PSD, PVR, and OpenEXR.
-homepage: https://github.com/brendan-duncan/image
-documentation: https://github.com/brendan-duncan/image/wiki
-environment:
-  sdk: '>=2.0.0-dev.49.0 <3.0.0'
-dependencies:
-  archive: '>=1.0.16 <3.0.0'
-  xml: '>=3.2.5 <4.0.0'
-dev_dependencies:
-  test: '>=0.12.42 <2.0.0'
+name: image

+version: 2.0.8

+author: Brendan Duncan <brendanduncan@gmail.com>

+description: Provides server and web apps the ability to load, manipulate, and save images with various image file formats including PNG, JPEG, GIF, WebP, TIFF, TGA, PSD, PVR, and OpenEXR.

+homepage: https://github.com/brendan-duncan/image

+documentation: https://github.com/brendan-duncan/image/wiki

+environment:

+  sdk: '>=2.0.0-dev.49.0 <3.0.0'

+dependencies:

+  archive: '>=1.0.16 <3.0.0'

+  xml: '>=3.2.5 <4.0.0'

+dev_dependencies:

+  test: '>=0.12.42 <2.0.0'

diff --git a/image/tool/travis.sh b/image/tool/travis.sh
index fe6764a..10bff95 100755
--- a/image/tool/travis.sh
+++ b/image/tool/travis.sh
@@ -1,10 +1,10 @@
-#!/bin/bash
-
-# Fast fail the script on failures.
-set -e
-
-# Analyze the code.
-dartanalyzer --fatal-warnings lib/image.dart
-
-# Run the tests.
-pub run build_runner test
+#!/bin/bash

+

+# Fast fail the script on failures.

+set -e

+

+# Analyze the code.

+dartanalyzer --fatal-warnings lib/image.dart

+

+# Run the tests.

+pub run build_runner test

diff --git a/image/web/filter_lab.dart b/image/web/filter_lab.dart
old mode 100644
new mode 100755
index 547046b..c56498e
--- a/image/web/filter_lab.dart
+++ b/image/web/filter_lab.dart
@@ -1,378 +1,378 @@
-import 'dart:html' as Html;
-import 'package:image/image.dart';
-
-Html.ImageData filterImageData;
-Html.CanvasElement canvas;
-Html.DivElement logDiv;
-Image origImage;
-
-void _addControl(String label, String value, Html.DivElement parent,
-                 callback) {
-  Html.LabelElement amountLabel = new Html.LabelElement();
-  amountLabel.text = label + ':';
-  var amountEdit = new Html.InputElement();
-  amountEdit.value = value;
-  amountEdit.id = label + '_edit';
-  amountEdit.onChange.listen((e) {
-    try {
-      double d = double.parse(amountEdit.value);
-      callback(d);
-    } catch (e) {
-    }
-  });
-  amountLabel.htmlFor = label + '_edit';
-  parent.append(amountLabel);
-  parent.append(amountEdit);
-  parent.append(new Html.ParagraphElement());
-}
-
-
-void testSepia() {
-  Html.DivElement sidebar = Html.document.querySelector('#sidebar');
-  sidebar.children.clear();
-
-  var label = new Html.Element.tag('h1');
-  label.text = 'Sepia';
-  sidebar.children.add(label);
-
-  double amount = 1.0;
-
-  void _apply() {
-    Stopwatch t = new Stopwatch();
-    t.start();
-    Image image = new Image.from(origImage);
-    image = sepia(image, amount: amount);
-
-    // Fill the buffer with our image data.
-    filterImageData.data.setRange(0, filterImageData.data.length,
-                                  image.getBytes());
-    // Draw the buffer onto the canvas.
-    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);
-    canvas.context2D.putImageData(filterImageData, 0, 0);
-    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';
-    print(t.elapsedMilliseconds / 1000.0);
-  }
-
-  _addControl('Amount', amount.toString(), sidebar, (v) {
-    amount = v;
-    _apply();
-  });
-
-  _apply();
-}
-
-void testSobel() {
-  Html.DivElement sidebar = Html.document.querySelector('#sidebar');
-  sidebar.children.clear();
-
-  var label = new Html.Element.tag('h1');
-  label.text = 'Sepia';
-  sidebar.children.add(label);
-
-  double amount = 1.0;
-
-  void _apply() {
-    Stopwatch t = new Stopwatch();
-    t.start();
-    Image image = new Image.from(origImage);
-    image = sobel(image, amount: amount);
-
-    // Fill the buffer with our image data.
-    filterImageData.data.setRange(0, filterImageData.data.length,
-                                  image.getBytes());
-    // Draw the buffer onto the canvas.
-    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);
-    canvas.context2D.putImageData(filterImageData, 0, 0);
-    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';
-    print(t.elapsedMilliseconds / 1000.0);
-  }
-
-  _addControl('Amount', amount.toString(), sidebar, (v) {
-    amount = v;
-    _apply();
-  });
-
-  _apply();
-}
-
-void testGaussian() {
-  Html.DivElement sidebar = Html.document.querySelector('#sidebar');
-  sidebar.children.clear();
-
-  var label = new Html.Element.tag('h1');
-  label.text = 'Gaussian Blur';
-  sidebar.children.add(label);
-
-  int radius = 5;
-
-  void _apply() {
-    Stopwatch t = new Stopwatch();
-    t.start();
-    Image image = new Image.from(origImage);
-    image = gaussianBlur(image, radius);
-
-    // Fill the buffer with our image data.
-    filterImageData.data.setRange(0, filterImageData.data.length,
-                                  image.getBytes());
-    // Draw the buffer onto the canvas.
-    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);
-    canvas.context2D.putImageData(filterImageData, 0, 0);
-    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';
-    print(t.elapsedMilliseconds / 1000.0);
-  }
-
-  _addControl('Radius', radius.toString(), sidebar, (v) {
-    radius = v.toInt();
-    _apply();
-  });
-
-  _apply();
-}
-
-void testVignette() {
-  Html.DivElement sidebar = Html.document.querySelector('#sidebar');
-  sidebar.children.clear();
-
-  var label = new Html.Element.tag('h1');
-  label.text = 'Vignette';
-  sidebar.children.add(label);
-
-  double start = 0.3;
-  double end = 0.75;
-  double amount = 1.0;
-
-  void _apply() {
-    Stopwatch t = new Stopwatch();
-    t.start();
-    Image image = new Image.from(origImage);
-    image = vignette(image, start: start, end: end, amount: amount);
-
-    // Fill the buffer with our image data.
-    filterImageData.data.setRange(0, filterImageData.data.length,
-                                  image.getBytes());
-    // Draw the buffer onto the canvas.
-    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);
-    canvas.context2D.putImageData(filterImageData, 0, 0);
-    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';
-    print(t.elapsedMilliseconds / 1000.0);
-  }
-
-  _addControl('Start', start.toString(), sidebar, (v) {
-    start = v;
-    _apply();
-  });
-
-  _addControl('End', end.toString(), sidebar, (v) {
-      end = v;
-      _apply();
-    });
-
-  _addControl('Amount', amount.toString(), sidebar, (v) {
-      amount = v;
-      _apply();
-    });
-
-  _apply();
-}
-
-void testPixelate() {
-  Html.DivElement sidebar = Html.document.querySelector('#sidebar');
-  sidebar.children.clear();
-
-  var label = new Html.Element.tag('h1');
-  label.text = 'Pixelate';
-  sidebar.children.add(label);
-
-  int blockSize = 5;
-
-  void _apply() {
-    Stopwatch t = new Stopwatch();
-    t.start();
-    Image image = new Image.from(origImage);
-    image = pixelate(image, blockSize);
-
-    // Fill the buffer with our image data.
-    filterImageData.data.setRange(0, filterImageData.data.length,
-                                  image.getBytes());
-    // Draw the buffer onto the canvas.
-    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);
-    canvas.context2D.putImageData(filterImageData, 0, 0);
-    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';
-    print(t.elapsedMilliseconds / 1000.0);
-  }
-
-  _addControl('blockSize', blockSize.toString(), sidebar, (v) {
-    blockSize = v.toInt();
-    _apply();
-  });
-
-  _apply();
-}
-
-void testColorOffset() {
-  Html.DivElement sidebar = Html.document.querySelector('#sidebar');
-  sidebar.children.clear();
-
-  var label = new Html.Element.tag('h1');
-  label.text = 'Pixelate';
-  sidebar.children.add(label);
-
-  int red = 0;
-  int green = 0;
-  int blue = 0;
-  int alpha = 0;
-
-  void _apply() {
-    Stopwatch t = new Stopwatch();
-    t.start();
-    Image image = new Image.from(origImage);
-    image = colorOffset(image, red, green, blue, alpha);
-
-    // Fill the buffer with our image data.
-    filterImageData.data.setRange(0, filterImageData.data.length,
-                                  image.getBytes());
-    // Draw the buffer onto the canvas.
-    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);
-    canvas.context2D.putImageData(filterImageData, 0, 0);
-    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';
-    print(t.elapsedMilliseconds / 1000.0);
-  }
-
-  _addControl('red', red.toString(), sidebar, (v) {
-    red = v.toInt();
-    _apply();
-  });
-
-  _addControl('green', red.toString(), sidebar, (v) {
-      green = v.toInt();
-      _apply();
-    });
-
-  _addControl('blue', red.toString(), sidebar, (v) {
-      blue = v.toInt();
-      _apply();
-    });
-
-  _addControl('alpha', red.toString(), sidebar, (v) {
-      alpha = v.toInt();
-      _apply();
-    });
-
-  _apply();
-}
-
-void testAdjustColor() {
-  Html.DivElement sidebar = Html.document.querySelector('#sidebar');
-  sidebar.children.clear();
-
-  var label = new Html.Element.tag('h1');
-  label.text = 'Adjust Color';
-  sidebar.children.add(label);
-
-  double contrast = 1.0;
-  double saturation = 1.0;
-  double brightness = 1.0;
-  double gamma = 0.8;
-  double exposure = 0.3;
-  double hue = 0.0;
-  double amount = 1.0;
-
-  void _apply() {
-    Stopwatch t = new Stopwatch();
-    t.start();
-    Image image = new Image.from(origImage);
-
-    image = adjustColor(image, contrast: contrast, saturation: saturation,
-        brightness: brightness, gamma: gamma, exposure: exposure,
-        hue: hue, amount: amount);
-
-    // Fill the buffer with our image data.
-    filterImageData.data.setRange(0, filterImageData.data.length,
-                                  image.getBytes());
-    // Draw the buffer onto the canvas.
-    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);
-    canvas.context2D.putImageData(filterImageData, 0, 0);
-
-    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';
-    print(t.elapsedMilliseconds / 1000.0);
-  }
-
-  _addControl('Contrast', contrast.toString(), sidebar, (v) {
-    contrast = v;
-    _apply();
-  });
-
-  _addControl('Saturation', saturation.toString(), sidebar, (v) {
-      saturation = v;
-      _apply();
-    });
-
-  _addControl('Brightness', brightness.toString(), sidebar, (v) {
-      brightness = v;
-      _apply();
-    });
-
-  _addControl('Gamma', gamma.toString(), sidebar, (v) {
-      gamma = v;
-      _apply();
-    });
-
-  _addControl('Exposure', exposure.toString(), sidebar, (v) {
-      exposure = v;
-      _apply();
-    });
-
-  _addControl('Hue', hue.toString(), sidebar, (v) {
-      hue = v;
-      _apply();
-    });
-
-  _addControl('Amount', amount.toString(), sidebar, (v) {
-    amount = v;
-    _apply();
-  });
-
-  _apply();
-}
-
-void main() {
-  canvas = Html.document.querySelector('#filter_canvas');
-  logDiv = Html.document.querySelector('#log');
-
-  Html.SelectElement menu = Html.document.querySelector('#FilterType');
-  menu.onChange.listen((e) {
-    if (menu.value == 'Pixelate') {
-      testPixelate();
-    } else if (menu.value == 'Sepia') {
-      testSepia();
-    } else if (menu.value == 'Gaussian') {
-      testGaussian();
-    } else if (menu.value == 'Adjust Color') {
-      testAdjustColor();
-    } else if (menu.value == 'Sobel') {
-      testSobel();
-    } else if (menu.value == 'Vignette') {
-      testVignette();
-    } else if (menu.value == 'Color Offset') {
-      testColorOffset();
-    }
-  });
-
-  Html.ImageElement img = new Html.ImageElement();
-  img.src = 'res/big_buck_bunny.jpg';
-  img.onLoad.listen((e) {
-    var c = new Html.CanvasElement();
-    c.width = img.width;
-    c.height = img.height;
-    c.context2D.drawImage(img, 0, 0);
-
-    var imageData = c.context2D.getImageData(0, 0, img.width, img.height);
-    origImage = new Image.fromBytes(img.width, img.height, imageData.data);
-
-    canvas.width = img.width;
-    canvas.height = img.height;
-    filterImageData = canvas.context2D.createImageData(img.width, img.height);
-
-    testSepia();
-  });
-}
+import 'dart:html' as Html;

+import 'package:image/image.dart';

+

+Html.ImageData filterImageData;

+Html.CanvasElement canvas;

+Html.DivElement logDiv;

+Image origImage;

+

+void _addControl(String label, String value, Html.DivElement parent,

+                 callback) {

+  Html.LabelElement amountLabel = Html.LabelElement();

+  amountLabel.text = label + ':';

+  var amountEdit = Html.InputElement();

+  amountEdit.value = value;

+  amountEdit.id = label + '_edit';

+  amountEdit.onChange.listen((e) {

+    try {

+      double d = double.parse(amountEdit.value);

+      callback(d);

+    } catch (e) {

+    }

+  });

+  amountLabel.htmlFor = label + '_edit';

+  parent.append(amountLabel);

+  parent.append(amountEdit);

+  parent.append(new Html.ParagraphElement());

+}

+

+

+void testSepia() {

+  Html.DivElement sidebar = Html.document.querySelector('#sidebar');

+  sidebar.children.clear();

+

+  var label = Html.Element.tag('h1');

+  label.text = 'Sepia';

+  sidebar.children.add(label);

+

+  double amount = 1.0;

+

+  void _apply() {

+    Stopwatch t = Stopwatch();

+    t.start();

+    Image image = Image.from(origImage);

+    image = sepia(image, amount: amount);

+

+    // Fill the buffer with our image data.

+    filterImageData.data.setRange(0, filterImageData.data.length,

+                                  image.getBytes());

+    // Draw the buffer onto the canvas.

+    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);

+    canvas.context2D.putImageData(filterImageData, 0, 0);

+    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';

+    print(t.elapsedMilliseconds / 1000.0);

+  }

+

+  _addControl('Amount', amount.toString(), sidebar, (v) {

+    amount = v;

+    _apply();

+  });

+

+  _apply();

+}

+

+void testSobel() {

+  Html.DivElement sidebar = Html.document.querySelector('#sidebar');

+  sidebar.children.clear();

+

+  var label = Html.Element.tag('h1');

+  label.text = 'Sepia';

+  sidebar.children.add(label);

+

+  double amount = 1.0;

+

+  void _apply() {

+    Stopwatch t = Stopwatch();

+    t.start();

+    Image image = Image.from(origImage);

+    image = sobel(image, amount: amount);

+

+    // Fill the buffer with our image data.

+    filterImageData.data.setRange(0, filterImageData.data.length,

+                                  image.getBytes());

+    // Draw the buffer onto the canvas.

+    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);

+    canvas.context2D.putImageData(filterImageData, 0, 0);

+    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';

+    print(t.elapsedMilliseconds / 1000.0);

+  }

+

+  _addControl('Amount', amount.toString(), sidebar, (v) {

+    amount = v;

+    _apply();

+  });

+

+  _apply();

+}

+

+void testGaussian() {

+  Html.DivElement sidebar = Html.document.querySelector('#sidebar');

+  sidebar.children.clear();

+

+  var label = Html.Element.tag('h1');

+  label.text = 'Gaussian Blur';

+  sidebar.children.add(label);

+

+  int radius = 5;

+

+  void _apply() {

+    Stopwatch t = Stopwatch();

+    t.start();

+    Image image = Image.from(origImage);

+    image = gaussianBlur(image, radius);

+

+    // Fill the buffer with our image data.

+    filterImageData.data.setRange(0, filterImageData.data.length,

+                                  image.getBytes());

+    // Draw the buffer onto the canvas.

+    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);

+    canvas.context2D.putImageData(filterImageData, 0, 0);

+    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';

+    print(t.elapsedMilliseconds / 1000.0);

+  }

+

+  _addControl('Radius', radius.toString(), sidebar, (v) {

+    radius = v.toInt();

+    _apply();

+  });

+

+  _apply();

+}

+

+void testVignette() {

+  Html.DivElement sidebar = Html.document.querySelector('#sidebar');

+  sidebar.children.clear();

+

+  var label = Html.Element.tag('h1');

+  label.text = 'Vignette';

+  sidebar.children.add(label);

+

+  double start = 0.3;

+  double end = 0.75;

+  double amount = 1.0;

+

+  void _apply() {

+    Stopwatch t = Stopwatch();

+    t.start();

+    Image image = Image.from(origImage);

+    image = vignette(image, start: start, end: end, amount: amount);

+

+    // Fill the buffer with our image data.

+    filterImageData.data.setRange(0, filterImageData.data.length,

+                                  image.getBytes());

+    // Draw the buffer onto the canvas.

+    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);

+    canvas.context2D.putImageData(filterImageData, 0, 0);

+    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';

+    print(t.elapsedMilliseconds / 1000.0);

+  }

+

+  _addControl('Start', start.toString(), sidebar, (v) {

+    start = v;

+    _apply();

+  });

+

+  _addControl('End', end.toString(), sidebar, (v) {

+      end = v;

+      _apply();

+    });

+

+  _addControl('Amount', amount.toString(), sidebar, (v) {

+      amount = v;

+      _apply();

+    });

+

+  _apply();

+}

+

+void testPixelate() {

+  Html.DivElement sidebar = Html.document.querySelector('#sidebar');

+  sidebar.children.clear();

+

+  var label = Html.Element.tag('h1');

+  label.text = 'Pixelate';

+  sidebar.children.add(label);

+

+  int blockSize = 5;

+

+  void _apply() {

+    Stopwatch t = Stopwatch();

+    t.start();

+    Image image = Image.from(origImage);

+    image = pixelate(image, blockSize);

+

+    // Fill the buffer with our image data.

+    filterImageData.data.setRange(0, filterImageData.data.length,

+                                  image.getBytes());

+    // Draw the buffer onto the canvas.

+    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);

+    canvas.context2D.putImageData(filterImageData, 0, 0);

+    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';

+    print(t.elapsedMilliseconds / 1000.0);

+  }

+

+  _addControl('blockSize', blockSize.toString(), sidebar, (v) {

+    blockSize = v.toInt();

+    _apply();

+  });

+

+  _apply();

+}

+

+void testColorOffset() {

+  Html.DivElement sidebar = Html.document.querySelector('#sidebar');

+  sidebar.children.clear();

+

+  var label = Html.Element.tag('h1');

+  label.text = 'Pixelate';

+  sidebar.children.add(label);

+

+  int red = 0;

+  int green = 0;

+  int blue = 0;

+  int alpha = 0;

+

+  void _apply() {

+    Stopwatch t = Stopwatch();

+    t.start();

+    Image image = Image.from(origImage);

+    image = colorOffset(image, red, green, blue, alpha);

+

+    // Fill the buffer with our image data.

+    filterImageData.data.setRange(0, filterImageData.data.length,

+                                  image.getBytes());

+    // Draw the buffer onto the canvas.

+    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);

+    canvas.context2D.putImageData(filterImageData, 0, 0);

+    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';

+    print(t.elapsedMilliseconds / 1000.0);

+  }

+

+  _addControl('red', red.toString(), sidebar, (v) {

+    red = v.toInt();

+    _apply();

+  });

+

+  _addControl('green', red.toString(), sidebar, (v) {

+      green = v.toInt();

+      _apply();

+    });

+

+  _addControl('blue', red.toString(), sidebar, (v) {

+      blue = v.toInt();

+      _apply();

+    });

+

+  _addControl('alpha', red.toString(), sidebar, (v) {

+      alpha = v.toInt();

+      _apply();

+    });

+

+  _apply();

+}

+

+void testAdjustColor() {

+  Html.DivElement sidebar = Html.document.querySelector('#sidebar');

+  sidebar.children.clear();

+

+  var label = Html.Element.tag('h1');

+  label.text = 'Adjust Color';

+  sidebar.children.add(label);

+

+  double contrast = 1.0;

+  double saturation = 1.0;

+  double brightness = 1.0;

+  double gamma = 0.8;

+  double exposure = 0.3;

+  double hue = 0.0;

+  double amount = 1.0;

+

+  void _apply() {

+    Stopwatch t = Stopwatch();

+    t.start();

+    Image image = Image.from(origImage);

+

+    image = adjustColor(image, contrast: contrast, saturation: saturation,

+        brightness: brightness, gamma: gamma, exposure: exposure,

+        hue: hue, amount: amount);

+

+    // Fill the buffer with our image data.

+    filterImageData.data.setRange(0, filterImageData.data.length,

+                                  image.getBytes());

+    // Draw the buffer onto the canvas.

+    canvas.context2D.clearRect(0, 0, canvas.width, canvas.height);

+    canvas.context2D.putImageData(filterImageData, 0, 0);

+

+    logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}';

+    print(t.elapsedMilliseconds / 1000.0);

+  }

+

+  _addControl('Contrast', contrast.toString(), sidebar, (v) {

+    contrast = v;

+    _apply();

+  });

+

+  _addControl('Saturation', saturation.toString(), sidebar, (v) {

+      saturation = v;

+      _apply();

+    });

+

+  _addControl('Brightness', brightness.toString(), sidebar, (v) {

+      brightness = v;

+      _apply();

+    });

+

+  _addControl('Gamma', gamma.toString(), sidebar, (v) {

+      gamma = v;

+      _apply();

+    });

+

+  _addControl('Exposure', exposure.toString(), sidebar, (v) {

+      exposure = v;

+      _apply();

+    });

+

+  _addControl('Hue', hue.toString(), sidebar, (v) {

+      hue = v;

+      _apply();

+    });

+

+  _addControl('Amount', amount.toString(), sidebar, (v) {

+    amount = v;

+    _apply();

+  });

+

+  _apply();

+}

+

+void main() {

+  canvas = Html.document.querySelector('#filter_canvas');

+  logDiv = Html.document.querySelector('#log');

+

+  Html.SelectElement menu = Html.document.querySelector('#FilterType');

+  menu.onChange.listen((e) {

+    if (menu.value == 'Pixelate') {

+      testPixelate();

+    } else if (menu.value == 'Sepia') {

+      testSepia();

+    } else if (menu.value == 'Gaussian') {

+      testGaussian();

+    } else if (menu.value == 'Adjust Color') {

+      testAdjustColor();

+    } else if (menu.value == 'Sobel') {

+      testSobel();

+    } else if (menu.value == 'Vignette') {

+      testVignette();

+    } else if (menu.value == 'Color Offset') {

+      testColorOffset();

+    }

+  });

+

+  Html.ImageElement img = Html.ImageElement();

+  img.src = 'res/big_buck_bunny.jpg';

+  img.onLoad.listen((e) {

+    var c = Html.CanvasElement();

+    c.width = img.width;

+    c.height = img.height;

+    c.context2D.drawImage(img, 0, 0);

+

+    var imageData = c.context2D.getImageData(0, 0, img.width, img.height);

+    origImage = Image.fromBytes(img.width, img.height, imageData.data);

+

+    canvas.width = img.width;

+    canvas.height = img.height;

+    filterImageData = canvas.context2D.createImageData(img.width, img.height);

+

+    testSepia();

+  });

+}

diff --git a/image/web/image_http_input.dart b/image/web/image_http_input.dart
old mode 100644
new mode 100755
index 8a720b4..4b5d991
--- a/image/web/image_http_input.dart
+++ b/image/web/image_http_input.dart
@@ -1,86 +1,86 @@
-import 'dart:html' as Html;
-
-import 'package:image/image.dart';
-import 'dart:convert';
-
-Html.InputElement fileInput;
-
-void main() {
-  // There are at least two ways to get a file into an html dart app:
-  // using a file Input element, or an AJAX HttpRequest.
-
-  // This example demonstrates using a file Input element.
-  fileInput = Html.querySelector("#file");
-
-  fileInput.addEventListener("change", onFileChanged);
-}
-
-/**
- * Called when the user has selected a file.
- */
-void onFileChanged(Html.Event event) {
-  Html.FileList files = fileInput.files;
-  var file = files.item(0);
-
-  Html.FileReader reader = new Html.FileReader();
-  reader.addEventListener("load", onFileLoaded);
-  reader.readAsArrayBuffer(file);
-}
-
-/**
- * Called when the file has been read.
- */
-void onFileLoaded(Html.Event event) {
-  Html.FileReader reader = event.currentTarget;
-
-  var bytes = reader.result;
-
-  // Find a decoder that is able to decode the given file contents.
-  Decoder decoder = findDecoderForData(bytes);
-  if (decoder == null) {
-    print('Could not find format decoder for file');
-    return;
-  }
-
-  // If a decoder was found, decode the file contents into an image.
-  Image image = decoder.decodeImage(bytes);
-
-  // If the image was able to be decoded, we can display it in a couple
-  // different ways.  We could encode it to a format that can be displayed
-  // by an IMG image element (like PNG or JPEG); or we could draw it into
-  // a canvas.
-  if (image != null) {
-    // Add a separator to the html page
-    Html.document.body.append(new Html.ParagraphElement());
-
-    // Draw the image into a canvas.  First create a canvas at the correct
-    // resolution.
-    var c = new Html.CanvasElement();
-    Html.document.body.append(c);
-    c.width = image.width;
-    c.height = image.height;
-
-    // Create a buffer that the canvas can draw.
-    Html.ImageData d = c.context2D.createImageData(c.width, c.height);
-    // Fill the buffer with our image data.
-    d.data.setRange(0, d.data.length, image.getBytes());
-    // Draw the buffer onto the canvas.
-    c.context2D.putImageData(d, 0, 0);
-
-
-    // OR we could use an IMG element to display the image.
-    // This requires encoding it to a common format (like PNG), base64 encoding
-    // the encoded image, and using a data url for the img src.
-
-    var img = new Html.ImageElement();
-    Html.document.body.append(img);
-    // encode the image to a PNG
-    var png = encodePng(image);
-    // base64 encode the png
-    var png64 = base64Encode(png);
-    // set the img src as a data url
-    img.src = 'data:image/png;base64,${png64}';
-  }
-
-  return;
-}
+import 'dart:html' as Html;

+

+import 'package:image/image.dart';

+import 'dart:convert';

+

+Html.InputElement fileInput;

+

+void main() {

+  // There are at least two ways to get a file into an html dart app:

+  // using a file Input element, or an AJAX HttpRequest.

+

+  // This example demonstrates using a file Input element.

+  fileInput = Html.querySelector("#file");

+

+  fileInput.addEventListener("change", onFileChanged);

+}

+

+/**

+ * Called when the user has selected a file.

+ */

+void onFileChanged(Html.Event event) {

+  Html.FileList files = fileInput.files;

+  var file = files.item(0);

+

+  Html.FileReader reader = Html.FileReader();

+  reader.addEventListener("load", onFileLoaded);

+  reader.readAsArrayBuffer(file);

+}

+

+/**

+ * Called when the file has been read.

+ */

+void onFileLoaded(Html.Event event) {

+  Html.FileReader reader = event.currentTarget;

+

+  var bytes = reader.result;

+

+  // Find a decoder that is able to decode the given file contents.

+  Decoder decoder = findDecoderForData(bytes);

+  if (decoder == null) {

+    print('Could not find format decoder for file');

+    return;

+  }

+

+  // If a decoder was found, decode the file contents into an image.

+  Image image = decoder.decodeImage(bytes);

+

+  // If the image was able to be decoded, we can display it in a couple

+  // different ways.  We could encode it to a format that can be displayed

+  // by an IMG image element (like PNG or JPEG); or we could draw it into

+  // a canvas.

+  if (image != null) {

+    // Add a separator to the html page

+    Html.document.body.append(new Html.ParagraphElement());

+

+    // Draw the image into a canvas.  First create a canvas at the correct

+    // resolution.

+    var c = Html.CanvasElement();

+    Html.document.body.append(c);

+    c.width = image.width;

+    c.height = image.height;

+

+    // Create a buffer that the canvas can draw.

+    Html.ImageData d = c.context2D.createImageData(c.width, c.height);

+    // Fill the buffer with our image data.

+    d.data.setRange(0, d.data.length, image.getBytes());

+    // Draw the buffer onto the canvas.

+    c.context2D.putImageData(d, 0, 0);

+

+

+    // OR we could use an IMG element to display the image.

+    // This requires encoding it to a common format (like PNG), base64 encoding

+    // the encoded image, and using a data url for the img src.

+

+    var img = Html.ImageElement();

+    Html.document.body.append(img);

+    // encode the image to a PNG

+    var png = encodePng(image);

+    // base64 encode the png

+    var png64 = base64Encode(png);

+    // set the img src as a data url

+    img.src = 'data:image/png;base64,${png64}';

+  }

+

+  return;

+}

diff --git a/image/web/image_server.dart b/image/web/image_server.dart
old mode 100644
new mode 100755
index 38c1269..ae1b0ea
--- a/image/web/image_server.dart
+++ b/image/web/image_server.dart
@@ -1,34 +1,34 @@
-import 'dart:io' as Io;
-import 'package:image/image.dart';
-
-void main(List<String> argv) {
-  if (argv.length < 1) {
-    print('Usage: image_server <image_file>');
-    return;
-  }
-
-  String filename = argv[0];
-
-  Io.File file = new Io.File(filename);
-  if (!file.existsSync()) {
-    print('File does not exist: ${filename}');
-    return;
-  }
-
-  List<int> fileBytes = file.readAsBytesSync();
-
-  Decoder decoder = findDecoderForData(fileBytes);
-  if (decoder == null) {
-    print('Could not find format decoder for: ${filename}');
-    return;
-  }
-
-  Image image = decoder.decodeImage(fileBytes);
-
-  // ... do something with image ...
-
-  // Save the image as a PNG
-  List<int> png = new PngEncoder().encodeImage(image);
-  // Write the PNG to disk
-  new Io.File(filename + '.png').writeAsBytesSync(png);
-}
+import 'dart:io' as Io;

+import 'package:image/image.dart';

+

+void main(List<String> argv) {

+  if (argv.length < 1) {

+    print('Usage: image_server <image_file>');

+    return;

+  }

+

+  String filename = argv[0];

+

+  Io.File file = Io.File(filename);

+  if (!file.existsSync()) {

+    print('File does not exist: ${filename}');

+    return;

+  }

+

+  List<int> fileBytes = file.readAsBytesSync();

+

+  Decoder decoder = findDecoderForData(fileBytes);

+  if (decoder == null) {

+    print('Could not find format decoder for: ${filename}');

+    return;

+  }

+

+  Image image = decoder.decodeImage(fileBytes);

+

+  // ... do something with image ...

+

+  // Save the image as a PNG

+  List<int> png = PngEncoder().encodeImage(image);

+  // Write the PNG to disk

+  new Io.File(filename + '.png').writeAsBytesSync(png);

+}

diff --git a/image/web/mandelbrot.dart b/image/web/mandelbrot.dart
old mode 100644
new mode 100755
index 25cfde2..5ef0d6c
--- a/image/web/mandelbrot.dart
+++ b/image/web/mandelbrot.dart
@@ -1,72 +1,72 @@
-import 'dart:html' as Html;
-import 'dart:math';
-import 'package:image/image.dart';
-
-double logN(num x, num div) {
-  return log(x) / div;
-}
-
-/**
- * Render the Mandelbrot Set into an Image and display it.
- */
-void main() {
-  const int width = 1024;
-  const int height = 1024;
-
-  // Create a canvas to put our decoded image into.
-  var c = new Html.CanvasElement(width: width, height: height);
-  Html.document.body.append(c);
-
-  double zoom = 1.0;
-  double moveX = -0.5;
-  double moveY = 0.0;
-  const int MaxIterations = 255;
-  const double radius = 2.0;
-  const double radius_squared = radius * radius;
-  final double log2 = log(2.0);
-  double Log2MaxIterations = logN(MaxIterations, log2);
-  const double h_2 = height / 2.0;
-  const double w_2 = width / 2.0;
-  const double aspect = 0.5;
-
-  Image image = new Image(width, height);
-  for (int y = 0; y < height; ++y) {
-    double pi = (y - h_2) / (0.5 * zoom * aspect * height) + moveY;
-
-    for (int x = 0; x < width; ++x) {
-      double pr = 1.5 * (x - w_2) / (0.5 * zoom * width) + moveX;
-
-      double newRe = 0.0;
-      double newIm = 0.0;
-      int i = 0;
-      for (; i < MaxIterations; i++) {
-        double oldRe = newRe;
-        double oldIm = newIm;
-
-        newRe = oldRe * oldRe - oldIm * oldIm + pr;
-        newIm = 2.0 * oldRe * oldIm + pi;
-
-        if ((newRe * newRe + newIm * newIm) > radius_squared) {
-          break;
-        }
-      }
-
-      if (i == MaxIterations) {
-        image.setPixelRGBA(x, y, 0, 0, 0);
-      } else {
-        double z = sqrt(newRe * newRe + newIm * newIm);
-        double b = 256.0 * logN(1.75 + i -
-                   logN(logN(z, log2), log2), log2) / Log2MaxIterations;
-        int brightness = b.toInt();
-        image.setPixelRGBA(x, y, brightness, brightness, 255);
-      }
-    }
-  }
-
-  // Create a buffer that the canvas can draw.
-  Html.ImageData d = c.context2D.createImageData(image.width, image.height);
-  // Fill the buffer with our image data.
-  d.data.setRange(0, d.data.length, image.getBytes());
-  // Draw the buffer onto the canvas.
-  c.context2D.putImageData(d, 0, 0);
-}
+import 'dart:html' as Html;

+import 'dart:math';

+import 'package:image/image.dart';

+

+double logN(num x, num div) {

+  return log(x) / div;

+}

+

+/**

+ * Render the Mandelbrot Set into an Image and display it.

+ */

+void main() {

+  const int width = 1024;

+  const int height = 1024;

+

+  // Create a canvas to put our decoded image into.

+  var c = Html.CanvasElement(width: width, height: height);

+  Html.document.body.append(c);

+

+  double zoom = 1.0;

+  double moveX = -0.5;

+  double moveY = 0.0;

+  const int MaxIterations = 255;

+  const double radius = 2.0;

+  const double radius_squared = radius * radius;

+  final double log2 = log(2.0);

+  double Log2MaxIterations = logN(MaxIterations, log2);

+  const double h_2 = height / 2.0;

+  const double w_2 = width / 2.0;

+  const double aspect = 0.5;

+

+  Image image = Image(width, height);

+  for (int y = 0; y < height; ++y) {

+    double pi = (y - h_2) / (0.5 * zoom * aspect * height) + moveY;

+

+    for (int x = 0; x < width; ++x) {

+      double pr = 1.5 * (x - w_2) / (0.5 * zoom * width) + moveX;

+

+      double newRe = 0.0;

+      double newIm = 0.0;

+      int i = 0;

+      for (; i < MaxIterations; i++) {

+        double oldRe = newRe;

+        double oldIm = newIm;

+

+        newRe = oldRe * oldRe - oldIm * oldIm + pr;

+        newIm = 2.0 * oldRe * oldIm + pi;

+

+        if ((newRe * newRe + newIm * newIm) > radius_squared) {

+          break;

+        }

+      }

+

+      if (i == MaxIterations) {

+        image.setPixelRGBA(x, y, 0, 0, 0);

+      } else {

+        double z = sqrt(newRe * newRe + newIm * newIm);

+        double b = 256.0 * logN(1.75 + i -

+                   logN(logN(z, log2), log2), log2) / Log2MaxIterations;

+        int brightness = b.toInt();

+        image.setPixelRGBA(x, y, brightness, brightness, 255);

+      }

+    }

+  }

+

+  // Create a buffer that the canvas can draw.

+  Html.ImageData d = c.context2D.createImageData(image.width, image.height);

+  // Fill the buffer with our image data.

+  d.data.setRange(0, d.data.length, image.getBytes());

+  // Draw the buffer onto the canvas.

+  c.context2D.putImageData(d, 0, 0);

+}

diff --git a/image/web/res/1.webp b/image/web/res/1.webp
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/1_webp_ll.webp b/image/web/res/1_webp_ll.webp
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/3_webp_a.webp b/image/web/res/3_webp_a.webp
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/BladeRunner_lossy.webp b/image/web/res/BladeRunner_lossy.webp
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/animated.png b/image/web/res/animated.png
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/big_buck_bunny.jpg b/image/web/res/big_buck_bunny.jpg
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/cars.gif b/image/web/res/cars.gif
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/penguins.jpg b/image/web/res/penguins.jpg
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/puppies.jpg b/image/web/res/puppies.jpg
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/res/trees.png b/image/web/res/trees.png
old mode 100644
new mode 100755
Binary files differ
diff --git a/image/web/test_formats.dart b/image/web/test_formats.dart
old mode 100644
new mode 100755
index af839f2..7005f75
--- a/image/web/test_formats.dart
+++ b/image/web/test_formats.dart
@@ -1,102 +1,102 @@
-import 'dart:html' as Html;
-import 'dart:async' as Async;
-import 'dart:typed_data';
-import 'package:image/image.dart';
-
-/**
- * Decode and display various image formats.  This is used as a visual
- * unit-test to indentify problems that may occur after the translation to
- * javascript.
- */
-void main() {
-  // An img on the html page is used to establish the path to the images
-  // directory.  It's removed after we get the path since we'll be populating
-  // the page with our own decoded images.
-  Html.ImageElement img = Html.querySelectorAll('img')[0];
-  String path = img.src.substring(0, img.src.lastIndexOf('/'));
-  img.remove();
-
-  // The list of images we'll be decoding, representing a wide range
-  // of formats and sub-formats.
-  List<String> images = ['penguins.jpg', '1_webp_ll.webp', '1.webp', '3_webp_a.webp',
-                         'puppies.jpg', 'cars.gif', 'trees.png',
-                         'animated.png', 'BladeRunner_lossy.webp'];
-
-  for (String name in images) {
-    // Use an http request to get the image file from disk.
-    var req = new Html.HttpRequest();
-    req.open('GET', path + '/' + name);
-    req.responseType = 'arraybuffer';
-    req.onLoadEnd.listen((e) {
-      if (req.status == 200) {
-        // Convert the text to binary byte list.
-        List<int> bytes = new Uint8List.view(req.response);
-
-        var label = new Html.DivElement();
-        Html.document.body.append(label);
-        label.text = name;
-
-        // Create a canvas to put our decoded image into.
-        var c = new Html.CanvasElement();
-        Html.document.body.append(c);
-
-        // Find the best decoder for the image.
-        Decoder decoder = findDecoderForData(bytes);
-        if (decoder == null) {
-          return;
-        }
-
-        // Some of the files are animated, so always decode to animation.
-        // Single image files will decode to a single framed animation.
-        Animation anim = decoder.decodeAnimation(bytes);
-        if (anim == null) {
-          return;
-        }
-
-        // If it's a single image, dump the decoded image into the canvas.
-        if (anim.length == 1) {
-          Image image = anim.frames[0];
-
-          //Image newImage = copyResize(image, 2000, -1, CUBIC);
-          var newImage = image;
-
-          c.width = newImage.width;
-          c.height = newImage.height;
-
-          // Create a buffer that the canvas can draw.
-          Html.ImageData d = c.context2D.createImageData(c.width, c.height);
-          // Fill the buffer with our image data.
-          d.data.setRange(0, d.data.length, newImage.getBytes());
-          // Draw the buffer onto the canvas.
-          c.context2D.putImageData(d, 0, 0);
-
-          return;
-        }
-
-        // A multi-frame animation, use a timer to draw frames.
-        // TODO this is currently not using the timing information in the
-        // [Animation], and using a hard-coded delay instead.
-
-        // Setup the canvas size to the size of the first image.
-        c.width = anim.frames[0].width;
-        c.height = anim.frames[0].height;
-        // Create a buffer that the canvas can draw.
-        Html.ImageData d = c.context2D.createImageData(c.width, c.height);
-
-        int frame = 0;
-        new Async.Timer.periodic(new Duration(milliseconds: 40), (t) {
-          Image image = anim.frames[frame++];
-          if (frame >= anim.numFrames) {
-            frame = 0;
-          }
-
-          // Fill the buffer with our image data.
-          d.data.setRange(0, d.data.length, image.getBytes());
-          // Draw the buffer onto the canvas.
-          c.context2D.putImageData(d, 0, 0);
-        });
-      }
-   });
-   req.send('');
-  }
-}
+import 'dart:html' as Html;

+import 'dart:async' as Async;

+import 'dart:typed_data';

+import 'package:image/image.dart';

+

+/**

+ * Decode and display various image formats.  This is used as a visual

+ * unit-test to indentify problems that may occur after the translation to

+ * javascript.

+ */

+void main() {

+  // An img on the html page is used to establish the path to the images

+  // directory.  It's removed after we get the path since we'll be populating

+  // the page with our own decoded images.

+  Html.ImageElement img = Html.querySelectorAll('img')[0];

+  String path = img.src.substring(0, img.src.lastIndexOf('/'));

+  img.remove();

+

+  // The list of images we'll be decoding, representing a wide range

+  // of formats and sub-formats.

+  List<String> images = ['penguins.jpg', '1_webp_ll.webp', '1.webp', '3_webp_a.webp',

+                         'puppies.jpg', 'cars.gif', 'trees.png',

+                         'animated.png', 'BladeRunner_lossy.webp'];

+

+  for (String name in images) {

+    // Use an http request to get the image file from disk.

+    var req = Html.HttpRequest();

+    req.open('GET', path + '/' + name);

+    req.responseType = 'arraybuffer';

+    req.onLoadEnd.listen((e) {

+      if (req.status == 200) {

+        // Convert the text to binary byte list.

+        List<int> bytes = Uint8List.view(req.response);

+

+        var label = Html.DivElement();

+        Html.document.body.append(label);

+        label.text = name;

+

+        // Create a canvas to put our decoded image into.

+        var c = Html.CanvasElement();

+        Html.document.body.append(c);

+

+        // Find the best decoder for the image.

+        Decoder decoder = findDecoderForData(bytes);

+        if (decoder == null) {

+          return;

+        }

+

+        // Some of the files are animated, so always decode to animation.

+        // Single image files will decode to a single framed animation.

+        Animation anim = decoder.decodeAnimation(bytes);

+        if (anim == null) {

+          return;

+        }

+

+        // If it's a single image, dump the decoded image into the canvas.

+        if (anim.length == 1) {

+          Image image = anim.frames[0];

+

+          //Image newImage = copyResize(image, 2000, -1, CUBIC);

+          var newImage = image;

+

+          c.width = newImage.width;

+          c.height = newImage.height;

+

+          // Create a buffer that the canvas can draw.

+          Html.ImageData d = c.context2D.createImageData(c.width, c.height);

+          // Fill the buffer with our image data.

+          d.data.setRange(0, d.data.length, newImage.getBytes());

+          // Draw the buffer onto the canvas.

+          c.context2D.putImageData(d, 0, 0);

+

+          return;

+        }

+

+        // A multi-frame animation, use a timer to draw frames.

+        // TODO this is currently not using the timing information in the

+        // [Animation], and using a hard-coded delay instead.

+

+        // Setup the canvas size to the size of the first image.

+        c.width = anim.frames[0].width;

+        c.height = anim.frames[0].height;

+        // Create a buffer that the canvas can draw.

+        Html.ImageData d = c.context2D.createImageData(c.width, c.height);

+

+        int frame = 0;

+        new Async.Timer.periodic(new Duration(milliseconds: 40), (t) {

+          Image image = anim.frames[frame++];

+          if (frame >= anim.numFrames) {

+            frame = 0;

+          }

+

+          // Fill the buffer with our image data.

+          d.data.setRange(0, d.data.length, image.getBytes());

+          // Draw the buffer onto the canvas.

+          c.context2D.putImageData(d, 0, 0);

+        });

+      }

+   });

+   req.send('');

+  }

+}

diff --git a/image/web/test_jpeg_encoder.dart b/image/web/test_jpeg_encoder.dart
old mode 100644
new mode 100755
index ed11261..fdad554
--- a/image/web/test_jpeg_encoder.dart
+++ b/image/web/test_jpeg_encoder.dart
@@ -1,24 +1,24 @@
-import 'dart:html' as Html;
-import 'dart:convert';
-import 'package:image/image.dart';
-
-void main() {
-  var theImg = Html.document.getElementById('testimage') as Html.ImageElement;
-  var cvs = Html.document.createElement('canvas') as Html.CanvasElement;
-  cvs.width = theImg.width;
-  cvs.height = theImg.height;
-
-  var ctx = cvs.getContext("2d") as Html.CanvasRenderingContext2D;
-
-  ctx.drawImage(theImg,0,0);
-
-  var bytes = ctx.getImageData(0, 0, cvs.width, cvs.height).data;
-  Image image = new Image.fromBytes(cvs.width, cvs.height, bytes);
-
-  var jpg = encodeJpg(image, quality: 25);
-
-  var jpg64 = base64Encode(jpg);
-  var img = Html.document.createElement('img') as Html.ImageElement;
-  img.src = 'data:image/png;base64,${jpg64}';
-  Html.document.body.append(img);
-}
+import 'dart:html' as Html;

+import 'dart:convert';

+import 'package:image/image.dart';

+

+void main() {

+  var theImg = Html.document.getElementById('testimage') as Html.ImageElement;

+  var cvs = Html.document.createElement('canvas') as Html.CanvasElement;

+  cvs.width = theImg.width;

+  cvs.height = theImg.height;

+

+  var ctx = cvs.getContext("2d") as Html.CanvasRenderingContext2D;

+

+  ctx.drawImage(theImg,0,0);

+

+  var bytes = ctx.getImageData(0, 0, cvs.width, cvs.height).data;

+  Image image = Image.fromBytes(cvs.width, cvs.height, bytes);

+

+  var jpg = encodeJpg(image, quality: 25);

+

+  var jpg64 = base64Encode(jpg);

+  var img = Html.document.createElement('img') as Html.ImageElement;

+  img.src = 'data:image/png;base64,${jpg64}';

+  Html.document.body.append(img);

+}

diff --git a/image/web/webp_viewer.dart b/image/web/webp_viewer.dart
old mode 100644
new mode 100755
index aec6f60..26aa389
--- a/image/web/webp_viewer.dart
+++ b/image/web/webp_viewer.dart
@@ -1,34 +1,34 @@
-import 'dart:html' as Html;
-import 'dart:convert';
-import 'package:image/image.dart';
-
-/**
- * Convert all .webp IMG elements on the page to PNG so that they can be viewed
- * by browsers like FireFox and IE.
- */
-void main() {
-  var images = Html.querySelectorAll('img');
-
-  for (var _img in images) {
-    var img = _img as Html.ImageElement;
-    if (img.src.toLowerCase().endsWith('.webp')) {
-      var req = new Html.HttpRequest();
-      req.open('GET', img.src);
-      req.overrideMimeType('text\/plain; charset=x-user-defined');
-      req.onLoadEnd.listen((e) {
-        if (req.status == 200) {
-          var bytes = req.responseText.split('').map((e){
-            return new String.fromCharCode(e.codeUnitAt(0) & 0xff);
-           }).join('').codeUnits;
-
-          Image image = decodeWebP(bytes);
-          List<int> png = encodePng(image);
-
-          var png64 = base64Encode(png);
-          img.src = 'data:image/png;base64,${png64}';
-        }
-      });
-      req.send('');
-    }
-  }
-}
+import 'dart:html' as Html;

+import 'dart:convert';

+import 'package:image/image.dart';

+

+/**

+ * Convert all .webp IMG elements on the page to PNG so that they can be viewed

+ * by browsers like FireFox and IE.

+ */

+void main() {

+  var images = Html.querySelectorAll('img');

+

+  for (var _img in images) {

+    var img = _img as Html.ImageElement;

+    if (img.src.toLowerCase().endsWith('.webp')) {

+      var req = Html.HttpRequest();

+      req.open('GET', img.src);

+      req.overrideMimeType('text\/plain; charset=x-user-defined');

+      req.onLoadEnd.listen((e) {

+        if (req.status == 200) {

+          var bytes = req.responseText.split('').map((e){

+            return new String.fromCharCode(e.codeUnitAt(0) & 0xff);

+           }).join('').codeUnits;

+

+          Image image = decodeWebP(bytes);

+          List<int> png = encodePng(image);

+

+          var png64 = base64Encode(png);

+          img.src = 'data:image/png;base64,${png64}';

+        }

+      });

+      req.send('');

+    }

+  }

+}