diff --git a/Info.plist b/Info.plist
new file mode 100644
index 00000000..00043b43
--- /dev/null
+++ b/Info.plist
@@ -0,0 +1,53 @@
+
+
+
+
+ NSUIElement
+ 1
+ CFBundleName
+ compass.app
+ CFBundleVersion
+ 0.0.1
+ CFBundleAllowMixedLocalizations
+ true
+ CFBundleExecutable
+ JavaApplicationStub
+ CFBundleDevelopmentRegion
+ English
+ CFBundlePackageType
+ APPL
+ CFBundleSignature
+ ????
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleIconFile
+ icon-osx.icns
+ Java
+
+ MainClass
+ org.rubyforge.rawr.Main
+ JVMVersion
+ 1.6*
+ ClassPath
+
+ $JAVAROOT/compass-app.jar
+
+ Properties
+
+ apple.laf.useScreenMenuBar
+ true
+
+ JVMArchs
+
+ i386
+
+ StartOnMainThread
+ true
+ VMOptions
+
+ -Xverify:none
+ -Xbootclasspath/p:$APP_PACKAGE/Contents/Resources/Java/lib/java/jruby-complete.jar
+
+
+
+
diff --git a/Info.plist.new b/Info.plist.new
new file mode 100644
index 00000000..fcc988d7
--- /dev/null
+++ b/Info.plist.new
@@ -0,0 +1,53 @@
+
+
+
+
+ NSUIElement
+ 1
+ CFBundleName
+ compass.app
+ CFBundleVersion
+ 1.0
+ CFBundleAllowMixedLocalizations
+ true
+ CFBundleExecutable
+ JavaApplicationStub
+ CFBundleDevelopmentRegion
+ English
+ CFBundlePackageType
+ APPL
+ CFBundleSignature
+ ????
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleIconFile
+ icon-osx.icns
+ Java
+
+ MainClass
+ org.rubyforge.rawr.Main
+ JVMVersion
+ 1.6*
+ ClassPath
+
+ $JAVAROOT/compass-app.jar
+
+ Properties
+
+ apple.laf.useScreenMenuBar
+ true
+
+ JVMArchs
+
+ i386
+
+ StartOnMainThread
+ true
+ VMOptions
+
+ -Xverify:none
+ -Xbootclasspath/p:$APP_PACKAGE/Contents/Resources/Java/lib/java/jruby-complete.jar
+
+
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..d159169d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/README b/README
index e69de29b..8d8f913a 100644
--- a/README
+++ b/README
@@ -0,0 +1,8 @@
+Homepage
+======
+http://compass.handlino.com
+
+System Requirement
+======
+* jruby http://jruby.org/
+* rawr http://rawr.rubyforge.org/
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 00000000..0a6a47bc
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,122 @@
+require 'rawr'
+require 'app_bundler'
+require 'exe_bundler'
+require 'yaml'
+module Rawr
+ class AppBundler
+ # monkey patch again, option mac_do_not_generate_plist not work
+ def generate_info_plist
+ return
+ end
+ end
+end
+
+namespace :rawr do
+ namespace :link_swt do
+ task :clean do
+ @swt_file = File.join( File.dirname(__FILE__), 'lib', 'java', 'swt.jar')
+ File.delete( File.join( File.dirname(__FILE__), 'lib', 'java', 'swt.jar')) if File.exists?( @swt_file )
+ end
+
+ task :win => ['rawr:link_swt:clean'] do
+ @current_os = "win"
+ copy( File.join( File.dirname(__FILE__), 'lib','swt','swt_win32.jar'), @swt_file )
+ end
+
+ task :linux => ['rawr:link_swt:clean'] do
+ @current_os = "linux"
+ copy( File.join( File.dirname(__FILE__), 'lib','swt','swt_linux32.jar'), @swt_file )
+ end
+
+ task :osx => ['rawr:link_swt:clean'] do
+ @current_os = "osx"
+ copy( File.join( File.dirname(__FILE__), 'lib','swt','swt_osx32.jar'), @swt_file )
+ end
+ end
+
+ namespace :bundle do
+ task :create_packages_dir do
+ @packages_dir = File.join(File.dirname(__FILE__), 'packages')
+ Dir.mkdir( @packages_dir ) unless File.exists?( @packages_dir )
+ end
+
+ task :write_version_info do
+ @revision ||= (%x{git log | head -c 17 | tail -c 10}).strip
+ @compile_time ||= Time.now.strftime('%Y%m%d%H%M')
+ @update_url = open('update_url').readline.strip if File.exists?("update_url")
+ File.open "src/compile_version.rb", 'w' do |file|
+ file << <<-INFO_ENDL
+ module CompileVersion
+ REVISION = '#{@revision}'
+ COMPILE_TIME = '#{@compile_time}'
+ UPDATE_URL = '#{@update_url}'
+ end
+INFO_ENDL
+ end
+ end
+
+ task(:app).clear_prerequisites.clear_actions
+ desc "Bundles the jar from rawr:jar into a native Mac OS X application (.app)"
+ task :app => ["rawr:bundle:create_packages_dir", "rawr:link_swt:osx", "rawr:bundle:write_version_info", "rawr:jar", CONFIG.osx_output_dir ] do
+ Rawr::AppBundler.new.deploy CONFIG
+ Dir.chdir File.dirname(__FILE__)
+ %x{cp -R lib/ruby #{CONFIG.osx_output_dir}/#{CONFIG.project_name}.app/Contents/Resources/ruby}
+ %x{cp -R lib/applescript #{CONFIG.osx_output_dir}/#{CONFIG.project_name}.app/Contents/Resources/applescript}
+ Dir.chdir CONFIG.osx_output_dir
+ %x{mv #{CONFIG.project_name}.app compass.app;}
+ @osx_bundle_file="compass.app.osx.#{@compile_time}-#{@revision}.zip"
+ %x{zip -9 -r #{@packages_dir}/#{@osx_bundle_file} compass.app}
+ end
+
+ task(:exe).clear_prerequisites.clear_actions
+ desc "Bundles the jar from rawr:jar into a native Windows application (.exe)"
+ task :exe => ["rawr:bundle:create_packages_dir", "rawr:link_swt:win", "rawr:bundle:write_version_info", "rawr:jar", CONFIG.windows_output_dir ] do
+ Dir.chdir File.dirname(__FILE__)
+ %x{mkdir -p package/windows/package/windows} # yo~ show me the monkey, path for launch4j link fle
+ Rawr::ExeBundler.new.deploy CONFIG
+ %x{cp -R lib/ruby #{CONFIG.windows_output_dir}/lib}
+ %x{mv package/windows/package/windows/*.exe package/windows}
+ %x{rm -rf package/windows/package}
+ Dir.chdir 'package'
+ %x{rm -rf compass.app windows/*.xml; mv windows compass.app}
+ @windows_bundle_file="compass.app.windows.#{@compile_time}-#{@revision}.zip"
+ %x{zip -9 -r #{@packages_dir}/#{@windows_bundle_file} compass.app}
+ end
+
+ desc "Bundles the jar from rawr:jar into a Linux script"
+ task :linux => ["rawr:bundle:create_packages_dir", "rawr:link_swt:linux", "rawr:bundle:write_version_info", "rawr:jar" ] do
+ Dir.chdir File.dirname(__FILE__)
+ %x{cp -R lib/ruby package/jar/lib}
+ %x{mv package/jar package/compass.app}
+ %x{echo "#!/bin/sh\njava -d32 -client -jar compass-app.jar" > package/compass.app/run.sh}
+ %x{chmod +x package/compass.app/run.sh}
+ Dir.chdir 'package'
+ @linux_bundle_file="compass.app.linux.#{@compile_time}-#{@revision}.zip"
+ %x{zip -9 -r #{@packages_dir}/#{@linux_bundle_file} compass.app}
+ end
+
+ desc "Bundles Linux, OSX and Window package"
+ task :all do
+ Dir.chdir File.dirname(__FILE__)
+ %x{rm -rf package/* packages/*}
+ Rake::Task['rawr:bundle:app'].invoke
+
+ Rake::Task.tasks.each{|t| t.reenable}
+ Dir.chdir File.dirname(__FILE__)
+ %x{rm -rf package/*}
+ Rake::Task['rawr:bundle:exe'].invoke
+
+ Rake::Task.tasks.each{|t| t.reenable}
+ Dir.chdir File.dirname(__FILE__)
+ %x{rm -rf package/*}
+ Rake::Task['rawr:bundle:linux'].invoke
+ url_base=File.dirname(@update_url)
+ info={ "linux" => { "compile_version"=> @compile_time, "url"=> File.join(url_base, @linux_bundle_file) },
+ "osx" => { "compile_version"=> @compile_time, "url"=> File.join(url_base, @osx_bundle_file) },
+ "windows" => { "compile_version"=> @compile_time, "url"=> File.join(url_base, @windows_bundle_file)} }
+ open( File.join(@packages_dir,'update.yml'),'w' ) do |f|
+ f.write info.to_yaml
+ end
+ end
+ end
+end
diff --git a/bin/build-all.sh b/bin/build-all.sh
new file mode 100755
index 00000000..cde11b93
--- /dev/null
+++ b/bin/build-all.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+rake rawr:bundle:all
diff --git a/bin/startJar-linux.sh b/bin/startJar-linux.sh
new file mode 100755
index 00000000..f0b35973
--- /dev/null
+++ b/bin/startJar-linux.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+if [ "$1" = "full" ]; then
+ rm `pwd`/lib/java/swt*
+ cp `pwd`/lib/swt/swt_linux32.jar `pwd`/lib/java/swt.jar
+ rake rawr:clean
+fi
+rake rawr:jar
+java -d32 -client -Xverify:none -Xbootclasspath/a:lib/java/jruby-complete.jar -jar package/jar/compass-app.jar
diff --git a/bin/startJar-osx.sh b/bin/startJar-osx.sh
new file mode 100755
index 00000000..610a9a8c
--- /dev/null
+++ b/bin/startJar-osx.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+if [ "$1" = "full" ]; then
+ rm `pwd`/lib/java/swt*
+ cp `pwd`/lib/swt/swt_osx32.jar `pwd`/lib/java/swt.jar
+ rake rawr:clean
+fi
+rake rawr:jar
+java -d32 -client -Xverify:none -XstartOnFirstThread -Xbootclasspath/a:lib/java/jruby-complete.jar -jar package/jar/compass-app.jar
diff --git a/build_configuration.rb b/build_configuration.rb
new file mode 100644
index 00000000..11617369
--- /dev/null
+++ b/build_configuration.rb
@@ -0,0 +1,89 @@
+configuration do |c|
+ # The name for your resulting application file (e.g., if the project_name is 'foo' then you'll get foo.jar, foo.exe, etc.)
+ # default value: "tka"
+ #
+ c.project_name = "compass-app"
+
+ # Undocumented option 'output_dir'
+ # default value: "package"
+ #
+ #c.output_dir = "package"
+
+ # The main ruby file to invoke, minus the .rb extension
+ # default value: "main"
+ #
+ #c.main_ruby_file = "main"
+
+ # The fully-qualified name of the main Java file used to initiate the application.
+ # default value: "org.rubyforge.rawr.Main"
+ #
+ #c.main_java_file = "org.rubyforge.rawr.Main"
+
+ # A list of directories where source files reside
+ # default value: ["src"]
+ #
+ #c.source_dirs = ["src",'lib/ruby/gem/gems/haml-3.0.24']
+
+ # A list of regexps of files to exclude
+ # default value: []
+ #
+ #c.source_exclude_filter = [/spec/,/test/,/example/]
+
+ # Whether Ruby source files should be compiled into .class files
+ # default value: true
+ #
+ #c.compile_ruby_files = true
+
+ # A list of individual Java library files to include.
+ # default value: []
+ #
+ #c.java_lib_files = []
+
+ # A list of directories for rawr to include . All files in the given directories get bundled up.
+ # default value: ["lib/java"]
+ #
+ #c.java_lib_dirs = ["lib/java"]
+
+ # Undocumented option 'files_to_copy'
+ # default value: []
+ #
+ #c.files_to_copy = ['lib/ruby', 'lib/applescript']
+
+ # Undocumented option 'target_jvm_version'
+ # default value: 1.6
+ #
+ #c.target_jvm_version = 1.6
+
+ # Undocumented option 'jvm_arguments'
+ # default value: ""
+ #
+ #c.jvm_arguments = ""
+
+ # Undocumented option 'java_library_path'
+ # default value: ""
+ #
+ #c.java_library_path = ""
+
+ # Undocumented option 'extra_user_jars'
+ # default value: {}
+ #
+ #c.extra_user_jars[:data] = { :directory => 'data/images/png',
+ # :location_in_jar => 'images',
+ # :exclude => /*.bak$/ }
+
+ # Undocumented option 'mac_do_not_generate_plist'
+ # default value: nil
+ #
+ #c.mac_do_not_generate_plist = true
+
+ # Undocumented option 'mac_icon_path'
+ # default value: nil
+ #
+ c.mac_icon_path = Dir.pwd + "/src/data/images/icon/icon-osx.icns"
+
+ # Undocumented option 'windows_icon_path'
+ # default value: nil
+ #
+ c.windows_icon_path = Dir.pwd + "/src/data/images/icon/icon-win.ico"
+
+end
diff --git a/lib/applescript/64.png b/lib/applescript/64.png
new file mode 100644
index 00000000..d6d36e1e
Binary files /dev/null and b/lib/applescript/64.png differ
diff --git a/lib/applescript/growl.applescript b/lib/applescript/growl.applescript
new file mode 100644
index 00000000..c3c3bce1
Binary files /dev/null and b/lib/applescript/growl.applescript differ
diff --git a/lib/java/jruby-complete.jar b/lib/java/jruby-complete.jar
new file mode 100644
index 00000000..6d51cf01
Binary files /dev/null and b/lib/java/jruby-complete.jar differ
diff --git a/lib/ruby/gem/bin/compass b/lib/ruby/gem/bin/compass
new file mode 100644
index 00000000..45a689c9
--- /dev/null
+++ b/lib/ruby/gem/bin/compass
@@ -0,0 +1,19 @@
+#!/usr/bin/env jruby
+#
+# This file was generated by RubyGems.
+#
+# The application 'compass' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = ">= 0"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+ version = $1
+ ARGV.shift
+end
+
+gem 'compass', version
+load Gem.bin_path('compass', 'compass', version)
diff --git a/lib/ruby/gem/bin/css2sass b/lib/ruby/gem/bin/css2sass
new file mode 100644
index 00000000..7c399036
--- /dev/null
+++ b/lib/ruby/gem/bin/css2sass
@@ -0,0 +1,19 @@
+#!/usr/bin/env jruby
+#
+# This file was generated by RubyGems.
+#
+# The application 'haml' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = ">= 0"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+ version = $1
+ ARGV.shift
+end
+
+gem 'haml', version
+load Gem.bin_path('haml', 'css2sass', version)
diff --git a/lib/ruby/gem/bin/haml b/lib/ruby/gem/bin/haml
new file mode 100644
index 00000000..ecfc89de
--- /dev/null
+++ b/lib/ruby/gem/bin/haml
@@ -0,0 +1,19 @@
+#!/usr/bin/env jruby
+#
+# This file was generated by RubyGems.
+#
+# The application 'haml' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = ">= 0"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+ version = $1
+ ARGV.shift
+end
+
+gem 'haml', version
+load Gem.bin_path('haml', 'haml', version)
diff --git a/lib/ruby/gem/bin/html2haml b/lib/ruby/gem/bin/html2haml
new file mode 100644
index 00000000..7962398c
--- /dev/null
+++ b/lib/ruby/gem/bin/html2haml
@@ -0,0 +1,19 @@
+#!/usr/bin/env jruby
+#
+# This file was generated by RubyGems.
+#
+# The application 'haml' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = ">= 0"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+ version = $1
+ ARGV.shift
+end
+
+gem 'haml', version
+load Gem.bin_path('haml', 'html2haml', version)
diff --git a/lib/ruby/gem/bin/sass b/lib/ruby/gem/bin/sass
new file mode 100644
index 00000000..0592c7b3
--- /dev/null
+++ b/lib/ruby/gem/bin/sass
@@ -0,0 +1,19 @@
+#!/usr/bin/env jruby
+#
+# This file was generated by RubyGems.
+#
+# The application 'haml' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = ">= 0"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+ version = $1
+ ARGV.shift
+end
+
+gem 'haml', version
+load Gem.bin_path('haml', 'sass', version)
diff --git a/lib/ruby/gem/bin/sass-convert b/lib/ruby/gem/bin/sass-convert
new file mode 100644
index 00000000..39071ccf
--- /dev/null
+++ b/lib/ruby/gem/bin/sass-convert
@@ -0,0 +1,19 @@
+#!/usr/bin/env jruby
+#
+# This file was generated by RubyGems.
+#
+# The application 'haml' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = ">= 0"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+ version = $1
+ ARGV.shift
+end
+
+gem 'haml', version
+load Gem.bin_path('haml', 'sass-convert', version)
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/.gitignore b/lib/ruby/gem/gems/chunky_png-0.11.1/.gitignore
new file mode 100644
index 00000000..90e787eb
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/.gitignore
@@ -0,0 +1,8 @@
+.DS_Store
+spec/resources/_*.png
+/pkg
+/tmp
+/doc
+/.yardoc
+/.bundle
+*.rbc
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/.infinity_test b/lib/ruby/gem/gems/chunky_png-0.11.1/.infinity_test
new file mode 100644
index 00000000..8cac7800
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/.infinity_test
@@ -0,0 +1,3 @@
+infinity_test do
+ use :rubies => %w(1.8.7 1.9.2 ree jruby rbx), :test_framework => :rspec
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/BENCHMARKS.rdoc b/lib/ruby/gem/gems/chunky_png-0.11.1/BENCHMARKS.rdoc
new file mode 100644
index 00000000..e5b19e13
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/BENCHMARKS.rdoc
@@ -0,0 +1,31 @@
+= ChunkyPNG benchmark suite
+
+This small benchmark suite is intended to test the speed of PNG decoding
+and encoding against different ruby interpreters. You can set the number
+of runs by passing the N environment variable. You can execute them as
+rake task or as standalone script.
+
+ rake benchmark:encoding
+ rake benchmark:decoding
+
+ rake benchmark N=10 # Run all of them, using n=10
+
+Use rvm to simply run the tests against different interpreters. Of course,
+make sure that the chunky_png is installed for all your interpreters.
+
+ rvm 1.8.7,1.9.1,rbx rake benchmark N=10
+
+== Results
+
+Some of my benchmark (N=50) result on my 2007 iMac can be found in this gist:
+http://gist.github.com/495323
+
+== Why is this relevant?
+
+ChunkyPNG is a pure Ruby library to handle PNG files. Decoding a PNG requires
+a lot of integer math and bitwise operations, and moderate use of the unpack
+method to read binary data. Encoding is a good test for Array#pack, and
+depending on the encoding options, also requires a lot of calculations.
+Therefore, the library is a good benchmark candidate for these methods and
+algorithms. It has been used to improve the Array#pack and String#unpack
+methods in Rubinius.
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/Gemfile b/lib/ruby/gem/gems/chunky_png-0.11.1/Gemfile
new file mode 100644
index 00000000..e45e65f8
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/Gemfile
@@ -0,0 +1,2 @@
+source :rubygems
+gemspec
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/Gemfile.lock b/lib/ruby/gem/gems/chunky_png-0.11.1/Gemfile.lock
new file mode 100644
index 00000000..48fad93e
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/Gemfile.lock
@@ -0,0 +1,27 @@
+PATH
+ remote: .
+ specs:
+ chunky_png (0.11.1)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ diff-lcs (1.1.2)
+ rake (0.8.7)
+ rspec (2.1.0)
+ rspec-core (~> 2.1.0)
+ rspec-expectations (~> 2.1.0)
+ rspec-mocks (~> 2.1.0)
+ rspec-core (2.1.0)
+ rspec-expectations (2.1.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.1.0)
+
+PLATFORMS
+ java
+ ruby
+
+DEPENDENCIES
+ chunky_png!
+ rake
+ rspec (~> 2.1)
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/LICENSE b/lib/ruby/gem/gems/chunky_png-0.11.1/LICENSE
new file mode 100644
index 00000000..028783f9
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2010 Willem van Bergen
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/README.rdoc b/lib/ruby/gem/gems/chunky_png-0.11.1/README.rdoc
new file mode 100644
index 00000000..b8be5e63
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/README.rdoc
@@ -0,0 +1,67 @@
+= Chunky PNG
+
+This library can read and write PNG files. It is written in pure Ruby for
+maximum portability. Let me rephrase: it does NOT require RMagick or any other
+memory leaking image library.
+
+Source code:: http://github.com/wvanbergen/chunky_png/tree
+RDoc:: http://rdoc.info/github/wvanbergen/chunky_png/master/file/README.rdoc
+Wiki:: http://github.com/wvanbergen/chunky_png/wiki
+Issue tracker:: http://github.com/wvanbergen/chunky_png/issues
+
+== Features
+
+* Decodes any image that the PNG standard allows. This includes all standard
+ color modes, all bit depths and all transparency, interlacing and filtering options.
+* Encodes images supports all color modes (true color, grayscale and indexed)
+ and transparency for all these color modes. The best color mode will be
+ chosen automatically, based on the amount of used colors.
+* R/W access to the image's pixels.
+* R/W access to all image metadata that is stored in chunks.
+* Memory efficient (uses a Fixnum, i.e. 4 or 8 bytes of memory per pixel, depending
+ on the hardware)
+* Reasonably fast for Ruby standards, by only using integer math and a highly
+ optimized saving routine.
+* Interoperability with RMagick if you really have to.
+
+Also, have a look at OilyPNG at http://github.com/wvanbergen/oily_png. OilyPNG is a
+mixin module that implements some of the ChunkyPNG algorithms in C, which
+provides a massive speed boost to encoding and decoding.
+
+== Usage
+
+ require 'chunky_png'
+
+ # Creating an image from scratch, save as an interlaced PNG
+ png = ChunkyPNG::Image.new(16, 16, ChunkyPNG::Color::TRANSPARENT)
+ png[1,1] = ChunkyPNG::Color.rgba(10, 20, 30, 128)
+ png[2,1] = ChunkyPNG::Color.rgba(0, 0, 0, 128)
+ png.save('filename.png', :interlace => true)
+
+ # Compose images using alpha blending.
+ avatar = ChunkyPNG::Image.from_file('avatar.png')
+ badge = ChunkyPNG::Image.from_file('no_ie_badge.png')
+ avatar.compose(badge, 10, 10)
+ avatar.save('composited.png', :fast_rgba) # Force the fast saving routine.
+
+ # Accessing metadata
+ image = ChunkyPNG::Image.from_file('with_metadata.png')
+ puts image.metadata['Title']
+ image.metadata['Author'] = 'Willem van Bergen'
+ image.save('with_metadata.png') # Overwrite file
+
+ # Low level access to PNG chunks
+ png_stream = ChunkyPNG::Datastream.from_file('filename.png')
+ png_stream.each_chunk { |chunk| p chunk.type }
+
+For more information, see the project wiki on http://github.com/wvanbergen/chunky_png/wiki
+or the RDOC documentation on http://rdoc.info/github/wvanbergen/chunky_png/master/file/README.rdoc.
+
+== About
+
+The library is written by Willem van Bergen for Floorplanner.com, and released
+under the MIT license (see LICENSE). Please contact me for questions or
+remarks. Patches are greatly appreciated!
+
+P.S.: The name of this library is intentionally similar to Chunky Bacon and
+Chunky GIF. Use Google if you want to know _why. :-)
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/Rakefile b/lib/ruby/gem/gems/chunky_png-0.11.1/Rakefile
new file mode 100644
index 00000000..d39faa51
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/Rakefile
@@ -0,0 +1,9 @@
+require 'rubygems'
+require 'bundler'
+
+Bundler.setup
+
+Dir['tasks/*.rake'].each { |file| load(file) }
+
+GithubGem::RakeTasks.new(:gem)
+task :default => [:spec]
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/decoding_benchmark.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/decoding_benchmark.rb
new file mode 100644
index 00000000..447d7c7e
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/decoding_benchmark.rb
@@ -0,0 +1,38 @@
+require 'rubygems'
+require 'bundler'
+
+Bundler.setup
+
+require 'benchmark'
+require 'chunky_png'
+
+def image_file(name)
+ File.join(File.dirname(__FILE__), '..', 'spec', 'resources', name)
+end
+
+def image_data(name)
+ data = nil
+ File.open(image_file(name), 'rb') { |f| data = f.read }
+ data
+end
+
+no_filtering_stream = image_data('pixelstream_fast_rgba.png')
+up_filtering_stream = image_data('pixelstream_reference.png')
+paeth_filtering_stream = image_data('pixelstream_best_compression.png')
+rgba_pixelstream = image_data('pixelstream.rgba')
+rgb_pixelstream = image_data('pixelstream.rgb')
+
+n = (ENV['N'] || '5').to_i
+
+puts "---------------------------------------------"
+puts "ChunkyPNG (#{ChunkyPNG::VERSION}) decoding benchmark (n=#{n})"
+puts "---------------------------------------------"
+puts
+
+Benchmark.bmbm do |x|
+ x.report('PNG - no filtering') { n.times { ChunkyPNG::Image.from_blob(no_filtering_stream) } }
+ x.report('PNG - UP filtering') { n.times { ChunkyPNG::Image.from_blob(up_filtering_stream) } }
+ x.report('PNG - PAETH filtering') { n.times { ChunkyPNG::Image.from_blob(paeth_filtering_stream) } }
+ x.report('From RGBA pixelstream') { n.times { ChunkyPNG::Image.from_rgba_stream(240, 180, rgba_pixelstream) } }
+ x.report('From RGB pixelstream') { n.times { ChunkyPNG::Image.from_rgb_stream(240, 180, rgb_pixelstream) } }
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/encoding_benchmark.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/encoding_benchmark.rb
new file mode 100644
index 00000000..782b5c74
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/encoding_benchmark.rb
@@ -0,0 +1,42 @@
+require 'rubygems'
+require 'bundler'
+
+Bundler.setup
+
+require 'benchmark'
+require 'chunky_png'
+
+image = ChunkyPNG::Image.new(240, 180, ChunkyPNG::Color::TRANSPARENT)
+
+# set some random pixels
+image[10, 20] = ChunkyPNG::Color.rgba(255, 0, 0, 255)
+image[50, 87] = ChunkyPNG::Color.rgba( 0, 255, 0, 255)
+image[33, 99] = ChunkyPNG::Color.rgba( 0, 0, 255, 255)
+
+n = (ENV['N'] || '5').to_i
+
+puts "---------------------------------------------"
+puts "ChunkyPNG (#{ChunkyPNG::VERSION}) encoding benchmark (n=#{n})"
+puts "---------------------------------------------"
+puts
+
+Benchmark.bmbm do |x|
+ x.report('Autodetect (indexed)') { n.times { image.to_blob } }
+
+ # Presets
+ x.report(':no_compression') { n.times { image.to_blob(:no_compression) } }
+ x.report(':fast_rgba') { n.times { image.to_blob(:fast_rgba) } }
+ x.report(':fast_rgb') { n.times { image.to_blob(:fast_rgb) } }
+ x.report(':good_compression') { n.times { image.to_blob(:good_compression) } }
+ x.report(':best_compression') { n.times { image.to_blob(:best_compression) } }
+
+ # Some options
+ x.report(':rgb') { n.times { image.to_blob(:color_mode => ChunkyPNG::COLOR_TRUECOLOR) } }
+ x.report(':rgba') { n.times { image.to_blob(:color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA) } }
+ x.report(':indexed') { n.times { image.to_blob(:color_mode => ChunkyPNG::COLOR_INDEXED) } }
+ x.report(':interlaced') { n.times { image.to_blob(:interlaced => true) } }
+
+ # Exports
+ x.report('to RGBA pixelstream') { n.times { image.to_rgba_stream } }
+ x.report('to RGB pixelstream') { n.times { image.to_rgb_stream } }
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/filesize_benchmark.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/filesize_benchmark.rb
new file mode 100644
index 00000000..a51e7c79
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/benchmarks/filesize_benchmark.rb
@@ -0,0 +1,30 @@
+require 'rubygems'
+require 'bundler'
+
+Bundler.setup
+
+require 'benchmark'
+require 'chunky_png'
+
+files = ['pixelstream_reference.png', 'operations.png', 'clock_stubbed.png']
+
+def encode_png(image, constraints = {})
+ filesize = nil
+ time = Benchmark.realtime { filesize = image.to_blob(constraints).bytesize }
+ [filesize, time]
+end
+
+files.each do |file|
+ filename = File.join(File.dirname(__FILE__), '..', 'spec', 'resources', file)
+ image = ChunkyPNG::Canvas.from_file(filename)
+
+ puts "#{file}: #{image.width}x#{image.height} - #{image.palette.size} colors"
+ puts "------------------------------------------------"
+ puts " : %8d bytes in %0.4fs" % encode_png(image)
+ puts ":no_compression : %8d bytes in %0.4fs" % encode_png(image, :no_compression)
+ puts ":fast_rgba : %8d bytes in %0.4fs" % encode_png(image, :fast_rgba)
+ puts ":fast_rgb : %8d bytes in %0.4fs" % encode_png(image, :fast_rgb)
+ puts ":good_compression : %8d bytes in %0.4fs" % encode_png(image, :good_compression)
+ puts ":best_compression : %8d bytes in %0.4fs" % encode_png(image, :best_compression)
+ puts
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/chunky_png.gemspec b/lib/ruby/gem/gems/chunky_png-0.11.1/chunky_png.gemspec
new file mode 100644
index 00000000..496b8d75
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/chunky_png.gemspec
@@ -0,0 +1,43 @@
+Gem::Specification.new do |s|
+ s.name = 'chunky_png'
+
+ # Do not change the version and date fields by hand. This will be done
+ # automatically by the gem release script.
+ s.version = "0.11.1"
+ s.date = "2010-11-16"
+
+ s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
+ s.description = <<-EOT
+ This pure Ruby library can read and write PNG images without depending on an external
+ image library, like RMagick. It tries to be memory efficient and reasonably fast.
+
+ It supports reading and writing all PNG variants that are defined in the specification,
+ with one limitation: only 8-bit color depth is supported. It supports all transparency,
+ interlacing and filtering options the PNG specifications allows. It can also read and
+ write textual metadata from PNG files. Low-level read/write access to PNG chunks is
+ also possible.
+
+ This library supports simple drawing on the image canvas and simple operations like
+ alpha composition and cropping. Finally, it can import from and export to RMagick for
+ interoperability.
+
+ Also, have a look at OilyPNG at http://github.com/wvanbergen/oily_png. OilyPNG is a
+ drop in mixin module that implements some of the ChunkyPNG algorithms in C, which
+ provides a massive speed boost to encoding and decoding.
+ EOT
+
+ s.authors = ['Willem van Bergen']
+ s.email = ['willem@railsdoctors.com']
+ s.homepage = 'http://wiki.github.com/wvanbergen/chunky_png'
+
+ s.add_development_dependency('rake')
+ s.add_development_dependency('rspec', '~> 2.1')
+
+ s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
+ s.extra_rdoc_files = ['README.rdoc', 'BENCHMARKS.rdoc']
+
+ # Do not change the files and test_files fields by hand. This will be done
+ # automatically by the gem release script.
+ s.files = %w(.gitignore .infinity_test BENCHMARKS.rdoc Gemfile Gemfile.lock LICENSE README.rdoc Rakefile benchmarks/decoding_benchmark.rb benchmarks/encoding_benchmark.rb benchmarks/filesize_benchmark.rb chunky_png.gemspec lib/chunky_png.rb lib/chunky_png/canvas.rb lib/chunky_png/canvas/adam7_interlacing.rb lib/chunky_png/canvas/drawing.rb lib/chunky_png/canvas/operations.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/stream_exporting.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/chunk.rb lib/chunky_png/color.rb lib/chunky_png/compatibility.rb lib/chunky_png/datastream.rb lib/chunky_png/image.rb lib/chunky_png/palette.rb lib/chunky_png/rmagick.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/png_suite/background_chunks/bgai4a08.png spec/png_suite/background_chunks/bgai4a16.png spec/png_suite/background_chunks/bgan6a08.png spec/png_suite/background_chunks/bgan6a16.png spec/png_suite/background_chunks/bgbn4a08.png spec/png_suite/background_chunks/bggn4a16.png spec/png_suite/background_chunks/bgwn6a08.png spec/png_suite/background_chunks/bgyn6a16.png spec/png_suite/basic/basi0g01.png spec/png_suite/basic/basi0g01.rgba spec/png_suite/basic/basi0g02.png spec/png_suite/basic/basi0g02.rgba spec/png_suite/basic/basi0g04.png spec/png_suite/basic/basi0g04.rgba spec/png_suite/basic/basi0g08.png spec/png_suite/basic/basi0g08.rgba spec/png_suite/basic/basi0g16.png spec/png_suite/basic/basi0g16.rgba spec/png_suite/basic/basi2c08.png spec/png_suite/basic/basi2c08.rgba spec/png_suite/basic/basi2c16.png spec/png_suite/basic/basi2c16.rgba spec/png_suite/basic/basi3p01.png spec/png_suite/basic/basi3p01.rgba spec/png_suite/basic/basi3p02.png spec/png_suite/basic/basi3p02.rgba spec/png_suite/basic/basi3p04.png spec/png_suite/basic/basi3p04.rgba spec/png_suite/basic/basi3p08.png spec/png_suite/basic/basi3p08.rgba spec/png_suite/basic/basi4a08.png spec/png_suite/basic/basi4a08.rgba spec/png_suite/basic/basi4a16.png spec/png_suite/basic/basi4a16.rgba spec/png_suite/basic/basi6a08.png spec/png_suite/basic/basi6a08.rgba spec/png_suite/basic/basi6a16.png spec/png_suite/basic/basi6a16.rgba spec/png_suite/basic/basn0g01.png spec/png_suite/basic/basn0g01.rgba spec/png_suite/basic/basn0g02.png spec/png_suite/basic/basn0g02.rgba spec/png_suite/basic/basn0g04.png spec/png_suite/basic/basn0g04.rgba spec/png_suite/basic/basn0g08.png spec/png_suite/basic/basn0g08.rgba spec/png_suite/basic/basn0g16.png spec/png_suite/basic/basn0g16.rgba spec/png_suite/basic/basn2c08.png spec/png_suite/basic/basn2c08.rgba spec/png_suite/basic/basn2c16.png spec/png_suite/basic/basn2c16.rgba spec/png_suite/basic/basn3p01.png spec/png_suite/basic/basn3p01.rgba spec/png_suite/basic/basn3p02.png spec/png_suite/basic/basn3p02.rgba spec/png_suite/basic/basn3p04.png spec/png_suite/basic/basn3p04.rgba spec/png_suite/basic/basn3p08.png spec/png_suite/basic/basn3p08.rgba spec/png_suite/basic/basn4a08.png spec/png_suite/basic/basn4a08.rgba spec/png_suite/basic/basn4a16.png spec/png_suite/basic/basn4a16.rgba spec/png_suite/basic/basn6a08.png spec/png_suite/basic/basn6a08.rgba spec/png_suite/basic/basn6a16.png spec/png_suite/basic/basn6a16.rgba spec/png_suite/broken/x00n0g01.png spec/png_suite/broken/xcrn0g04.png spec/png_suite/broken/xlfn0g04.png spec/png_suite/chunk_ordering/oi1n0g16.png spec/png_suite/chunk_ordering/oi1n2c16.png spec/png_suite/chunk_ordering/oi2n0g16.png spec/png_suite/chunk_ordering/oi2n2c16.png spec/png_suite/chunk_ordering/oi4n0g16.png spec/png_suite/chunk_ordering/oi4n2c16.png spec/png_suite/chunk_ordering/oi9n0g16.png spec/png_suite/chunk_ordering/oi9n2c16.png spec/png_suite/compression_levels/z00n2c08.png spec/png_suite/compression_levels/z03n2c08.png spec/png_suite/compression_levels/z06n2c08.png spec/png_suite/compression_levels/z09n2c08.png spec/png_suite/filtering/f00n0g08.png spec/png_suite/filtering/f00n0g08.rgba spec/png_suite/filtering/f00n0g08_reference.png spec/png_suite/filtering/f00n0g08_reference.rgba spec/png_suite/filtering/f00n2c08.png spec/png_suite/filtering/f00n2c08.rgba spec/png_suite/filtering/f00n2c08_reference.png spec/png_suite/filtering/f00n2c08_reference.rgba spec/png_suite/filtering/f01n0g08.png spec/png_suite/filtering/f01n0g08.rgba spec/png_suite/filtering/f01n0g08_reference.png spec/png_suite/filtering/f01n0g08_reference.rgba spec/png_suite/filtering/f01n2c08.png spec/png_suite/filtering/f01n2c08.rgba spec/png_suite/filtering/f01n2c08_reference.png spec/png_suite/filtering/f01n2c08_reference.rgba spec/png_suite/filtering/f02n0g08.png spec/png_suite/filtering/f02n0g08.rgba spec/png_suite/filtering/f02n0g08_reference.png spec/png_suite/filtering/f02n0g08_reference.rgba spec/png_suite/filtering/f02n2c08.png spec/png_suite/filtering/f02n2c08.rgba spec/png_suite/filtering/f02n2c08_reference.png spec/png_suite/filtering/f02n2c08_reference.rgba spec/png_suite/filtering/f03n0g08.png spec/png_suite/filtering/f03n0g08.rgba spec/png_suite/filtering/f03n0g08_reference.png spec/png_suite/filtering/f03n0g08_reference.rgba spec/png_suite/filtering/f03n2c08.png spec/png_suite/filtering/f03n2c08.rgba spec/png_suite/filtering/f03n2c08_reference.png spec/png_suite/filtering/f03n2c08_reference.rgba spec/png_suite/filtering/f04n0g08.png spec/png_suite/filtering/f04n0g08.rgba spec/png_suite/filtering/f04n0g08_reference.png spec/png_suite/filtering/f04n0g08_reference.rgba spec/png_suite/filtering/f04n2c08.png spec/png_suite/filtering/f04n2c08.rgba spec/png_suite/filtering/f04n2c08_reference.png spec/png_suite/filtering/f04n2c08_reference.rgba spec/png_suite/gamma/g03n0g16.png spec/png_suite/gamma/g03n2c08.png spec/png_suite/gamma/g03n3p04.png spec/png_suite/gamma/g04n0g16.png spec/png_suite/gamma/g04n2c08.png spec/png_suite/gamma/g04n3p04.png spec/png_suite/gamma/g05n0g16.png spec/png_suite/gamma/g05n2c08.png spec/png_suite/gamma/g05n3p04.png spec/png_suite/gamma/g07n0g16.png spec/png_suite/gamma/g07n2c08.png spec/png_suite/gamma/g07n3p04.png spec/png_suite/gamma/g10n0g16.png spec/png_suite/gamma/g10n2c08.png spec/png_suite/gamma/g10n3p04.png spec/png_suite/gamma/g25n0g16.png spec/png_suite/gamma/g25n2c08.png spec/png_suite/gamma/g25n3p04.png spec/png_suite/metadata/cm0n0g04.png spec/png_suite/metadata/cm7n0g04.png spec/png_suite/metadata/cm9n0g04.png spec/png_suite/other/ccwn2c08.png spec/png_suite/other/ccwn3p08.png spec/png_suite/other/cdfn2c08.png spec/png_suite/other/cdhn2c08.png spec/png_suite/other/cdsn2c08.png spec/png_suite/other/cdun2c08.png spec/png_suite/other/ch1n3p04.png spec/png_suite/other/ch2n3p08.png spec/png_suite/other/cs3n2c16.png spec/png_suite/other/cs3n3p08.png spec/png_suite/other/cs5n2c08.png spec/png_suite/other/cs5n3p08.png spec/png_suite/other/cs8n2c08.png spec/png_suite/other/cs8n3p08.png spec/png_suite/other/ct0n0g04.png spec/png_suite/other/ct1n0g04.png spec/png_suite/other/ctzn0g04.png spec/png_suite/other/pp0n2c16.png spec/png_suite/other/pp0n6a08.png spec/png_suite/other/ps1n0g08.png spec/png_suite/other/ps1n2c16.png spec/png_suite/other/ps2n0g08.png spec/png_suite/other/ps2n2c16.png spec/png_suite/sizes/s01i3p01.png spec/png_suite/sizes/s01n3p01.png spec/png_suite/sizes/s02i3p01.png spec/png_suite/sizes/s02n3p01.png spec/png_suite/sizes/s03i3p01.png spec/png_suite/sizes/s03n3p01.png spec/png_suite/sizes/s04i3p01.png spec/png_suite/sizes/s04n3p01.png spec/png_suite/sizes/s05i3p02.png spec/png_suite/sizes/s05n3p02.png spec/png_suite/sizes/s06i3p02.png spec/png_suite/sizes/s06n3p02.png spec/png_suite/sizes/s07i3p02.png spec/png_suite/sizes/s07n3p02.png spec/png_suite/sizes/s08i3p02.png spec/png_suite/sizes/s08n3p02.png spec/png_suite/sizes/s09i3p02.png spec/png_suite/sizes/s09n3p02.png spec/png_suite/sizes/s32i3p04.png spec/png_suite/sizes/s32n3p04.png spec/png_suite/sizes/s33i3p04.png spec/png_suite/sizes/s33n3p04.png spec/png_suite/sizes/s34i3p04.png spec/png_suite/sizes/s34n3p04.png spec/png_suite/sizes/s35i3p04.png spec/png_suite/sizes/s35n3p04.png spec/png_suite/sizes/s36i3p04.png spec/png_suite/sizes/s36n3p04.png spec/png_suite/sizes/s37i3p04.png spec/png_suite/sizes/s37n3p04.png spec/png_suite/sizes/s38i3p04.png spec/png_suite/sizes/s38n3p04.png spec/png_suite/sizes/s39i3p04.png spec/png_suite/sizes/s39n3p04.png spec/png_suite/sizes/s40i3p04.png spec/png_suite/sizes/s40n3p04.png spec/png_suite/transparency/tbbn1g04.png spec/png_suite/transparency/tbbn2c16.png spec/png_suite/transparency/tbbn3p08.png spec/png_suite/transparency/tbgn2c16.png spec/png_suite/transparency/tbgn3p08.png spec/png_suite/transparency/tbrn2c08.png spec/png_suite/transparency/tbwn1g16.png spec/png_suite/transparency/tbwn3p08.png spec/png_suite/transparency/tbyn3p08.png spec/png_suite/transparency/tp0n1g08.png spec/png_suite/transparency/tp0n2c08.png spec/png_suite/transparency/tp0n3p08.png spec/png_suite/transparency/tp1n3p08.png spec/png_suite_spec.rb spec/resources/adam7.png spec/resources/clock.png spec/resources/clock_base.png spec/resources/clock_flip_horizontally.png spec/resources/clock_flip_vertically.png spec/resources/clock_mask.png spec/resources/clock_mask_updated.png spec/resources/clock_rotate_180.png spec/resources/clock_rotate_left.png spec/resources/clock_rotate_right.png spec/resources/clock_stubbed.png spec/resources/clock_updated.png spec/resources/composited.png spec/resources/cropped.png spec/resources/damaged_chunk.png spec/resources/damaged_signature.png spec/resources/lines.png spec/resources/operations.png spec/resources/pixelstream.rgb spec/resources/pixelstream.rgba spec/resources/pixelstream_best_compression.png spec/resources/pixelstream_fast_rgba.png spec/resources/pixelstream_reference.png spec/resources/rect.png spec/resources/replaced.png spec/resources/text_chunk.png spec/resources/ztxt_chunk.png spec/spec_helper.rb tasks/benchmarks.rake tasks/github-gem.rake)
+ s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/png_suite_spec.rb)
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png.rb
new file mode 100644
index 00000000..c20c2fdb
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png.rb
@@ -0,0 +1,87 @@
+require 'set'
+require 'zlib'
+require 'stringio'
+require 'enumerator'
+
+require 'chunky_png/compatibility'
+require 'chunky_png/datastream'
+require 'chunky_png/chunk'
+require 'chunky_png/palette'
+require 'chunky_png/color'
+require 'chunky_png/canvas/png_encoding'
+require 'chunky_png/canvas/png_decoding'
+require 'chunky_png/canvas/adam7_interlacing'
+require 'chunky_png/canvas/stream_exporting'
+require 'chunky_png/canvas/stream_importing'
+require 'chunky_png/canvas/operations'
+require 'chunky_png/canvas/drawing'
+require 'chunky_png/canvas'
+require 'chunky_png/image'
+
+# ChunkyPNG - the pury ruby library to access PNG files.
+#
+# The ChunkyPNG module defines some constants that are used in the
+# PNG specification.
+#
+# @author Willem van Bergen
+module ChunkyPNG
+
+ # The current version of ChunkyPNG. This value will be updated automatically
+ # by them gem:release rake task.
+ VERSION = "0.11.1"
+
+ ###################################################
+ # PNG international standard defined constants
+ ###################################################
+
+ COLOR_GRAYSCALE = 0
+ COLOR_TRUECOLOR = 2
+ COLOR_INDEXED = 3
+ COLOR_GRAYSCALE_ALPHA = 4
+ COLOR_TRUECOLOR_ALPHA = 6
+
+ FILTERING_DEFAULT = 0
+
+ COMPRESSION_DEFAULT = 0
+
+ INTERLACING_NONE = 0
+ INTERLACING_ADAM7 = 1
+
+ FILTER_NONE = 0
+ FILTER_SUB = 1
+ FILTER_UP = 2
+ FILTER_AVERAGE = 3
+ FILTER_PAETH = 4
+
+ ###################################################
+ # ChunkyPNG exception classes
+ ###################################################
+
+ # Default exception class for ChunkyPNG
+ class Exception < ::StandardError
+ end
+
+ # Exception that is raised for an unsopported PNG image.
+ class NotSupported < ChunkyPNG::Exception
+ end
+
+ # Exception that is raised if the PNG signature is not encountered at the
+ # beginning of the file.
+ class SignatureMismatch < ChunkyPNG::Exception
+ end
+
+ # Exception that is raised if the CRC check for a block failes
+ class CRCMismatch < ChunkyPNG::Exception
+ end
+
+ # Exception that is raised if an expectation fails.
+ class ExpectationFailed < ChunkyPNG::Exception
+ end
+
+ # Exception that is raised if an expectation fails.
+ class OutOfBounds < ChunkyPNG::ExpectationFailed
+ end
+
+ EMPTY_BYTEARRAY = String.method_defined?(:force_encoding) ? "".force_encoding('ASCII-8BIT').freeze : "".freeze
+ EXTRA_BYTE = String.method_defined?(:force_encoding) ? "\0".force_encoding('ASCII-8BIT') : "\0"
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas.rb
new file mode 100644
index 00000000..9e7fc2e4
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas.rb
@@ -0,0 +1,264 @@
+module ChunkyPNG
+
+ # The ChunkPNG::Canvas class represents a raster image as a matrix of
+ # pixels.
+ #
+ # This class supports loading a Canvas from a PNG datastream, and creating a
+ # {ChunkyPNG::Datastream PNG datastream} based on this matrix. ChunkyPNG
+ # only supports 8-bit color depth, otherwise all of the PNG format's
+ # variations are supported for both reading and writing.
+ #
+ # This class offers per-pixel access to the matrix by using x,y coordinates.
+ # It uses a palette (see {ChunkyPNG::Palette}) to keep track of the
+ # different colors used in this matrix.
+ #
+ # The pixels in the canvas are stored as 4-byte fixnum, representing 32-bit
+ # RGBA colors (8 bit per channel). The module {ChunkyPNG::Color} is provided
+ # to work more easily with these number as color values.
+ #
+ # The module {ChunkyPNG::Canvas::Operations} is imported for operations on
+ # the whole canvas, like cropping and alpha compositing. Simple drawing
+ # functions are imported from the {ChunkyPNG::Canvas::Drawing} module.
+ class Canvas
+
+ include PNGEncoding
+ extend PNGDecoding
+ extend Adam7Interlacing
+
+ include StreamExporting
+ extend StreamImporting
+
+ include Operations
+ include Drawing
+
+ # @return [Integer] The number of columns in this canvas
+ attr_reader :width
+
+ # @return [Integer] The number of rows in this canvas
+ attr_reader :height
+
+ # @return [Array] The list of pixels in this canvas.
+ # This array always should have +width * height+ elements.
+ attr_reader :pixels
+
+
+ #################################################################
+ # CONSTRUCTORS
+ #################################################################
+
+ # Initializes a new Canvas instance
+ # @param [Integer] width The width in pixels of this canvas
+ # @param [Integer] width The height in pixels of this canvas
+ # @param [ChunkyPNG::Pixel, Array] initial The initial value of te pixels:
+ #
+ # * If a color is passed to this parameter, this color will be used as background color.
+ #
+ # * If an array of pixels is provided, these pixels will be used as initial value. Note
+ # that the amount of pixels in this array should equal +width * height+.
+ def initialize(width, height, initial = ChunkyPNG::Color::TRANSPARENT)
+
+ @width, @height = width, height
+
+ if initial.kind_of?(Integer)
+ @pixels = Array.new(width * height, initial)
+ elsif initial.kind_of?(Array) && initial.size == width * height
+ @pixels = initial
+ else
+ raise ChunkyPNG::ExpectationFailed, "Cannot use this value as initial canvas: #{initial.inspect}!"
+ end
+ end
+
+ # Initializes a new Canvas instances when being cloned.
+ # @param [ChunkyPNG::Canvas] other The canvas to duplicate
+ def initialize_copy(other)
+ @width, @height = other.width, other.height
+ @pixels = other.pixels.dup
+ end
+
+ # Creates a new canvas instance by duplicating another instance.
+ # @param [ChunkyPNG::Canvas] canvas The canvas to duplicate
+ # @return [ChunkyPNG::Canvas] The newly constructed canvas instance.
+ def self.from_canvas(canvas)
+ self.new(canvas.width, canvas.height, canvas.pixels.dup)
+ end
+
+
+ #################################################################
+ # PROPERTIES
+ #################################################################
+
+ # Returns the size ([width, height]) for this canvas.
+ # @return Array An array with the width and height of this canvas as elements.
+ def size
+ [@width, @height]
+ end
+
+ # Replaces a single pixel in this canvas.
+ # @param [Integer] x The x-coordinate of the pixel (column)
+ # @param [Integer] y The y-coordinate of the pixel (row)
+ # @param [ChunkyPNG::Color] pixel The new pixel for the provided coordinates.
+ # @return [Integer] the new pixel value, i.e. color.
+ # @raise [ChunkyPNG::OutOfBounds] when the coordinates are outside of the image's dimensions.
+ def []=(x, y, color)
+ assert_xy!(x, y)
+ @pixels[y * width + x] = color
+ end
+
+ # Replaces a single pixel in this canvas, without bounds checking.
+ # @param (see #[]=)
+ # @return [Integer] the new pixel value, i.e. color.
+ def set_pixel(x, y, color)
+ @pixels[y * width + x] = color
+ end
+
+ # Returns a single pixel from this canvas.
+ # @param [Integer] x The x-coordinate of the pixel (column)
+ # @param [Integer] y The y-coordinate of the pixel (row)
+ # @return [ChunkyPNG::Color] The current pixel at the provided coordinates.
+ # @raise [ChunkyPNG::OutOfBounds] when the coordinates are outside of the image's dimensions.
+ def [](x, y)
+ assert_xy!(x, y)
+ @pixels[y * width + x]
+ end
+
+ # Returns a single pixel from this canvas, without checking bounds.
+ # @param (see #[])
+ # @return [ChunkyPNG::Color] The current pixel at the provided coordinates.
+ def get_pixel(x, y)
+ @pixels[y * width + x]
+ end
+
+ # Returns an extracted row as vector of pixels
+ # @param [Integer] y The 0-based row index
+ # @return [Array] The vector of pixels in the requested row
+ def row(y)
+ assert_y!(y)
+ pixels.slice(y * width, width)
+ end
+
+ # Returns an extracted column as vector of pixels.
+ # @param [Integer] x The 0-based column index.
+ # @return [Array] The vector of pixels in the requested column.
+ def column(x)
+ assert_x!(x)
+ (0...height).inject([]) { |pixels, y| pixels << get_pixel(x, y) }
+ end
+
+ # Replaces a row of pixels on this canvas.
+ # @param [Integer] y The 0-based row index.
+ # @param [Array] vector The vector of pixels to replace the row with.
+ def replace_row!(y, vector)
+ assert_y!(y) && assert_width!(vector.length)
+ pixels[y * width, width] = vector
+ end
+
+ # Replaces a column of pixels on this canvas.
+ # @param [Integer] x The 0-based column index.
+ # @param [Array] vector The vector of pixels to replace the column with.
+ def replace_column!(x, vector)
+ assert_x!(x) && assert_height!(vector.length)
+ for y in 0...height do
+ set_pixel(x, y, vector[y])
+ end
+ end
+
+ # Checks whether the given coordinates are in the range of the canvas
+ # @param [Integer] x The x-coordinate of the pixel (column)
+ # @param [Integer] y The y-coordinate of the pixel (row)
+ # @return [true, false] True if the x and y coordinate are in the range
+ # of this canvas.
+ def include_xy?(x, y)
+ include_x?(x) && include_y?(y)
+ end
+
+ alias_method :include?, :include_xy?
+
+ # Checks whether the given y-coordinate is in the range of the canvas
+ # @param [Integer] y The y-coordinate of the pixel (row)
+ # @return [true, false] True if the y-coordinate is in the range of this canvas.
+ def include_y?(y)
+ y >= 0 && y < height
+ end
+
+ # Checks whether the given x-coordinate is in the range of the canvas
+ # @param [Integer] x The y-coordinate of the pixel (column)
+ # @return [true, false] True if the x-coordinate is in the range of this canvas.
+ def include_x?(x)
+ x >= 0 && x < width
+ end
+
+ # Returns the palette used for this canvas.
+ # @return [ChunkyPNG::Palette] A pallete which contains all the colors that are
+ # being used for this image.
+ def palette
+ ChunkyPNG::Palette.from_canvas(self)
+ end
+
+ # Equality check to compare this canvas with other matrices.
+ # @param other The object to compare this Matrix to.
+ # @return [true, false] True if the size and pixel values of the other canvas
+ # are exactly the same as this canvas's size and pixel values.
+ def eql?(other)
+ other.kind_of?(self.class) && other.pixels == self.pixels &&
+ other.width == self.width && other.height == self.height
+ end
+
+ alias :== :eql?
+
+ #################################################################
+ # EXPORTING
+ #################################################################
+
+ # Creates an ChunkyPNG::Image object from this canvas.
+ # @return [ChunkyPNG::Image] This canvas wrapped in an Image instance.
+ def to_image
+ ChunkyPNG::Image.from_canvas(self)
+ end
+
+ # Alternative implementation of the inspect method.
+ # @return [String] A nicely formatted string representation of this canvas.
+ def inspect
+ inspected = "<#{self.class.name} #{width}x#{height} ["
+ for y in 0...height
+ inspected << "\n\t[" << row(y).map { |p| ChunkyPNG::Color.to_hex(p) }.join(' ') << ']'
+ end
+ inspected << "\n]>"
+ end
+
+ protected
+
+ # Throws an exception if the x-coordinate is out of bounds.
+ def assert_x!(x)
+ raise ChunkyPNG::OutOfBounds, "Column index out of bounds!" unless include_x?(x)
+ return true
+ end
+
+ # Throws an exception if the y-coordinate is out of bounds.
+ def assert_y!(y)
+ raise ChunkyPNG::OutOfBounds, "Row index out of bounds!" unless include_y?(y)
+ return true
+ end
+
+ # Throws an exception if the x- or y-coordinate is out of bounds.
+ def assert_xy!(x, y)
+ raise ChunkyPNG::OutOfBounds, "Coordinates out of bounds!" unless include_xy?(x, y)
+ return true
+ end
+
+ def assert_height!(vector_length)
+ raise ChunkyPNG::ExpectationFailed, "The length of the vector does not match the canvas height!" if height != vector_length
+ return true
+ end
+
+ def assert_width!(vector_length)
+ raise ChunkyPNG::ExpectationFailed, "The length of the vector does not match the canvas width!" if width != vector_length
+ return true
+ end
+
+ def assert_size!(matrix_width, matrix_height)
+ raise ChunkyPNG::ExpectationFailed, "The width of the matrix does not match the canvas width!" if width != matrix_width
+ raise ChunkyPNG::ExpectationFailed, "The height of the matrix does not match the canvas height!" if height != matrix_height
+ return true
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/adam7_interlacing.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/adam7_interlacing.rb
new file mode 100644
index 00000000..7ad57041
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/adam7_interlacing.rb
@@ -0,0 +1,72 @@
+module ChunkyPNG
+ class Canvas
+
+ # Methods for decoding and encoding Adam7 interlacing.
+ #
+ # Adam7 interlacing extractg 7 pass images out of a single image, that can be encoded to a
+ # stream separately so the image can be built up progressively. The module is included into
+ # ChunkyPNG canvas and is used to extract the pass images from the original image, or to
+ # reconstruct an original image from separate pass images.
+ module Adam7Interlacing
+
+ # Returns an array with the x-shift, x-offset, y-shift and y-offset for the requested pass.
+ # @param [Integer] pass The pass number, should be in 0..6.
+ def adam7_multiplier_offset(pass)
+ [3 - (pass >> 1), (pass & 1 == 0) ? 0 : 8 >> ((pass + 1) >> 1),
+ pass == 0 ? 3 : 3 - ((pass - 1) >> 1), (pass == 0 || pass & 1 == 1) ? 0 : 8 >> (pass >> 1)]
+ end
+
+ # Returns the pixel dimensions of the requested pass.
+ # @param [Integer] pass The pass number, should be in 0..6.
+ # @param [Integer] original_width The width of the original image.
+ # @param [Integer] original_height The height of the original image.
+ def adam7_pass_size(pass, original_width, original_height)
+ x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
+ [ (original_width - x_offset + (1 << x_shift) - 1) >> x_shift,
+ (original_height - y_offset + (1 << y_shift) - 1) >> y_shift]
+ end
+
+ # Returns an array of the dimension of all the pass images.
+ # @param [Integer] original_width The width of the original image.
+ # @param [Integer] original_height The height of the original image.
+ # @return [Array>] Returns an array with 7 pairs of dimensions.
+ # @see #adam7_pass_size
+ def adam7_pass_sizes(original_width, original_height)
+ (0...7).map { |pass| adam7_pass_size(pass, original_width, original_height) }
+ end
+
+ # Merges a pass image into a total image that is being constructed.
+ # @param [Integer] pass The pass number, should be in 0..6.
+ # @param [ChunkyPNG::Canvas] canvas The image that is being constructed.
+ # @param [ChunkyPNG::Canvas] subcanvas The pass image that should be merged
+ def adam7_merge_pass(pass, canvas, subcanvas)
+ x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
+ for y in 0...subcanvas.height do
+ for x in 0...subcanvas.width do
+ new_x = (x << x_shift) | x_offset
+ new_y = (y << y_shift) | y_offset
+ canvas[new_x, new_y] = subcanvas[x, y]
+ end
+ end
+ end
+
+ # Extracts a pass from a complete image
+ # @param [Integer] pass The pass number, should be in 0..6.
+ # @param [ChunkyPNG::Canvas] canvas The image that is being deconstructed.
+ # @return [ChunkyPNG::Canvas] The extracted pass image.
+ def adam7_extract_pass(pass, canvas)
+ x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
+ sm_pixels = []
+
+ y_offset.step(canvas.height - 1, 1 << y_shift) do |y|
+ x_offset.step(canvas.width - 1, 1 << x_shift) do |x|
+ sm_pixels << canvas[x, y]
+ end
+ end
+
+ new_canvas_args = adam7_pass_size(pass, canvas.width, canvas.height) + [sm_pixels]
+ ChunkyPNG::Canvas.new(*new_canvas_args)
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/drawing.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/drawing.rb
new file mode 100644
index 00000000..9cd5b11c
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/drawing.rb
@@ -0,0 +1,87 @@
+module ChunkyPNG
+ class Canvas
+
+ module Drawing
+
+ # Sets a point on the canvas by composing a pixel with its background color.
+ def point(x, y, color)
+ set_pixel(x, y, ChunkyPNG::Color.compose(color, get_pixel(x, y)))
+ end
+
+ # Draws an anti-aliased line using Xiaolin Wu's algorithm.
+ #
+ def line_xiaolin_wu(x0, y0, x1, y1, color)
+ y0, y1, x0, x1 = y1, y0, x1, x0 if y0 > y1
+ dx = x1 - x0
+ sx = dx < 0 ? -1 : 1
+ dx *= sx
+ dy = y1 - y0
+
+ if dy == 0 # vertical line
+ Range.new(*[x0,x1].sort).each do |x|
+ point(x, y0, color)
+ end
+ elsif dx == 0 # horizontal line
+ (y0..y1).each do |y|
+ point(x0, y, color)
+ end
+ elsif dx == dy # diagonal
+ x0.step(x1, sx) do |x|
+ point(x, y0, color)
+ y0 += 1
+ end
+
+ elsif dy > dx # vertical displacement
+ point(x0, y0, color)
+ e_acc = 0
+ e = ((dx << 16) / dy.to_f).round
+ (y0...y1-1).each do |i|
+ e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xffff
+ x0 = x0 + sx if (e_acc <= e_acc_temp)
+ w = 0xff - (e_acc >> 8)
+ point(x0, y0, ChunkyPNG::Color.fade(color, w)) if include_xy?(x0, y0)
+ y0 = y0 + 1
+ point(x0 + sx, y0, ChunkyPNG::Color.fade(color, 0xff - w)) if include_xy?(x0 + sx, y0)
+ end
+ point(x1, y1, color)
+
+ else # horizontal displacement
+ point(x0, y0, color)
+ e_acc = 0
+ e = (dy << 16) / dx
+ (dx - 1).downto(0) do |i|
+ e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xffff
+ y0 += 1 if (e_acc <= e_acc_temp)
+ w = 0xff - (e_acc >> 8)
+ point(x0, y0, ChunkyPNG::Color.fade(color, w)) if include_xy?(x0, y0)
+ x0 += sx
+ point(x0, y0 + 1, ChunkyPNG::Color.fade(color, 0xff - w)) if include_xy?(x0, y0 + 1)
+ end
+ point(x1, y1, color)
+ end
+
+ return self
+ end
+
+ alias_method :line, :line_xiaolin_wu
+
+ def rect(x0, y0, x1, y1, line_color, fill_color = ChunkyPNG::COLOR::TRANSPARENT)
+
+ # Fill
+ [x0, x1].min.upto([x0, x1].max) do |x|
+ [y0, y1].min.upto([y0, y1].max) do |y|
+ point(x, y, fill_color)
+ end
+ end
+
+ # Stroke
+ line(x0, y0, x0, y1, line_color)
+ line(x0, y1, x1, y1, line_color)
+ line(x1, y1, x1, y0, line_color)
+ line(x1, y0, x0, y0, line_color)
+
+ return self
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/operations.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/operations.rb
new file mode 100644
index 00000000..5b428a15
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/operations.rb
@@ -0,0 +1,238 @@
+module ChunkyPNG
+ class Canvas
+
+ # The ChunkyPNG::Canvas::Operations module defines methods to perform operations
+ # on a {ChunkyPNG::Canvas}. The module is included into the Canvas class so all
+ # these methods are available on every canvas.
+ #
+ # Note that some of these operations modify the canvas, while some operations return
+ # a new canvas and leave the original intact.
+ #
+ # @see ChunkyPNG::Canvas
+ module Operations
+
+ # Composes another image onto this image using alpha blending.
+ #
+ # If you simply want to replace pixels or when the other image does not have
+ # transparency, it is faster to use {#replace}.
+ #
+ # @param [ChunkyPNG::Canvas] other The foreground canvas to compose on the
+ # current canvas, using alpha compositing.
+ # @param [Integer] offset_x The x-offset to apply the new forgeround on.
+ # @param [Integer] offset_y The y-offset to apply the new forgeround on.
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the other canvas composed onto it.
+ # @raise [ChunkyPNG::OutOfBounds] when the other canvas doesn't fit on this one,
+ # given the offset and size of the other canavs.
+ # @see #replace
+ def compose(other, offset_x = 0, offset_y = 0)
+ check_size_constraints!(other, offset_x, offset_y)
+
+ for y in 0...other.height do
+ for x in 0...other.width do
+ set_pixel(x + offset_x, y + offset_y, ChunkyPNG::Color.compose(other.get_pixel(x, y), get_pixel(x + offset_x, y + offset_y)))
+ end
+ end
+ self
+ end
+
+ # Replaces pixels on this image by pixels from another pixels, on a given offset.
+ #
+ # This will completely replace the pixels of the background image. If you want to blend
+ # them with semi-transparent pixels from the foreground image, see {#compose}.
+ #
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the other canvas composed onto it.
+ # @raise [ChunkyPNG::OutOfBounds] when the other canvas doesn't fit on this one,
+ # given the offset and size of the other canavs.
+ # @see #compose
+ def replace(other, offset_x = 0, offset_y = 0)
+ check_size_constraints!(other, offset_x, offset_y)
+
+ for y in 0...other.height do
+ pixels[(y + offset_y) * width + offset_x, other.width] = other.pixels[y * other.width, other.width]
+ end
+ self
+ end
+
+ # Crops an image, given the coordinates and size of the image that needs to be cut out.
+ # This will leave the original image intact and return a new, cropped image with pixels
+ # copied from the original image.
+ #
+ # @param [Integer] x The x-coordinate of the top left corner of the image to be cropped.
+ # @param [Integer] y The y-coordinate of the top left corner of the image to be cropped.
+ # @param [Integer] crop_width The width of the image to be cropped.
+ # @param [Integer] crop_height The height of the image to be cropped.
+ # @return [ChunkyPNG::Canvas] Returns the newly created cropped image.
+ # @raise [ChunkyPNG::OutOfBounds] when the crop dimensions plus the given coordinates
+ # are bigger then the original image.
+ def crop(x, y, crop_width, crop_height)
+
+ raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_width + x > width
+ raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_height + y > height
+
+ new_pixels = []
+ for cy in 0...crop_height do
+ new_pixels += pixels.slice((cy + y) * width + x, crop_width)
+ end
+ ChunkyPNG::Canvas.new(crop_width, crop_height, new_pixels)
+ end
+
+ # Creates a new image, based on the current image but with a new theme color.
+ #
+ # This method will replace one color in an image with another image. This is done by
+ # first extracting the pixels with a color close to the original theme color as a mask
+ # image, changing the color of this mask image and then apply it on the original image.
+ #
+ # Mask extraction works best when the theme colored pixels are clearly distinguishable
+ # from a background color (preferably white). You can set a tolerance level to influence
+ # the extraction process.
+ #
+ # @param [Integer] old_theme_color The original theme color in this image.
+ # @param [Integer] new_theme_color The color to replace the old theme color with.
+ # @param [Integer] The backrgound color opn which the theme colored pixels are placed.
+ # @param [Integer] tolerance The tolerance level to use when extracting the mask image. Five is
+ # the default; increase this if the masked image does not extract all the required pixels,
+ # decrease it if too many pixels get extracted.
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the theme colored pixels changed.
+ # @see #change_theme_color!
+ # @see #change_mask_color!
+ def change_theme_color!(old_theme_color, new_theme_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
+ base, mask = extract_mask(old_theme_color, bg_color, tolerance)
+ mask.change_mask_color!(new_theme_color)
+ self.replace(base.compose(mask))
+ end
+
+ # Creates a base image and a mask image from an original image that has a particular theme color.
+ # This can be used to easily change a theme color in an image.
+ #
+ # It will extract all the pixels that look like the theme color (with a tolerance level) and put
+ # these in a mask image. All the other pixels will be stored in a base image. Both images will be
+ # of the exact same size as the original image. The original image will be left untouched.
+ #
+ # The color of the mask image can be changed with {#change_mask_color!}. This new mask image can
+ # then be composed upon the base image to create an image with a new theme color. A call to
+ # {#change_theme_color!} will perform this in one go.
+ #
+ # @param [Integer] mask_color The current theme color.
+ # @param [Integer] bg_color The background color on which the theme colored pxiels are applied.
+ # @param [Integer] tolerance The tolerance level to use when extracting the mask image. Five is
+ # the default; increase this if the masked image does not extract all the required pixels,
+ # decrease it if too many pixels get extracted.
+ # @return [Array] An array with the base canvas and the mask
+ # canvas as elements.
+ # @see #change_theme_color!
+ # @see #change_mask_color!
+ def extract_mask(mask_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
+ base_pixels = []
+ mask_pixels = []
+
+ pixels.each do |pixel|
+ if ChunkyPNG::Color.alpha_decomposable?(pixel, mask_color, bg_color, tolerance)
+ mask_pixels << ChunkyPNG::Color.decompose_color(pixel, mask_color, bg_color, tolerance)
+ base_pixels << bg_color
+ else
+ mask_pixels << (mask_color & 0xffffff00)
+ base_pixels << pixel
+ end
+ end
+
+ [ self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels) ]
+ end
+
+ # Changes the color of a mask image.
+ #
+ # This method works on acanavs extracte out of another image using the {#extract_mask} method.
+ # It can then be applied on the extracted base image. See {#change_theme_color!} to perform
+ # these operations in one go.
+ #
+ # @param [Integer] new_color The color to replace the original mask color with.
+ # @raise [ChunkyPNG::ExpectationFailed] when this canvas is not a mask image, i.e. its palette
+ # has more than once color, disregarding transparency.
+ # @see #change_theme_color!
+ # @see #extract_mask
+ def change_mask_color!(new_color)
+ raise ChunkyPNG::ExpectationFailed, "This is not a mask image!" if palette.opaque_palette.size != 1
+ pixels.map! { |pixel| (new_color & 0xffffff00) | ChunkyPNG::Color.a(pixel) }
+ self
+ end
+
+ # Flips the image horizontally.
+ #
+ # This will flip the image on its horizontal axis, e.g. pixels on the top will now
+ # be pixels on the bottom. Chaining this method twice will return the original canvas.
+ # This method will leave the original object intact and return a new canvas.
+ #
+ # @return [ChunkyPNG::Canvas] The flipped image
+ def flip_horizontally
+ self.class.new(width, height).tap do |flipped|
+ for y in 0...height do
+ flipped.replace_row!(height - (y + 1), row(y))
+ end
+ end
+ end
+
+ # Flips the image horizontally.
+ #
+ # This will flip the image on its vertical axis, e.g. pixels on the left will now
+ # be pixels on the right. Chaining this method twice will return the original canvas.
+ # This method will leave the original object intact and return a new canvas.
+ #
+ # @return [ChunkyPNG::Canvas] The flipped image
+ def flip_vertically
+ self.class.new(width, height).tap do |flipped|
+ for x in 0...width do
+ flipped.replace_column!(width - (x + 1), column(x))
+ end
+ end
+ end
+
+ # Rotates the image 90 degrees clockwise.
+ # This method will leave the original object intact and return a new canvas.
+ #
+ # @return [ChunkyPNG::Canvas] The rotated image
+ def rotate_right
+ self.class.new(height, width).tap do |rotated|
+ for i in 0...width do
+ rotated.replace_row!(i, column(i).reverse)
+ end
+ end
+ end
+
+ # Rotates the image 90 degrees counter-clockwise.
+ # This method will leave the original object intact and return a new canvas.
+ #
+ # @return [ChunkyPNG::Canvas] The rotated image.
+ def rotate_left
+ self.class.new(height, width).tap do |rotated|
+ for i in 0...width do
+ rotated.replace_row!(width - (i + 1), column(i))
+ end
+ end
+ end
+
+ # Rotates the image 180 degrees.
+ # This method will leave the original object intact and return a new canvas.
+ #
+ # @return [ChunkyPNG::Canvas] The rotated image.
+ def rotate_180
+ self.class.new(width, height).tap do |flipped|
+ for y in 0...height do
+ flipped.replace_row!(height - (y + 1), row(y).reverse)
+ end
+ end
+ end
+
+ protected
+
+ # Checks whether another image has the correct dimension to be used for an operation
+ # on the current image, given an offset coordinate to work with.
+ # @param [ChunkyPNG::Canvas] other The other canvas
+ # @param [Integer] offset_x The x offset on which the other image will be applied.
+ # @param [Integer] offset_y The y offset on which the other image will be applied.
+ # @raise [ChunkyPNG::OutOfBounds] when the other image doesn't fit.
+ def check_size_constraints!(other, offset_x, offset_y)
+ raise ChunkyPNG::OutOfBounds, "Background image width is too small!" if width < other.width + offset_x
+ raise ChunkyPNG::OutOfBounds, "Background image height is too small!" if height < other.height + offset_y
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/png_decoding.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/png_decoding.rb
new file mode 100644
index 00000000..1e38e72e
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/png_decoding.rb
@@ -0,0 +1,484 @@
+module ChunkyPNG
+ class Canvas
+
+ # The PNGDecoding contains methods for decoding PNG datastreams to create a
+ # Canvas object. The datastream can be provided as filename, string or IO
+ # stream.
+ #
+ # Overview of the decoding process:
+ #
+ # * The optional PLTE and tRNS chunk are decoded for the color palette of
+ # the original image.
+ # * The contents of the IDAT chunks is combined, and uncompressed using
+ # Inflate decompression to the image pixelstream.
+ # * Based on the color mode, width and height of the original image, which
+ # is read from the PNG header (IHDR chunk), the amount of bytes
+ # per line is determined.
+ # * For every line of pixels in the encoded image, the original byte values
+ # are restored by unapplying the milter method for that line.
+ # * The read bytes are unfiltered given by the filter function specified by
+ # the first byte of the line.
+ # * The unfiltered pixelstream are is into colored pixels, using the color mode.
+ # * All lines combined to form the original image.
+ #
+ # For interlaced images, the original image was split into 7 subimages.
+ # These images get decoded just like the process above (from step 3), and get
+ # combined to form the original images.
+ #
+ # @see ChunkyPNG::Canvas::PNGEncoding
+ # @see http://www.w3.org/TR/PNG/ The W3C PNG format specification
+ module PNGDecoding
+
+ # The palette that is used to decode the image, loading from the PLTE and
+ # tRNS chunk from the PNG stream. For RGB(A) images, no palette is required.
+ # @return [ChunkyPNG::Palette]
+ attr_accessor :decoding_palette
+
+ # Decodes a Canvas from a PNG encoded string.
+ # @param [String] str The string to read from.
+ # @return [ChunkyPNG::Canvas] The canvas decoded from the PNG encoded string.
+ def from_blob(str)
+ from_datastream(ChunkyPNG::Datastream.from_blob(str))
+ end
+
+ alias_method :from_string, :from_blob
+
+ # Decodes a Canvas from a PNG encoded file.
+ # @param [String] filename The file to read from.
+ # @return [ChunkyPNG::Canvas] The canvas decoded from the PNG file.
+ def from_file(filename)
+ from_datastream(ChunkyPNG::Datastream.from_file(filename))
+ end
+
+ # Decodes a Canvas from a PNG encoded stream.
+ # @param [IO, #read] io The stream to read from.
+ # @return [ChunkyPNG::Canvas] The canvas decoded from the PNG stream.
+ def from_io(io)
+ from_datastream(ChunkyPNG::Datastream.from_io(io))
+ end
+
+ alias_method :from_stream, :from_io
+
+ # Decodes the Canvas from a PNG datastream instance.
+ # @param [ChunkyPNG::Datastream] ds The datastream to decode.
+ # @return [ChunkyPNG::Canvas] The canvas decoded from the PNG datastream.
+ def from_datastream(ds)
+ width = ds.header_chunk.width
+ height = ds.header_chunk.height
+ color_mode = ds.header_chunk.color
+ interlace = ds.header_chunk.interlace
+ depth = ds.header_chunk.depth
+
+ if width == 0 || height == 0
+ raise ExpectationFailed, "Invalid image size, width: #{width}, height: #{height}"
+ end
+
+ self.decoding_palette = ChunkyPNG::Palette.from_chunks(ds.palette_chunk, ds.transparency_chunk)
+ decode_png_pixelstream(ds.imagedata, width, height, color_mode, depth, interlace)
+ end
+
+ # Decodes a canvas from a PNG encoded pixelstream, using a given width, height,
+ # color mode and interlacing mode.
+ # @param [String] stream The pixelstream to read from.
+ # @param [Integer] width The width of the image.
+ # @param [Integer] width The height of the image.
+ # @param [Integer] color_mode The color mode of the encoded pixelstream.
+ # @param [Integer] depth The bit depth of the pixel samples.
+ # @param [Integer] interlace The interlace method of the encoded pixelstream.
+ # @return [ChunkyPNG::Canvas] The decoded Canvas instance.
+ def decode_png_pixelstream(stream, width, height, color_mode, depth, interlace)
+ raise ChunkyPNG::ExpectationFailed, "This palette is not suitable for decoding!" if decoding_palette && !decoding_palette.can_decode?
+ case interlace
+ when ChunkyPNG::INTERLACING_NONE; decode_png_without_interlacing(stream, width, height, color_mode, depth)
+ when ChunkyPNG::INTERLACING_ADAM7; decode_png_with_adam7_interlacing(stream, width, height, color_mode, depth)
+ else raise ChunkyPNG::NotSupported, "Don't know how the handle interlacing method #{interlace}!"
+ end
+ end
+
+ protected
+
+ # Decodes a canvas from a non-interlaced PNG encoded pixelstream, using a
+ # given width, height and color mode.
+ # @param stream (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param width (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param height (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param color_mode (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param depth (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ def decode_png_without_interlacing(stream, width, height, color_mode, depth)
+ decode_png_image_pass(stream, width, height, color_mode, depth, 0)
+ end
+
+ # Decodes a canvas from a Adam 7 interlaced PNG encoded pixelstream, using a
+ # given width, height and color mode.
+ # @param stream (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param width (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param height (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param color_mode (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param depth (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ def decode_png_with_adam7_interlacing(stream, width, height, color_mode, depth)
+ canvas = new(width, height)
+ start_pos = 0
+ for pass in 0...7
+ sm_width, sm_height = adam7_pass_size(pass, width, height)
+ sm = decode_png_image_pass(stream, sm_width, sm_height, color_mode, depth, start_pos)
+ adam7_merge_pass(pass, canvas, sm)
+ start_pos += ChunkyPNG::Color.pass_bytesize(color_mode, depth, sm_width, sm_height)
+ end
+ canvas
+ end
+
+ # Extract 4 consecutive bits from a byte.
+ # @param [Integer] byte The byte (0..255) value to extract a 4 bit value from.
+ # @param [Integer] index The index within the byte. This should be either 0 or 2;
+ # the value will be modded by 2 to enforce this.
+ # @return [Integer] The extracted 4bit value (0..15)
+ def decode_png_extract_4bit_value(byte, index)
+ (index & 0x01 == 0) ? ((byte & 0xf0) >> 4) : (byte & 0x0f)
+ end
+
+ # Extract 2 consecutive bits from a byte.
+ # @param [Integer] byte The byte (0..255) value to extract a 2 bit value from.
+ # @param [Integer] index The index within the byte. This should be either 0, 1, 2, or 3;
+ # the value will be modded by 4 to enforce this.
+ # @return [Integer] The extracted 2 bit value (0..3)
+ def decode_png_extract_2bit_value(byte, index)
+ bitshift = 6 - ((index & 0x03) << 1)
+ (byte & (0x03 << bitshift)) >> bitshift
+ end
+
+ # Extract a bit from a byte on a given index.
+ # @param [Integer] byte The byte (0..255) value to extract a a bit from.
+ # @param [Integer] index The index within the byte. This should be 0..7;
+ # the value will be modded by 8 to enforce this.
+ # @return [Integer] Either 1 or 0.
+ def decode_png_extract_1bit_value(byte, index)
+ bitshift = 7 - (index & 0x07)
+ (byte & (0x01 << bitshift)) >> bitshift
+ end
+
+ # Resamples a 16 bit value to an 8 bit value. This will discard some color information.
+ # @param [Integer] value The 16 bit value to resample.
+ # @return [Integer] The 8 bit resampled value
+ def decode_png_resample_16bit_value(value)
+ value >> 8
+ end
+
+ # Resamples a 4 bit value to an 8 bit value.
+ # @param [Integer] value The 4 bit value to resample.
+ # @return [Integer] The 8 bit resampled value.
+ def decode_png_resample_4bit_value(value)
+ case value
+ when 0x00; 0
+ when 0x01; 17
+ when 0x02; 34
+ when 0x03; 51
+ when 0x04; 68
+ when 0x05; 85
+ when 0x06; 102
+ when 0x07; 119
+ when 0x08; 137
+ when 0x09; 154
+ when 0x0a; 171
+ when 0x0b; 188
+ when 0x0c; 205
+ when 0x0d; 222
+ when 0x0e; 239
+ when 0x0f; 255
+ end
+ end
+
+ # Resamples a 2 bit value to an 8 bit value.
+ # @param [Integer] value The 2 bit value to resample.
+ # @return [Integer] The 8 bit resampled value.
+ def decode_png_resample_2bit_value(value)
+ case value
+ when 0x00; 0x00
+ when 0x01; 0x55
+ when 0x02; 0xaa
+ when 0x03; 0xff
+ end
+ end
+
+ # Decodes a scanline of a 1-bit, indexed image into a row of pixels.
+ # @param [String] stream The stream to decode from.
+ # @param [Integer] pos The position in the stream on qhich the scanline starts (including the filter byte).
+ # @param [Integer] width The width in pixels of the scanline.
+ # @return [Array] An array of decoded pixels.
+ def decode_png_pixels_from_scanline_indexed_1bit(stream, pos, width)
+ (0...width).map do |index|
+ palette_pos = decode_png_extract_1bit_value(stream.getbyte(pos + 1 + (index >> 3)), index)
+ decoding_palette[palette_pos]
+ end
+ end
+
+ # Decodes a scanline of a 2-bit, indexed image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_indexed_2bit(stream, pos, width)
+ (0...width).map do |index|
+ palette_pos = decode_png_extract_2bit_value(stream.getbyte(pos + 1 + (index >> 2)), index)
+ decoding_palette[palette_pos]
+ end
+ end
+
+ # Decodes a scanline of a 4-bit, indexed image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_indexed_4bit(stream, pos, width)
+ (0...width).map do |index|
+ palette_pos = decode_png_extract_4bit_value(stream.getbyte(pos + 1 + (index >> 1)), index)
+ decoding_palette[palette_pos]
+ end
+ end
+
+ # Decodes a scanline of a 8-bit, indexed image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_indexed_8bit(stream, pos, width)
+ (1..width).map { |i| decoding_palette[stream.getbyte(pos + i)] }
+ end
+
+ # Decodes a scanline of an 8-bit, true color image with transparency into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_truecolor_alpha_8bit(stream, pos, width)
+ stream.unpack("@#{pos + 1}N#{width}")
+ end
+
+ # Decodes a scanline of a 16-bit, true color image with transparency into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_truecolor_alpha_16bit(stream, pos, width)
+ [].tap do |pixels|
+ stream.unpack("@#{pos + 1}n#{width * 4}").each_slice(4) do |r, g, b, a|
+ pixels << ChunkyPNG::Color.rgba(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g),
+ decode_png_resample_16bit_value(b), decode_png_resample_16bit_value(a))
+ end
+ end
+ end
+
+ # Decodes a scanline of an 8-bit, true color image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_truecolor_8bit(stream, pos, width)
+ stream.unpack("@#{pos + 1}" << ('NX' * width)).map { |c| c | 0x000000ff }
+ end
+
+ # Decodes a scanline of a 16-bit, true color image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_truecolor_16bit(stream, pos, width)
+ [].tap do |pixels|
+ stream.unpack("@#{pos + 1}n#{width * 3}").each_slice(3) do |r, g, b|
+ pixels << ChunkyPNG::Color.rgb(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(b))
+ end
+ end
+ end
+
+ # Decodes a scanline of an 8-bit, grayscale image with transparency into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_grayscale_alpha_8bit(stream, pos, width)
+ (0...width).map { |i| ChunkyPNG::Color.grayscale_alpha(stream.getbyte(pos + (i * 2) + 1), stream.getbyte(pos + (i * 2) + 2)) }
+ end
+
+ # Decodes a scanline of a 16-bit, grayscale image with transparency into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_grayscale_alpha_16bit(stream, pos, width)
+ [].tap do |pixels|
+ stream.unpack("@#{pos + 1}n#{width * 2}").each_slice(2) do |g, a|
+ pixels << ChunkyPNG::Color.grayscale_alpha(decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(a))
+ end
+ end
+ end
+
+ # Decodes a scanline of a 1-bit, grayscale image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_grayscale_1bit(stream, pos, width)
+ (0...width).map do |index|
+ value = decode_png_extract_1bit_value(stream.getbyte(pos + 1 + (index >> 3)), index)
+ value == 1 ? ChunkyPNG::Color::WHITE : ChunkyPNG::Color::BLACK
+ end
+ end
+
+ # Decodes a scanline of a 2-bit, grayscale image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_grayscale_2bit(stream, pos, width)
+ (0...width).map do |index|
+ value = decode_png_extract_2bit_value(stream.getbyte(pos + 1 + (index >> 2)), index)
+ ChunkyPNG::Color.grayscale(decode_png_resample_2bit_value(value))
+ end
+ end
+
+ # Decodes a scanline of a 4-bit, grayscale image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_grayscale_4bit(stream, pos, width)
+ (0...width).map do |index|
+ value = decode_png_extract_4bit_value(stream.getbyte(pos + 1 + (index >> 1)), index)
+ ChunkyPNG::Color.grayscale(decode_png_resample_4bit_value(value))
+ end
+ end
+
+ # Decodes a scanline of an 8-bit, grayscale image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_grayscale_8bit(stream, pos, width)
+ (1..width).map { |i| ChunkyPNG::Color.grayscale(stream.getbyte(pos + i)) }
+ end
+
+ # Decodes a scanline of a 16-bit, grayscale image into a row of pixels.
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
+ def decode_png_pixels_from_scanline_grayscale_16bit(stream, pos, width)
+ values = stream.unpack("@#{pos + 1}n#{width}")
+ values.map { |value| ChunkyPNG::Color.grayscale(decode_png_resample_16bit_value(value)) }
+ end
+
+ # Returns the method name to use to decode scanlines into pixels.
+ # @param [Integer] color_mode The color mode of the image.
+ # @param [Integer] depth The bit depth of the image.
+ # @return [Symbol] The method name to use for decoding, to be called on the canvas class.
+ # @raise [ChunkyPNG::NotSupported] when the color_mode and/or bit depth is not supported.
+ def decode_png_pixels_from_scanline_method(color_mode, depth)
+ decoder_method = case color_mode
+ when ChunkyPNG::COLOR_TRUECOLOR; :"decode_png_pixels_from_scanline_truecolor_#{depth}bit"
+ when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; :"decode_png_pixels_from_scanline_truecolor_alpha_#{depth}bit"
+ when ChunkyPNG::COLOR_INDEXED; :"decode_png_pixels_from_scanline_indexed_#{depth}bit"
+ when ChunkyPNG::COLOR_GRAYSCALE; :"decode_png_pixels_from_scanline_grayscale_#{depth}bit"
+ when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; :"decode_png_pixels_from_scanline_grayscale_alpha_#{depth}bit"
+ else nil
+ end
+
+ raise ChunkyPNG::NotSupported, "No decoder found for color mode #{color_mode} and #{depth}-bit depth!" unless respond_to?(decoder_method)
+ decoder_method
+ end
+
+ # Decodes a single PNG image pass width a given width, height and color
+ # mode, to a Canvas, starting at the given position in the stream.
+ #
+ # A non-interlaced image only consists of one pass, while an Adam7
+ # image consists of 7 passes that must be combined after decoding.
+ #
+ # @param stream (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param width (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param height (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param color_mode (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ # @param [Integer] start_pos The position in the pixel stream to start reading.
+ # @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
+ def decode_png_image_pass(stream, width, height, color_mode, depth, start_pos)
+
+ pixels = []
+ if width > 0 && height > 0
+
+ stream << ChunkyPNG::EXTRA_BYTE if color_mode == ChunkyPNG::COLOR_TRUECOLOR
+ pixel_decoder = decode_png_pixels_from_scanline_method(color_mode, depth)
+ line_length = ChunkyPNG::Color.scanline_bytesize(color_mode, depth, width)
+ pixel_size = ChunkyPNG::Color.pixel_bytesize(color_mode, depth)
+
+ raise ChunkyPNG::ExpectationFailed, "Invalid stream length!" unless stream.bytesize - start_pos >= ChunkyPNG::Color.pass_bytesize(color_mode, depth, width, height)
+
+ pos, prev_pos = start_pos, nil
+ for line_no in 0...height do
+ decode_png_str_scanline(stream, pos, prev_pos, line_length, pixel_size)
+ pixels += send(pixel_decoder, stream, pos, width)
+
+ prev_pos = pos
+ pos += line_length + 1
+ end
+ end
+
+ new(width, height, pixels)
+ end
+
+ # Decodes a scanline if it was encoded using filtering.
+ #
+ # It will extract the filtering method from the first byte of the scanline, and uses the
+ # method to change the subsequent bytes to unfiltered values. This will modify the pixelstream.
+ #
+ # The bytes of the scanline can then be used to construct pixels, based on the color mode..
+ #
+ # @param [String] stream The pixelstream to undo the filtering in.
+ # @param [Integer] pos The starting position of the scanline to decode.
+ # @param [Integer, nil] prev_pos The starting position of the previously decoded scanline, or nil
+ # if this is the first scanline of the image.
+ # @param [Integer] line_length The number of bytes in the scanline, discounting the filter method byte.
+ # @param [Integer] pixel_size The number of bytes used per pixel, based on the color mode.
+ # @return [nil]
+ def decode_png_str_scanline(stream, pos, prev_pos, line_length, pixel_size)
+ case stream.getbyte(pos)
+ when ChunkyPNG::FILTER_NONE; # noop
+ when ChunkyPNG::FILTER_SUB; decode_png_str_scanline_sub( stream, pos, prev_pos, line_length, pixel_size)
+ when ChunkyPNG::FILTER_UP; decode_png_str_scanline_up( stream, pos, prev_pos, line_length, pixel_size)
+ when ChunkyPNG::FILTER_AVERAGE; decode_png_str_scanline_average( stream, pos, prev_pos, line_length, pixel_size)
+ when ChunkyPNG::FILTER_PAETH; decode_png_str_scanline_paeth( stream, pos, prev_pos, line_length, pixel_size)
+ else raise ChunkyPNG::NotSupported, "Unknown filter type: #{stream.getbyte(pos)}!"
+ end
+ end
+
+ # Decodes a scanline that wasn't encoded using filtering. This is a no-op.
+ # @params (see #decode_png_str_scanline)
+ # @return [nil]
+ def decode_png_str_scanline_sub_none(stream, pos, prev_pos, line_length, pixel_size)
+ # noop - this method shouldn't get called.
+ end
+
+ # Decodes a scanline in a pxielstream that was encoded using SUB filtering.
+ # This will chnage the pixelstream to have unfiltered values.
+ # @params (see #decode_png_str_scanline)
+ # @return [nil]
+ def decode_png_str_scanline_sub(stream, pos, prev_pos, line_length, pixel_size)
+ for i in 1..line_length do
+ stream.setbyte(pos + i, (stream.getbyte(pos + i) + (i > pixel_size ? stream.getbyte(pos + i - pixel_size) : 0)) & 0xff)
+ end
+ end
+
+ # Decodes a scanline in a pxielstream that was encoded using UP filtering.
+ # This will chnage the pixelstream to have unfiltered values.
+ # @params (see #decode_png_str_scanline)
+ # @return [nil]
+ def decode_png_str_scanline_up(stream, pos, prev_pos, line_length, pixel_size)
+ for i in 1..line_length do
+ up = prev_pos ? stream.getbyte(prev_pos + i) : 0
+ stream.setbyte(pos + i, (stream.getbyte(pos + i) + up) & 0xff)
+ end
+ end
+
+ # Decodes a scanline in a pxielstream that was encoded using AVERAGE filtering.
+ # This will chnage the pixelstream to have unfiltered values.
+ # @params (see #decode_png_str_scanline)
+ # @return [nil]
+ def decode_png_str_scanline_average(stream, pos, prev_pos, line_length, pixel_size)
+ for i in 1..line_length do
+ a = (i > pixel_size) ? stream.getbyte(pos + i - pixel_size) : 0
+ b = prev_pos ? stream.getbyte(prev_pos + i) : 0
+ stream.setbyte(pos + i, (stream.getbyte(pos + i) + ((a + b) >> 1)) & 0xff)
+ end
+ end
+
+ # Decodes a scanline in a pxielstream that was encoded using PAETH filtering.
+ # This will chnage the pixelstream to have unfiltered values.
+ # @params (see #decode_png_str_scanline)
+ # @return [nil]
+ def decode_png_str_scanline_paeth(stream, pos, prev_pos, line_length, pixel_size)
+ for i in 1..line_length do
+ cur_pos = pos + i
+ a = (i > pixel_size) ? stream.getbyte(cur_pos - pixel_size) : 0
+ b = prev_pos ? stream.getbyte(prev_pos + i) : 0
+ c = (prev_pos && i > pixel_size) ? stream.getbyte(prev_pos + i - pixel_size) : 0
+ p = a + b - c
+ pa = (p - a).abs
+ pb = (p - b).abs
+ pc = (p - c).abs
+ pr = (pa <= pb) ? (pa <= pc ? a : c) : (pb <= pc ? b : c)
+ stream.setbyte(cur_pos, (stream.getbyte(cur_pos) + pr) & 0xff)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/png_encoding.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/png_encoding.rb
new file mode 100644
index 00000000..35f6853c
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/png_encoding.rb
@@ -0,0 +1,292 @@
+module ChunkyPNG
+ class Canvas
+
+ # Methods for encoding a Canvas instance into a PNG datastream.
+ #
+ # Overview of the encoding process:
+ #
+ # * The image is split up in scanlines (i.e. rows of pixels);
+ # * All pixels are encoded as a pixelstream, based on the color mode.
+ # * All the pixel bytes in the pixelstream are adjusted using a filtering
+ # method if one is specified.
+ # * Compress the resulting string using deflate compression.
+ # * Split compressed data over one or more PNG chunks.
+ # * These chunks should be embedded in a datastream with at least a IHDR and
+ # IEND chunk and possibly a PLTE chunk.
+ #
+ # For interlaced images, the initial image is first split into 7 subimages.
+ # These images get encoded exectly as above, and the result gets combined
+ # before the compression step.
+ #
+ # @see ChunkyPNG::Canvas::PNGDecoding
+ # @see http://www.w3.org/TR/PNG/ The W3C PNG format specification
+ module PNGEncoding
+
+ # The palette used for encoding the image.This is only in used for images
+ # that get encoded using indexed colors.
+ # @return [ChunkyPNG::Palette]
+ attr_accessor :encoding_palette
+
+ # Writes the canvas to an IO stream, encoded as a PNG image.
+ # @param [IO] io The output stream to write to.
+ # @param constraints (see ChunkyPNG::Canvas::PNGEncoding#to_datastream)
+ def write(io, constraints = {})
+ to_datastream(constraints).write(io)
+ end
+
+ # Writes the canvas to a file, encoded as a PNG image.
+ # @param [String] filname The file to save the PNG image to.
+ # @param constraints (see ChunkyPNG::Canvas::PNGEncoding#to_datastream)
+ def save(filename, constraints = {})
+ File.open(filename, 'wb') { |io| write(io, constraints) }
+ end
+
+ # Encoded the canvas to a PNG formatted string.
+ # @param constraints (see ChunkyPNG::Canvas::PNGEncoding#to_datastream)
+ # @return [String] The PNG encoded canvas as string.
+ def to_blob(constraints = {})
+ to_datastream(constraints).to_blob
+ end
+
+ alias_method :to_string, :to_blob
+ alias_method :to_s, :to_blob
+
+ # Converts this Canvas to a datastream, so that it can be saved as a PNG image.
+ # @param [Hash, Symbol] constraints The constraints to use when encoding the canvas.
+ # This can either be a hash with different constraints, or a symbol which acts as a
+ # preset for some constraints. If no constraints are given, ChunkyPNG will decide
+ # for itself how to best create the PNG datastream.
+ # Supported presets are :fast_rgba for quickly saving images with transparency,
+ # :fast_rgb for quickly saving opaque images, and :best_compression to
+ # obtain the smallest possible filesize.
+ # @option constraints [Fixnum] :color_mode The color mode to use. Use one of the
+ # ChunkyPNG::COLOR_* constants.
+ # @option constraints [true, false] :interlace Whether to use interlacing.
+ # @option constraints [Fixnum] :compression The compression level for Zlib. This can be a
+ # value between 0 and 9, or a Zlib constant like Zlib::BEST_COMPRESSION.
+ # @return [ChunkyPNG::Datastream] The PNG datastream containing the encoded canvas.
+ # @see ChunkyPNG::Canvas::PNGEncoding#determine_png_encoding
+ def to_datastream(constraints = {})
+ encoding = determine_png_encoding(constraints)
+
+ ds = Datastream.new
+ ds.header_chunk = Chunk::Header.new(:width => width, :height => height,
+ :color => encoding[:color_mode], :interlace => encoding[:interlace])
+
+ if encoding[:color_mode] == ChunkyPNG::COLOR_INDEXED
+ ds.palette_chunk = encoding_palette.to_plte_chunk
+ ds.transparency_chunk = encoding_palette.to_trns_chunk unless encoding_palette.opaque?
+ end
+ data = encode_png_pixelstream(encoding[:color_mode], encoding[:interlace], encoding[:filtering])
+ ds.data_chunks = Chunk::ImageData.split_in_chunks(data, encoding[:compression])
+ ds.end_chunk = Chunk::End.new
+ return ds
+ end
+
+ protected
+
+ # Determines the best possible PNG encoding variables for this image, by analyzing
+ # the colors used for the image.
+ #
+ # You can provide constraints for the encoding variables by passing a hash with
+ # encoding variables to this method.
+ #
+ # @param [Hash, Symbol] constraints The constraints for the encoding. This can be a
+ # Hash or a preset symbol.
+ # @return [Hash] A hash with encoding options for {ChunkyPNG::Canvas::PNGEncoding#to_datastream}
+ def determine_png_encoding(constraints = {})
+
+ if constraints == :fast_rgb
+ encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR, :compression => Zlib::BEST_SPEED }
+ elsif constraints == :fast_rgba
+ encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA, :compression => Zlib::BEST_SPEED }
+ elsif constraints == :best_compression
+ encoding = { :compression => Zlib::BEST_COMPRESSION, :filtering => ChunkyPNG::FILTER_PAETH }
+ elsif constraints == :good_compression
+ encoding = { :compression => Zlib::BEST_COMPRESSION, :filtering => ChunkyPNG::FILTER_NONE }
+ elsif constraints == :no_compression
+ encoding = { :compression => Zlib::NO_COMPRESSION }
+ else
+ encoding = constraints
+ end
+
+ # Do not create a pallete when the encoding is given and does not require a palette.
+ if encoding[:color_mode]
+ if encoding[:color_mode] == ChunkyPNG::COLOR_INDEXED
+ self.encoding_palette = self.palette
+ end
+ else
+ self.encoding_palette = self.palette
+ encoding[:color_mode] ||= encoding_palette.best_colormode
+ end
+
+ # Use Zlib's default for compression unless otherwise provided.
+ encoding[:compression] ||= Zlib::DEFAULT_COMPRESSION
+
+ encoding[:interlace] = case encoding[:interlace]
+ when nil, false, ChunkyPNG::INTERLACING_NONE; ChunkyPNG::INTERLACING_NONE
+ when true, ChunkyPNG::INTERLACING_ADAM7; ChunkyPNG::INTERLACING_ADAM7
+ else encoding[:interlace]
+ end
+
+ encoding[:filtering] ||= case encoding[:compression]
+ when Zlib::BEST_COMPRESSION; ChunkyPNG::FILTER_PAETH
+ when Zlib::NO_COMPRESSION..Zlib::BEST_SPEED; ChunkyPNG::FILTER_NONE
+ else ChunkyPNG::FILTER_UP
+ end
+ return encoding
+ end
+
+ # Encodes the canvas according to the PNG format specification with a given color
+ # mode, possibly with interlacing.
+ # @param [Integer] color_mode The color mode to use for encoding.
+ # @param [Integer] interlace The interlacing method to use.
+ # @return [String] The PNG encoded canvas as string.
+ def encode_png_pixelstream(color_mode = ChunkyPNG::COLOR_TRUECOLOR, interlace = ChunkyPNG::INTERLACING_NONE, filtering = ChunkyPNG::FILTER_NONE)
+
+ if color_mode == ChunkyPNG::COLOR_INDEXED && (encoding_palette.nil? || !encoding_palette.can_encode?)
+ raise ChunkyPNG::ExpectationFailed, "This palette is not suitable for encoding!"
+ end
+
+ case interlace
+ when ChunkyPNG::INTERLACING_NONE; encode_png_image_without_interlacing(color_mode, filtering)
+ when ChunkyPNG::INTERLACING_ADAM7; encode_png_image_with_interlacing(color_mode, filtering)
+ else raise ChunkyPNG::NotSupported, "Unknown interlacing method: #{interlace}!"
+ end
+ end
+
+ # Encodes the canvas according to the PNG format specification with a given color mode.
+ # @param [Integer] color_mode The color mode to use for encoding.
+ # @param [Integer] filtering The filtering method to use.
+ # @return [String] The PNG encoded canvas as string.
+ def encode_png_image_without_interlacing(color_mode, filtering = ChunkyPNG::FILTER_NONE)
+ stream = ChunkyPNG::Datastream.empty_bytearray
+ encode_png_image_pass_to_stream(stream, color_mode, filtering)
+ stream
+ end
+
+ # Encodes the canvas according to the PNG format specification with a given color
+ # mode and Adam7 interlacing.
+ #
+ # This method will split the original canva in 7 smaller canvases and encode them
+ # one by one, concatenating the resulting strings.
+ #
+ # @param [Integer] color_mode The color mode to use for encoding.
+ # @param [Integer] filtering The filtering method to use.
+ # @return [String] The PNG encoded canvas as string.
+ def encode_png_image_with_interlacing(color_mode, filtering = ChunkyPNG::FILTER_NONE)
+ stream = ChunkyPNG::Datastream.empty_bytearray
+ 0.upto(6) do |pass|
+ subcanvas = self.class.adam7_extract_pass(pass, self)
+ subcanvas.encoding_palette = encoding_palette
+ subcanvas.encode_png_image_pass_to_stream(stream, color_mode, filtering)
+ end
+ stream
+ end
+
+ # Encodes the canvas to a stream, in a given color mode.
+ # @param [String] stream The stream to write to.
+ # @param [Integer] color_mode The color mode to use for encoding.
+ # @param [Integer] filtering The filtering method to use.
+ def encode_png_image_pass_to_stream(stream, color_mode, filtering)
+
+ start_pos = stream.bytesize
+ pixel_size = Color.pixel_bytesize(color_mode)
+ line_width = pixel_size * width
+
+ # Encode the whole image without filtering
+ stream << case color_mode
+ when ChunkyPNG::COLOR_TRUECOLOR; pixels.pack(('x' + ('NX' * width)) * height)
+ when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; pixels.pack("xN#{width}" * height)
+ when ChunkyPNG::COLOR_INDEXED; pixels.map { |p| encoding_palette.index(p) }.pack("xC#{width}" * height)
+ when ChunkyPNG::COLOR_GRAYSCALE; pixels.map { |p| p >> 8 }.pack("xC#{width}" * height)
+ when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; pixels.pack("xn#{width}" * height)
+ else raise ChunkyPNG::NotSupported, "Cannot encode pixels for this mode: #{color_mode}!"
+ end
+
+ # Determine the filter method
+ filter_method = case filtering
+ when ChunkyPNG::FILTER_SUB; :encode_png_str_scanline_sub
+ when ChunkyPNG::FILTER_UP; :encode_png_str_scanline_up
+ when ChunkyPNG::FILTER_AVERAGE; :encode_png_str_scanline_average
+ when ChunkyPNG::FILTER_PAETH; :encode_png_str_scanline_paeth
+ else nil
+ end
+
+ # Now, apply filtering if any
+ if filter_method
+ (height - 1).downto(0) do |y|
+ pos = start_pos + y * (line_width + 1)
+ prev_pos = (y == 0) ? nil : pos - (line_width + 1)
+ send(filter_method, stream, pos, prev_pos, line_width, pixel_size)
+ end
+ end
+ end
+
+ # Encodes a scanline of a pixelstream without filtering. This is a no-op.
+ # @param [String] stream The pixelstream to work on. This string will be modified.
+ # @param [Integer] pos The starting position of the scanline.
+ # @param [Integer, nil] prev_pos The starting position of the previous scanline. nil if
+ # this is the first line.
+ # @param [Integer] line_width The number of bytes in this scanline, without counting the filtering
+ # method byte.
+ # @param [Integer] pixel_size The number of bytes used per pixel.
+ # @return [nil]
+ def encode_png_str_scanline_none(stream, pos, prev_pos, line_width, pixel_size)
+ # noop - this method shouldn't get called at all.
+ end
+
+ # Encodes a scanline of a pixelstream using SUB filtering. This will modify the stream.
+ # @param (see #encode_png_str_scanline_none)
+ # @return [nil]
+ def encode_png_str_scanline_sub(stream, pos, prev_pos, line_width, pixel_size)
+ line_width.downto(1) do |i|
+ a = (i > pixel_size) ? stream.getbyte(pos + i - pixel_size) : 0
+ stream.setbyte(pos + i, (stream.getbyte(pos + i) - a) & 0xff)
+ end
+ stream.setbyte(pos, ChunkyPNG::FILTER_SUB)
+ end
+
+ # Encodes a scanline of a pixelstream using UP filtering. This will modify the stream.
+ # @param (see #encode_png_str_scanline_none)
+ # @return [nil]
+ def encode_png_str_scanline_up(stream, pos, prev_pos, line_width, pixel_size)
+ line_width.downto(1) do |i|
+ b = prev_pos ? stream.getbyte(prev_pos + i) : 0
+ stream.setbyte(pos + i, (stream.getbyte(pos + i) - b) & 0xff)
+ end
+ stream.setbyte(pos, ChunkyPNG::FILTER_UP)
+ end
+
+ # Encodes a scanline of a pixelstream using AVERAGE filtering. This will modify the stream.
+ # @param (see #encode_png_str_scanline_none)
+ # @return [nil]
+ def encode_png_str_scanline_average(stream, pos, prev_pos, line_width, pixel_size)
+ line_width.downto(1) do |i|
+ a = (i > pixel_size) ? stream.getbyte(pos + i - pixel_size) : 0
+ b = prev_pos ? stream.getbyte(prev_pos + i) : 0
+ stream.setbyte(pos + i, (stream.getbyte(pos + i) - ((a + b) >> 1)) & 0xff)
+ end
+ stream.setbyte(pos, ChunkyPNG::FILTER_AVERAGE)
+ end
+
+ # Encodes a scanline of a pixelstream using PAETH filtering. This will modify the stream.
+ # @param (see #encode_png_str_scanline_none)
+ # @return [nil]
+ def encode_png_str_scanline_paeth(stream, pos, prev_pos, line_width, pixel_size)
+ line_width.downto(1) do |i|
+ a = (i > pixel_size) ? stream.getbyte(pos + i - pixel_size) : 0
+ b = (prev_pos) ? stream.getbyte(prev_pos + i) : 0
+ c = (prev_pos && i > pixel_size) ? stream.getbyte(prev_pos + i - pixel_size) : 0
+ p = a + b - c
+ pa = (p - a).abs
+ pb = (p - b).abs
+ pc = (p - c).abs
+ pr = (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c)
+ stream.setbyte(pos + i, (stream.getbyte(pos + i) - pr) & 0xff)
+ end
+ stream.setbyte(pos, ChunkyPNG::FILTER_PAETH)
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/stream_exporting.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/stream_exporting.rb
new file mode 100644
index 00000000..d3e4dca7
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/stream_exporting.rb
@@ -0,0 +1,41 @@
+module ChunkyPNG
+ class Canvas
+
+ # Methods to save load a canvas from to stream, encoded in RGB, RGBA, BGR or ABGR format.
+ module StreamExporting
+
+ # Creates an RGB-formatted pixelstream with the pixel data from this canvas.
+ #
+ # Note that this format is fast but bloated, because no compression is used
+ # and the internal representation is left intact. To reconstruct the
+ # canvas, the width and height should be known.
+ #
+ # @return [String] The RGBA-formatted pixel data.
+ def to_rgba_stream
+ pixels.pack('N*')
+ end
+
+ # Creates an RGB-formatted pixelstream with the pixel data from this canvas.
+ #
+ # Note that this format is fast but bloated, because no compression is used
+ # and the internal representation is almost left intact. To reconstruct
+ # the canvas, the width and height should be known.
+ #
+ # @return [String] The RGB-formatted pixel data.
+ def to_rgb_stream
+ pixels.pack('NX' * (width * height))
+ end
+
+ # Creates an ABGR-formatted pixelstream with the pixel data from this canvas.
+ #
+ # Note that this format is fast but bloated, because no compression is used
+ # and the internal representation is left intact. To reconstruct the
+ # canvas, the width and height should be known.
+ #
+ # @return [String] The RGBA-formatted pixel data.
+ def to_abgr_stream
+ pixels.pack('V*')
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/stream_importing.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/stream_importing.rb
new file mode 100644
index 00000000..c6030629
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/canvas/stream_importing.rb
@@ -0,0 +1,77 @@
+module ChunkyPNG
+ class Canvas
+
+ # Methods to quikcly load a canvas from a stream, encoded in RGB, RGBA, BGR or ABGR format.
+ module StreamImporting
+
+ # Creates a canvas by reading pixels from an RGB formatted stream with a
+ # provided with and height.
+ #
+ # Every pixel should be represented by 3 bytes in the stream, in the correct
+ # RGB order. This format closely resembles the internal representation of a
+ # canvas object, so this kind of stream can be read extremely quickly.
+ #
+ # @param [Integer] width The width of the new canvas.
+ # @param [Integer] height The height of the new canvas.
+ # @param [#read, String] stream The stream to read the pixel data from.
+ # @return [ChunkyPNG::Canvas] The newly constructed canvas instance.
+ def from_rgb_stream(width, height, stream)
+ string = stream.respond_to?(:read) ? stream.read(3 * width * height) : stream.to_s[0, 3 * width * height]
+ string << ChunkyPNG::EXTRA_BYTE # Add a fourth byte to the last RGB triple.
+ unpacker = 'NX' * (width * height)
+ pixels = string.unpack(unpacker).map { |color| color | 0x000000ff }
+ self.new(width, height, pixels)
+ end
+
+ # Creates a canvas by reading pixels from an RGBA formatted stream with a
+ # provided with and height.
+ #
+ # Every pixel should be represented by 4 bytes in the stream, in the correct
+ # RGBA order. This format is exactly like the internal representation of a
+ # canvas object, so this kind of stream can be read extremely quickly.
+ #
+ # @param [Integer] width The width of the new canvas.
+ # @param [Integer] height The height of the new canvas.
+ # @param [#read, String] stream The stream to read the pixel data from.
+ # @return [ChunkyPNG::Canvas] The newly constructed canvas instance.
+ def from_rgba_stream(width, height, stream)
+ string = stream.respond_to?(:read) ? stream.read(4 * width * height) : stream.to_s[0, 4 * width * height]
+ self.new(width, height, string.unpack("N*"))
+ end
+
+ # Creates a canvas by reading pixels from an BGR formatted stream with a
+ # provided with and height.
+ #
+ # Every pixel should be represented by 3 bytes in the stream, in the correct
+ # BGR order. This format closely resembles the internal representation of a
+ # canvas object, so this kind of stream can be read extremely quickly.
+ #
+ # @param [Integer] width The width of the new canvas.
+ # @param [Integer] height The height of the new canvas.
+ # @param [#read, String] stream The stream to read the pixel data from.
+ # @return [ChunkyPNG::Canvas] The newly constructed canvas instance.
+ def from_bgr_stream(width, height, stream)
+ string = ChunkyPNG::EXTRA_BYTE # Add a first byte to the first BGR triple.
+ string << stream.respond_to?(:read) ? stream.read(3 * width * height) : stream.to_s[0, 3 * width * height]
+ pixels = string.unpack("@1" << ('XV' * (width * height))).map { |color| color | 0x000000ff }
+ self.new(width, height, pixels)
+ end
+
+ # Creates a canvas by reading pixels from an ARGB formatted stream with a
+ # provided with and height.
+ #
+ # Every pixel should be represented by 4 bytes in the stream, in the correct
+ # ARGB order. This format is almost like the internal representation of a
+ # canvas object, so this kind of stream can be read extremely quickly.
+ #
+ # @param [Integer] width The width of the new canvas.
+ # @param [Integer] height The height of the new canvas.
+ # @param [#read, String] stream The stream to read the pixel data from.
+ # @return [ChunkyPNG::Canvas] The newly constructed canvas instance.
+ def from_abgr_stream(width, height, stream)
+ string = stream.respond_to?(:read) ? stream.read(4 * width * height) : stream.to_s[0, 4 * width * height]
+ self.new(width, height, string.unpack("V*"))
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/chunk.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/chunk.rb
new file mode 100644
index 00000000..0a85cfb7
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/chunk.rb
@@ -0,0 +1,294 @@
+module ChunkyPNG
+
+ # A PNG datastream consists of multiple chunks. This module, and the classes
+ # contained within, help with handling these chunks. It supports both
+ # reading and writing chunks.
+ #
+ # All chunck types are instances of the {ChunkyPNG::Chunk::Base} class. For
+ # some chunk types a specialized class is available, e.g. the IHDR chunk is
+ # represented by the {ChunkyPNG::Chunk::Header} class. These specialized
+ # classes help accessing the content of the chunk. All other chunks are
+ # represented by the {ChunkyPNG::Chunk::Generic} class.
+ #
+ # @see ChunkyPNG::Datastream
+ module Chunk
+
+ # Reads a chunk from an IO stream.
+ #
+ # @param [IO, #read] io The IO stream to read from.
+ # @return [ChunkyPNG::Chung::Base] The loaded chunk instance.
+ def self.read(io)
+
+ length, type = io.read(8).unpack('Na4')
+ content = io.read(length)
+ crc = io.read(4).unpack('N').first
+
+ verify_crc!(type, content, crc)
+
+ CHUNK_TYPES.fetch(type, Generic).read(type, content)
+ end
+
+ # Verifies the CRC of a chunk.
+ # @param [String] type The chunk's type.
+ # @param [String] content The chunk's content.
+ # @param [Integer] content The chunk's content.
+ # @raise [RuntimeError] An exception is raised if the found CRC value
+ # is not equal to the expected CRC value.
+ def self.verify_crc!(type, content, found_crc)
+ expected_crc = Zlib.crc32(content, Zlib.crc32(type))
+ raise ChunkyPNG::CRCMismatch, "Chuck CRC mismatch!" if found_crc != expected_crc
+ end
+
+ # The base chunk class is the superclass for every chunk type. It contains
+ # methods to write the chunk to an output stream.
+ #
+ # A subclass should implement the +content+ method, which gets called when
+ # the chunk gets written to a PNG datastream
+ #
+ # @abstract
+ class Base
+
+ # The four-character type indicator for the chunk. This field is used to
+ # find the correct class for a chunk when it is loaded from a PNG stream.
+ # @return [String]
+ attr_accessor :type
+
+ # Initializes the chunk instance.
+ # @param [String] type The four character chunk type indicator.
+ # @param [Hash] attributes A hash of attributes to set on this chunk.
+ def initialize(type, attributes = {})
+ self.type = type
+ attributes.each { |k, v| send("#{k}=", v) }
+ end
+
+ # Writes the chunk to the IO stream, using the provided content.
+ # The checksum will be calculated and appended to the stream.
+ # @param [IO] io The IO stream to write to.
+ # @param [String] content The content for this chunk.
+ def write_with_crc(io, content)
+ io << [content.length].pack('N') << type << content
+ io << [Zlib.crc32(content, Zlib.crc32(type))].pack('N')
+ end
+
+ # Writes the chunk to the IO stream.
+ #
+ # It will call te +content+ method to get the content for this chunk,
+ # and will calculate and append the checksum automatically.
+ # @param [IO] io The IO stream to write to.
+ def write(io)
+ write_with_crc(io, content || '')
+ end
+ end
+
+ # The Generic chunk type will read the content from the chunk as it,
+ # and will write it back as it was read.
+ class Generic < Base
+
+ # The attribute to store the content from the chunk, which gets
+ # written by the +write+ method.
+ attr_accessor :content
+
+
+ def initialize(type, content = '')
+ super(type, :content => content)
+ end
+
+ # Creates an instance, given the chunk's type and content.
+ # @param [String] type The four character chunk type indicator.
+ # @param [String] content The content read from the chunk.
+ # @return [ChunkyPNG::Chunk::Generic] The new chunk instance.
+ def self.read(type, content)
+ self.new(type, content)
+ end
+ end
+
+ # The header (IHDR) chunk is the first chunk of every PNG image, and
+ # contains information about the image: i.e. its width, height, color
+ # depth, color mode, compression method, filtering method and interlace
+ # method.
+ #
+ # ChunkyPNG supports all values for these variables that are defined in
+ # the PNG spec, except for color depth: Only 8-bit depth images are
+ # supported. Note that it is still possible to access the chunk for such
+ # an image, but ChunkyPNG will raise an exception if you try to access
+ # the pixel data.
+ class Header < Base
+
+ attr_accessor :width, :height, :depth, :color, :compression, :filtering, :interlace
+
+ def initialize(attrs = {})
+ super('IHDR', attrs)
+ @depth ||= 8
+ @color ||= ChunkyPNG::COLOR_TRUECOLOR
+ @compression ||= ChunkyPNG::COMPRESSION_DEFAULT
+ @filtering ||= ChunkyPNG::FILTERING_DEFAULT
+ @interlace ||= ChunkyPNG::INTERLACING_NONE
+ end
+
+ # Reads the 13 bytes of content from the header chunk to set the image attributes.
+ # @param [String] type The four character chunk type indicator (= "IHDR").
+ # @param [String] content The 13 bytes of content read from the chunk.
+ # @return [ChunkyPNG::Chunk::End] The new Header chunk instance with the
+ # variables set to the values according to the content.
+ def self.read(type, content)
+ fields = content.unpack('NNC5')
+ self.new(:width => fields[0], :height => fields[1], :depth => fields[2], :color => fields[3],
+ :compression => fields[4], :filtering => fields[5], :interlace => fields[6])
+ end
+
+ # Returns the content for this chunk when it gets written to a file, by packing the
+ # image information variables into the correct format.
+ # @return [String] The 13-byte content for the header chunk.
+ def content
+ [width, height, depth, color, compression, filtering, interlace].pack('NNC5')
+ end
+ end
+
+ # The End (IEND) chunk indicates the last chunk of a PNG stream. It does not
+ # contain any data.
+ class End < Base
+
+ def initialize
+ super('IEND')
+ end
+
+ # Reads the END chunk. It will check if the content is empty.
+ # @param [String] type The four character chunk type indicator (= "IEND").
+ # @param [String] content The content read from the chunk. Should be empty.
+ # @return [ChunkyPNG::Chunk::End] The new End chunk instance.
+ # @raise [RuntimeError] Raises an exception if the content was not empty.
+ def self.read(type, content)
+ raise ExpectationFailed, 'The IEND chunk should be empty!' if content.bytesize > 0
+ self.new
+ end
+
+ # Returns an empty string, because this chunk should always be empty.
+ # @return [""] An empty string.
+ def content
+ ChunkyPNG::Datastream.empty_bytearray
+ end
+ end
+
+ # The Palette (PLTE) chunk contains the image's palette, i.e. the
+ # 8-bit RGB colors this image is using.
+ #
+ # @see ChunkyPNG::Chunk::Transparency
+ # @see ChunkyPNG::Palette
+ class Palette < Generic
+ end
+
+ # A transparency (tRNS) chunk contains the alpha channel for the colors
+ # defined in the Palette (PLTE) chunk
+ #
+ # @see ChunkyPNG::Chunk::Palette
+ # @see ChunkyPNG::Palette
+ class Transparency < Generic
+ end
+
+ class ImageData < Generic
+
+ def self.read(type, content)
+ raise ExpectationFailed, 'The IDAT chunk should not be empty!' if content.bytesize == 0
+ super
+ end
+
+ def self.combine_chunks(data_chunks)
+ Zlib::Inflate.inflate(data_chunks.map { |c| c.content }.join(''))
+ end
+
+ def self.split_in_chunks(data, level = Zlib::DEFAULT_COMPRESSION, chunk_size = 2147483647)
+ streamdata = Zlib::Deflate.deflate(data, level)
+ # TODO: Split long streamdata over multiple chunks
+ [ ChunkyPNG::Chunk::ImageData.new('IDAT', streamdata) ]
+ end
+ end
+
+ # The Text (tEXt) chunk contains keyword/value metadata about the PNG stream.
+ # In this chunk, the value is stored uncompressed.
+ #
+ # The tEXt chunk only supports Latin-1 encoded textual data. If you need UTF-8
+ # support, check out the InternationalText chunk type.
+ #
+ # @see ChunkyPNG::Chunk::CompressedText
+ # @see ChunkyPNG::Chunk::InternationalText
+ class Text < Base
+
+ attr_accessor :keyword, :value
+
+ def initialize(keyword, value)
+ super('tEXt')
+ @keyword, @value = keyword, value
+ end
+
+ def self.read(type, content)
+ keyword, value = content.unpack('Z*a*')
+ new(keyword, value)
+ end
+
+ # Creates the content to write to the stream, by concatenating the keyword
+ # with the value, joined by a null character.
+ #
+ # @return The content that should be written to the datastream.
+ def content
+ [keyword, value].pack('Z*a*')
+ end
+ end
+
+ # The CompressedText (zTXt) chunk contains keyword/value metadata about
+ # the PNG stream. In this chunk, the value is compressed using Deflate
+ # compression.
+ #
+ # @see ChunkyPNG::Chunk::CompressedText
+ # @see ChunkyPNG::Chunk::InternationalText
+ class CompressedText < Base
+
+ attr_accessor :keyword, :value
+
+ def initialize(keyword, value)
+ super('zTXt')
+ @keyword, @value = keyword, value
+ end
+
+ def self.read(type, content)
+ keyword, compression, value = content.unpack('Z*Ca*')
+ raise ChunkyPNG::NotSupported, "Compression method #{compression.inspect} not supported!" unless compression == ChunkyPNG::COMPRESSION_DEFAULT
+ new(keyword, Zlib::Inflate.inflate(value))
+ end
+
+ # Creates the content to write to the stream, by concatenating the keyword
+ # with the deflated value, joined by a null character.
+ #
+ # @return The content that should be written to the datastream.
+ def content
+ [keyword, ChunkyPNG::COMPRESSION_DEFAULT, Zlib::Deflate.deflate(value)].pack('Z*Ca*')
+ end
+ end
+
+ # The Text (iTXt) chunk contains keyword/value metadata about the PNG stream.
+ # The metadata in this chunk can be encoded using UTF-8 characters. Moreover,
+ # it is possible to define the language of the metadata, and give a translation
+ # of the keyword name. Finally, it supports bot compressed and uncompressed
+ # values.
+ #
+ # @todo This chunk is currently not implemented, but merely read and written
+ # back intact.
+ #
+ # @see ChunkyPNG::Chunk::Text
+ # @see ChunkyPNG::Chunk::CompressedText
+ class InternationalText < Generic
+
+ # TODO
+ end
+
+ # Maps chunk types to classes, based on the four byte chunk type indicator at the
+ # beginning of a chunk.
+ #
+ # If a chunk type is not specified in this hash, the Generic chunk type will be used.
+ #
+ # @see ChunkyPNG::Chunk.read
+ CHUNK_TYPES = {
+ 'IHDR' => Header, 'IEND' => End, 'IDAT' => ImageData, 'PLTE' => Palette, 'tRNS' => Transparency,
+ 'tEXt' => Text, 'zTXt' => CompressedText, 'iTXt' => InternationalText
+ }
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/color.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/color.rb
new file mode 100644
index 00000000..7e0d6990
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/color.rb
@@ -0,0 +1,439 @@
+module ChunkyPNG
+
+ # The Color module defines methods for handling colors. Within the ChunkyPNG
+ # library, the concepts of pixels and colors are both used, and they are
+ # both represented by a Integer.
+ #
+ # Pixels/colors are represented in RGBA componetns. Each of the four
+ # components is stored with a depth of 8 bits (maximum value = 255 =
+ # {ChunkyPNG::Color::MAX}). Together, these components are stored in a 4-byte
+ # Integer.
+ #
+ # A color will always be represented using these 4 components in memory.
+ # When the image is encoded, a more suitable representation can be used
+ # (e.g. rgb, grayscale, palette-based), for which several conversion methods
+ # are provided in this module.
+ module Color
+ extend self
+
+ # The maximum value of each color component.
+ MAX = 0xff
+
+ ####################################################################
+ # CONSTRUCTING COLOR VALUES
+ ####################################################################
+
+ # Creates a new color using an r, g, b triple and an alpha value.
+ # @return [Integer] The newly constructed color value.
+ def rgba(r, g, b, a)
+ r << 24 | g << 16 | b << 8 | a
+ end
+
+ # Creates a new color using an r, g, b triple.
+ # @return [Integer] The newly constructed color value.
+ def rgb(r, g, b)
+ r << 24 | g << 16 | b << 8 | 0xff
+ end
+
+ # Creates a new color using a grayscale teint.
+ # @return [ChunkyPNG::Color] The newly constructed color value.
+ def grayscale(teint)
+ teint << 24 | teint << 16 | teint << 8 | 0xff
+ end
+
+ # Creates a new color using a grayscale teint and alpha value.
+ # @return [Integer] The newly constructed color value.
+ def grayscale_alpha(teint, a)
+ teint << 24 | teint << 16 | teint << 8 | a
+ end
+
+ ####################################################################
+ # COLOR IMPORTING
+ ####################################################################
+
+ # Creates a color by unpacking an rgb triple from a string.
+ #
+ # @param [String] stream The string to load the color from. It should be
+ # at least 3 + pos bytes long.
+ # @param [Integer] pos The position in the string to load the triple from.
+ # @return [Integer] The newly constructed color value.
+ def from_rgb_stream(stream, pos = 0)
+ rgb(*stream.unpack("@#{pos}C3"))
+ end
+
+ # Creates a color by unpacking an rgba triple from a string
+ #
+ # @param [String] stream The string to load the color from. It should be
+ # at least 4 + pos bytes long.
+ # @param [Integer] pos The position in the string to load the triple from.
+ # @return [Integer] The newly constructed color value.
+ def from_rgba_stream(stream, pos = 0)
+ rgba(*stream.unpack("@#{pos}C4"))
+ end
+
+ # Creates a color by converting it from a string in hex notation.
+ #
+ # It supports colors with (#rrggbbaa) or without (#rrggbb) alpha channel.
+ # Color strings may include the prefix "0x" or "#".
+ #
+ # @param [String] str The color in hex notation. @return [Integer] The
+ # converted color value.
+ def from_hex(str)
+ case str
+ when /^(?:#|0x)?([0-9a-f]{6})$/i; ($1.hex << 8) | 0xff
+ when /^(?:#|0x)?([0-9a-f]{8})$/i; $1.hex
+ else raise ChunkyPNG::ExpectationFailed, "Not a valid hex color notation: #{str.inspect}!"
+ end
+ end
+
+ ####################################################################
+ # PROPERTIES
+ ####################################################################
+
+ # Returns the red-component from the color value.
+ #
+ # @param [Integer] value The color value.
+ # @return [Integer] A value between 0 and MAX.
+ def r(value)
+ (value & 0xff000000) >> 24
+ end
+
+ # Returns the green-component from the color value.
+ #
+ # @param [Integer] value The color value.
+ # @return [Integer] A value between 0 and MAX.
+ def g(value)
+ (value & 0x00ff0000) >> 16
+ end
+
+ # Returns the blue-component from the color value.
+ #
+ # @param [Integer] value The color value.
+ # @return [Integer] A value between 0 and MAX.
+ def b(value)
+ (value & 0x0000ff00) >> 8
+ end
+
+ # Returns the alpha channel value for the color value.
+ #
+ # @param [Integer] value The color value.
+ # @return [Integer] A value between 0 and MAX.
+ def a(value)
+ value & 0x000000ff
+ end
+
+ # Returns true if this color is fully opaque.
+ #
+ # @param [Integer] value The color to test.
+ # @return [true, false] True if the alpha channel equals MAX.
+ def opaque?(value)
+ a(value) == 0x000000ff
+ end
+
+ # Returns the opaque value of this color by removing the alpha channel.
+ # @param [Integer] value The color to transform.
+ # @return [Integer] The opauq color
+ def opaque!(value)
+ value | 0x000000ff
+ end
+
+ # Returns true if this color is fully transparent.
+ #
+ # @param [Integer] value The color to test.
+ # @return [true, false] True if the r, g and b component are equal.
+ def grayscale?(value)
+ r(value) == b(value) && b(value) == g(value)
+ end
+
+ # Returns true if this color is fully transparent.
+ #
+ # @param [Integer] value The color to test.
+ # @return [true, false] True if the alpha channel equals 0.
+ def fully_transparent?(value)
+ a(value) == 0x00000000
+ end
+
+ ####################################################################
+ # ALPHA COMPOSITION
+ ####################################################################
+
+ # Multiplies two fractions using integer math, where the fractions are stored using an
+ # integer between 0 and 255. This method is used as a helper method for compositing
+ # colors using integer math.
+ #
+ # This is a quicker implementation of ((a * b) / 255.0).round.
+ #
+ # @param [Integer] a The first fraction.
+ # @param [Integer] b The second fraction.
+ # @return [Integer] The result of the multiplication.
+ def int8_mult(a, b)
+ t = a * b + 0x80
+ ((t >> 8) + t) >> 8
+ end
+
+ # Composes two colors with an alpha channel using integer math.
+ #
+ # This version is faster than the version based on floating point math, so this
+ # compositing function is used by default.
+ #
+ # @param [Integer] fg The foreground color.
+ # @param [Integer] bg The foreground color.
+ # @return [Integer] The composited color.
+ # @see ChunkyPNG::Color#compose_precise
+ def compose_quick(fg, bg)
+ return fg if opaque?(fg) || fully_transparent?(bg)
+ return bg if fully_transparent?(fg)
+
+ a_com = int8_mult(0xff - a(fg), a(bg))
+ new_r = int8_mult(a(fg), r(fg)) + int8_mult(a_com, r(bg))
+ new_g = int8_mult(a(fg), g(fg)) + int8_mult(a_com, g(bg))
+ new_b = int8_mult(a(fg), b(fg)) + int8_mult(a_com, b(bg))
+ new_a = a(fg) + a_com
+ rgba(new_r, new_g, new_b, new_a)
+ end
+
+ # Composes two colors with an alpha channel using floating point math.
+ #
+ # This method uses more precise floating point math, but this precision is lost
+ # when the result is converted back to an integer. Because it is slower than
+ # the version based on integer math, that version is preferred.
+ #
+ # @param [Integer] fg The foreground color.
+ # @param [Integer] bg The foreground color.
+ # @return [Integer] The composited color.
+ # @see ChunkyPNG::Color#compose_quick
+ def compose_precise(fg, bg)
+ return fg if opaque?(fg) || fully_transparent?(bg)
+ return bg if fully_transparent?(fg)
+
+ fg_a = a(fg).to_f / MAX
+ bg_a = a(bg).to_f / MAX
+ a_com = (1.0 - fg_a) * bg_a
+
+ new_r = (fg_a * r(fg) + a_com * r(bg)).round
+ new_g = (fg_a * g(fg) + a_com * g(bg)).round
+ new_b = (fg_a * b(fg) + a_com * b(bg)).round
+ new_a = ((fg_a + a_com) * MAX).round
+ rgba(new_r, new_g, new_b, new_a)
+ end
+
+ alias :compose :compose_quick
+
+ # Blends the foreground and background color by taking the average of
+ # the components.
+ #
+ # @param [Integer] fg The foreground color.
+ # @param [Integer] bg The foreground color.
+ # @return [Integer] The blended color.
+ def blend(fg, bg)
+ (fg + bg) >> 1
+ end
+
+ # Lowers the intensity of a color, by lowering its alpha by a given factor.
+ # @param [Integer] color The color to adjust.
+ # @param [Integer] factor Fade factor as an integer between 0 and 255.
+ # @return [Integer] The faded color.
+ def fade(color, factor)
+ new_alpha = int8_mult(a(color), factor)
+ (color & 0xffffff00) | new_alpha
+ end
+
+ # Decomposes a color, given a color, a mask color and a background color.
+ # The returned color will be a variant of the mask color, with the alpha
+ # channel set to the best fitting value. This basically is the reverse
+ # operation if alpha composition.
+ #
+ # If the color cannot be decomposed, this method will return the fully
+ # transparentvariant of the mask color.
+ #
+ # @param [Integer] color The color that was the result of compositing.
+ # @param [Integer] mask The opaque variant of the color that was being composed
+ # @param [Integer] bg The background color on which the color was composed.
+ # @param [Integer] tolerance The decomposition tolerance level, a value between 0 and 255.
+ # @return [Integer] The decomposed color,a variant of the masked color with the
+ # alpha channel set to an appropriate value.
+ def decompose_color(color, mask, bg, tolerance = 1)
+ if alpha_decomposable?(color, mask, bg, tolerance)
+ mask & 0xffffff00 | decompose_alpha(color, mask, bg)
+ else
+ mask & 0xffffff00
+ end
+ end
+
+ # Checks whether an alpha channel value can successfully be composed
+ # given the resulting color, the mask color and a background color,
+ # all of which should be opaque.
+ #
+ # @param [Integer] color The color that was the result of compositing.
+ # @param [Integer] mask The opauqe variant of the color that was being composed
+ # @param [Integer] bg The background color on which the color was composed.
+ # @param [Integer] tolerance The decomposition tolerance level, a value between 0 and 255.
+ # @return [Integer] The decomposed alpha channel value, between 0 and 255.
+ # @see #decompose_alpha
+ def alpha_decomposable?(color, mask, bg, tolerance = 1)
+ components = decompose_alpha_components(color, mask, bg)
+ sum = components.inject(0) { |a,b| a + b }
+ max = components.max * 3
+ return components.max <= 255 && components.min >= 0 && (sum + tolerance * 3) >= max
+ end
+
+ # Decomposes the alpha channel value given the resulting color, the mask color
+ # and a background color, all of which should be opaque.
+ #
+ # Make sure to call {#alpha_decomposable?} first to see if the alpha channel
+ # value can successfully decomposed with a given tolerance, otherwise the return
+ # value of this method is undefined.
+ #
+ # @param [Integer] color The color that was the result of compositing.
+ # @param [Integer] mask The opauqe variant of the color that was being composed
+ # @param [Integer] bg The background color on which the color was composed.
+ # @return [Integer] The best fitting alpha channel, a value between 0 and 255.
+ # @see #alpha_decomposable?
+ def decompose_alpha(color, mask, bg)
+ components = decompose_alpha_components(color, mask, bg)
+ (components.inject(0) { |a,b| a + b } / 3.0).round
+ end
+
+ # Decomposes an alpha channel for either the r, g or b color channel.
+ # @param [:r, :g, :b] The channel to decompose the alpha channel from.
+ # @param [Integer] color The color that was the result of compositing.
+ # @param [Integer] mask The opauqe variant of the color that was being composed
+ # @param [Integer] bg The background color on which the color was composed.
+ # @param [Integer] The decomposed alpha value for the channel.
+ def decompose_alpha_component(channel, color, mask, bg)
+ ((send(channel, bg) - send(channel, color)).to_f /
+ (send(channel, bg) - send(channel, mask)).to_f * MAX).round
+ end
+
+ # Decomposes the alpha channels for the r, g and b color channel.
+ # @param [Integer] color The color that was the result of compositing.
+ # @param [Integer] mask The opauqe variant of the color that was being composed
+ # @param [Integer] bg The background color on which the color was composed.
+ # @return [Array] The decomposed alpha values for the r, g and b channels.
+ def decompose_alpha_components(color, mask, bg)
+ [
+ decompose_alpha_component(:r, color, mask, bg),
+ decompose_alpha_component(:g, color, mask, bg),
+ decompose_alpha_component(:b, color, mask, bg)
+ ]
+ end
+
+ ####################################################################
+ # CONVERSIONS
+ ####################################################################
+
+ # Returns a string representing this color using hex notation (i.e. #rrggbbaa).
+ #
+ # @param [Integer] value The color to convert.
+ # @return [String] The color in hex notation, starting with a pound sign.
+ def to_hex(color, include_alpha = true)
+ include_alpha ? ('#%08x' % color) : ('#%06x' % [color >> 8])
+ end
+
+ # Returns an array with the separate RGBA values for this color.
+ #
+ # @param [Integer] color The color to convert.
+ # @return [Array] An array with 4 Integer elements.
+ def to_truecolor_alpha_bytes(color)
+ [r(color), g(color), b(color), a(color)]
+ end
+
+ # Returns an array with the separate RGB values for this color.
+ # The alpha channel will be discarded.
+ #
+ # @param [Integer] color The color to convert.
+ # @return [Array] An array with 3 Integer elements.
+ def to_truecolor_bytes(color)
+ [r(color), g(color), b(color)]
+ end
+
+ # Returns an array with the grayscale teint value for this color.
+ #
+ # This method expects the r,g and b value to be equal, and the alpha
+ # channel will be discarded.
+ #
+ # @param [Integer] color The grayscale color to convert.
+ # @return [Array] An array with 1 Integer element.
+ def to_grayscale_bytes(color)
+ [b(color)] # assumption r == g == b
+ end
+
+ # Returns an array with the grayscale teint and alpha channel values
+ # for this color.
+ #
+ # This method expects the r,g and b value to be equal.
+ #
+ # @param [Integer] color The grayscale color to convert.
+ # @return [Array] An array with 2 Integer elements.
+ def to_grayscale_alpha_bytes(color)
+ [b(color), a(color)] # assumption r == g == b
+ end
+
+ ####################################################################
+ # COLOR CONSTANTS
+ ####################################################################
+
+ # Black pixel/color
+ BLACK = rgb( 0, 0, 0)
+
+ # White pixel/color
+ WHITE = rgb(255, 255, 255)
+
+ # Fully transparent pixel/color
+ TRANSPARENT = rgba(0, 0, 0, 0)
+
+ ####################################################################
+ # STATIC UTILITY METHODS
+ ####################################################################
+
+ # Returns the number of sample values per pixel.
+ # @param [Integer] color_mode The color mode being used.
+ # @return [Integer] The number of sample values per pixel.
+ def samples_per_pixel(color_mode)
+ case color_mode
+ when ChunkyPNG::COLOR_INDEXED; 1
+ when ChunkyPNG::COLOR_TRUECOLOR; 3
+ when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; 4
+ when ChunkyPNG::COLOR_GRAYSCALE; 1
+ when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; 2
+ else raise ChunkyPNG::NotSupported, "Don't know the numer of samples for this colormode: #{color_mode}!"
+ end
+ end
+
+ # Returns the size in bytes of a pixel when it is stored using a given color mode.
+ # @param [Integer] color_mode The color mode in which the pixels are stored.
+ # @return [Integer] The number of bytes used per pixel in a datastream.
+ def pixel_bytesize(color_mode, depth = 8)
+ return 1 if depth < 8
+ (pixel_bitsize(color_mode, depth) + 7) >> 3
+ end
+
+ # Returns the size in bits of a pixel when it is stored using a given color mode.
+ # @param [Integer] color_mode The color mode in which the pixels are stored.
+ # @param [Integer] depth The color depth of the pixels.
+ # @return [Integer] The number of bytes used per pixel in a datastream.
+ def pixel_bitsize(color_mode, depth = 8)
+ samples_per_pixel(color_mode) * depth
+ end
+
+ # Returns the number of bytes used per scanline.
+ # @param [Integer] color_mode The color mode in which the pixels are stored.
+ # @param [Integer] depth The color depth of the pixels.
+ # @param [Integer] width The number of pixels per scanline.
+ # @return [Integer] The number of bytes used per scanline in a datastream.
+ def scanline_bytesize(color_mode, depth, width)
+ ((pixel_bitsize(color_mode, depth) * width) + 7) >> 3
+ end
+
+ # Returns the number of bytes used for an image pass
+ # @param [Integer] color_mode The color mode in which the pixels are stored.
+ # @param [Integer] depth The color depth of the pixels.
+ # @param [Integer] width The width of the image pass.
+ # @param [Integer] width The height of the image pass.
+ # @return [Integer] The number of bytes used per scanline in a datastream.
+ def pass_bytesize(color_mode, depth, width, height)
+ return 0 if width == 0 || height == 0
+ (scanline_bytesize(color_mode, depth, width) + 1) * height
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/compatibility.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/compatibility.rb
new file mode 100644
index 00000000..930202fa
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/compatibility.rb
@@ -0,0 +1,15 @@
+
+class String
+ alias_method :getbyte, :[] unless method_defined?(:getbyte)
+ alias_method :setbyte, :[]= unless method_defined?(:setbyte)
+ alias_method :bytesize, :size unless method_defined?(:bytesize)
+end
+
+class Object
+ unless method_defined?(:tap)
+ def tap(&block)
+ yield(self) if block_given?
+ return self
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/datastream.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/datastream.rb
new file mode 100644
index 00000000..098243fb
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/datastream.rb
@@ -0,0 +1,185 @@
+module ChunkyPNG
+
+ # The Datastream class represents a PNG formatted datastream. It supports
+ # both reading from and writing to strings, stremas and files.
+ #
+ # A PNG datastream begins with the PNG signature, and than contains multiple
+ # chunks, starting with a header (IHDR) chunk and finishing with an end
+ # (IEND) chunk.
+ #
+ # @see ChunkyPNG::Chunk
+ class Datastream
+
+ # The signature that each PNG file or stream should begin with.
+ SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10].pack('C8')
+
+ # The header chunk of this datastream.
+ # @return [ChunkyPNG::Chunk::Header]
+ attr_accessor :header_chunk
+
+ # All other chunks in this PNG file.
+ # @return [Array]
+ attr_accessor :other_chunks
+
+ # The chunk containing the image's palette.
+ # @return [ChunkyPNG::Chunk::Palette]
+ attr_accessor :palette_chunk
+
+ # The chunk containing the transparency information of the palette.
+ # @return [ChunkyPNG::Chunk::Transparency]
+ attr_accessor :transparency_chunk
+
+ # The chunks that together compose the images pixel data.
+ # @return [Array]
+ attr_accessor :data_chunks
+
+ # The empty chunk that signals the end of this datastream
+ # @return [ChunkyPNG::Chunk::Header]
+ attr_accessor :end_chunk
+
+ # Initializes a new Datastream instance.
+ def initialize
+ @other_chunks = []
+ @data_chunks = []
+ end
+
+ ##############################################################################
+ # LOADING DATASTREAMS
+ ##############################################################################
+
+ class << self
+
+ # Reads a PNG datastream from a string.
+ # @param [String] str The PNG encoded string to load from.
+ # @return [ChunkyPNG::Datastream] The loaded datastream instance.
+ def from_blob(str)
+ from_io(StringIO.new(str))
+ end
+
+ alias :from_string :from_blob
+
+ # Reads a PNG datastream from a file.
+ # @param [String] filename The path of the file to load from.
+ # @return [ChunkyPNG::Datastream] The loaded datastream instance.
+ def from_file(filename)
+ ds = nil
+ File.open(filename, 'rb') { |f| ds = from_io(f) }
+ ds
+ end
+
+ # Reads a PNG datastream from an input stream
+ # @param [IO] io The stream to read from.
+ # @return [ChunkyPNG::Datastream] The loaded datastream instance.
+ def from_io(io)
+ verify_signature!(io)
+
+ ds = self.new
+ until io.eof?
+ chunk = ChunkyPNG::Chunk.read(io)
+ case chunk
+ when ChunkyPNG::Chunk::Header; ds.header_chunk = chunk
+ when ChunkyPNG::Chunk::Palette; ds.palette_chunk = chunk
+ when ChunkyPNG::Chunk::Transparency; ds.transparency_chunk = chunk
+ when ChunkyPNG::Chunk::ImageData; ds.data_chunks << chunk
+ when ChunkyPNG::Chunk::End; ds.end_chunk = chunk
+ else ds.other_chunks << chunk
+ end
+ end
+ return ds
+ end
+
+ # Verifies that the current stream is a PNG datastream by checking its signature.
+ #
+ # This method reads the PNG signature from the stream, setting the current position
+ # of the stream directly after the signature, where the IHDR chunk should begin.
+ #
+ # @param [IO] io The stream to read the PNG signature from.
+ # @raise [RuntimeError] An exception is raised if the PNG signature is not found at
+ # the beginning of the stream.
+ def verify_signature!(io)
+ signature = io.read(ChunkyPNG::Datastream::SIGNATURE.length)
+ unless signature == ChunkyPNG::Datastream::SIGNATURE
+ raise ChunkyPNG::SignatureMismatch, "PNG signature not found!"
+ end
+ end
+ end
+
+ ##################################################################################
+ # CHUNKS
+ ##################################################################################
+
+ # Enumerates the chunks in this datastream.
+ #
+ # This will iterate over the chunks using the order in which the chunks
+ # should appear in the PNG file.
+ #
+ # @yield [chunk] Yields the chunks in this datastrean, one by one in the correct order.
+ # @yieldparam [ChunkyPNG::Chunk::Base] chunk A chunk in this datastream.
+ # @see ChunkyPNG::Datastream#chunks
+ def each_chunk
+ yield(header_chunk)
+ other_chunks.each { |chunk| yield(chunk) }
+ yield(palette_chunk) if palette_chunk
+ yield(transparency_chunk) if transparency_chunk
+ data_chunks.each { |chunk| yield(chunk) }
+ yield(end_chunk)
+ end
+
+ # Returns an enumerator instance for this datastream's chunks.
+ # @return [Enumerable::Enumerator] An enumerator for the :each_chunk method.
+ # @see ChunkyPNG::Datastream#each_chunk
+ def chunks
+ enum_for(:each_chunk)
+ end
+
+ # Returns all the textual metadata key/value pairs as hash.
+ # @return [Hash] A hash containing metadata fields and their values.
+ def metadata
+ metadata = {}
+ other_chunks.select do |chunk|
+ metadata[chunk.keyword] = chunk.value if chunk.respond_to?(:keyword)
+ end
+ metadata
+ end
+
+ # Returns the uncompressed image data, combined from all the IDAT chunks
+ # @return [String] The uncompressed image data for this datastream
+ def imagedata
+ ChunkyPNG::Chunk::ImageData.combine_chunks(data_chunks)
+ end
+
+ ##################################################################################
+ # WRITING DATASTREAMS
+ ##################################################################################
+
+ # Returns an empty stream using binary encoding that can be used as stream to encode to.
+ # @eturn [String] An empty, binary string.
+ def self.empty_bytearray
+ ChunkyPNG::EMPTY_BYTEARRAY.dup
+ end
+
+ # Writes the datastream to the given output stream.
+ # @param [IO] io The output stream to write to.
+ def write(io)
+ io << SIGNATURE
+ each_chunk { |c| c.write(io) }
+ end
+
+ # Saves this datastream as a PNG file.
+ # @param [String] filename The filename to use.
+ def save(filename)
+ File.open(filename, 'wb') { |f| write(f) }
+ end
+
+ # Encodes this datastream into a string.
+ # @return [String] The encoded PNG datastream.
+ def to_blob
+ str = StringIO.new
+ write(str)
+ return str.string
+ end
+
+ alias :to_string :to_blob
+ alias :to_s :to_blob
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/image.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/image.rb
new file mode 100644
index 00000000..e821477d
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/image.rb
@@ -0,0 +1,79 @@
+module ChunkyPNG
+
+ # ChunkyPNG::Image is an extension of the {ChunkyPNG::Canvas} class, that
+ # also includes support for metadata.
+ #
+ # @see ChunkyPNG::Canvas
+ class Image < Canvas
+
+ # The minimumsize of bytes the value of a metadata field should be before compression
+ # is enabled for the chunk.
+ METADATA_COMPRESSION_TRESHOLD = 300
+
+ # @return [Hash] The hash of metadata fields for this PNG image.
+ attr_accessor :metadata
+
+ # Initializes a new ChunkyPNG::Image instance.
+ # @param [Integer] width The width of the new image.
+ # @param [Integer] height The height of the new image.
+ # @param [Integer] bg_color The background color of the new image.
+ # @param [Hash] metadata A hash of metadata fields and values for this image.
+ # @see ChunkyPNG::Canvas#initialize
+ def initialize(width, height, bg_color = ChunkyPNG::Color::TRANSPARENT, metadata = {})
+ super(width, height, bg_color)
+ @metadata = metadata
+ end
+
+ # Initializes a copy of another ChunkyPNG::Image instance.
+ #
+ # @param [ChunkyPNG::Image] other The other image to copy.
+ def initialize_copy(other)
+ super(other)
+ @metadata = other.metadata
+ end
+
+ # Returns the metadata for this image as PNG chunks.
+ #
+ # Chunks will either be of the {ChunkyPNG::Chunk::Text} type for small
+ # values (in bytes), or of the {ChunkyPNG::Chunk::CompressedText} type
+ # for values that are larger in size.
+ #
+ # @return [Array] An array of metadata chunks.
+ # @see ChunkyPNG::Image::METADATA_COMPRESSION_TRESHOLD
+ def metadata_chunks
+ metadata.map do |key, value|
+ if value.length >= METADATA_COMPRESSION_TRESHOLD
+ ChunkyPNG::Chunk::CompressedText.new(key, value)
+ else
+ ChunkyPNG::Chunk::Text.new(key, value)
+ end
+ end
+ end
+
+ # Encodes the image to a PNG datastream for saving to disk or writing to an IO stream.
+ #
+ # Besides encoding the canvas, it will also encode the metadata fields to text chunks.
+ #
+ # @param [Hash] constraints The constraints to use when encoding the canvas.
+ # @return [ChunkyPNG::Datastream] The datastream that contains this image.
+ # @see ChunkyPNG::Canvas::PNGEncoding#to_datastream
+ # @see #metadata_chunks
+ def to_datastream(constraints = {})
+ ds = super(constraints)
+ ds.other_chunks += metadata_chunks
+ return ds
+ end
+
+ # Reads a ChunkyPNG::Image intance from a data stream.
+ #
+ # Besides decoding the canvas, this will also read the metadata fields
+ # from the datastream.
+ #
+ # @param [ChunkyPNG::Datastream] The datastream to read from.
+ def self.from_datastream(ds)
+ image = super(ds)
+ image.metadata = ds.metadata
+ return image
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/palette.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/palette.rb
new file mode 100644
index 00000000..54dfa0c4
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/palette.rb
@@ -0,0 +1,187 @@
+module ChunkyPNG
+
+ # A palette describes the set of colors that is being used for an image.
+ #
+ # A PNG image can contain an explicit palette which defines the colors of
+ # that image, but can also use an implicit palette, e.g. all truecolor
+ # colors or all grayscale colors.
+ #
+ # This palette supports decoding colors from a palette if an explicit
+ # palette is provided in a PNG datastream, and it supports encoding colors
+ # to an explicit palette (stores as PLTE & tRNS chunks in a PNG file).
+ #
+ # @see ChunkyPNG::Color
+ class Palette < SortedSet
+
+ # Builds a new palette given a set (Enumerable instance) of colors.
+ #
+ # @param [Enumerbale] enum The set of colors to include in this palette.
+ # This Enumerbale can contains duplicates.
+ # @param [Array] decoding_map An array of colors in the exact order at which
+ # they appeared in the palette chunk, so that this array can be used for decoding.
+ def initialize(enum, decoding_map = nil)
+ super(enum)
+ @decoding_map = decoding_map if decoding_map
+ end
+
+ # Builds a palette instance from a PLTE chunk and optionally a tRNS chunk
+ # from a PNG datastream.
+ #
+ # This method will cerate a palette that is suitable for decoding an image.
+ #
+ # @param [ChunkyPNG::Chunk::Palette] The palette chunk to load from
+ # @param [ChunkyPNG::Chunk::Transparency, nil] The optional transparency chunk.
+ # @return [ChunkyPNG::Palette] The loaded palette instance.
+ # @see ChunkyPNG::Palette#can_decode?
+ def self.from_chunks(palette_chunk, transparency_chunk = nil)
+ return nil if palette_chunk.nil?
+
+ decoding_map = []
+ index = 0
+
+ palatte_bytes = palette_chunk.content.unpack('C*')
+ if transparency_chunk
+ alpha_channel = transparency_chunk.content.unpack('C*')
+ else
+ alpha_channel = []
+ end
+
+ index = 0
+ palatte_bytes.each_slice(3) do |bytes|
+ bytes << alpha_channel.fetch(index, ChunkyPNG::Color::MAX)
+ decoding_map << ChunkyPNG::Color.rgba(*bytes)
+ index += 1
+ end
+
+ self.new(decoding_map, decoding_map)
+ end
+
+ # Builds a palette instance from a given canvas.
+ # @param [ChunkyPNG::Canvas] canvas The canvas to create a palette for.
+ # @return [ChunkyPNG::Palette] The palette instance.
+ def self.from_canvas(canvas)
+ self.new(canvas.pixels)
+ end
+
+ # Builds a palette instance from a given set of pixels.
+ # @param [Enumerable] pixels An enumeration of pixels to create a palette for
+ # @return [ChunkyPNG::Palette] The palette instance.
+ def self.from_pixels(pixels)
+ self.new(pixels)
+ end
+
+ # Checks whether the size of this palette is suitable for indexed storage.
+ # @return [true, false] True if the number of colors in this palette is at most 256.
+ def indexable?
+ size <= 256
+ end
+
+ # Check whether this pelette only contains opaque colors.
+ # @return [true, false] True if all colors in this palette are opaque.
+ # @see ChunkyPNG::Color#opaque?
+ def opaque?
+ all? { |color| Color.opaque?(color) }
+ end
+
+ # Check whether this pelette only contains grayscale colors.
+ # @return [true, false] True if all colors in this palette are grayscale teints.
+ # @see ChunkyPNG::Color#grayscale??
+ def grayscale?
+ all? { |color| Color.grayscale?(color) }
+ end
+
+ # Returns a palette with all the opaque variants of the colors in this palette.
+ # @return [ChunkyPNG::Palette] A new Palette instance with only opaque colors.
+ # @see ChunkyPNG::Color#opaque!
+ def opaque_palette
+ self.class.new(map { |c| ChunkyPNG::Color.opaque!(c) })
+ end
+
+ # Checks whether this palette is suitable for decoding an image from a datastream.
+ #
+ # This requires that the positions of the colors in the original palette chunk is known,
+ # which is stored as an array in the +@decoding_map+ instance variable.
+ #
+ # @return [true, false] True if a decoding map was built when this palette was loaded.
+ def can_decode?
+ !@decoding_map.nil?
+ end
+
+ # Checks whether this palette is suitable for encoding an image from to datastream.
+ #
+ # This requires that the position of the color in the future palette chunk is known,
+ # which is stored as a hash in the +@encoding_map+ instance variable.
+ #
+ # @return [true, false] True if a encoding map was built when this palette was loaded.
+ def can_encode?
+ !@encoding_map.nil?
+ end
+
+ # Returns a color, given the position in the original palette chunk.
+ # @param [Integer] index The 0-based position of the color in the palette.
+ # @return [ChunkyPNG::Color] The color that is stored in the palette under the given index
+ # @see ChunkyPNG::Palette#can_decode?
+ def [](index)
+ @decoding_map[index]
+ end
+
+ # Returns the position of a color in the palette
+ # @param [ChunkyPNG::Color] color The color for which to look up the index.
+ # @return [Integer] The 0-based position of the color in the palette.
+ # @see ChunkyPNG::Palette#can_encode?
+ def index(color)
+ @encoding_map[color]
+ end
+
+ # Creates a tRNS chunk that corresponds with this palette to store the
+ # alpha channel of all colors.
+ #
+ # Note that this chunk can be left out of every color in the palette is
+ # opaque, and the image is encoded using indexed colors.
+ #
+ # @return [ChunkyPNG::Chunk::Transparency] The tRNS chunk.
+ def to_trns_chunk
+ ChunkyPNG::Chunk::Transparency.new('tRNS', map { |c| ChunkyPNG::Color.a(c) }.pack('C*'))
+ end
+
+ # Creates a PLTE chunk that corresponds with this palette to store the
+ # r, g and b channels of all colors.
+ #
+ # Note that a PLTE chunk should only be included if the image is
+ # encoded using index colors. After this chunk has been built, the
+ # palette becomes suitable for encoding an image.
+ #
+ # @return [ChunkyPNG::Chunk::Palette] The PLTE chunk.
+ # @see ChunkyPNG::Palette#can_encode?
+ def to_plte_chunk
+ @encoding_map = {}
+ colors = []
+
+ each_with_index do |color, index|
+ @encoding_map[color] = index
+ colors += ChunkyPNG::Color.to_truecolor_bytes(color)
+ end
+
+ ChunkyPNG::Chunk::Palette.new('PLTE', colors.pack('C*'))
+ end
+
+ # Determines the most suitable colormode for this palette.
+ # @return [Integer] The colormode which would create the smalles possible
+ # file for images that use this exact palette.
+ def best_colormode
+ if grayscale?
+ if opaque?
+ ChunkyPNG::COLOR_GRAYSCALE
+ else
+ ChunkyPNG::COLOR_GRAYSCALE_ALPHA
+ end
+ elsif indexable?
+ ChunkyPNG::COLOR_INDEXED
+ elsif opaque?
+ ChunkyPNG::COLOR_TRUECOLOR
+ else
+ ChunkyPNG::COLOR_TRUECOLOR_ALPHA
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/rmagick.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/rmagick.rb
new file mode 100644
index 00000000..be24ce3a
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/lib/chunky_png/rmagick.rb
@@ -0,0 +1,43 @@
+require 'rmagick'
+
+module ChunkyPNG
+
+ # Methods for importing and exporting RMagick image objects.
+ #
+ # By default, this module is disabled because of the dependency on RMagick.
+ # You need to include this module yourself if you want to use it.
+ #
+ # @example
+ #
+ # require 'rmagick'
+ # require 'chunky_png/rmagick'
+ #
+ # canvas = ChunkyPNG::Canvas.from_file('filename.png')
+ # image = ChunkyPNG::RMagick.export(canvas)
+ #
+ # # do something with the image using RMagick
+ #
+ # updated_canvas = ChunkyPNG::RMagick.import(image)
+ #
+ module RMagick
+
+ extend self
+
+ # Imports an RMagick image as Canvas object.
+ # @param [Magick::Image] image The image to import
+ # @return [ChunkyPNG::Canvas] The canvas, constructed from the RMagick image.
+ def import(image)
+ pixels = image.export_pixels_to_str(0, 0, image.columns, image.rows, 'RGBA')
+ ChunkyPNG::Canvas.from_rgba_stream(image.columns, image.rows, pixels)
+ end
+
+ # Exports a Canvas as RMagick image instance.
+ # @param [ChunkyPNG::Canvas] canvas The canvas to export.
+ # @return [Magick::Image] The RMagick image constructed from the Canvas instance.
+ def export(canvas)
+ image = Magick::Image.new(canvas.width, canvas.height)
+ image.import_pixels(0,0, canvas.width, canvas.height, 'RGBA', canvas.pixels.pack('N*'))
+ image
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/adam7_interlacing_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/adam7_interlacing_spec.rb
new file mode 100644
index 00000000..48a9b0a8
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/adam7_interlacing_spec.rb
@@ -0,0 +1,106 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Canvas::Adam7Interlacing do
+ include ChunkyPNG::Canvas::Adam7Interlacing
+
+ describe '#adam7_pass_sizes' do
+ it "should get the pass sizes for a 8x8 image correctly" do
+ adam7_pass_sizes(8, 8).should == [
+ [1, 1], [1, 1], [2, 1], [2, 2], [4, 2], [4, 4], [8, 4]
+ ]
+ end
+
+ it "should get the pass sizes for a 12x12 image correctly" do
+ adam7_pass_sizes(12, 12).should == [
+ [2, 2], [1, 2], [3, 1], [3, 3], [6, 3], [6, 6], [12, 6]
+ ]
+ end
+
+ it "should get the pass sizes for a 33x47 image correctly" do
+ adam7_pass_sizes(33, 47).should == [
+ [5, 6], [4, 6], [9, 6], [8, 12], [17, 12], [16, 24], [33, 23]
+ ]
+ end
+
+ it "should get the pass sizes for a 1x1 image correctly" do
+ adam7_pass_sizes(1, 1).should == [
+ [1, 1], [0, 1], [1, 0], [0, 1], [1, 0], [0, 1], [1, 0]
+ ]
+ end
+
+ it "should get the pass sizes for a 0x0 image correctly" do
+ adam7_pass_sizes(0, 0).should == [
+ [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
+ ]
+ end
+
+ it "should always maintain the same amount of pixels in total" do
+ [[8, 8], [12, 12], [33, 47], [1, 1], [0, 0]].each do |(width, height)|
+ pass_sizes = adam7_pass_sizes(width, height)
+ pass_sizes.inject(0) { |sum, (w, h)| sum + (w*h) }.should == width * height
+ end
+ end
+ end
+
+ describe '#adam7_multiplier_offset' do
+ it "should get the multiplier and offset values for pass 1 correctly" do
+ adam7_multiplier_offset(0).should == [3, 0, 3, 0]
+ end
+
+ it "should get the multiplier and offset values for pass 2 correctly" do
+ adam7_multiplier_offset(1).should == [3, 4, 3, 0]
+ end
+
+ it "should get the multiplier and offset values for pass 3 correctly" do
+ adam7_multiplier_offset(2).should == [2, 0, 3, 4]
+ end
+
+ it "should get the multiplier and offset values for pass 4 correctly" do
+ adam7_multiplier_offset(3).should == [2, 2, 2, 0]
+ end
+
+ it "should get the multiplier and offset values for pass 5 correctly" do
+ adam7_multiplier_offset(4).should == [1, 0, 2, 2]
+ end
+
+ it "should get the multiplier and offset values for pass 6 correctly" do
+ adam7_multiplier_offset(5).should == [1, 1, 1, 0]
+ end
+
+ it "should get the multiplier and offset values for pass 7 correctly" do
+ adam7_multiplier_offset(6).should == [0, 0, 1, 1]
+ end
+ end
+
+ describe '#adam7_merge_pass' do
+ it "should merge the submatrices correctly" do
+ submatrices = [
+ ChunkyPNG::Canvas.new(1, 1, 168430335), # r = 10
+ ChunkyPNG::Canvas.new(1, 1, 336860415), # r = 20
+ ChunkyPNG::Canvas.new(2, 1, 505290495), # r = 30
+ ChunkyPNG::Canvas.new(2, 2, 677668095), # r = 40
+ ChunkyPNG::Canvas.new(4, 2, 838912255), # r = 50
+ ChunkyPNG::Canvas.new(4, 4, 1023344895), # r = 60
+ ChunkyPNG::Canvas.new(8, 4, 1175063295), # r = 70
+ ]
+
+ canvas = ChunkyPNG::Image.new(8,8)
+ submatrices.each_with_index { |m, pass| adam7_merge_pass(pass, canvas, m) }
+ canvas.should == reference_image('adam7')
+ end
+ end
+
+ describe '#adam7_extract_pass' do
+ before(:each) { @canvas = reference_canvas('adam7') }
+
+ 1.upto(7) do |pass|
+ it "should extract pass #{pass} correctly" do
+ sm = adam7_extract_pass(pass - 1, @canvas)
+ sm.pixels.length.should == sm.width * sm.height
+ sm.pixels.uniq.length.should == 1
+ ChunkyPNG::Color.r(sm[0,0]).should == pass * 10
+ end
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/drawing_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/drawing_spec.rb
new file mode 100644
index 00000000..e1bcecaf
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/drawing_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Canvas::Drawing do
+
+ describe '#point' do
+ it "should compose colors correctly" do
+ canvas = ChunkyPNG::Canvas.new(1, 1, ChunkyPNG::Color.rgb(200, 150, 100))
+ canvas.point(0,0, ChunkyPNG::Color.rgba(100, 150, 200, 128))
+ canvas[0,0].should == ChunkyPNG::Color.rgb(150, 150, 150)
+ end
+ end
+
+ describe '#line' do
+ it "should draw lines correctly with anti-aliasing" do
+ canvas = ChunkyPNG::Canvas.new(32, 32, ChunkyPNG::Color::WHITE)
+
+ canvas.line( 0, 0, 31, 31, ChunkyPNG::Color::BLACK)
+ canvas.line( 0, 31, 31, 0, ChunkyPNG::Color::BLACK)
+ canvas.line(15, 31, 15, 0, ChunkyPNG::Color.rgba(200, 0, 0, 128))
+ canvas.line( 0, 15, 31, 15, ChunkyPNG::Color.rgba(200, 0, 0, 128))
+ canvas.line( 0, 15, 31, 31, ChunkyPNG::Color.rgba( 0, 200, 0, 128))
+ canvas.line( 0, 15, 31, 0, ChunkyPNG::Color.rgba( 0, 200, 0, 128))
+ canvas.line(15, 0, 31, 31, ChunkyPNG::Color.rgba( 0, 0, 200, 128))
+ canvas.line(15, 0, 0, 31, ChunkyPNG::Color.rgba( 0, 0, 200, 128))
+
+ canvas.should == reference_canvas('lines')
+ end
+ end
+
+ describe '#rect' do
+ it "should draw a rectangle with the correct colors" do
+ canvas = ChunkyPNG::Canvas.new(16, 16, ChunkyPNG::Color::WHITE)
+ canvas.rect(1, 1, 10, 10, ChunkyPNG::Color.rgb(0, 255, 0), ChunkyPNG::Color.rgba(255, 0, 0, 100))
+ canvas.rect(5, 5, 14, 14, ChunkyPNG::Color.rgb(0, 0, 255), ChunkyPNG::Color.rgba(255, 255, 0, 100))
+ canvas.should == reference_canvas('rect')
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/operations_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/operations_spec.rb
new file mode 100644
index 00000000..c59e49d6
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/operations_spec.rb
@@ -0,0 +1,173 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Canvas::Operations do
+ describe '#crop' do
+ before { @canvas = reference_canvas('operations') }
+
+ it "should crop the right pixels from the original canvas" do
+ cropped = @canvas.crop(10, 5, 4, 8)
+ cropped.should == reference_canvas('cropped')
+ end
+
+ it "should raise an exception when the cropped image falls outside the oiginal image" do
+ lambda { @canvas.crop(16, 16, 2, 2) }.should raise_error(ChunkyPNG::OutOfBounds)
+ end
+ end
+
+ describe '#compose' do
+ it "should compose pixels correctly" do
+ canvas = reference_canvas('operations')
+ subcanvas = ChunkyPNG::Canvas.new(4, 8, ChunkyPNG::Color.rgba(0, 0, 0, 75))
+ canvas.compose(subcanvas, 8, 4)
+ canvas.should == reference_canvas('composited')
+ end
+
+ it "should compose a base image and mask correctly" do
+ base = reference_canvas('clock_base')
+ mask = reference_canvas('clock_mask_updated')
+ base.compose(mask).should == reference_canvas('clock_updated')
+ end
+
+ it "should raise an exception when the pixels to compose fall outside the image" do
+ lambda { reference_canvas('operations').compose(ChunkyPNG::Canvas.new(1,1), 16, 16) }.should raise_error(ChunkyPNG::OutOfBounds)
+ end
+ end
+
+ describe '#replace' do
+ before { @canvas = reference_canvas('operations') }
+
+ it "should replace the correct pixels" do
+ subcanvas = ChunkyPNG::Canvas.new(3, 2, ChunkyPNG::Color.rgb(200, 255, 0))
+ @canvas.replace(subcanvas, 5, 4)
+ @canvas.should == reference_canvas('replaced')
+ end
+
+ it "should raise an exception when the pixels to replace fall outside the image" do
+ lambda { @canvas.replace(ChunkyPNG::Canvas.new(1,1), 16, 16) }.should raise_error(ChunkyPNG::OutOfBounds)
+ end
+ end
+
+ describe '#change_theme_color!' do
+
+ before(:each) do
+ @theme_color = ChunkyPNG::Color.from_hex('#e10f7a')
+ @new_color = ChunkyPNG::Color.from_hex('#ff0000')
+ @canvas = reference_canvas('clock')
+ end
+
+ it "should change the theme color correctly" do
+ @canvas.change_theme_color!(@theme_color, @new_color)
+ @canvas.should == reference_canvas('clock_updated')
+ end
+ end
+
+ describe '#extract_mask' do
+ before(:each) do
+ @mask_color = ChunkyPNG::Color.from_hex('#e10f7a')
+ @canvas = reference_canvas('clock')
+ end
+
+ it "should create the correct base and mask image" do
+ base, mask = @canvas.extract_mask(@mask_color, ChunkyPNG::Color::WHITE)
+ base.should == reference_canvas('clock_base')
+ mask.should == reference_canvas('clock_mask')
+ end
+
+ it "should create a mask image with only one opaque color" do
+ base, mask = @canvas.extract_mask(@mask_color, ChunkyPNG::Color::WHITE)
+ mask.palette.opaque_palette.size.should == 1
+ end
+ end
+
+ describe '#change_mask_color!' do
+ before(:each) do
+ @new_color = ChunkyPNG::Color.from_hex('#ff0000')
+ @mask = reference_canvas('clock_mask')
+ end
+
+ it "should replace the mask color correctly" do
+ @mask.change_mask_color!(@new_color)
+ @mask.should == reference_canvas('clock_mask_updated')
+ end
+
+ it "should still only have one opaque color" do
+ @mask.change_mask_color!(@new_color)
+ @mask.palette.opaque_palette.size.should == 1
+ end
+
+ it "should raise an exception when the mask image has more than once color" do
+ not_a_mask = reference_canvas('operations')
+ lambda { not_a_mask.change_mask_color!(@new_color) }.should raise_error(ChunkyPNG::ExpectationFailed)
+ end
+ end
+end
+
+describe ChunkyPNG::Canvas::Operations do
+ before { @stubbed = reference_canvas('clock_stubbed') }
+
+ describe '#flip_horizontally' do
+ it "should flip the pixels horizontally" do
+ @stubbed.flip_horizontally.should == reference_canvas('clock_flip_horizontally')
+ end
+
+ it "should return itself when applied twice" do
+ @stubbed.flip_horizontally.flip_horizontally.should == @stubbed
+ end
+ end
+
+ describe '#flip_vertically' do
+ it "should flip the pixels vertically" do
+ @stubbed.flip_vertically.should == reference_canvas('clock_flip_vertically')
+ end
+
+ it "should return itself when applied twice" do
+ @stubbed.flip_vertically.flip_vertically.should == @stubbed
+ end
+ end
+
+ describe '#rotate_left' do
+ it "should rotate the pixels 90 degrees counter-clockwise" do
+ @stubbed.rotate_left.should == reference_canvas('clock_rotate_left')
+ end
+
+ it "it should rotate 180 degrees when applied twice" do
+ @stubbed.rotate_left.rotate_left.should == reference_canvas('clock_rotate_180')
+ end
+
+ it "it should rotate right when applied three times" do
+ @stubbed.rotate_left.rotate_left.rotate_left.should == reference_canvas('clock_rotate_right')
+ end
+
+ it "should return itself when applied four times" do
+ @stubbed.rotate_left.rotate_left.rotate_left.rotate_left.should == @stubbed
+ end
+ end
+
+ describe '#rotate_right' do
+ it "should rotate the pixels 90 degrees clockwise" do
+ @stubbed.rotate_right.should == reference_canvas('clock_rotate_right')
+ end
+
+ it "it should rotate 180 degrees when applied twice" do
+ @stubbed.rotate_right.rotate_right.should == reference_canvas('clock_rotate_180')
+ end
+
+ it "it should rotate left when applied three times" do
+ @stubbed.rotate_right.rotate_right.rotate_right.should == reference_canvas('clock_rotate_left')
+ end
+
+ it "should return itself when applied four times" do
+ @stubbed.rotate_right.rotate_right.rotate_right.rotate_right.should == @stubbed
+ end
+ end
+
+ describe '#rotate_180' do
+ it "should rotate the pixels 180 degrees" do
+ @stubbed.rotate_180.should == reference_canvas('clock_rotate_180')
+ end
+
+ it "should return itself when applied twice" do
+ @stubbed.rotate_180.rotate_180.should == @stubbed
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/png_decoding_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/png_decoding_spec.rb
new file mode 100644
index 00000000..59bc6112
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/png_decoding_spec.rb
@@ -0,0 +1,97 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Canvas::PNGDecoding do
+ include ChunkyPNG::Canvas::PNGDecoding
+
+ describe '#decode_png_scanline' do
+
+ it "should decode a line without filtering as is" do
+ stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack('C*')
+ decode_png_str_scanline(stream, 0, nil, 9, 3)
+ stream.unpack('@1C*').should == [255, 255, 255, 255, 255, 255, 255, 255, 255]
+ end
+
+ it "should decode a line with sub filtering correctly" do
+ # all white pixels
+ stream = [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0].pack('C*')
+ decode_png_str_scanline(stream, 0, nil, 9, 3)
+ stream.unpack('@1C*').should == [255, 255, 255, 255, 255, 255, 255, 255, 255]
+
+ # all black pixels
+ stream = [ChunkyPNG::FILTER_SUB, 0, 0, 0, 0, 0, 0, 0, 0, 0].pack('C*')
+ decode_png_str_scanline(stream, 0, nil, 9, 3)
+ stream.unpack('@1C*').should == [0, 0, 0, 0, 0, 0, 0, 0, 0]
+
+ # various colors
+ stream = [ChunkyPNG::FILTER_SUB, 255, 0, 45, 0, 255, 0, 112, 200, 178].pack('C*')
+ decode_png_str_scanline(stream, 0, nil, 9, 3)
+ stream.unpack('@1C*').should == [255, 0, 45, 255, 255, 45, 111, 199, 223]
+ end
+
+ it "should decode a line with up filtering correctly" do
+ # previous line has various pixels
+ previous = [ChunkyPNG::FILTER_UP, 255, 255, 255, 127, 127, 127, 0, 0, 0]
+ current = [ChunkyPNG::FILTER_UP, 0, 127, 255, 0, 127, 255, 0, 127, 255]
+ stream = (previous + current).pack('C*')
+ decode_png_str_scanline(stream, 10, 0, 9, 3)
+ stream.unpack('@11C9').should == [255, 126, 254, 127, 254, 126, 0, 127, 255]
+ end
+
+ it "should decode a line with average filtering correctly" do
+ previous = [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120]
+ current = [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53]
+ stream = (previous + current).pack('C*')
+ decode_png_str_scanline(stream, 13, 0, 12, 3)
+ stream.unpack('@14C12').should == [5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165]
+ end
+
+ it "should decode a line with paeth filtering correctly" do
+ previous = [ChunkyPNG::FILTER_PAETH, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120]
+ current = [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0]
+ stream = (previous + current).pack('C*')
+ decode_png_str_scanline(stream, 13, 0, 12, 3)
+ stream.unpack('@14C12').should == [10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120]
+ end
+ end
+
+ describe '#decode_png_extract_4bit_value' do
+ it "should extract the high bits successfully" do
+ decode_png_extract_4bit_value('10010110'.to_i(2), 0).should == '1001'.to_i(2)
+ end
+
+ it "should extract the low bits successfully" do
+ decode_png_extract_4bit_value('10010110'.to_i(2), 17).should == '0110'.to_i(2)
+ end
+ end
+
+ describe '#decode_png_extract_2bit_value' do
+ it "should extract the first 2 bits successfully" do
+ decode_png_extract_2bit_value('10010110'.to_i(2), 0).should == '10'.to_i(2)
+ end
+
+ it "should extract the second 2 bits successfully" do
+ decode_png_extract_2bit_value('10010110'.to_i(2), 5).should == '01'.to_i(2)
+ end
+
+ it "should extract the third 2 bits successfully" do
+ decode_png_extract_2bit_value('10010110'.to_i(2), 2).should == '01'.to_i(2)
+ end
+
+ it "should extract the low two bits successfully" do
+ decode_png_extract_2bit_value('10010110'.to_i(2), 7).should == '10'.to_i(2)
+ end
+ end
+
+ describe '#decode_png_extract_1bit_value' do
+ it "should extract all separate bits correctly" do
+ decode_png_extract_1bit_value('10010110'.to_i(2), 0).should == 1
+ decode_png_extract_1bit_value('10010110'.to_i(2), 1).should == 0
+ decode_png_extract_1bit_value('10010110'.to_i(2), 2).should == 0
+ decode_png_extract_1bit_value('10010110'.to_i(2), 3).should == 1
+ decode_png_extract_1bit_value('10010110'.to_i(2), 4).should == 0
+ decode_png_extract_1bit_value('10010110'.to_i(2), 5).should == 1
+ decode_png_extract_1bit_value('10010110'.to_i(2), 6).should == 1
+ decode_png_extract_1bit_value('10010110'.to_i(2), 7).should == 0
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/png_encoding_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/png_encoding_spec.rb
new file mode 100644
index 00000000..68f714ce
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas/png_encoding_spec.rb
@@ -0,0 +1,171 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Canvas::PNGEncoding do
+ include ChunkyPNG::Canvas::PNGEncoding
+
+ describe '.encode_png' do
+ [:indexed, :grayscale, :grayscale_alpha, :truecolor, :truecolor_alpha].each do |color_mode_name|
+ it "should encode an image with color mode #{color_mode_name} correctly" do
+ filename = resource_file("_tmp_#{color_mode_name}.png")
+ canvas = ChunkyPNG::Canvas.new(10, 10, ChunkyPNG::Color.rgb(100, 100, 100))
+ color_mode = ChunkyPNG.const_get("COLOR_#{color_mode_name.to_s.upcase}")
+ canvas.save(filename, :color_mode => color_mode)
+
+ ds = ChunkyPNG::Datastream.from_file(filename)
+ ds.header_chunk.color.should == color_mode
+ ChunkyPNG::Canvas.from_datastream(ds).should == ChunkyPNG::Canvas.new(10, 10, ChunkyPNG::Color.rgb(100, 100, 100))
+
+ File.unlink(filename)
+ end
+ end
+
+ it "should encode an image with interlacing correctly" do
+ input_canvas = ChunkyPNG::Canvas.from_file(resource_file('operations.png'))
+ filename = resource_file("_tmp_interlaced.png")
+ input_canvas.save(filename, :interlace => true)
+
+ ds = ChunkyPNG::Datastream.from_file(filename)
+ ds.header_chunk.interlace.should == ChunkyPNG::INTERLACING_ADAM7
+ ChunkyPNG::Canvas.from_datastream(ds).should == input_canvas
+
+ File.unlink(filename)
+ end
+
+ it "should save an image using the normal routine correctly" do
+ canvas = reference_canvas('operations')
+ Zlib::Deflate.should_receive(:deflate).with(anything, Zlib::DEFAULT_COMPRESSION).and_return('')
+ canvas.to_blob
+ end
+
+ it "should save an image using the :fast_rgba routine correctly" do
+ canvas = reference_canvas('operations')
+ canvas.should_not_receive(:encode_png_str_scanline_none)
+ canvas.should_not_receive(:encode_png_str_scanline_sub)
+ canvas.should_not_receive(:encode_png_str_scanline_up)
+ canvas.should_not_receive(:encode_png_str_scanline_average)
+ canvas.should_not_receive(:encode_png_str_scanline_paeth)
+ Zlib::Deflate.should_receive(:deflate).with(anything, Zlib::BEST_SPEED).and_return('')
+ canvas.to_blob(:fast_rgba)
+ end
+
+ it "should save an image using the :good_compression routine correctly" do
+ canvas = reference_canvas('operations')
+ canvas.should_not_receive(:encode_png_str_scanline_none)
+ canvas.should_not_receive(:encode_png_str_scanline_sub)
+ canvas.should_not_receive(:encode_png_str_scanline_up)
+ canvas.should_not_receive(:encode_png_str_scanline_average)
+ canvas.should_not_receive(:encode_png_str_scanline_paeth)
+ Zlib::Deflate.should_receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return('')
+ canvas.to_blob(:good_compression)
+ end
+
+ it "should save an image using the :best_compression routine correctly" do
+ canvas = reference_canvas('operations')
+ canvas.should_receive(:encode_png_str_scanline_paeth).exactly(canvas.height).times
+ Zlib::Deflate.should_receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return('')
+ canvas.to_blob(:best_compression)
+ end
+ end
+
+ describe '#encode_png_image_pass_to_stream' do
+ before { @canvas = ChunkyPNG::Canvas.new(2, 2, ChunkyPNG::Color.rgba(1, 2, 3, 4)) }
+
+ it "should encode using RGBA / no filtering mode correctly" do
+ @canvas.encode_png_image_pass_to_stream(stream = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR_ALPHA, ChunkyPNG::FILTER_NONE)
+ stream.should == "\0\1\2\3\4\1\2\3\4\0\1\2\3\4\1\2\3\4"
+ end
+
+ it "should encode using RGBA / SUB filtering mode correctly" do
+ @canvas.encode_png_image_pass_to_stream(stream = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR_ALPHA, ChunkyPNG::FILTER_SUB)
+ stream.should == "\1\1\2\3\4\0\0\0\0\1\1\2\3\4\0\0\0\0"
+ end
+
+ it "should encode using RGBA / UP filtering mode correctly" do
+ @canvas.encode_png_image_pass_to_stream(stream = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR_ALPHA, ChunkyPNG::FILTER_UP)
+ stream.should == "\2\1\2\3\4\1\2\3\4\2\0\0\0\0\0\0\0\0"
+ end
+
+ it "should encode using RGBA / AVERAGE filtering mode correctly" do
+ @canvas.encode_png_image_pass_to_stream(stream = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR_ALPHA, ChunkyPNG::FILTER_AVERAGE)
+ stream.should == "\3\1\2\3\4\1\1\2\2\3\1\1\2\2\0\0\0\0"
+ end
+
+ it "should encode using RGB / no filtering mode correctly" do
+ @canvas.encode_png_image_pass_to_stream(stream = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, ChunkyPNG::FILTER_NONE)
+ stream.should == "\0\1\2\3\1\2\3\0\1\2\3\1\2\3"
+ end
+
+ it "should encode using indexed / no filtering mode correctly" do
+ @canvas.stub(:encoding_palette).and_return(mock('Palette', :index => 1))
+ @canvas.encode_png_image_pass_to_stream(stream = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, ChunkyPNG::FILTER_NONE)
+ stream.should == "\0\1\1\0\1\1"
+ end
+
+ it "should encode using indexed / PAETH filtering mode correctly" do
+ @canvas.stub(:encoding_palette).and_return(mock('Palette', :index => 1))
+ @canvas.encode_png_image_pass_to_stream(stream = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, ChunkyPNG::FILTER_PAETH)
+ stream.should == "\4\1\0\4\0\0"
+ end
+ end
+
+ describe '#encode_png_str_scanline' do
+
+ it "should encode a scanline without filtering correctly" do
+ stream = [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2].pack('C*')
+ encode_png_str_scanline_none(stream, 0, nil, 9, 3)
+ stream.unpack('C*').should == [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2]
+ end
+
+ it "should encode a scanline with sub filtering correctly" do
+ stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack('C*')
+
+ # Check line with previous line
+ encode_png_str_scanline_sub(stream, 10, 0, 9, 3)
+ stream.unpack('@10C10').should == [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0]
+
+ # Check line without previous line
+ encode_png_str_scanline_sub(stream, 0, nil, 9, 3)
+ stream.unpack('@0C10').should == [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0]
+ end
+
+ it "should encode a scanline with up filtering correctly" do
+ stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack('C*')
+
+ # Check line with previous line
+ encode_png_str_scanline_up(stream, 10, 0, 9, 3)
+ stream.unpack('@10C10').should == [ChunkyPNG::FILTER_UP, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+
+ # Check line without previous line
+ encode_png_str_scanline_up(stream, 0, nil, 9, 3)
+ stream.unpack('@0C10').should == [ChunkyPNG::FILTER_UP, 255, 255, 255, 255, 255, 255, 255, 255, 255]
+ end
+
+ it "should encode a scanline with average filtering correctly" do
+ stream = [ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120,
+ ChunkyPNG::FILTER_NONE, 5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165].pack('C*')
+
+ # Check line with previous line
+ encode_png_str_scanline_average(stream, 13, 0, 12, 3)
+ stream.unpack('@13C13').should == [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53]
+
+ # Check line without previous line
+ encode_png_str_scanline_average(stream, 0, nil, 12, 3)
+ stream.unpack('@0C13').should == [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 35, 40, 45, 50, 55, 50, 65, 70, 80]
+ end
+
+ it "should encode a scanline with paeth filtering correctly" do
+ stream = [ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120,
+ ChunkyPNG::FILTER_NONE, 10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120].pack('C*')
+
+ # Check line with previous line
+ encode_png_str_scanline_paeth(stream, 13, 0, 12, 3)
+ stream.unpack('@13C13').should == [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0]
+
+ # Check line without previous line
+ encode_png_str_scanline_paeth(stream, 0, nil, 12, 3)
+ stream.unpack('@0C13').should == [ChunkyPNG::FILTER_PAETH, 10, 20, 30, 30, 30, 30, 30, 30, 20, 30, 30, 40]
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas_spec.rb
new file mode 100644
index 00000000..e6e6747d
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/canvas_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Canvas do
+
+ describe '.from_rgb_stream' do
+ it "should load an image correctly from a datastream" do
+ File.open(resource_file('pixelstream.rgb')) do |stream|
+ matrix = ChunkyPNG::Canvas.from_rgb_stream(240, 180, stream)
+ matrix.should == reference_canvas('pixelstream_reference')
+ end
+ end
+ end
+
+ describe '.from_rgba_stream' do
+ it "should load an image correctly from a datastream" do
+ File.open(resource_file('pixelstream.rgba')) do |stream|
+ matrix = ChunkyPNG::Canvas.from_rgba_stream(240, 180, stream)
+ matrix.should == reference_canvas('pixelstream_reference')
+ end
+ end
+ end
+
+ describe '#to_rgba_stream' do
+ before { File.open(resource_file('pixelstream.rgba'), 'rb') { |f| @reference_data = f.read } }
+
+ it "should load an image correctly from a datastream" do
+ reference_canvas('pixelstream_reference').to_rgba_stream.should == @reference_data
+ end
+ end
+
+ describe '#to_rgb_stream' do
+ before { File.open(resource_file('pixelstream.rgb'), 'rb') { |f| @reference_data = f.read } }
+
+ it "should load an image correctly from a datastream" do
+ reference_canvas('pixelstream_reference').to_rgb_stream.should == @reference_data
+ end
+ end
+
+ describe '#row' do
+ before { @canvas = reference_canvas('operations') }
+
+ it "should give an out of bounds exception when y-coordinate is out of bounds" do
+ lambda { @canvas.row(-1) }.should raise_error(ChunkyPNG::OutOfBounds)
+ lambda { @canvas.row(16) }.should raise_error(ChunkyPNG::OutOfBounds)
+ end
+
+ it "should return the correct pixels" do
+ data = @canvas.row(0)
+ data.should have(@canvas.width).items
+ data.should == [65535, 268500991, 536936447, 805371903, 1073807359, 1342242815, 1610678271, 1879113727, 2147549183, 2415984639, 2684420095, 2952855551, 3221291007, 3489726463, 3758161919, 4026597375]
+ end
+ end
+
+ describe '#column' do
+ before { @canvas = reference_canvas('operations') }
+
+ it "should give an out of bounds exception when x-coordinate is out of bounds" do
+ lambda { @canvas.column(-1) }.should raise_error(ChunkyPNG::OutOfBounds)
+ lambda { @canvas.column(16) }.should raise_error(ChunkyPNG::OutOfBounds)
+ end
+
+ it "should return the correct pixels" do
+ data = @canvas.column(0)
+ data.should have(@canvas.height).items
+ data.should == [65535, 1114111, 2162687, 3211263, 4259839, 5308415, 6356991, 7405567, 8454143, 9502719, 10551295, 11599871, 12648447, 13697023, 14745599, 15794175]
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/color_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/color_spec.rb
new file mode 100644
index 00000000..1c467a4a
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/color_spec.rb
@@ -0,0 +1,144 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Color do
+ include ChunkyPNG::Color
+
+ before(:each) do
+ @white = 0xffffffff
+ @black = 0x000000ff
+ @opaque = 0x0a6496ff
+ @non_opaque = 0x0a649664
+ @fully_transparent = 0x0a649600
+ end
+
+ describe '#pixel_bytesize' do
+ it "should return the normal amount of bytes with a bit depth of 8" do
+ pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8).should == 3
+ end
+
+ it "should return a multiple of the normal amount of bytes with a bit depth greater than 8" do
+ pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 16).should == 6
+ pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 16).should == 8
+ pixel_bytesize(ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 16).should == 4
+ end
+
+ it "should return 1 with a bit depth lower than 0" do
+ pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 4).should == 1
+ pixel_bytesize(ChunkyPNG::COLOR_INDEXED, 2).should == 1
+ pixel_bytesize(ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 1).should == 1
+ end
+ end
+
+ describe '#pass_bytesize' do
+ it "should calculate a pass size correctly" do
+ pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 10, 10).should == 310
+ end
+
+ it "should return 0 if one of the dimensions is zero" do
+ pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 0, 10).should == 0
+ pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 10, 0).should == 0
+ end
+ end
+
+ describe '#rgba' do
+ it "should represent pixels as the correct number" do
+ rgba(255, 255, 255, 255).should == @white
+ rgba( 0, 0, 0, 255).should == @black
+ rgba( 10, 100, 150, 255).should == @opaque
+ rgba( 10, 100, 150, 100).should == @non_opaque
+ rgba( 10, 100, 150, 0).should == @fully_transparent
+ end
+ end
+
+ describe '#from_hex' do
+ it "should load colors correctlt from hex notation" do
+ from_hex('0a649664').should == @non_opaque
+ from_hex('#0a649664').should == @non_opaque
+ from_hex('0x0a649664').should == @non_opaque
+ from_hex('0a6496').should == @opaque
+ from_hex('#0a6496').should == @opaque
+ from_hex('0x0a6496').should == @opaque
+ end
+ end
+
+ describe '#opaque?' do
+ it "should correctly check for opaqueness" do
+ opaque?(@white).should be_true
+ opaque?(@black).should be_true
+ opaque?(@opaque).should be_true
+ opaque?(@non_opaque).should be_false
+ opaque?(@fully_transparent).should be_false
+ end
+ end
+
+ describe 'extractiion of separate color channels' do
+ it "should extract components from a color correctly" do
+ r(@opaque).should == 10
+ g(@opaque).should == 100
+ b(@opaque).should == 150
+ a(@opaque).should == 255
+ end
+ end
+
+ describe '#to_hex' do
+ it "should represent colors correcly using hex notation" do
+ to_hex(@white).should == '#ffffffff'
+ to_hex(@black).should == '#000000ff'
+ to_hex(@opaque).should == '#0a6496ff'
+ to_hex(@non_opaque).should == '#0a649664'
+ to_hex(@fully_transparent).should == '#0a649600'
+ end
+
+ it "should represent colors correcly using hex notation without alpha channel" do
+ to_hex(@white, false).should == '#ffffff'
+ to_hex(@black, false).should == '#000000'
+ to_hex(@opaque, false).should == '#0a6496'
+ to_hex(@non_opaque, false).should == '#0a6496'
+ to_hex(@fully_transparent, false).should == '#0a6496'
+ end
+ end
+
+ describe 'conversion to other formats' do
+ it "should convert the individual color values back correctly" do
+ to_truecolor_bytes(@opaque).should == [10, 100, 150]
+ to_truecolor_alpha_bytes(@non_opaque).should == [10, 100, 150, 100]
+ end
+ end
+
+ describe '#compose' do
+
+ it "should use the foregorund color as is when the background color is fully transparent" do
+ compose(@non_opaque, @fully_transparent).should == @non_opaque
+ end
+
+ it "should use the foregorund color as is when an opaque color is given as foreground color" do
+ compose(@opaque, @white).should == @opaque
+ end
+
+ it "should use the background color as is when a fully transparent pixel is given as foreground color" do
+ compose(@fully_transparent, @white).should == @white
+ end
+
+ it "should compose pixels correctly with both algorithms" do
+ compose_quick(@non_opaque, @white).should == 0x9fc2d6ff
+ compose_precise(@non_opaque, @white).should == 0x9fc2d6ff
+ end
+ end
+
+ describe '#decompose_alpha' do
+ it "should decompose the alpha channel correctly" do
+ decompose_alpha(0x9fc2d6ff, @opaque, @white).should == 0x00000064
+ end
+ end
+
+ describe '#blend' do
+ it "should blend colors correctly" do
+ blend(@opaque, @black).should == 0x05324bff
+ end
+
+ it "should not matter what color is used as foreground, and what as background" do
+ blend(@opaque, @black).should == blend(@black, @opaque)
+ end
+ end
+end
+
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/datastream_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/datastream_spec.rb
new file mode 100644
index 00000000..7104e33e
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/datastream_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Datastream do
+
+ describe '.from_io'do
+ it "should raise an error when loading a file with a bad signature" do
+ filename = resource_file('damaged_signature.png')
+ lambda { ChunkyPNG::Datastream.from_file(filename) }.should raise_error
+ end
+
+ it "should raise an error if the CRC of a chunk is incorrect" do
+ filename = resource_file('damaged_chunk.png')
+ lambda { ChunkyPNG::Datastream.from_file(filename) }.should raise_error
+ end
+ end
+
+ describe '#metadata' do
+ it "should load uncompressed tXTt chunks correctly" do
+ filename = resource_file('text_chunk.png')
+ ds = ChunkyPNG::Datastream.from_file(filename)
+ ds.metadata['Title'].should == 'My amazing icon!'
+ ds.metadata['Author'].should == "Willem van Bergen"
+ end
+
+ it "should load compressed zTXt chunks correctly" do
+ filename = resource_file('ztxt_chunk.png')
+ ds = ChunkyPNG::Datastream.from_file(filename)
+ ds.metadata['Title'].should == 'PngSuite'
+ ds.metadata['Copyright'].should == "Copyright Willem van Schaik, Singapore 1995-96"
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/image_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/image_spec.rb
new file mode 100644
index 00000000..b34aa296
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/image_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe ChunkyPNG::Image do
+ describe '#metadata' do
+
+ it "should load metadata from an existing file" do
+ image = ChunkyPNG::Image.from_file(resource_file('text_chunk.png'))
+ image.metadata['Title'].should == 'My amazing icon!'
+ image.metadata['Author'].should == 'Willem van Bergen'
+ end
+
+ it "should write metadata to the file correctly" do
+ filename = resource_file('_metadata.png')
+
+ image = ChunkyPNG::Image.new(10, 10)
+ image.metadata['Title'] = 'My amazing icon!'
+ image.metadata['Author'] = 'Willem van Bergen'
+ image.save(filename)
+
+ metadata = ChunkyPNG::Datastream.from_file(filename).metadata
+ metadata['Title'].should == 'My amazing icon!'
+ metadata['Author'].should == 'Willem van Bergen'
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/rmagick_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/rmagick_spec.rb
new file mode 100644
index 00000000..d039ab40
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png/rmagick_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+begin
+ require 'chunky_png/rmagick'
+
+ describe ChunkyPNG::RMagick do
+
+ it "should import an image from RMagick correctly" do
+ image = Magick::Image.read(resource_file('composited.png')).first
+ canvas = ChunkyPNG::RMagick.import(image)
+ canvas.should == reference_canvas('composited')
+ end
+
+ it "should export an image to RMagick correctly" do
+ canvas = reference_canvas('composited')
+ image = ChunkyPNG::RMagick.export(canvas)
+ image.format = 'PNG32'
+ canvas.should == ChunkyPNG::Canvas.from_blob(image.to_blob)
+ end
+ end
+rescue LoadError => e
+ # skipping RMagick tests
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png_spec.rb
new file mode 100644
index 00000000..80a6e487
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/chunky_png_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe ChunkyPNG do
+
+ # it "should create reference images for all color modes" do
+ # image = ChunkyPNG::Image.new(10, 10, ChunkyPNG::Color.rgb(100, 100, 100))
+ # [:indexed, :grayscale, :grayscale_alpha, :truecolor, :truecolor_alpha].each do |color_mode|
+ #
+ # color_mode_id = ChunkyPNG.const_get("COLOR_#{color_mode.to_s.upcase}")
+ # filename = resource_file("gray_10x10_#{color_mode}.png")
+ # image.save(filename, :color_mode => color_mode_id)
+ # end
+ # end
+
+ # it "should create a reference image for operations" do
+ # image = ChunkyPNG::Image.new(16, 16, ChunkyPNG::Color::WHITE)
+ # r = 0
+ # image.width.times do |x|
+ # g = 0
+ # image.height.times do |y|
+ # image[x, y] = ChunkyPNG::Color.rgb(r, g, 255)
+ # g += 16
+ # end
+ # r += 16
+ # end
+ # filename = resource_file('operations.png')
+ # image.save(filename)
+ # # `open #{filename}`
+ # end
+
+ # it "should create damaged CRC values" do
+ # Zlib.stub!(:crc32).and_return(12345)
+ # image = ChunkyPNG::Image.new(10, 10, ChunkyPNG::Color::BLACK)
+ # image.save(resource_file('damaged_chunk.png'))
+ # end
+end
+
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgai4a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgai4a08.png
new file mode 100644
index 00000000..398132be
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgai4a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgai4a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgai4a16.png
new file mode 100644
index 00000000..51192e73
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgai4a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgan6a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgan6a08.png
new file mode 100644
index 00000000..e6087387
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgan6a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgan6a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgan6a16.png
new file mode 100644
index 00000000..984a9952
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgan6a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgbn4a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgbn4a08.png
new file mode 100644
index 00000000..7cbefc3b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgbn4a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bggn4a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bggn4a16.png
new file mode 100644
index 00000000..13fd85ba
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bggn4a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgwn6a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgwn6a08.png
new file mode 100644
index 00000000..a67ff205
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgwn6a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgyn6a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgyn6a16.png
new file mode 100644
index 00000000..ae3e9be5
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/background_chunks/bgyn6a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g01.png
new file mode 100644
index 00000000..556fa727
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g01.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g01.rgba
new file mode 100644
index 00000000..6a932558
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g01.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g02.png
new file mode 100644
index 00000000..ce09821e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g02.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g02.rgba
new file mode 100644
index 00000000..86b1485b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g02.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g04.png
new file mode 100644
index 00000000..3853273f
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g04.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g04.rgba
new file mode 100644
index 00000000..68c23404
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g04.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g08.png
new file mode 100644
index 00000000..faed8bec
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g08.rgba
new file mode 100644
index 00000000..391a129e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g16.png
new file mode 100644
index 00000000..a9f28165
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g16.rgba
new file mode 100644
index 00000000..22271a8b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi0g16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c08.png
new file mode 100644
index 00000000..2aab44d4
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c08.rgba
new file mode 100644
index 00000000..877ead96
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c16.png
new file mode 100644
index 00000000..cd7e50f9
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c16.rgba
new file mode 100644
index 00000000..45b1277b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi2c16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p01.png
new file mode 100644
index 00000000..00a7cea6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p01.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p01.rgba
new file mode 100644
index 00000000..5c0721d2
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p01.rgba
@@ -0,0 +1 @@
+îÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ
\ No newline at end of file
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p02.png
new file mode 100644
index 00000000..bb16b44b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p02.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p02.rgba
new file mode 100644
index 00000000..67839c3e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p02.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p04.png
new file mode 100644
index 00000000..b4e888e2
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p04.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p04.rgba
new file mode 100644
index 00000000..ec333980
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p04.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p08.png
new file mode 100644
index 00000000..50a6d1ca
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p08.rgba
new file mode 100644
index 00000000..7e0e15ba
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi3p08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a08.png
new file mode 100644
index 00000000..398132be
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a08.rgba
new file mode 100644
index 00000000..1946bed1
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a16.png
new file mode 100644
index 00000000..51192e73
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a16.rgba
new file mode 100644
index 00000000..a2d6f3d9
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi4a16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a08.png
new file mode 100644
index 00000000..aecb32e0
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a08.rgba
new file mode 100644
index 00000000..acac3d35
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a16.png
new file mode 100644
index 00000000..4181533a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a16.rgba
new file mode 100644
index 00000000..4e114c9a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basi6a16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g01.png
new file mode 100644
index 00000000..1d722423
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g01.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g01.rgba
new file mode 100644
index 00000000..6a932558
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g01.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g02.png
new file mode 100644
index 00000000..50833241
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g02.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g02.rgba
new file mode 100644
index 00000000..86b1485b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g02.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g04.png
new file mode 100644
index 00000000..0bf36878
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g04.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g04.rgba
new file mode 100644
index 00000000..68c23404
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g04.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g08.png
new file mode 100644
index 00000000..23c82379
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g08.rgba
new file mode 100644
index 00000000..391a129e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g16.png
new file mode 100644
index 00000000..e7c82f78
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g16.rgba
new file mode 100644
index 00000000..22271a8b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn0g16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c08.png
new file mode 100644
index 00000000..db5ad158
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c08.rgba
new file mode 100644
index 00000000..877ead96
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c16.png
new file mode 100644
index 00000000..50c1cb91
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c16.rgba
new file mode 100644
index 00000000..45b1277b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn2c16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p01.png
new file mode 100644
index 00000000..b145c2b8
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p01.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p01.rgba
new file mode 100644
index 00000000..5c0721d2
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p01.rgba
@@ -0,0 +1 @@
+îÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ"fÿÿ"fÿÿ"fÿÿ"fÿÿîÿ"ÿîÿ"ÿîÿ"ÿîÿ"ÿ
\ No newline at end of file
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p02.png
new file mode 100644
index 00000000..8985b3d8
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p02.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p02.rgba
new file mode 100644
index 00000000..67839c3e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p02.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p04.png
new file mode 100644
index 00000000..0fbf9e82
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p04.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p04.rgba
new file mode 100644
index 00000000..ec333980
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p04.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p08.png
new file mode 100644
index 00000000..0ddad07e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p08.rgba
new file mode 100644
index 00000000..7e0e15ba
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn3p08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a08.png
new file mode 100644
index 00000000..3e130522
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a08.rgba
new file mode 100644
index 00000000..1946bed1
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a16.png
new file mode 100644
index 00000000..8243644d
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a16.rgba
new file mode 100644
index 00000000..a2d6f3d9
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn4a16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a08.png
new file mode 100644
index 00000000..e6087387
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a08.rgba
new file mode 100644
index 00000000..acac3d35
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a16.png
new file mode 100644
index 00000000..984a9952
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a16.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a16.rgba
new file mode 100644
index 00000000..4e114c9a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/basic/basn6a16.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/x00n0g01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/x00n0g01.png
new file mode 100644
index 00000000..db3a5fda
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/x00n0g01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/xcrn0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/xcrn0g04.png
new file mode 100644
index 00000000..5bce9f3a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/xcrn0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/xlfn0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/xlfn0g04.png
new file mode 100644
index 00000000..1fd104ba
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/broken/xlfn0g04.png
@@ -0,0 +1,13 @@
+‰PNG
+
+
+
+
+
+IHDR “áÈ)ÈIDATxœ]ÑÁ
+Â0P*@ð¡#°
+
+#TâÈ10lPF`Ø F=•ŸÄIQâ*çÅuí”`%qk
+Hžñšˆ©ñ´€m÷Íüµàߟ Ñ=,¸fìOK
+
+ç ÐtŽÀ(Èïä’צíF;èPº€¯¾{xpç]9‡/p*$(ì*éyìÕƒ ×þÚéçè@÷C¼ cÔqž‹NÛU#„)11·.räðfä0°ägh(¥týÙÂEøÿ‰kIEND®B`‚
\ No newline at end of file
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi1n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi1n0g16.png
new file mode 100644
index 00000000..e7c82f78
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi1n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi1n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi1n2c16.png
new file mode 100644
index 00000000..50c1cb91
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi1n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi2n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi2n0g16.png
new file mode 100644
index 00000000..14d64c58
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi2n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi2n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi2n2c16.png
new file mode 100644
index 00000000..4c2e3e33
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi2n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi4n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi4n0g16.png
new file mode 100644
index 00000000..69e73ede
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi4n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi4n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi4n2c16.png
new file mode 100644
index 00000000..93691e37
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi4n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi9n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi9n0g16.png
new file mode 100644
index 00000000..92484135
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi9n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi9n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi9n2c16.png
new file mode 100644
index 00000000..f0512e49
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/chunk_ordering/oi9n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z00n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z00n2c08.png
new file mode 100644
index 00000000..7669eb83
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z00n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z03n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z03n2c08.png
new file mode 100644
index 00000000..bfb10de8
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z03n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z06n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z06n2c08.png
new file mode 100644
index 00000000..b90ebc10
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z06n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z09n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z09n2c08.png
new file mode 100644
index 00000000..5f191a78
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/compression_levels/z09n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08.png
new file mode 100644
index 00000000..45a00759
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08.rgba
new file mode 100644
index 00000000..6427b7c2
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08_reference.png
new file mode 100644
index 00000000..34a9ff45
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08_reference.rgba
new file mode 100644
index 00000000..6427b7c2
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n0g08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08.png
new file mode 100644
index 00000000..d6a1ffff
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08.rgba
new file mode 100644
index 00000000..3cb35479
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08_reference.png
new file mode 100644
index 00000000..c72d87c1
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08_reference.rgba
new file mode 100644
index 00000000..3cb35479
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f00n2c08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08.png
new file mode 100644
index 00000000..4a1107b4
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08.rgba
new file mode 100644
index 00000000..71ffc091
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08_reference.png
new file mode 100644
index 00000000..f5595f0c
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08_reference.rgba
new file mode 100644
index 00000000..71ffc091
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n0g08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08.png
new file mode 100644
index 00000000..26fee958
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08.rgba
new file mode 100644
index 00000000..bd4776b3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08_reference.png
new file mode 100644
index 00000000..a8fcdab7
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08_reference.rgba
new file mode 100644
index 00000000..bd4776b3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f01n2c08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08.png
new file mode 100644
index 00000000..bfe410c5
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08.rgba
new file mode 100644
index 00000000..857e69d2
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08_reference.png
new file mode 100644
index 00000000..44877cb7
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08_reference.rgba
new file mode 100644
index 00000000..857e69d2
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n0g08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08.png
new file mode 100644
index 00000000..e590f123
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08.rgba
new file mode 100644
index 00000000..56b7d61f
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08_reference.png
new file mode 100644
index 00000000..09f22e5d
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08_reference.rgba
new file mode 100644
index 00000000..56b7d61f
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f02n2c08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08.png
new file mode 100644
index 00000000..ed01e292
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08.rgba
new file mode 100644
index 00000000..f59ea792
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08_reference.png
new file mode 100644
index 00000000..6d197230
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08_reference.rgba
new file mode 100644
index 00000000..f59ea792
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n0g08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08.png
new file mode 100644
index 00000000..75811505
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08.rgba
new file mode 100644
index 00000000..fcb5088a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08_reference.png
new file mode 100644
index 00000000..36829ce9
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08_reference.rgba
new file mode 100644
index 00000000..fcb5088a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f03n2c08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08.png
new file mode 100644
index 00000000..663fdae3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08.rgba
new file mode 100644
index 00000000..79535b09
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08_reference.png
new file mode 100644
index 00000000..b5e52b69
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08_reference.rgba
new file mode 100644
index 00000000..79535b09
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n0g08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08.png
new file mode 100644
index 00000000..3c8b5116
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08.rgba
new file mode 100644
index 00000000..3653c27b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08_reference.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08_reference.png
new file mode 100644
index 00000000..8b2e6068
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08_reference.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08_reference.rgba b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08_reference.rgba
new file mode 100644
index 00000000..3653c27b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/filtering/f04n2c08_reference.rgba differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n0g16.png
new file mode 100644
index 00000000..41083ca8
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n2c08.png
new file mode 100644
index 00000000..a9354dbe
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n3p04.png
new file mode 100644
index 00000000..60396c95
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g03n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n0g16.png
new file mode 100644
index 00000000..32395b76
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n2c08.png
new file mode 100644
index 00000000..a652b0ce
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n3p04.png
new file mode 100644
index 00000000..5661cc31
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g04n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n0g16.png
new file mode 100644
index 00000000..70b37f01
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n2c08.png
new file mode 100644
index 00000000..932c1365
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n3p04.png
new file mode 100644
index 00000000..96199305
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g05n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n0g16.png
new file mode 100644
index 00000000..d6a47c2d
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n2c08.png
new file mode 100644
index 00000000..59734646
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n3p04.png
new file mode 100644
index 00000000..c73fb613
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g07n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n0g16.png
new file mode 100644
index 00000000..85f2c958
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n2c08.png
new file mode 100644
index 00000000..b3039970
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n3p04.png
new file mode 100644
index 00000000..1b6a6be2
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g10n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n0g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n0g16.png
new file mode 100644
index 00000000..a9f6787c
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n0g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n2c08.png
new file mode 100644
index 00000000..03f505a6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n3p04.png
new file mode 100644
index 00000000..4f943c61
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/gamma/g25n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm0n0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm0n0g04.png
new file mode 100644
index 00000000..9fba5db3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm0n0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm7n0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm7n0g04.png
new file mode 100644
index 00000000..f7dc46e6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm7n0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm9n0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm9n0g04.png
new file mode 100644
index 00000000..dd70911a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/metadata/cm9n0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ccwn2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ccwn2c08.png
new file mode 100644
index 00000000..47c24817
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ccwn2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ccwn3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ccwn3p08.png
new file mode 100644
index 00000000..8bb2c109
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ccwn3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdfn2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdfn2c08.png
new file mode 100644
index 00000000..559e5261
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdfn2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdhn2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdhn2c08.png
new file mode 100644
index 00000000..3e07e8ec
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdhn2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdsn2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdsn2c08.png
new file mode 100644
index 00000000..076c32cc
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdsn2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdun2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdun2c08.png
new file mode 100644
index 00000000..846033be
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cdun2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ch1n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ch1n3p04.png
new file mode 100644
index 00000000..17cd12df
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ch1n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ch2n3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ch2n3p08.png
new file mode 100644
index 00000000..25c17987
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ch2n3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs3n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs3n2c16.png
new file mode 100644
index 00000000..bf5fd20a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs3n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs3n3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs3n3p08.png
new file mode 100644
index 00000000..f4a66237
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs3n3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs5n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs5n2c08.png
new file mode 100644
index 00000000..40f947c3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs5n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs5n3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs5n3p08.png
new file mode 100644
index 00000000..dfd6e6e6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs5n3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs8n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs8n2c08.png
new file mode 100644
index 00000000..8e01d329
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs8n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs8n3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs8n3p08.png
new file mode 100644
index 00000000..a44066eb
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/cs8n3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ct0n0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ct0n0g04.png
new file mode 100644
index 00000000..40d1e062
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ct0n0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ct1n0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ct1n0g04.png
new file mode 100644
index 00000000..3ba110aa
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ct1n0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ctzn0g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ctzn0g04.png
new file mode 100644
index 00000000..b4401c9c
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ctzn0g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/pp0n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/pp0n2c16.png
new file mode 100644
index 00000000..8f2aad73
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/pp0n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/pp0n6a08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/pp0n6a08.png
new file mode 100644
index 00000000..4ed7a30e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/pp0n6a08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps1n0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps1n0g08.png
new file mode 100644
index 00000000..2053df2b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps1n0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps1n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps1n2c16.png
new file mode 100644
index 00000000..b03ecfc6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps1n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps2n0g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps2n0g08.png
new file mode 100644
index 00000000..beeab8ff
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps2n0g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps2n2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps2n2c16.png
new file mode 100644
index 00000000..c256f909
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/other/ps2n2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s01i3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s01i3p01.png
new file mode 100644
index 00000000..6c0fad1f
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s01i3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s01n3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s01n3p01.png
new file mode 100644
index 00000000..cb2c8c78
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s01n3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s02i3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s02i3p01.png
new file mode 100644
index 00000000..2defaed9
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s02i3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s02n3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s02n3p01.png
new file mode 100644
index 00000000..2b1b6696
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s02n3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s03i3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s03i3p01.png
new file mode 100644
index 00000000..c23fdc46
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s03i3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s03n3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s03n3p01.png
new file mode 100644
index 00000000..6d96ee4f
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s03n3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s04i3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s04i3p01.png
new file mode 100644
index 00000000..0e710c2c
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s04i3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s04n3p01.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s04n3p01.png
new file mode 100644
index 00000000..956396c4
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s04n3p01.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s05i3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s05i3p02.png
new file mode 100644
index 00000000..d14cbd35
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s05i3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s05n3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s05n3p02.png
new file mode 100644
index 00000000..bf940f05
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s05n3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s06i3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s06i3p02.png
new file mode 100644
index 00000000..456ada32
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s06i3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s06n3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s06n3p02.png
new file mode 100644
index 00000000..501064dc
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s06n3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s07i3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s07i3p02.png
new file mode 100644
index 00000000..44b66bab
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s07i3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s07n3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s07n3p02.png
new file mode 100644
index 00000000..6a582593
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s07n3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s08i3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s08i3p02.png
new file mode 100644
index 00000000..acf74f3f
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s08i3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s08n3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s08n3p02.png
new file mode 100644
index 00000000..b7094e1b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s08n3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s09i3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s09i3p02.png
new file mode 100644
index 00000000..0bfae8e4
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s09i3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s09n3p02.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s09n3p02.png
new file mode 100644
index 00000000..711ab824
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s09n3p02.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s32i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s32i3p04.png
new file mode 100644
index 00000000..0841910b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s32i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s32n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s32n3p04.png
new file mode 100644
index 00000000..fa58e3e3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s32n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s33i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s33i3p04.png
new file mode 100644
index 00000000..ab0dc14a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s33i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s33n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s33n3p04.png
new file mode 100644
index 00000000..764f1a3d
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s33n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s34i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s34i3p04.png
new file mode 100644
index 00000000..bd99039b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s34i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s34n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s34n3p04.png
new file mode 100644
index 00000000..9cbc68b3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s34n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s35i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s35i3p04.png
new file mode 100644
index 00000000..e2a5e0a6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s35i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s35n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s35n3p04.png
new file mode 100644
index 00000000..90b892eb
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s35n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s36i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s36i3p04.png
new file mode 100644
index 00000000..eb61b6f9
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s36i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s36n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s36n3p04.png
new file mode 100644
index 00000000..b38d1797
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s36n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s37i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s37i3p04.png
new file mode 100644
index 00000000..6e2b1e9b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s37i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s37n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s37n3p04.png
new file mode 100644
index 00000000..4d3054da
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s37n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s38i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s38i3p04.png
new file mode 100644
index 00000000..a0a8a140
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s38i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s38n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s38n3p04.png
new file mode 100644
index 00000000..1233ed04
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s38n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s39i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s39i3p04.png
new file mode 100644
index 00000000..04fee93e
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s39i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s39n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s39n3p04.png
new file mode 100644
index 00000000..c750100d
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s39n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s40i3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s40i3p04.png
new file mode 100644
index 00000000..68f358b8
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s40i3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s40n3p04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s40n3p04.png
new file mode 100644
index 00000000..864b6b96
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/sizes/s40n3p04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn1g04.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn1g04.png
new file mode 100644
index 00000000..fc800205
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn1g04.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn2c16.png
new file mode 100644
index 00000000..5abfbbb3
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn3p08.png
new file mode 100644
index 00000000..4210d168
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbbn3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbgn2c16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbgn2c16.png
new file mode 100644
index 00000000..236c81dc
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbgn2c16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbgn3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbgn3p08.png
new file mode 100644
index 00000000..42db2325
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbgn3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbrn2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbrn2c08.png
new file mode 100644
index 00000000..8c214746
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbrn2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbwn1g16.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbwn1g16.png
new file mode 100644
index 00000000..dba2cbb6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbwn1g16.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbwn3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbwn3p08.png
new file mode 100644
index 00000000..7922135a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbwn3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbyn3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbyn3p08.png
new file mode 100644
index 00000000..5b2c6cbb
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tbyn3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n1g08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n1g08.png
new file mode 100644
index 00000000..caad31de
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n1g08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n2c08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n2c08.png
new file mode 100644
index 00000000..f26be446
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n2c08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n3p08.png
new file mode 100644
index 00000000..4d6cf9e4
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp0n3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp1n3p08.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp1n3p08.png
new file mode 100644
index 00000000..6c5fd6ec
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite/transparency/tp1n3p08.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite_spec.rb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite_spec.rb
new file mode 100644
index 00000000..81c71192
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/png_suite_spec.rb
@@ -0,0 +1,119 @@
+require 'spec_helper'
+
+describe 'PNG testuite' do
+
+ context 'Decoding broken images' do
+ png_suite_files(:broken).each do |file|
+ it "should report #{File.basename(file)} as broken" do
+ lambda { ChunkyPNG::Image.from_file(file) }.should raise_error(ChunkyPNG::Exception)
+ end
+
+ it "should not report #{File.basename(file)} as unsupported" do
+ lambda { ChunkyPNG::Image.from_file(file) }.should_not raise_error(ChunkyPNG::NotSupported)
+ end
+ end
+ end
+
+ context 'Decoding unsupported images' do
+
+ # TODO: we eventually want to support these!
+
+ png_suite_files(:basic_not_supported).each do |file|
+ color_mode = file.match(/[in](\d)[apgc](\d\d)\.png$/)[1].to_i
+ bit_depth = file.match(/[in](\d)[apgc](\d\d)\.png$/)[2].to_i
+
+ it "should report #{File.basename(file)} (color mode: #{color_mode}, bit depth: #{bit_depth}) as unsupported" do
+ lambda { ChunkyPNG::Image.from_file(file) }.should raise_error(ChunkyPNG::NotSupported)
+ end
+ end
+ end
+
+ context 'Decoding supported images' do
+ png_suite_files(:basic, '*.png').each do |file|
+
+ reference = file.sub(/\.png$/, '.rgba')
+ color_mode = file.match(/[in](\d)[apgc](\d\d)\.png$/)[1].to_i
+ bit_depth = file.match(/[in](\d)[apgc](\d\d)\.png$/)[2].to_i
+
+ it "should decode #{File.basename(file)} (color mode: #{color_mode}, bit depth: #{bit_depth}) exactly the same as the reference image" do
+ decoded = ChunkyPNG::Canvas.from_file(file)
+ File.open(reference, 'rb') { |f| decoded.to_rgba_stream.should == f.read }
+ end
+ end
+ end
+
+ context 'Decoding text chunks' do
+
+ it "should not find metadata in a file without text chunks" do
+ image = ChunkyPNG::Image.from_file(png_suite_file(:metadata, 'cm0n0g04.png'))
+ image.metadata.should be_empty
+ end
+
+ # it "should find metadata in a file with uncompressed text chunks" do
+ # image = ChunkyPNG::Image.from_file(png_suite_file(:metadata, 'cm7n0g04.png'))
+ # image.metadata.should_not be_empty
+ # end
+ #
+ # it "should find metadata in a file with compressed text chunks" do
+ # image = ChunkyPNG::Image.from_file(png_suite_file(:metadata, 'cm9n0g04.png'))
+ # image.metadata.should_not be_empty
+ # end
+ end
+
+ context 'Decoding filter methods' do
+ png_suite_files(:filtering, '*_reference.png').each do |reference_file|
+
+ file = reference_file.sub(/_reference\.png$/, '.png')
+ filter_method = file.match(/f(\d\d)[a-z0-9]+\.png/)[1].to_i
+
+ it "should decode #{File.basename(file)} (filter method: #{filter_method}) exactly the same as the reference image" do
+ decoded = ChunkyPNG::Canvas.from_file(file)
+ reference = ChunkyPNG::Canvas.from_file(reference_file)
+ decoded.should == reference
+ end
+ end
+ end
+
+ context 'Decoding different chunk splits' do
+ it "should decode grayscale images successfully regardless of the data chunk ordering and splitting" do
+ reference = ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi1n0g16.png')).imagedata
+ ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi2n0g16.png')).imagedata.should == reference
+ ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi4n0g16.png')).imagedata.should == reference
+ ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi9n0g16.png')).imagedata.should == reference
+ end
+
+ it "should decode color images successfully regardless of the data chunk ordering and splitting" do
+ reference = ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi1n2c16.png')).imagedata
+ ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi2n2c16.png')).imagedata.should == reference
+ ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi4n2c16.png')).imagedata.should == reference
+ ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi9n2c16.png')).imagedata.should == reference
+ end
+ end
+
+ context 'Decoding different compression levels' do
+ it "should decode the image successfully regardless of the compression level" do
+ reference = ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z00n2c08.png')).imagedata
+ ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z03n2c08.png')).imagedata.should == reference
+ ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z06n2c08.png')).imagedata.should == reference
+ ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z09n2c08.png')).imagedata.should == reference
+ end
+ end
+
+ context 'Decoding different sizes' do
+
+ png_suite_files(:sizes, '*n*.png').each do |file|
+ dimension = file.match(/s(\d\d)n\dp\d\d/)[1].to_i
+
+ it "should create a canvas with a #{dimension}x#{dimension} size" do
+ canvas = ChunkyPNG::Image.from_file(file)
+ canvas.width.should == dimension
+ canvas.height.should == dimension
+ end
+
+ it "should decode the #{dimension}x#{dimension} interlaced image exactly the same the non-interlaced version" do
+ interlaced_file = file.sub(/n3p(\d\d)\.png$/, 'i3p\\1.png')
+ ChunkyPNG::Image.from_file(interlaced_file).should == ChunkyPNG::Image.from_file(file)
+ end
+ end
+ end
+end
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/adam7.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/adam7.png
new file mode 100644
index 00000000..3bab12c5
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/adam7.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock.png
new file mode 100644
index 00000000..c37e23a6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_base.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_base.png
new file mode 100644
index 00000000..39949f3f
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_base.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_flip_horizontally.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_flip_horizontally.png
new file mode 100644
index 00000000..cde88849
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_flip_horizontally.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_flip_vertically.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_flip_vertically.png
new file mode 100644
index 00000000..437e594b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_flip_vertically.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_mask.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_mask.png
new file mode 100644
index 00000000..480d512b
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_mask.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_mask_updated.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_mask_updated.png
new file mode 100644
index 00000000..108646f6
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_mask_updated.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_180.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_180.png
new file mode 100644
index 00000000..1eaaa7c0
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_180.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_left.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_left.png
new file mode 100644
index 00000000..48ee2b8a
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_left.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_right.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_right.png
new file mode 100644
index 00000000..04475233
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_rotate_right.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_stubbed.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_stubbed.png
new file mode 100644
index 00000000..e254c79d
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_stubbed.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_updated.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_updated.png
new file mode 100644
index 00000000..a05406ca
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/clock_updated.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/composited.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/composited.png
new file mode 100644
index 00000000..3c79532c
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/composited.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/cropped.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/cropped.png
new file mode 100644
index 00000000..9b9299b0
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/cropped.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/damaged_chunk.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/damaged_chunk.png
new file mode 100644
index 00000000..cf1fbcb7
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/damaged_chunk.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/damaged_signature.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/damaged_signature.png
new file mode 100644
index 00000000..1fd104ba
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/damaged_signature.png
@@ -0,0 +1,13 @@
+‰PNG
+
+
+
+
+
+IHDR “áÈ)ÈIDATxœ]ÑÁ
+Â0P*@ð¡#°
+
+#TâÈ10lPF`Ø F=•ŸÄIQâ*çÅuí”`%qk
+Hžñšˆ©ñ´€m÷Íüµàߟ Ñ=,¸fìOK
+
+ç ÐtŽÀ(Èïä’צíF;èPº€¯¾{xpç]9‡/p*$(ì*éyìÕƒ ×þÚéçè@÷C¼ cÔqž‹NÛU#„)11·.räðfä0°ägh(¥týÙÂEøÿ‰kIEND®B`‚
\ No newline at end of file
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/lines.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/lines.png
new file mode 100644
index 00000000..f3543851
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/lines.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/operations.png b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/operations.png
new file mode 100644
index 00000000..fe820f95
Binary files /dev/null and b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/operations.png differ
diff --git a/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/pixelstream.rgb b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/pixelstream.rgb
new file mode 100644
index 00000000..b4183a37
--- /dev/null
+++ b/lib/ruby/gem/gems/chunky_png-0.11.1/spec/resources/pixelstream.rgb
@@ -0,0 +1,67 @@
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýûûûúúúøøø÷÷÷öööõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ÷÷÷øøøùùùúúúûûûýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýúúú÷÷÷ôôôðððìììéééæææåååååååååååååååååååååååååååååååååääääääääääääääääääääääääääääääääääääåååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååèèèëëëïïïòòòõõõùùùüüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûûûöööñññëëëåååßßßÚÚÚÕÕÕÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÒÒÒÑÑÑÑÑÑÏÏÏÎÎÎÎÎÎÍÍÍÍÍÍÍÍÍÎÎÎÎÎÎÎÎÎÎÎÎÏÏÏÏÏÏÑÑÑÒÒÒÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÒÒÒÒÒÒÑÑÑÐÐÐÏÏÏÏÏÏÎÎÎÏÏÏÏÏÏÐÐÐÑÑÑÑÑÑÒÒÒÒÒÒÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÔÔÔØØØÝÝÝãããèèèîîîôôôúúúþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúòòòêêêÈÈȦ¦¦ œœœ–––•••••••••••••••“““’’’’’’‘‘‘ŽŽŽŒŒŒ‹‹‹ŠŠŠŠŠŠŠŠŠ‹‹‹‹‹‹ŒŒŒŽŽŽ’’’“““”””•••–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––————————————–––•••””””””“““’’’’’’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘’’’’’’“““””””””•••–––———————————————––––––—————————————————————––––––••••••””””””””””””””””””••••••––––––——————————————————————————————––––––––––––•••••••••••••••••••••••••••••••••••••••••••••••••••––––––––––––—————————————————————•••”””’’’‘‘‘ŽŽŽŒŒŒ‹‹‹ŒŒŒ’’’”””•••–––————————————————————————–––––––––™™™ŸŸŸ¤¤¤ÓÓÓçççïïï÷÷÷ýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøîîîäääooo £££àààêêêõõõýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööêêêÞÞÞkkk žžžÚÚÚåååòòòüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôæææØØØggg '%#
#" $" (&$*'%*(&+(&,)'*(')'%
&$#(%#*'%+(&+(&,)'//////.........///+(&+)')'&)&%)&$'$"!$" %"!#!#! # $" %"!&$"(%#)'%*(&,)(-*(-*(-*(-+)-+).+),*(*)'*(&$" (&$(&$*(&+)&-*(-+),*(-+)-*(,*(+(&)&%'&$ '$#(&$*(&+(&,)'-+)-+).+)-*(,)',)',*(+(')'%'%# ™™™ÓÓÓàààïïïûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýóóóâââÓÓÓddd JA:nM3 ÿÿÿþþþúúúõõõñññìììæææàààÚÚÚÔÔÔÎÎΣ££VVV
¸¸¸ÖÖÖÜÜÜãããééé T6Z:!0 jG,qM0[=|U6d<f?!`; 8)08)08)08*18*18*18*18*18*18*18*18*18*18*1=/5 mK1wT8uQ4xR4†`AqJ+///™™™™™™˜˜˜–––™™™™™™,)'pH)|U8Z